17 import Control.Arrow.ArrowList
18 import Data.Ascii (Ascii)
19 import qualified Data.Ascii as A
20 import qualified Data.ByteString as BS
21 import qualified Data.ByteString.Char8 as C8
22 import qualified Data.ByteString.Unsafe as BS
23 import qualified Data.ByteString.Lazy as LS
25 import qualified Data.Text as T
26 import Data.Text.Encoding
28 import Network.HTTP.Lucu
31 import Prelude.Unicode
32 import System.IO.Unsafe
34 yesOrNo ∷ Bool → String
38 trueOrFalse ∷ Bool → String
39 trueOrFalse True = "true"
40 trueOrFalse False = "false"
42 parseYesOrNo ∷ ArrowChoice a ⇒ a String Bool
44 = proc str → do case str of
45 "yes" → returnA ⤙ True
46 "no" → returnA ⤙ False
47 _ → returnA ⤙ error ("Expected yes or no: " ⧺ str)
49 maybeA ∷ (ArrowList a, ArrowChoice a) ⇒ a b c → a b (Maybe c)
53 [] → returnA ⤙ Nothing
54 (x:_) → returnA ⤙ Just x
56 deleteIfEmpty ∷ (ArrowList a, ArrowChoice a) ⇒ a String String
58 = proc str → do case str of
62 chomp ∷ String → String
64 chomp = reverse . snd . break (≢ '\n') . reverse
66 guessMIMEType ∷ LS.ByteString → MIMEType
67 {-# INLINEABLE guessMIMEType #-}
70 ∘ flip BS.unsafeUseAsCStringLen (magicCString magic)
75 {-# NOINLINE magic #-}
76 magic = unsafePerformIO
77 $ do m ← magicOpen [MagicMime]
82 isSafeChar ∷ Char → Bool
83 {-# INLINEABLE isSafeChar #-}
86 | isReserved c = False
87 | c > ' ' ∧ c ≤ '~' = True
91 mkQueryString ∷ [(T.Text, T.Text)] → Ascii
92 {-# INLINEABLE mkQueryString #-}
93 mkQueryString = A.unsafeFromByteString
94 ∘ BS.intercalate (C8.singleton ';')
97 encodePair ∷ (T.Text, T.Text) → BS.ByteString
98 {-# INLINE encodePair #-}
100 = BS.intercalate (C8.singleton '=') [encodeText k, encodeText v]
102 encodeText ∷ T.Text → BS.ByteString
103 {-# INLINE encodeText #-}
104 encodeText = toURLEncoded ∘ encodeUtf8
106 toURLEncoded ∷ BS.ByteString → BS.ByteString
107 {-# INLINEABLE toURLEncoded #-}
108 toURLEncoded = C8.concatMap go
110 go ∷ Char → BS.ByteString
112 go c | c ≡ ' ' = C8.singleton '+'
113 | isReserved c = urlEncode c
114 | isUnreserved c = C8.singleton c
115 | otherwise = urlEncode c
117 urlEncode ∷ Char → BS.ByteString
118 {-# INLINE urlEncode #-}
119 urlEncode c = C8.pack ('%':toHex (ord c))
124 = case showIntAtBase 16 toChrHex n "" of
129 toChrHex ∷ Int → Char
130 {-# INLINE toChrHex #-}
132 | d < 10 = chr (ord '0' + fromIntegral d )
133 | otherwise = chr (ord 'A' + fromIntegral (d-10))