module Control.Monad.Apiary.Filter.Internal.Query where
import Control.Monad.Apiary
import Control.Monad.Apiary.Filter.Internal
import Data.Apiary.Param
import Data.Apiary.SList
import Network.Wai
import qualified Network.HTTP.Types as HTTP
import qualified Data.ByteString as S
import Data.Maybe
import Data.Proxy
query :: (Query a, Strategy w, Monad m)
=> S.ByteString
-> Proxy (w a)
-> ApiaryT (SNext w as a) m b
-> ApiaryT as m b
query k p = function $ \l r -> readStrategy k p (queryString r) l
class Strategy (w :: * -> *) where
type SNext w (as :: [*]) a :: [*]
readStrategy :: Query a => S.ByteString -> Proxy (w a)
-> HTTP.Query -> SList as -> Maybe (SList (SNext w as a))
getQuery :: Query a => Proxy (w a) -> S.ByteString -> HTTP.Query -> [Maybe a]
getQuery _ k = map readQuery . map snd . filter ((k ==) . fst)
data Option a
instance Strategy Option where
type SNext Option as a = Snoc as (Maybe a)
readStrategy k p q l =
let rs = getQuery p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[] -> Just $ sSnoc l (Nothing `asMaybe` p)
a:_ -> Just $ sSnoc l (Just a)
where
asMaybe :: Maybe a -> Proxy (w a) -> Maybe a
asMaybe a _ = asProxyTypeOf a Proxy
data First a
instance Strategy First where
type SNext First as a = Snoc as a
readStrategy k p q l =
let rs = getQuery p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[] -> Nothing
a:_ -> Just $ sSnoc l a
data One a
instance Strategy One where
type SNext One as a = Snoc as a
readStrategy k p q l =
let rs = getQuery p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[a] -> Just $ sSnoc l a
_ -> Nothing
data Many a
instance Strategy Many where
type SNext Many as a = Snoc as [a]
readStrategy k p q l =
let rs = getQuery p k q
in if any isNothing rs
then Nothing
else Just $ sSnoc l (catMaybes rs)
data Some a
instance Strategy Some where
type SNext Some as a = Snoc as [a]
readStrategy k p q l =
let rs = getQuery p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[] -> Nothing
as -> Just $ sSnoc l as
data Check a
instance Strategy Check where
type SNext Check as a = as
readStrategy k p q l =
let rs = getQuery p k q
in if any isNothing rs
then Nothing
else case catMaybes rs of
[] -> Nothing
_ -> Just l