module Network.WebSockets.Handshake.ShyIterParser
( shyIterParser
) where
import Data.Attoparsec.Enumerator (ParseError(..))
import qualified Data.Attoparsec as A
import qualified Data.ByteString as B
import qualified Data.Enumerator as E
shyIterParser :: (Monad m) => A.Parser a -> E.Iteratee B.ByteString m a
shyIterParser p = parseLoop (A.parse p) [B.empty]
where
step parse (E.Chunks xs) = parseLoop parse (notEmpty xs)
step parse E.EOF = case A.feed (parse B.empty) B.empty of
A.Done _ a -> E.yield a E.EOF
A.Partial _ -> err [] "iterParser: divergent parser"
A.Fail _ ctx msg -> err ctx msg
parseLoop parse [] = E.continue (step parse)
parseLoop parse (x:xs) = case parse x of
A.Done extra a -> E.yield a $ if B.null extra
then E.Chunks xs
else E.Chunks (extra:xs)
A.Partial parse' -> parseLoop parse' xs
A.Fail _ ctx msg -> err ctx msg
err ctx msg = E.throwError (ParseError ctx msg)
notEmpty = filter (not . B.null)