module Network.HTTP.Utils
( trim
, trimL
, trimR
, crlf
, lf
, sp
, split
, splitBy
, readsOne
, dropWhileTail
, chopAtDelim
, toUTF8BS
, fromUTF8BS
) where
import Data.Bits
import Data.Char
import Data.List ( elemIndex )
import Data.Maybe ( fromMaybe )
import Data.Word ( Word8 )
import qualified Data.ByteString as BS
crlf :: String
crlf :: String
crlf = String
"\r\n"
lf :: String
lf :: String
lf = String
"\n"
sp :: String
sp :: String
sp = String
" "
split :: Eq a => a -> [a] -> Maybe ([a],[a])
split :: forall a. Eq a => a -> [a] -> Maybe ([a], [a])
split a
delim [a]
list = case a
delim forall a. Eq a => a -> [a] -> Maybe Int
`elemIndex` [a]
list of
Maybe Int
Nothing -> forall a. Maybe a
Nothing
Just Int
x -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. Int -> [a] -> ([a], [a])
splitAt Int
x [a]
list
trim :: String -> String
trim :: String -> String
trim String
xs = String -> String
trimR (String -> String
trimL String
xs)
trimL :: String -> String
trimL :: String -> String
trimL String
xs = forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace String
xs
trimR :: String -> String
trimR :: String -> String
trimR String
str = forall a. a -> Maybe a -> a
fromMaybe String
"" forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Char -> Maybe String -> Maybe String
trimIt forall a. Maybe a
Nothing String
str
where
trimIt :: Char -> Maybe String -> Maybe String
trimIt Char
x (Just String
xs) = forall a. a -> Maybe a
Just (Char
xforall a. a -> [a] -> [a]
:String
xs)
trimIt Char
x Maybe String
Nothing
| Char -> Bool
isSpace Char
x = forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just [Char
x]
splitBy :: Eq a => a -> [a] -> [[a]]
splitBy :: forall a. Eq a => a -> [a] -> [[a]]
splitBy a
_ [] = []
splitBy a
c [a]
xs =
case forall a. (a -> Bool) -> [a] -> ([a], [a])
break (forall a. Eq a => a -> a -> Bool
==a
c) [a]
xs of
([a]
_,[]) -> [[a]
xs]
([a]
as,a
_:[a]
bs) -> [a]
as forall a. a -> [a] -> [a]
: forall a. Eq a => a -> [a] -> [[a]]
splitBy a
c [a]
bs
readsOne :: Read a => (a -> b) -> b -> String -> b
readsOne :: forall a b. Read a => (a -> b) -> b -> String -> b
readsOne a -> b
f b
n String
str =
case forall a. Read a => ReadS a
reads String
str of
((a
v,String
_):[(a, String)]
_) -> a -> b
f a
v
[(a, String)]
_ -> b
n
dropWhileTail :: (a -> Bool) -> [a] -> [a]
dropWhileTail :: forall a. (a -> Bool) -> [a] -> [a]
dropWhileTail a -> Bool
f [a]
ls =
case forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> Maybe [a] -> Maybe [a]
chop forall a. Maybe a
Nothing [a]
ls of { Just [a]
xs -> [a]
xs; Maybe [a]
Nothing -> [] }
where
chop :: a -> Maybe [a] -> Maybe [a]
chop a
x (Just [a]
xs) = forall a. a -> Maybe a
Just (a
xforall a. a -> [a] -> [a]
:[a]
xs)
chop a
x Maybe [a]
_
| a -> Bool
f a
x = forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just [a
x]
chopAtDelim :: Eq a => a -> [a] -> ([a],[a])
chopAtDelim :: forall a. Eq a => a -> [a] -> ([a], [a])
chopAtDelim a
elt [a]
xs =
case forall a. (a -> Bool) -> [a] -> ([a], [a])
break (forall a. Eq a => a -> a -> Bool
==a
elt) [a]
xs of
([a]
_,[]) -> ([a]
xs,[])
([a]
as,a
_:[a]
bs) -> ([a]
as,[a]
bs)
toUTF8BS :: String -> BS.ByteString
toUTF8BS :: String -> ByteString
toUTF8BS = [Word8] -> ByteString
BS.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [Word8]
encodeStringUtf8
fromUTF8BS :: BS.ByteString -> String
fromUTF8BS :: ByteString -> String
fromUTF8BS = [Word8] -> String
decodeStringUtf8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Word8]
BS.unpack
encodeStringUtf8 :: String -> [Word8]
encodeStringUtf8 :: String -> [Word8]
encodeStringUtf8 [] = []
encodeStringUtf8 (Char
c:String
cs)
| Char
c forall a. Ord a => a -> a -> Bool
<= Char
'\x07F' = Word8
w8
forall a. a -> [a] -> [a]
: String -> [Word8]
encodeStringUtf8 String
cs
| Char
c forall a. Ord a => a -> a -> Bool
<= Char
'\x7FF' = (Word8
0xC0 forall a. Bits a => a -> a -> a
.|. Int -> Word8
w8ShiftR Int
6 )
forall a. a -> [a] -> [a]
: (Word8
0x80 forall a. Bits a => a -> a -> a
.|. (Word8
w8 forall a. Bits a => a -> a -> a
.&. Word8
0x3F))
forall a. a -> [a] -> [a]
: String -> [Word8]
encodeStringUtf8 String
cs
| Char
c forall a. Ord a => a -> a -> Bool
<= Char
'\xD7FF'= (Word8
0xE0 forall a. Bits a => a -> a -> a
.|. Int -> Word8
w8ShiftR Int
12 )
forall a. a -> [a] -> [a]
: (Word8
0x80 forall a. Bits a => a -> a -> a
.|. (Int -> Word8
w8ShiftR Int
6 forall a. Bits a => a -> a -> a
.&. Word8
0x3F))
forall a. a -> [a] -> [a]
: (Word8
0x80 forall a. Bits a => a -> a -> a
.|. (Word8
w8 forall a. Bits a => a -> a -> a
.&. Word8
0x3F))
forall a. a -> [a] -> [a]
: String -> [Word8]
encodeStringUtf8 String
cs
| Char
c forall a. Ord a => a -> a -> Bool
<= Char
'\xDFFF'= Word8
0xEF forall a. a -> [a] -> [a]
: Word8
0xBF forall a. a -> [a] -> [a]
: Word8
0xBD
forall a. a -> [a] -> [a]
: String -> [Word8]
encodeStringUtf8 String
cs
| Char
c forall a. Ord a => a -> a -> Bool
<= Char
'\xFFFF'= (Word8
0xE0 forall a. Bits a => a -> a -> a
.|. Int -> Word8
w8ShiftR Int
12 )
forall a. a -> [a] -> [a]
: (Word8
0x80 forall a. Bits a => a -> a -> a
.|. (Int -> Word8
w8ShiftR Int
6 forall a. Bits a => a -> a -> a
.&. Word8
0x3F))
forall a. a -> [a] -> [a]
: (Word8
0x80 forall a. Bits a => a -> a -> a
.|. (Word8
w8 forall a. Bits a => a -> a -> a
.&. Word8
0x3F))
forall a. a -> [a] -> [a]
: String -> [Word8]
encodeStringUtf8 String
cs
| Bool
otherwise = (Word8
0xf0 forall a. Bits a => a -> a -> a
.|. Int -> Word8
w8ShiftR Int
18 )
forall a. a -> [a] -> [a]
: (Word8
0x80 forall a. Bits a => a -> a -> a
.|. (Int -> Word8
w8ShiftR Int
12 forall a. Bits a => a -> a -> a
.&. Word8
0x3F))
forall a. a -> [a] -> [a]
: (Word8
0x80 forall a. Bits a => a -> a -> a
.|. (Int -> Word8
w8ShiftR Int
6 forall a. Bits a => a -> a -> a
.&. Word8
0x3F))
forall a. a -> [a] -> [a]
: (Word8
0x80 forall a. Bits a => a -> a -> a
.|. (Word8
w8 forall a. Bits a => a -> a -> a
.&. Word8
0x3F))
forall a. a -> [a] -> [a]
: String -> [Word8]
encodeStringUtf8 String
cs
where
w8 :: Word8
w8 = forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c) :: Word8
w8ShiftR :: Int -> Word8
w8ShiftR :: Int -> Word8
w8ShiftR = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Bits a => a -> Int -> a
shiftR (Char -> Int
ord Char
c)
decodeStringUtf8 :: [Word8] -> String
decodeStringUtf8 :: [Word8] -> String
decodeStringUtf8 = [Word8] -> String
go
where
go :: [Word8] -> String
go :: [Word8] -> String
go [] = []
go (Word8
c : [Word8]
cs)
| Word8
c forall a. Ord a => a -> a -> Bool
<= Word8
0x7F = Int -> Char
chr (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
c) forall a. a -> [a] -> [a]
: [Word8] -> String
go [Word8]
cs
| Word8
c forall a. Ord a => a -> a -> Bool
<= Word8
0xBF = Char
replacementChar forall a. a -> [a] -> [a]
: [Word8] -> String
go [Word8]
cs
| Word8
c forall a. Ord a => a -> a -> Bool
<= Word8
0xDF = Word8 -> [Word8] -> String
twoBytes Word8
c [Word8]
cs
| Word8
c forall a. Ord a => a -> a -> Bool
<= Word8
0xEF = Int -> Int -> [Word8] -> Int -> String
moreBytes Int
3 Int
0x800 [Word8]
cs (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Word8
c forall a. Bits a => a -> a -> a
.&. Word8
0xF)
| Word8
c forall a. Ord a => a -> a -> Bool
<= Word8
0xF7 = Int -> Int -> [Word8] -> Int -> String
moreBytes Int
4 Int
0x10000 [Word8]
cs (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Word8
c forall a. Bits a => a -> a -> a
.&. Word8
0x7)
| Word8
c forall a. Ord a => a -> a -> Bool
<= Word8
0xFB = Int -> Int -> [Word8] -> Int -> String
moreBytes Int
5 Int
0x200000 [Word8]
cs (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Word8
c forall a. Bits a => a -> a -> a
.&. Word8
0x3)
| Word8
c forall a. Ord a => a -> a -> Bool
<= Word8
0xFD = Int -> Int -> [Word8] -> Int -> String
moreBytes Int
6 Int
0x4000000 [Word8]
cs (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Word8
c forall a. Bits a => a -> a -> a
.&. Word8
0x1)
| Bool
otherwise = Char
replacementChar forall a. a -> [a] -> [a]
: [Word8] -> String
go [Word8]
cs
twoBytes :: Word8 -> [Word8] -> String
twoBytes :: Word8 -> [Word8] -> String
twoBytes Word8
c0 (Word8
c1:[Word8]
cs')
| Word8
c1 forall a. Bits a => a -> a -> a
.&. Word8
0xC0 forall a. Eq a => a -> a -> Bool
== Word8
0x80
= let d :: Int
d = (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8
c0 forall a. Bits a => a -> a -> a
.&. Word8
0x1F) forall a. Bits a => a -> Int -> a
`shiftL` Int
6)
forall a. Bits a => a -> a -> a
.|. forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8
c1 forall a. Bits a => a -> a -> a
.&. Word8
0x3F)
in if Int
d forall a. Ord a => a -> a -> Bool
>= Int
0x80
then Int -> Char
chr Int
d forall a. a -> [a] -> [a]
: [Word8] -> String
go [Word8]
cs'
else Char
replacementChar forall a. a -> [a] -> [a]
: [Word8] -> String
go [Word8]
cs'
twoBytes Word8
_ [Word8]
cs' = Char
replacementChar forall a. a -> [a] -> [a]
: [Word8] -> String
go [Word8]
cs'
moreBytes :: Int -> Int -> [Word8] -> Int -> [Char]
moreBytes :: Int -> Int -> [Word8] -> Int -> String
moreBytes Int
1 Int
overlong [Word8]
cs' Int
acc
| Int
overlong forall a. Ord a => a -> a -> Bool
<= Int
acc Bool -> Bool -> Bool
&& Int
acc forall a. Ord a => a -> a -> Bool
<= Int
0x10FFFF Bool -> Bool -> Bool
&& (Int
acc forall a. Ord a => a -> a -> Bool
< Int
0xD800 Bool -> Bool -> Bool
|| Int
0xDFFF forall a. Ord a => a -> a -> Bool
< Int
acc)
= Int -> Char
chr Int
acc forall a. a -> [a] -> [a]
: [Word8] -> String
go [Word8]
cs'
| Bool
otherwise
= Char
replacementChar forall a. a -> [a] -> [a]
: [Word8] -> String
go [Word8]
cs'
moreBytes Int
byteCount Int
overlong (Word8
cn:[Word8]
cs') Int
acc
| Word8
cn forall a. Bits a => a -> a -> a
.&. Word8
0xC0 forall a. Eq a => a -> a -> Bool
== Word8
0x80
= Int -> Int -> [Word8] -> Int -> String
moreBytes (Int
byteCountforall a. Num a => a -> a -> a
-Int
1) Int
overlong [Word8]
cs'
((Int
acc forall a. Bits a => a -> Int -> a
`shiftL` Int
6) forall a. Bits a => a -> a -> a
.|. forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
cn forall a. Bits a => a -> a -> a
.&. Int
0x3F)
moreBytes Int
_ Int
_ [Word8]
cs' Int
_
= Char
replacementChar forall a. a -> [a] -> [a]
: [Word8] -> String
go [Word8]
cs'
replacementChar :: Char
replacementChar = Char
'\xfffd'