X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Rakka%2FUtils.hs;h=051685cbf8a93cfedb07258fe44a04e0ac9169d3;hb=bea735cd0409bc96e2962ee9e97cae5f7bf4d585;hp=92f3b1232f51eacb51cdddefeaa15c6db36258db;hpb=885faf1cabc3f79c90e1885268e2a9138b1ddefb;p=Rakka.git diff --git a/Rakka/Utils.hs b/Rakka/Utils.hs index 92f3b12..051685c 100644 --- a/Rakka/Utils.hs +++ b/Rakka/Utils.hs @@ -1,82 +1,109 @@ +{-# LANGUAGE + Arrows + , UnicodeSyntax + #-} module Rakka.Utils ( yesOrNo + , trueOrFalse , parseYesOrNo , maybeA - , defaultTo , deleteIfEmpty - , formatW3CDateTime + , chomp + , guessMIMEType + , isSafeChar + , mkQueryString ) where +import qualified Blaze.ByteString.Builder as BBB +import Control.Arrow +import Control.Arrow.ArrowList +import Data.Ascii (Ascii) +import qualified Data.Ascii as A +import qualified Data.ByteString as BS +import qualified Data.ByteString.Unsafe as BS +import qualified Data.ByteString.Lazy as LS +import Data.Monoid.Unicode +import qualified Data.Text as T +import qualified Data.Text.Lazy as LT +import Data.Text.Encoding +import Magic +import Network.HTTP.Lucu +import Network.URI +import Prelude.Unicode +import System.IO.Unsafe -import Control.Arrow -import Control.Arrow.ArrowList -import System.Time -import Text.Printf - - -yesOrNo :: Bool -> String +yesOrNo ∷ Bool → String yesOrNo True = "yes" yesOrNo False = "no" +trueOrFalse ∷ Bool → String +trueOrFalse True = "true" +trueOrFalse False = "false" -parseYesOrNo :: ArrowChoice a => a String Bool +parseYesOrNo ∷ ArrowChoice a ⇒ a String Bool parseYesOrNo - = proc str -> do case str of - "yes" -> returnA -< True - "no" -> returnA -< False - _ -> returnA -< error ("Expected yes or no: " ++ str) - + = proc str → do case str of + "yes" → returnA ⤙ True + "no" → returnA ⤙ False + _ → returnA ⤙ error ("Expected yes or no: " ⧺ str) -maybeA :: (ArrowList a, ArrowChoice a) => a b c -> a b (Maybe c) +maybeA ∷ (ArrowList a, ArrowChoice a) ⇒ a b c → a b (Maybe c) maybeA a = listA a >>> - proc xs -> case xs of - [] -> returnA -< Nothing - (x:_) -> returnA -< Just x + proc xs → case xs of + [] → returnA ⤙ Nothing + (x:_) → returnA ⤙ Just x +deleteIfEmpty ∷ (ArrowList a, ArrowChoice a) ⇒ a String String +deleteIfEmpty + = proc str → do case str of + "" → none ⤙ () + _ → returnA ⤙ str -defaultTo :: ArrowChoice a => b -> a (Maybe b) b -defaultTo def - = proc m -> case m of - Nothing -> returnA -< def - Just x -> returnA -< x - +chomp ∷ String → String +{-# INLINE chomp #-} +chomp = reverse . snd . break (≢ '\n') . reverse -deleteIfEmpty :: (ArrowList a, ArrowChoice a) => a String String -deleteIfEmpty - = proc str -> do case str of - "" -> none -< () - _ -> returnA -< str +guessMIMEType ∷ LS.ByteString → MIMEType +{-# INLINEABLE guessMIMEType #-} +guessMIMEType = read + ∘ unsafePerformIO + ∘ flip BS.unsafeUseAsCStringLen (magicCString magic) + ∘ BS.concat + ∘ LS.toChunks + where + magic ∷ Magic + {-# NOINLINE magic #-} + magic = unsafePerformIO + $ do m ← magicOpen [MagicMime] + magicLoadDefault m + return m +isSafeChar ∷ Char → Bool +{-# INLINEABLE isSafeChar #-} +isSafeChar c + | c ≡ '/' = True + | isReserved c = False + | isUnreserved c = True + | otherwise = False -formatW3CDateTime :: CalendarTime -> String -formatW3CDateTime time - = formatDateTime time ++ formatTimeZone time +mkQueryString ∷ [(T.Text, T.Text)] → Ascii +{-# INLINE mkQueryString #-} +mkQueryString = A.unsafeFromByteString + ∘ BBB.toByteString + ∘ flip mkBBB (∅) where - formatDateTime :: CalendarTime -> String - formatDateTime time - = printf "%04d-%02d-%02dT%02d:%02d:%02d" - (ctYear time) - (fromEnum (ctMonth time) + 1) - (ctDay time) - (ctHour time) - (ctMin time) - (ctSec time) - - formatTimeZone :: CalendarTime -> String - formatTimeZone time - = case ctTZ time - of offset | offset < 0 -> '-':(showTZ $ negate offset) - | offset == 0 -> "Z" - | otherwise -> '+':(showTZ offset) - - showTZ :: Int -> String - showTZ offset - = let hour = offset `div` 3600 - min = (offset - hour * 3600) `div` 60 - in - show2 hour ++ ":" ++ show2 min - - show2 :: Int -> String - show2 n | n < 10 = '0':(show n) - | otherwise = show n \ No newline at end of file + mkBBB ∷ [(T.Text, T.Text)] → BBB.Builder → BBB.Builder + {-# INLINEABLE mkBBB #-} + mkBBB [] acc = acc + mkBBB (kv:[]) acc = acc ⊕ pair kv + mkBBB (kv:xs) acc = mkBBB xs (acc ⊕ pair kv ⊕ semicolon) + + pair ∷ (T.Text, T.Text) → BBB.Builder + {-# INLINE pair #-} + pair (k, v) + = encodeText k ⊕ equal ⊕ encodeText v + + encodeText ∷ T.Text → BBB.Builder + {-# INLINE encodeText #-} + encodeText = BBB.fromByteString ∘ URI.encode ∘ encodeUtf8