module Belka.BytePredicates where import Belka.Prelude hiding ((|||), (&&&), inRange, Predicate) import qualified Data.Vector as A import qualified Data.Char as B type Predicate = Word8 -> Bool {-# NOINLINE cached #-} cached :: Predicate -> Predicate cached predicate = case A.generate 256 (predicate . fromIntegral) of vector -> A.unsafeIndex vector . fromIntegral {-# NOINLINE cachedAscii #-} cachedAscii :: Predicate -> Predicate cachedAscii predicate = case A.generate 128 (predicate . fromIntegral) of vector -> A.unsafeIndex vector . fromIntegral oneOfChars :: [Char] -> Predicate oneOfChars string i = elem i (fmap (fromIntegral . ord) string) infixr 2 ||| (|||) :: Predicate -> Predicate -> Predicate (|||) left right i = left i || right i infixr 3 &&& (&&&) :: Predicate -> Predicate -> Predicate (&&&) left right i = left i && right i inRange :: Word8 -> Word8 -> Predicate inRange min max i = i >= min && i <= max inCharRange :: Char -> Char -> Predicate inCharRange min max = inRange (fromIntegral (ord min)) (fromIntegral (ord max)) charPredicate :: (Char -> Bool) -> Predicate charPredicate p = p . chr . fromIntegral {-| 7-bit -} septimal :: Predicate septimal i = i < 0x80 nonSeptimal :: Predicate nonSeptimal i = i >= 0x80 asciiAlphanumeric :: Predicate asciiAlphanumeric = inCharRange 'a' 'z' ||| inCharRange 'A' 'Z' ||| inCharRange '0' '9' mimeType :: Predicate mimeType = cachedAscii $ asciiAlphanumeric ||| oneOfChars "-/+*" space :: Predicate space = charPredicate B.isSpace semicolon :: Predicate semicolon = charPredicate (== ';') token :: Predicate token = mimeType quotedTokenUnescaped :: Predicate quotedTokenUnescaped = mimeType