servant/servant/src/Servant/Common/Text.hs

143 lines
3.3 KiB
Haskell

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Servant.Common.Text
( FromText(..)
, ToText(..)
) where
import Control.Applicative ((<$>))
import Data.Int (Int16, Int32, Int64, Int8)
import Data.String.Conversions (cs)
import Data.Text (Text)
import Data.Text.Read (Reader, decimal, rational, signed)
import Data.Word (Word, Word16, Word32, Word64, Word8)
-- | For getting values from url captures and query string parameters
-- Instances should obey:
-- > fromText (toText a) == Just a
class FromText a where
fromText :: Text -> Maybe a
-- | For putting values in paths and query string parameters
-- Instances should obey:
-- > fromText (toText a) == Just a
class ToText a where
toText :: a -> Text
instance FromText Text where
fromText = Just
instance ToText Text where
toText = id
instance FromText String where
fromText = Just . cs
instance ToText String where
toText = cs
-- |
-- >>> fromText ("true"::Text) :: Maybe Bool
-- Just True
-- >>> fromText ("false"::Text) :: Maybe Bool
-- Just False
-- >>> fromText ("anything else"::Text) :: Maybe Bool
-- Nothing
instance FromText Bool where
fromText "true" = Just True
fromText "false" = Just False
fromText _ = Nothing
-- |
-- >>> toText True
-- "true"
-- >>> toText False
-- "false"
instance ToText Bool where
toText True = "true"
toText False = "false"
instance FromText Int where
fromText = runReader (signed decimal)
instance ToText Int where
toText = cs . show
instance FromText Int8 where
fromText = runReader (signed decimal)
instance ToText Int8 where
toText = cs . show
instance FromText Int16 where
fromText = runReader (signed decimal)
instance ToText Int16 where
toText = cs . show
instance FromText Int32 where
fromText = runReader (signed decimal)
instance ToText Int32 where
toText = cs . show
instance FromText Int64 where
fromText = runReader (signed decimal)
instance ToText Int64 where
toText = cs . show
instance FromText Word where
fromText = runReader decimal
instance ToText Word where
toText = cs . show
instance FromText Word8 where
fromText = runReader decimal
instance ToText Word8 where
toText = cs . show
instance FromText Word16 where
fromText = runReader decimal
instance ToText Word16 where
toText = cs . show
instance FromText Word32 where
fromText = runReader decimal
instance ToText Word32 where
toText = cs . show
instance FromText Word64 where
fromText = runReader decimal
instance ToText Word64 where
toText = cs . show
instance FromText Integer where
fromText = runReader (signed decimal)
instance ToText Integer where
toText = cs . show
instance FromText Double where
fromText x = fromRational <$> runReader rational x
instance ToText Double where
toText = cs . show
instance FromText Float where
-- Double is more practically accurate due to weird rounding when using
-- rational. We convert to double and then convert to Float.
fromText x = fromRational <$> runReader rational x
instance ToText Float where
toText = cs . show
runReader :: Reader a -> Text -> Maybe a
runReader reader t = either (const Nothing) (Just . fst) $ reader t