{-# LANGUAGE DefaultSignatures #-}
module Web.Hyperbole.Effect.QueryData where
import Data.Text (Text, pack)
import Data.Time (UTCTime)
import Data.Word
import Text.Read (readMaybe)
import Web.HttpApiData
class ToQueryData a where
toQueryData :: a -> Text
default toQueryData :: (Show a) => a -> Text
toQueryData = a -> Text
forall a. Show a => a -> Text
showQueryParam
class FromQueryData a where
parseQueryData :: Text -> Either Text a
default parseQueryData :: (Read a) => Text -> Either Text a
parseQueryData = Text -> Either Text a
forall a. Read a => Text -> Either Text a
readQueryParam
instance ToQueryData Int where
toQueryData :: Int -> Text
toQueryData = Int -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Int where
parseQueryData :: Text -> Either Text Int
parseQueryData = Text -> Either Text Int
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Integer where
toQueryData :: Integer -> Text
toQueryData = Integer -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Integer where
parseQueryData :: Text -> Either Text Integer
parseQueryData = Text -> Either Text Integer
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Float where
toQueryData :: Float -> Text
toQueryData = Float -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Float where
parseQueryData :: Text -> Either Text Float
parseQueryData = Text -> Either Text Float
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Double where
toQueryData :: Double -> Text
toQueryData = Double -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Double where
parseQueryData :: Text -> Either Text Double
parseQueryData = Text -> Either Text Double
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Word where
toQueryData :: Word -> Text
toQueryData = Word -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Word where
parseQueryData :: Text -> Either Text Word
parseQueryData = Text -> Either Text Word
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Word8 where
toQueryData :: Word8 -> Text
toQueryData = Word8 -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Word8 where
parseQueryData :: Text -> Either Text Word8
parseQueryData = Text -> Either Text Word8
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Word16 where
toQueryData :: Word16 -> Text
toQueryData = Word16 -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Word16 where
parseQueryData :: Text -> Either Text Word16
parseQueryData = Text -> Either Text Word16
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Word32 where
toQueryData :: Word32 -> Text
toQueryData = Word32 -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Word32 where
parseQueryData :: Text -> Either Text Word32
parseQueryData = Text -> Either Text Word32
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Word64 where
toQueryData :: Word64 -> Text
toQueryData = Word64 -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Word64 where
parseQueryData :: Text -> Either Text Word64
parseQueryData = Text -> Either Text Word64
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Bool where
toQueryData :: Bool -> Text
toQueryData = Bool -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Bool where
parseQueryData :: Text -> Either Text Bool
parseQueryData = Text -> Either Text Bool
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Text where
toQueryData :: Text -> Text
toQueryData = Text -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Text where
parseQueryData :: Text -> Either Text Text
parseQueryData = Text -> Either Text Text
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData Char where
toQueryData :: Char -> Text
toQueryData = Char -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData Char where
parseQueryData :: Text -> Either Text Char
parseQueryData = Text -> Either Text Char
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance ToQueryData UTCTime where
toQueryData :: UTCTime -> Text
toQueryData = UTCTime -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam
instance FromQueryData UTCTime where
parseQueryData :: Text -> Either Text UTCTime
parseQueryData = Text -> Either Text UTCTime
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam
instance (Show a) => ToQueryData [a] where
toQueryData :: [a] -> Text
toQueryData = [a] -> Text
forall a. Show a => a -> Text
showQueryParam
instance (Read a) => FromQueryData [a] where
parseQueryData :: Text -> Either Text [a]
parseQueryData = Text -> Either Text [a]
forall a. Read a => Text -> Either Text a
readQueryParam
instance (ToQueryData a) => ToQueryData (Maybe a) where
toQueryData :: Maybe a -> Text
toQueryData Maybe a
Nothing = Text
""
toQueryData (Just a
a) = a -> Text
forall a. ToQueryData a => a -> Text
toQueryData a
a
instance (Read a) => FromQueryData (Maybe a) where
parseQueryData :: Text -> Either Text (Maybe a)
parseQueryData Text
"" = Maybe a -> Either Text (Maybe a)
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing
parseQueryData Text
t = Text -> Either Text (Maybe a)
forall a. Read a => Text -> Either Text a
readQueryParam Text
t
instance (ToQueryData a, ToQueryData b) => ToQueryData (Either a b) where
toQueryData :: Either a b -> Text
toQueryData (Left a
a) = a -> Text
forall a. ToQueryData a => a -> Text
toQueryData a
a
toQueryData (Right b
b) = b -> Text
forall a. ToQueryData a => a -> Text
toQueryData b
b
instance (FromQueryData a, FromQueryData b) => FromQueryData (Either a b) where
parseQueryData :: Text -> Either Text (Either a b)
parseQueryData Text
t =
case forall a. FromQueryData a => Text -> Either Text a
parseQueryData @a Text
t of
Right a
a -> Either a b -> Either Text (Either a b)
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either a b -> Either Text (Either a b))
-> Either a b -> Either Text (Either a b)
forall a b. (a -> b) -> a -> b
$ a -> Either a b
forall a b. a -> Either a b
Left a
a
Left Text
_ -> do
case forall a. FromQueryData a => Text -> Either Text a
parseQueryData @b Text
t of
Left Text
_ -> Text -> Either Text (Either a b)
forall a b. a -> Either a b
Left (Text -> Either Text (Either a b))
-> Text -> Either Text (Either a b)
forall a b. (a -> b) -> a -> b
$ Text
"Could not parseQueryData Either: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t
Right b
b -> Either a b -> Either Text (Either a b)
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either a b -> Either Text (Either a b))
-> Either a b -> Either Text (Either a b)
forall a b. (a -> b) -> a -> b
$ b -> Either a b
forall a b. b -> Either a b
Right b
b
showQueryParam :: (Show a) => a -> Text
showQueryParam :: forall a. Show a => a -> Text
showQueryParam a
a = String -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ a -> String
forall a. Show a => a -> String
show a
a
readQueryParam :: (Read a) => Text -> Either Text a
readQueryParam :: forall a. Read a => Text -> Either Text a
readQueryParam Text
t = do
String
str <- Text -> Either Text String
forall a. FromHttpApiData a => Text -> Either Text a
parseQueryParam Text
t
case String -> Maybe a
forall a. Read a => String -> Maybe a
readMaybe String
str of
Maybe a
Nothing -> Text -> Either Text a
forall a b. a -> Either a b
Left (Text -> Either Text a) -> Text -> Either Text a
forall a b. (a -> b) -> a -> b
$ String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
"Could not read query param: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
str
Just a
a -> a -> Either Text a
forall a. a -> Either Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
parseQueryDatas :: (Traversable t, FromQueryData a) => t Text -> Either Text (t a)
parseQueryDatas :: forall (t :: * -> *) a.
(Traversable t, FromQueryData a) =>
t Text -> Either Text (t a)
parseQueryDatas = (Text -> Either Text a) -> t Text -> Either Text (t a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> t a -> f (t b)
traverse Text -> Either Text a
forall a. FromQueryData a => Text -> Either Text a
parseQueryData