{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
module Dormouse.Uri.Encode
( encodeQuery
, encodePath
, encodeUnless
) where
import Data.Char (chr)
import Data.Word (Word8)
import qualified Data.ByteString as B
import qualified Data.Text as T
import qualified Data.Text.Encoding as E
import Dormouse.Uri.Types
import Dormouse.Uri.RFC3986
percentEncode :: Word8 -> B.ByteString
percentEncode :: Word8 -> ByteString
percentEncode Word8
w =
let h :: Word8
h = Word8
w Word8 -> Word8 -> Word8
forall a. Integral a => a -> a -> a
`div` Word8
16
l :: Word8
l = Word8
w Word8 -> Word8 -> Word8
forall a. Integral a => a -> a -> a
`mod` Word8
16 in
[Word8] -> ByteString
B.pack [Word8
37, Word8 -> Word8
forall a. (Ord a, Num a) => a -> a
hex Word8
h, Word8 -> Word8
forall a. (Ord a, Num a) => a -> a
hex Word8
l]
where
hex :: a -> a
hex a
x
| a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
10 = a
48a -> a -> a
forall a. Num a => a -> a -> a
+a
x
| Bool
otherwise = a
55a -> a -> a
forall a. Num a => a -> a -> a
+a
x
encodeUnless :: (Char -> Bool) -> T.Text -> B.ByteString
encodeUnless :: (Char -> Bool) -> Text -> ByteString
encodeUnless Char -> Bool
isAllowedChar = (Word8 -> ByteString) -> ByteString -> ByteString
B.concatMap Word8 -> ByteString
pEncodeQuery (ByteString -> ByteString)
-> (Text -> ByteString) -> Text -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
E.encodeUtf8
where
pEncodeQuery :: Word8 -> B.ByteString
pEncodeQuery :: Word8 -> ByteString
pEncodeQuery Word8
c
| Char -> Bool
isAllowedChar (Int -> Char
chr (Int -> Char) -> Int -> Char
forall a b. (a -> b) -> a -> b
$ Word8 -> Int
forall a. Enum a => a -> Int
fromEnum Word8
c) = Word8 -> ByteString
B.singleton Word8
c
| Bool
otherwise = Word8 -> ByteString
percentEncode Word8
c
encodeQuery :: Query -> B.ByteString
encodeQuery :: Query -> ByteString
encodeQuery = ByteString -> ByteString -> ByteString
B.append ByteString
"?" (ByteString -> ByteString)
-> (Query -> ByteString) -> Query -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> ByteString
encodeUnless Char -> Bool
isQueryChar (Text -> ByteString) -> (Query -> Text) -> Query -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Query -> Text
unQuery
encodePath :: Path 'Absolute -> B.ByteString
encodePath :: Path 'Absolute -> ByteString
encodePath = ByteString -> ByteString -> ByteString
B.append ByteString
"/" (ByteString -> ByteString)
-> (Path 'Absolute -> ByteString) -> Path 'Absolute -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString] -> ByteString
B.intercalate ByteString
"/" ([ByteString] -> ByteString)
-> (Path 'Absolute -> [ByteString]) -> Path 'Absolute -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PathSegment -> ByteString) -> [PathSegment] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Char -> Bool) -> Text -> ByteString
encodeUnless Char -> Bool
isPathChar (Text -> ByteString)
-> (PathSegment -> Text) -> PathSegment -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PathSegment -> Text
unPathSegment) ([PathSegment] -> [ByteString])
-> (Path 'Absolute -> [PathSegment])
-> Path 'Absolute
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path 'Absolute -> [PathSegment]
forall (ref :: UriReferenceType). Path ref -> [PathSegment]
unPath