@@ -1,12 +1,22 @@
11{-# LANGUAGE DefaultSignatures #-}
2+{-# LANGUAGE OverloadedStrings #-}
23module Web.HttpApiData (
34 ToHttpApiData (..),
45 FromHttpApiData (..),
6+ parseMaybeUrlPiece,
7+ showUrlPiece,
8+ readMaybeUrlPiece,
9+ readEitherUrlPiece,
510) where
611
12+import Data.Monoid
713import Data.ByteString (ByteString)
14+
815import Data.Text (Text)
916import Data.Text.Encoding (encodeUtf8, decodeUtf8)
17+import qualified Data.Text as Text
18+
19+import Text.Read (readMaybe)
1020
1121-- | Convert value to HTTP API data.
1222class ToHttpApiData a where
@@ -35,3 +45,23 @@ class FromHttpApiData a where
3545 -- | Parse query param value.
3646 parseQueryParam :: Text -> Either Text a
3747 parseQueryParam = parseUrlPiece
48+
49+-- | Convert @'Maybe'@ parser into @'Either' 'Text'@ parser with default error message.
50+parseMaybeUrlPiece :: (Text -> Maybe a) -> (Text -> Either Text a)
51+parseMaybeUrlPiece parse input =
52+ case parse input of
53+ Nothing -> Left ("parseUrlPiece: could not convert: `" <> input <> "'")
54+ Just val -> Right val
55+
56+-- | Convert to URL piece using @'Show'@ instance.
57+showUrlPiece :: Show a => a -> Text
58+showUrlPiece = Text.pack . show
59+
60+-- | Parse URL piece using @'Read'@ instance.
61+readMaybeUrlPiece :: Read a => Text -> Maybe a
62+readMaybeUrlPiece = readMaybe . Text.unpack
63+
64+-- | Parse URL piece using @'Read'@ instance.
65+readEitherUrlPiece :: Read a => Text -> Either Text a
66+readEitherUrlPiece = parseMaybeUrlPiece readMaybeUrlPiece
67+