@@ -34,6 +34,14 @@ import Data.Void
34import Text.Read (readMaybe)
34import Text.Read (readMaybe)
35import Text.ParserCombinators.ReadP (readP_to_S)
35import Text.ParserCombinators.ReadP (readP_to_S)
38+import TextShow (TextShow, showt)
42+-- >>> :set -XDeriveGeneric
43+-- >>> import TextShow.Generic
37-- | Convert value to HTTP API data.
45-- | Convert value to HTTP API data.
38class ToHttpApiData a where
46class ToHttpApiData a where
39 {-# MINIMAL toUrlPiece | toQueryParam #-}
47 {-# MINIMAL toUrlPiece | toQueryParam #-}
@@ -96,6 +104,22 @@ parseMaybeTextData parse input =
96 Nothing -> defaultParseError input
104 Nothing -> defaultParseError input
97 Just val -> Right val
105 Just val -> Right val
108+-- | Convert to URL piece using @'TextShow'@ instance.
109+-- The result is always lower cased.
111+-- >>> showTextData True
114+-- This can be used as a default implementation for enumeration types:
116+-- >>> data MyData = Foo | Bar | Baz deriving (Show)
117+-- >>> instance ToHttpApiData MyData where toUrlPiece = showTextData
118+-- >>> toUrlPiece Foo
120+showTextData :: TextShow a => a -> Text
121+showTextData = T.toLower . showt
99-- | Convert to URL piece using @'Show'@ instance.
123-- | Convert to URL piece using @'Show'@ instance.
100-- The result is always lower cased.
124-- The result is always lower cased.
@@ -110,6 +134,7 @@ parseMaybeTextData parse input =
111showTextData :: Show a => a -> Text
135showTextData :: Show a => a -> Text
112showTextData = T.toLower . T.pack . show
136showTextData = T.toLower . T.pack . show
114-- | Parse given text case insensitive and return the rest of the input.
139-- | Parse given text case insensitive and return the rest of the input.
@@ -131,6 +156,23 @@ parseUrlPieceWithPrefix pattern input
132 (prefix, rest) = T.splitAt (T.length pattern) input
157 (prefix, rest) = T.splitAt (T.length pattern) input
160+-- | Parse values case insensitively based on @'TextShow'@ instance.
162+-- >>> parseBoundedCaseInsensitiveTextData "true" :: Either Text Bool
164+-- >>> parseBoundedCaseInsensitiveTextData "FALSE" :: Either Text Bool
167+-- This can be used as a default implementation for enumeration types:
169+-- >>> data MyData = Foo | Bar | Baz deriving (Show, Bounded, Enum, Generic)
170+-- >>> instance TextShow MyData where showt = genericShowt
171+-- >>> instance FromHttpApiData MyData where parseUrlPiece = parseBoundedCaseInsensitiveTextData
172+-- >>> parseUrlPiece "foo" :: Either Text MyData
174+parseBoundedCaseInsensitiveTextData :: forall a. (TextShow a, Bounded a, Enum a) => Text -> Either Text a
134-- | Parse values case insensitively based on @'Show'@ instance.
176-- | Parse values case insensitively based on @'Show'@ instance.
136-- >>> parseBoundedCaseInsensitiveTextData "true" :: Either Text Bool
178-- >>> parseBoundedCaseInsensitiveTextData "true" :: Either Text Bool
@@ -145,6 +187,7 @@ parseUrlPieceWithPrefix pattern input
145-- >>> parseUrlPiece "foo" :: Either Text MyData
187-- >>> parseUrlPiece "foo" :: Either Text MyData
146-- Right Foo
188-- Right Foo
147parseBoundedCaseInsensitiveTextData :: forall a. (Show a, Bounded a, Enum a) => Text -> Either Text a
189parseBoundedCaseInsensitiveTextData :: forall a. (Show a, Bounded a, Enum a) => Text -> Either Text a
148parseBoundedCaseInsensitiveTextData = parseMaybeTextData (flip lookup values . T.toLower)
191parseBoundedCaseInsensitiveTextData = parseMaybeTextData (flip lookup values . T.toLower)
150 values = map (showTextData &&& id) [minBound..maxBound :: a]
193 values = map (showTextData &&& id) [minBound..maxBound :: a]
@@ -201,6 +244,23 @@ instance ToHttpApiData Void where
202instance ToHttpApiData Bool where toUrlPiece = showTextData
245instance ToHttpApiData Bool where toUrlPiece = showTextData
203instance ToHttpApiData Ordering where toUrlPiece = showTextData
246instance ToHttpApiData Ordering where toUrlPiece = showTextData
249+instance ToHttpApiData Double where toUrlPiece = showt
250+instance ToHttpApiData Float where toUrlPiece = showt
251+instance ToHttpApiData Int where toUrlPiece = showt
252+instance ToHttpApiData Int8 where toUrlPiece = showt
253+instance ToHttpApiData Int16 where toUrlPiece = showt
254+instance ToHttpApiData Int32 where toUrlPiece = showt
255+instance ToHttpApiData Int64 where toUrlPiece = showt
256+instance ToHttpApiData Integer where toUrlPiece = showt
257+instance ToHttpApiData Word where toUrlPiece = showt
258+instance ToHttpApiData Word8 where toUrlPiece = showt
259+instance ToHttpApiData Word16 where toUrlPiece = showt
260+instance ToHttpApiData Word32 where toUrlPiece = showt
261+instance ToHttpApiData Word64 where toUrlPiece = showt
262+instance ToHttpApiData Day where toUrlPiece = T.pack . show
204instance ToHttpApiData Double where toUrlPiece = showTextData
264instance ToHttpApiData Double where toUrlPiece = showTextData
205instance ToHttpApiData Float where toUrlPiece = showTextData
265instance ToHttpApiData Float where toUrlPiece = showTextData
206instance ToHttpApiData Int where toUrlPiece = showTextData
266instance ToHttpApiData Int where toUrlPiece = showTextData
@@ -214,10 +274,12 @@ instance ToHttpApiData Word8 where toUrlPiece = showTextData
214instance ToHttpApiData Word16 where toUrlPiece = showTextData
274instance ToHttpApiData Word16 where toUrlPiece = showTextData
215instance ToHttpApiData Word32 where toUrlPiece = showTextData
275instance ToHttpApiData Word32 where toUrlPiece = showTextData
216instance ToHttpApiData Word64 where toUrlPiece = showTextData
276instance ToHttpApiData Word64 where toUrlPiece = showTextData
277+instance ToHttpApiData Day where toUrlPiece = showTextData
217instance ToHttpApiData String where toUrlPiece = T.pack
280instance ToHttpApiData String where toUrlPiece = T.pack
218instance ToHttpApiData Text where toUrlPiece = id
281instance ToHttpApiData Text where toUrlPiece = id
219instance ToHttpApiData L.Text where toUrlPiece = L.toStrict
282instance ToHttpApiData L.Text where toUrlPiece = L.toStrict
220−instance ToHttpApiData Day where toUrlPiece = showTextData
222instance ToHttpApiData All where toUrlPiece = toUrlPiece . getAll
284instance ToHttpApiData All where toUrlPiece = toUrlPiece . getAll
223instance ToHttpApiData Any where toUrlPiece = toUrlPiece . getAny
285instance ToHttpApiData Any where toUrlPiece = toUrlPiece . getAny