@@ -1,3 +1,4 @@
1{-# LANGUAGE DefaultSignatures #-}
2{-# LANGUAGE DefaultSignatures #-}
2{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedStrings #-}
@@ -36,8 +37,14 @@ import qualified Data.Text as T
36import qualified Data.Text.Lazy as L
37import qualified Data.Text.Lazy as L
38import Data.Time (Day)
39import Data.Time (Day)
42+#if MIN_VERSION_base(4,8,0)
40import Text.Read (readMaybe)
46import Text.Read (readMaybe)
47+import Text.ParserCombinators.ReadP (readP_to_S)
@@ -124,7 +131,21 @@ parseBounded reader input = do
124instance ToHttpApiData () where
131instance ToHttpApiData () where
125 toUrlPiece () = "_"
132 toUrlPiece () = "_"
134+instance ToHttpApiData Char where toUrlPiece = T.singleton
137+-- >>> toUrlPiece (Version [1, 2, 3] [])
139+instance ToHttpApiData Version where
140+ toUrlPiece = T.pack . showVersion
142+#if MIN_VERSION_base(4,8,0)
143+instance ToHttpApiData Void where
127instance ToHttpApiData Bool where toUrlPiece = showUrlPiece
147instance ToHttpApiData Bool where toUrlPiece = showUrlPiece
148+instance ToHttpApiData Ordering where toUrlPiece = showUrlPiece
128instance ToHttpApiData Double where toUrlPiece = showUrlPiece
149instance ToHttpApiData Double where toUrlPiece = showUrlPiece
129instance ToHttpApiData Float where toUrlPiece = showUrlPiece
150instance ToHttpApiData Float where toUrlPiece = showUrlPiece
130instance ToHttpApiData Int where toUrlPiece = showUrlPiece
151instance ToHttpApiData Int where toUrlPiece = showUrlPiece
@@ -143,6 +164,15 @@ instance ToHttpApiData Text where toUrlPiece = id
143instance ToHttpApiData L.Text where toUrlPiece = L.toStrict
164instance ToHttpApiData L.Text where toUrlPiece = L.toStrict
144instance ToHttpApiData Day where toUrlPiece = showUrlPiece
165instance ToHttpApiData Day where toUrlPiece = showUrlPiece
167+instance ToHttpApiData All where toUrlPiece = toUrlPiece . getAll
168+instance ToHttpApiData Any where toUrlPiece = toUrlPiece . getAny
170+instance ToHttpApiData a => ToHttpApiData (Dual a) where toUrlPiece = toUrlPiece . getDual
171+instance ToHttpApiData a => ToHttpApiData (Sum a) where toUrlPiece = toUrlPiece . getSum
172+instance ToHttpApiData a => ToHttpApiData (Product a) where toUrlPiece = toUrlPiece . getProduct
173+instance ToHttpApiData a => ToHttpApiData (First a) where toUrlPiece = toUrlPiece . getFirst
174+instance ToHttpApiData a => ToHttpApiData (Last a) where toUrlPiece = toUrlPiece . getLast
147-- >>> toUrlPiece (Just "Hello")
177-- >>> toUrlPiece (Just "Hello")
148-- "Just Hello"
178-- "Just Hello"
@@ -150,6 +180,15 @@ instance ToHttpApiData a => ToHttpApiData (Maybe a) where
150 toUrlPiece (Just x) = "Just " <> toUrlPiece x
180 toUrlPiece (Just x) = "Just " <> toUrlPiece x
151 toUrlPiece Nothing = "Nothing"
181 toUrlPiece Nothing = "Nothing"
184+-- >>> toUrlPiece (Left "err" :: Either String Int)
186+-- >>> toUrlPiece (Right 3 :: Either String Int)
188+instance (ToHttpApiData a, ToHttpApiData b) => ToHttpApiData (Either a b) where
189+ toUrlPiece (Left x) = "Left " <> toUrlPiece x
190+ toUrlPiece (Right x) = "Right " <> toUrlPiece x
154-- >>> parseUrlPiece "_" :: Either Text ()
193-- >>> parseUrlPiece "_" :: Either Text ()
155-- Right ()
194-- Right ()
@@ -157,7 +196,28 @@ instance FromHttpApiData () where
157 parseUrlPiece "_" = return ()
196 parseUrlPiece "_" = return ()
158 parseUrlPiece s = defaultParseError s
197 parseUrlPiece s = defaultParseError s
199+instance FromHttpApiData Char where
202+ Just (c, s') | T.null s' -> return c
203+ _ -> defaultParseError s
206+-- >>> showVersion <$> parseUrlPiece "1.2.3"
208+instance FromHttpApiData Version where
210+ case reverse (readP_to_S parseVersion (T.unpack s)) of
211+ ((x, ""):_) -> return x
212+ _ -> defaultParseError s
214+#if MIN_VERSION_base(4,8,0)
215+instance FromHttpApiData Void where
216+ parseUrlPiece _ = Left "Void cannot be parsed!"
160instance FromHttpApiData Bool where parseUrlPiece = readEitherUrlPiece
219instance FromHttpApiData Bool where parseUrlPiece = readEitherUrlPiece
220+instance FromHttpApiData Ordering where parseUrlPiece = readEitherUrlPiece
161instance FromHttpApiData Double where parseUrlPiece = runReader rational
221instance FromHttpApiData Double where parseUrlPiece = runReader rational
162instance FromHttpApiData Float where parseUrlPiece = runReader rational
222instance FromHttpApiData Float where parseUrlPiece = runReader rational
163instance FromHttpApiData Int where parseUrlPiece = parseBounded (signed decimal)
223instance FromHttpApiData Int where parseUrlPiece = parseBounded (signed decimal)
@@ -176,6 +236,15 @@ instance FromHttpApiData Text where parseUrlPiece = Right
176instance FromHttpApiData L.Text where parseUrlPiece = Right . L.fromStrict
236instance FromHttpApiData L.Text where parseUrlPiece = Right . L.fromStrict
177instance FromHttpApiData Day where parseUrlPiece = readEitherUrlPiece
237instance FromHttpApiData Day where parseUrlPiece = readEitherUrlPiece
239+instance FromHttpApiData All where parseUrlPiece = fmap All . parseUrlPiece
240+instance FromHttpApiData Any where parseUrlPiece = fmap Any . parseUrlPiece
242+instance FromHttpApiData a => FromHttpApiData (Dual a) where parseUrlPiece = fmap Dual . parseUrlPiece
243+instance FromHttpApiData a => FromHttpApiData (Sum a) where parseUrlPiece = fmap Sum . parseUrlPiece
244+instance FromHttpApiData a => FromHttpApiData (Product a) where parseUrlPiece = fmap Product . parseUrlPiece
245+instance FromHttpApiData a => FromHttpApiData (First a) where parseUrlPiece = fmap First . parseUrlPiece
246+instance FromHttpApiData a => FromHttpApiData (Last a) where parseUrlPiece = fmap Last . parseUrlPiece
180-- >>> parseUrlPiece "Just 123" :: Either Text (Maybe Int)
249-- >>> parseUrlPiece "Just 123" :: Either Text (Maybe Int)
181-- Right (Just 123)
250-- Right (Just 123)
@@ -186,6 +255,17 @@ instance FromHttpApiData a => FromHttpApiData (Maybe a) where
186 Nothing -> defaultParseError s
255 Nothing -> defaultParseError s
187 Just x -> Just <$> parseUrlPiece x
256 Just x -> Just <$> parseUrlPiece x
259+-- >>> parseUrlPiece "Right 123" :: Either Text (Either String Int)
261+instance (FromHttpApiData a, FromHttpApiData b) => FromHttpApiData (Either a b) where
263+ case T.stripPrefix "Right " s of
264+ Just r -> Right <$> parseUrlPiece r
265+ _ -> case T.stripPrefix "Left " s of
266+ Just l -> Left <$> parseUrlPiece l
267+ _ -> defaultParseError s
189-- $examples
269-- $examples
191-- Booleans:
271-- Booleans: