git.iko.soy/typeable/http-api-data
on master help sign in
Add parse*Maybe helpers
68a9b35Nickolay Kudasov
Web/HttpApiData/Internal.hs+21
@@ -64,6 +64,27 @@ class FromHttpApiData a where
64 parseQueryParam :: Text -> Either Text a
64 parseQueryParam :: Text -> Either Text a
65 parseQueryParam = parseUrlPiece
65 parseQueryParam = parseUrlPiece
66
66
67+-- | Parse URL path piece in a @'Maybe'@.
68+--
69+-- >>> parseUrlPieceMaybe "12" :: Maybe Int
70+-- Just 12
71+parseUrlPieceMaybe :: FromHttpApiData a => Text -> Maybe a
72+parseUrlPieceMaybe = either (const Nothing) Just . parseUrlPiece
73+
74+-- | Parse HTTP header value in a @'Maybe'@.
75+--
76+-- >>> parseHeaderMaybe "hello" :: Maybe Text
77+-- Just "hello"
78+parseHeaderMaybe :: FromHttpApiData a => ByteString -> Maybe a
79+parseHeaderMaybe = either (const Nothing) Just . parseHeader
80+
81+-- | Parse query param value in a @'Maybe'@.
82+--
83+-- >>> parseQueryParamMaybe "true" :: Maybe Bool
84+-- Just True
85+parseQueryParamMaybe :: FromHttpApiData a => Text -> Maybe a
86+parseQueryParamMaybe = either (const Nothing) Just . parseQueryParam
87+
67-- | Default parsing error.
88-- | Default parsing error.
68defaultParseError :: Text -> Either Text a
89defaultParseError :: Text -> Either Text a
69defaultParseError input = Left ("could not parse: `" <> input <> "'")
90defaultParseError input = Left ("could not parse: `" <> input <> "'")
Web/PathPieces/Internal.hs+2−2
@@ -25,7 +25,7 @@ import Data.Void (Void)
25#endif
25#endif
26
26
27import Web.HttpApiData
27import Web.HttpApiData
28−import Web.HttpApiData.Internal (parseMaybeTextData)
28+import Web.HttpApiData.Internal (parseMaybeTextData, parseUrlPieceMaybe)
29
29
30-- | Convert Haskell values to and from route piece.
30-- | Convert Haskell values to and from route piece.
31class PathPiece s where
31class PathPiece s where
@@ -112,7 +112,7 @@ defaultToPathPiece = toUrlPiece
112
112
113-- | Convert value from route piece using @'FromHttpApiData'@ implementation.
113-- | Convert value from route piece using @'FromHttpApiData'@ implementation.
114defaultFromPathPiece :: FromHttpApiData a => S.Text -> Maybe a
114defaultFromPathPiece :: FromHttpApiData a => S.Text -> Maybe a
115−defaultFromPathPiece = either (const Nothing) Just . parseUrlPiece
115+defaultFromPathPiece = parseUrlPieceMaybe
116
116
117-- | Convert value to route piece using @'PathPiece'@ instance for its parameter.
117-- | Convert value to route piece using @'PathPiece'@ instance for its parameter.
118defaultToPathPiece1 :: (PathPiece a, ToHttpApiData (f (WrappedPathPiece a))) => f a -> S.Text
118defaultToPathPiece1 :: (PathPiece a, ToHttpApiData (f (WrappedPathPiece a))) => f a -> S.Text
test/Spec.hs+6−8
@@ -17,6 +17,7 @@ import Test.Hspec.QuickCheck(prop)
17import Test.QuickCheck
17import Test.QuickCheck
18
18
19import Web.HttpApiData
19import Web.HttpApiData
20+import Web.HttpApiData.Internal
20
21
21instance Arbitrary T.Text where
22instance Arbitrary T.Text where
22 arbitrary = T.pack <$> arbitrary
23 arbitrary = T.pack <$> arbitrary
@@ -63,13 +64,13 @@ instance ToHttpApiData a => ToHttpApiData (RandomCase a) where
63instance FromHttpApiData a => FromHttpApiData (RandomCase a) where
64instance FromHttpApiData a => FromHttpApiData (RandomCase a) where
64 parseUrlPiece s = RandomCase [] <$> parseUrlPiece s
65 parseUrlPiece s = RandomCase [] <$> parseUrlPiece s
65
66
66−-- | Check case insensitivity for @fromUrlPiece@.
67+-- | Check case insensitivity for @parseUrlPiece@.
67checkUrlPieceI :: forall a. (Eq a, ToHttpApiData a, FromHttpApiData a, Show a, Arbitrary a) => Proxy a -> String -> Spec
68checkUrlPieceI :: forall a. (Eq a, ToHttpApiData a, FromHttpApiData a, Show a, Arbitrary a) => Proxy a -> String -> Spec
68checkUrlPieceI _ = checkUrlPiece (Proxy :: Proxy (RandomCase a))
69checkUrlPieceI _ = checkUrlPiece (Proxy :: Proxy (RandomCase a))
69
70
70spec :: Spec
71spec :: Spec
71spec = do
72spec = do
72− describe "toUrlPiece <=> fromUrlPiece" $ do
73+ describe "toUrlPiece <=> parseUrlPiece" $ do
73 checkUrlPiece (Proxy :: Proxy ()) "()"
74 checkUrlPiece (Proxy :: Proxy ()) "()"
74 checkUrlPiece (Proxy :: Proxy Char) "Char"
75 checkUrlPiece (Proxy :: Proxy Char) "Char"
75 checkUrlPieceI (Proxy :: Proxy Bool) "Bool"
76 checkUrlPieceI (Proxy :: Proxy Bool) "Bool"
@@ -97,12 +98,9 @@ spec = do
97 checkUrlPieceI (Proxy :: Proxy (Either Version Day)) "Either Version Day"
98 checkUrlPieceI (Proxy :: Proxy (Either Version Day)) "Either Version Day"
98
99
99 it "bad integers are rejected" $ do
100 it "bad integers are rejected" $ do
100− fromUrlPiece (T.pack "123hello") `shouldBe` (Nothing :: Maybe Int)
101+ parseUrlPieceMaybe (T.pack "123hello") `shouldBe` (Nothing :: Maybe Int)
101
102
102 it "bounds checking works" $ do
103 it "bounds checking works" $ do
103− fromUrlPiece (T.pack "256") `shouldBe` (Nothing :: Maybe Int8)
104+ parseUrlPieceMaybe (T.pack "256") `shouldBe` (Nothing :: Maybe Int8)
104− fromUrlPiece (T.pack "-10") `shouldBe` (Nothing :: Maybe Word)
105+ parseUrlPieceMaybe (T.pack "-10") `shouldBe` (Nothing :: Maybe Word)
105− where
106− fromUrlPiece :: FromHttpApiData a => T.Text -> Maybe a
107− fromUrlPiece = either (const Nothing) Just . parseUrlPiece
108
106