{-# LANGUAGE FlexibleInstances #-} module Network.HTTP.Kinder.URI ( -- * Classes for encoding and decoding URIEncode (..) , URIDecode (..) -- * Extra serialization utilities , uriDecodeBS ) where import qualified Data.ByteString as S import Data.Int import Data.Text (Text) import qualified Data.Text as Text import qualified Data.Text.Encoding as Enc import Data.Text.Read (decimal) import Network.HTTP.Kinder.Common -- Class -- ---------------------------------------------------------------------------- -- | Determines a 'Text' serialization of a type with URI segment -- representation. class URIEncode a where uriEncode :: a -> Text -- | Parses a 'Text' serialization of a for some type from a representation -- as a URI segment. class URIDecode a where uriDecode :: Text -> Either String a -- | Since 'URIDecode' assumes a 'Text'-like representation but we may read -- a 'S.ByteString' off the wire, this helper function first tries to -- decode the 'S.ByteString' as UTF-8 'Text' then decodes according to -- 'URIDecode'. uriDecodeBS :: URIDecode a => S.ByteString -> Either String a uriDecodeBS s = case Enc.decodeUtf8' s of Left _err -> Left "could not parse UTF8 string" Right a -> uriDecode a -- Instances -- ---------------------------------------------------------------------------- instance URIDecode (Raw Text) where uriDecode text = Right (Raw text) -- | For URI segments this instance is the same as the one for @'Raw' -- 'Text'@ since URI segments don't contain quotations. instance URIDecode Text where uriDecode text = Right text -- | Decoder for any type with a decimal representation. Requires a 'Show' -- instance for the error message. uriDecodeDecimal :: (Show a, Integral a) => Text -> Either String a uriDecodeDecimal txt = case decimal txt of Left err -> Left err Right (a, t) | Text.null t -> Right a | otherwise -> Left ("incomplete parse: " ++ show (a, t)) instance URIDecode Int where uriDecode = uriDecodeDecimal instance URIDecode Int8 where uriDecode = uriDecodeDecimal instance URIDecode Int16 where uriDecode = uriDecodeDecimal instance URIDecode Int32 where uriDecode = uriDecodeDecimal instance URIDecode Int64 where uriDecode = uriDecodeDecimal instance URIDecode Integer where uriDecode = uriDecodeDecimal