module Amazonka.Data.Query where
import Amazonka.Data.ByteString
import Amazonka.Data.Text
import Amazonka.Prelude
import qualified Data.ByteString.Builder as Build
import qualified Data.ByteString.Char8 as BS8
import qualified Data.ByteString.Lazy as LBS
import qualified Data.HashMap.Strict as HashMap
import qualified Data.List as List
import qualified Data.Text.Encoding as Text
import qualified Network.HTTP.Types.URI as URI
data QueryString
= QList [QueryString]
| QPair ByteString QueryString
| QValue (Maybe ByteString)
deriving stock (QueryString -> QueryString -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: QueryString -> QueryString -> Bool
$c/= :: QueryString -> QueryString -> Bool
== :: QueryString -> QueryString -> Bool
$c== :: QueryString -> QueryString -> Bool
Eq, Int -> QueryString -> ShowS
[QueryString] -> ShowS
QueryString -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [QueryString] -> ShowS
$cshowList :: [QueryString] -> ShowS
show :: QueryString -> String
$cshow :: QueryString -> String
showsPrec :: Int -> QueryString -> ShowS
$cshowsPrec :: Int -> QueryString -> ShowS
Show)
instance Semigroup QueryString where
QueryString
a <> :: QueryString -> QueryString -> QueryString
<> QueryString
b = case (QueryString
a, QueryString
b) of
(QList [QueryString]
l, QList [QueryString]
r) -> [QueryString] -> QueryString
QList ([QueryString]
l forall a. [a] -> [a] -> [a]
++ [QueryString]
r)
(QList [QueryString]
l, QueryString
r) -> [QueryString] -> QueryString
QList (QueryString
r forall a. a -> [a] -> [a]
: [QueryString]
l)
(QueryString
l, QList [QueryString]
r) -> [QueryString] -> QueryString
QList (QueryString
l forall a. a -> [a] -> [a]
: [QueryString]
r)
(QueryString
l, QueryString
r) -> [QueryString] -> QueryString
QList [QueryString
l, QueryString
r]
instance Monoid QueryString where
mempty :: QueryString
mempty = [QueryString] -> QueryString
QList []
mappend :: QueryString -> QueryString -> QueryString
mappend = forall a. Semigroup a => a -> a -> a
(<>)
instance IsString QueryString where
fromString :: String -> QueryString
fromString = ByteString -> QueryString
parseQueryString forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IsString a => String -> a
fromString
{-# INLINE fromString #-}
parseQueryString :: ByteString -> QueryString
parseQueryString :: ByteString -> QueryString
parseQueryString ByteString
bs
| ByteString -> Bool
BS8.null ByteString
bs = forall a. Monoid a => a
mempty
| Bool
otherwise =
[QueryString] -> QueryString
QList (forall a b. (a -> b) -> [a] -> [b]
map ByteString -> QueryString
breakPair forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Bool
BS8.null) forall a b. (a -> b) -> a -> b
$ Char -> ByteString -> [ByteString]
BS8.split Char
'&' ByteString
bs)
where
breakPair :: ByteString -> QueryString
breakPair ByteString
x =
case (Char -> Bool) -> ByteString -> (ByteString, ByteString)
BS8.break (forall a. Eq a => a -> a -> Bool
== Char
'=') ByteString
x of
(ByteString
"", ByteString
"") -> forall a. Monoid a => a
mempty
(ByteString
"", ByteString
v) -> ByteString -> QueryString
stripValue ByteString
v
(ByteString
k, ByteString
v) -> ByteString -> QueryString -> QueryString
QPair (Bool -> ByteString -> ByteString
URI.urlDecode Bool
True ByteString
k) (ByteString -> QueryString
stripValue ByteString
v)
stripValue :: ByteString -> QueryString
stripValue :: ByteString -> QueryString
stripValue ByteString
x =
case ByteString
x of
ByteString
"" -> Maybe ByteString -> QueryString
QValue forall a. Maybe a
Nothing
ByteString
"=" -> Maybe ByteString -> QueryString
QValue forall a. Maybe a
Nothing
ByteString
_ -> Maybe ByteString -> QueryString
QValue (forall a. a -> Maybe a
Just (Bool -> ByteString -> ByteString
URI.urlDecode Bool
True forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS8.drop Int
1 ByteString
x))
instance ToByteString QueryString where
toBS :: QueryString -> ByteString
toBS = ByteString -> ByteString
LBS.toStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteStringBuilder -> ByteString
Build.toLazyByteString forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteStringBuilder
cat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> [a]
List.sort forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe ByteString -> QueryString -> [ByteString]
enc forall a. Maybe a
Nothing
where
enc :: Maybe ByteString -> QueryString -> [ByteString]
enc :: Maybe ByteString -> QueryString -> [ByteString]
enc Maybe ByteString
p = \case
QList [QueryString]
xs -> forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Maybe ByteString -> QueryString -> [ByteString]
enc Maybe ByteString
p) [QueryString]
xs
QPair (Bool -> ByteString -> ByteString
URI.urlEncode Bool
True -> ByteString
k) QueryString
x
| Just ByteString
n <- Maybe ByteString
p -> Maybe ByteString -> QueryString -> [ByteString]
enc (forall a. a -> Maybe a
Just (ByteString
n forall a. Semigroup a => a -> a -> a
<> ByteString
kdelim forall a. Semigroup a => a -> a -> a
<> ByteString
k)) QueryString
x
| Bool
otherwise -> Maybe ByteString -> QueryString -> [ByteString]
enc (forall a. a -> Maybe a
Just ByteString
k) QueryString
x
QValue (Just (Bool -> ByteString -> ByteString
URI.urlEncode Bool
True -> ByteString
v))
| Just ByteString
n <- Maybe ByteString
p -> [ByteString
n forall a. Semigroup a => a -> a -> a
<> ByteString
vsep forall a. Semigroup a => a -> a -> a
<> ByteString
v]
| Bool
otherwise -> [ByteString
v forall a. Semigroup a => a -> a -> a
<> ByteString
vsep]
QueryString
_
| Just ByteString
n <- Maybe ByteString
p -> [ByteString
n forall a. Semigroup a => a -> a -> a
<> ByteString
vsep]
| Bool
otherwise -> []
cat :: [ByteString] -> ByteStringBuilder
cat :: [ByteString] -> ByteStringBuilder
cat [] = forall a. Monoid a => a
mempty
cat [ByteString
x] = ByteString -> ByteStringBuilder
Build.byteString ByteString
x
cat (ByteString
x : [ByteString]
xs) = ByteString -> ByteStringBuilder
Build.byteString ByteString
x forall a. Semigroup a => a -> a -> a
<> ByteStringBuilder
ksep forall a. Semigroup a => a -> a -> a
<> [ByteString] -> ByteStringBuilder
cat [ByteString]
xs
kdelim :: ByteString
kdelim = ByteString
"."
ksep :: ByteStringBuilder
ksep = ByteStringBuilder
"&"
vsep :: ByteString
vsep = ByteString
"="
pair :: ToQuery a => ByteString -> a -> QueryString -> QueryString
pair :: forall a.
ToQuery a =>
ByteString -> a -> QueryString -> QueryString
pair ByteString
k a
v = forall a. Monoid a => a -> a -> a
mappend (ByteString -> QueryString -> QueryString
QPair ByteString
k (forall a. ToQuery a => a -> QueryString
toQuery a
v))
infixr 7 =:
(=:) :: ToQuery a => ByteString -> a -> QueryString
ByteString
k =: :: forall a. ToQuery a => ByteString -> a -> QueryString
=: a
v = ByteString -> QueryString -> QueryString
QPair ByteString
k (forall a. ToQuery a => a -> QueryString
toQuery a
v)
toQueryList ::
(IsList a, ToQuery (Item a)) =>
ByteString ->
a ->
QueryString
toQueryList :: forall a.
(IsList a, ToQuery (Item a)) =>
ByteString -> a -> QueryString
toQueryList ByteString
k = ByteString -> QueryString -> QueryString
QPair ByteString
k forall b c a. (b -> c) -> (a -> b) -> a -> c
. [QueryString] -> QueryString
QList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. ToQuery a => Int -> a -> QueryString
f [Int
1 ..] forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l. IsList l => l -> [Item l]
toList
where
f :: ToQuery a => Int -> a -> QueryString
f :: forall a. ToQuery a => Int -> a -> QueryString
f Int
n a
v = forall a. ToByteString a => a -> ByteString
toBS Int
n forall a. ToQuery a => ByteString -> a -> QueryString
=: forall a. ToQuery a => a -> QueryString
toQuery a
v
toQueryMap ::
(ToQuery k, ToQuery v) =>
ByteString ->
ByteString ->
ByteString ->
HashMap k v ->
QueryString
toQueryMap :: forall k v.
(ToQuery k, ToQuery v) =>
ByteString
-> ByteString -> ByteString -> HashMap k v -> QueryString
toQueryMap ByteString
e ByteString
k ByteString
v = forall a.
(IsList a, ToQuery (Item a)) =>
ByteString -> a -> QueryString
toQueryList ByteString
e forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (k, v) -> QueryString
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k v. HashMap k v -> [(k, v)]
HashMap.toList
where
f :: (k, v) -> QueryString
f (k
x, v
y) = [QueryString] -> QueryString
QList [ByteString
k forall a. ToQuery a => ByteString -> a -> QueryString
=: forall a. ToQuery a => a -> QueryString
toQuery k
x, ByteString
v forall a. ToQuery a => ByteString -> a -> QueryString
=: forall a. ToQuery a => a -> QueryString
toQuery v
y]
class ToQuery a where
toQuery :: a -> QueryString
default toQuery :: ToText a => a -> QueryString
toQuery = forall a. ToQuery a => a -> QueryString
toQuery forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToText a => a -> Text
toText
instance ToQuery QueryString where
toQuery :: QueryString -> QueryString
toQuery = forall a. a -> a
id
instance (ToByteString k, ToQuery v) => ToQuery (k, v) where
toQuery :: (k, v) -> QueryString
toQuery (k
k, v
v) = ByteString -> QueryString -> QueryString
QPair (forall a. ToByteString a => a -> ByteString
toBS k
k) (forall a. ToQuery a => a -> QueryString
toQuery v
v)
instance ToQuery Char where
toQuery :: Char -> QueryString
toQuery = forall a. ToQuery a => a -> QueryString
toQuery forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString
BS8.singleton
instance ToQuery ByteString where
toQuery :: ByteString -> QueryString
toQuery ByteString
"" = Maybe ByteString -> QueryString
QValue forall a. Maybe a
Nothing
toQuery ByteString
bs = Maybe ByteString -> QueryString
QValue (forall a. a -> Maybe a
Just ByteString
bs)
instance ToQuery Text where toQuery :: Text -> QueryString
toQuery = forall a. ToQuery a => a -> QueryString
toQuery forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8
instance ToQuery Int where toQuery :: Int -> QueryString
toQuery = forall a. ToQuery a => a -> QueryString
toQuery forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToByteString a => a -> ByteString
toBS
instance ToQuery Integer where toQuery :: Integer -> QueryString
toQuery = forall a. ToQuery a => a -> QueryString
toQuery forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToByteString a => a -> ByteString
toBS
instance ToQuery Double where toQuery :: Double -> QueryString
toQuery = forall a. ToQuery a => a -> QueryString
toQuery forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToByteString a => a -> ByteString
toBS
instance ToQuery Natural where toQuery :: Natural -> QueryString
toQuery = forall a. ToQuery a => a -> QueryString
toQuery forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToByteString a => a -> ByteString
toBS
instance ToQuery a => ToQuery (Maybe a) where
toQuery :: Maybe a -> QueryString
toQuery (Just a
x) = forall a. ToQuery a => a -> QueryString
toQuery a
x
toQuery Maybe a
Nothing = forall a. Monoid a => a
mempty
instance ToQuery Bool where
toQuery :: Bool -> QueryString
toQuery Bool
True = forall a. ToQuery a => a -> QueryString
toQuery (ByteString
"true" :: ByteString)
toQuery Bool
False = forall a. ToQuery a => a -> QueryString
toQuery (ByteString
"false" :: ByteString)