scanner-0.1: examples/Redis/Atto.hs
{-# LANGUAGE OverloadedStrings #-}
module Redis.Atto
( reply
)
where
import Redis.Reply
import Prelude hiding (error)
import Data.ByteString (ByteString)
import Data.Attoparsec.ByteString (Parser)
import qualified Data.Attoparsec.ByteString as Atto (takeTill)
import qualified Data.Attoparsec.ByteString.Char8 as Atto hiding (takeTill)
import Control.Monad
{-# INLINE reply #-}
reply :: Parser Reply
reply = do
c <- Atto.anyChar
case c of
'+' -> string
'-' -> error
':' -> integer
'$' -> bulk
'*' -> multi
_ -> fail "Unknown reply type"
{-# INLINE string #-}
string :: Parser Reply
string = String <$> line
{-# INLINE error #-}
error :: Parser Reply
error = Error <$> line
{-# INLINE integer #-}
integer :: Parser Reply
integer = Integer <$> integral
{-# INLINE bulk #-}
bulk :: Parser Reply
bulk = Bulk <$> do
len <- integral
if len < 0
then return Nothing
else Just <$> Atto.take len <* eol
-- don't inline it to break the circle between reply and multi
{-# NOINLINE multi #-}
multi :: Parser Reply
multi = Multi <$> do
len <- integral
if len < 0
then return Nothing
else Just <$> Atto.count len reply
{-# INLINE integral #-}
integral :: Integral i => Parser i
integral = Atto.signed Atto.decimal <* eol
{-# INLINE line #-}
line :: Parser ByteString
line = Atto.takeTill (== 13) <* eol
{-# INLINE eol #-}
eol :: Parser ()
eol = void $ Atto.string "\r\n"