wai-app-file-cgi-0.0.0: Network/Wai/Application/Classic/EnumLine.hs
{-# LANGUAGE OverloadedStrings #-}
module Network.Wai.Application.Classic.EnumLine (head) where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as S () -- for OverloadedStrings
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.Char8 as L () -- for OverloadedStrings
import Data.Enumerator (Iteratee, Stream(..), yield, continue)
import Prelude hiding (head)
head :: Iteratee BS.ByteString IO (Maybe BS.ByteString)
head = line id False
line :: Builder -> Bool
-> Iteratee BS.ByteString IO (Maybe BS.ByteString)
line build dropLF = continue go
where
go (Chunks cnk) = breakLine (BL.fromChunks cnk)
go EOF = yield Nothing EOF
breakLine "" = line build dropLF
breakLine xs | dropLF && y == lf = yield (Just ln) (Chunks cnk)
where
y = BL.head xs
ys = BL.tail xs
ln = toStrict . build $ ""
cnk = BL.toChunks ys
breakLine xs = case BL.break eol xs of
(ys, "") -> line (build +++ toB ys) False
(ys, zs) -> dropCRLF ys zs
dropCRLF xs ys
| z == cr = dropCR xs zs
| otherwise = yield (Just ln) (Chunks cnks) -- dropLF
where
z = BL.head ys
zs = BL.tail ys
ln = toStrict . build $ xs
cnks = BL.toChunks zs
dropCR xs "" = line (build +++ toB xs) True
dropCR xs ys
| z == lf = yield (Just ln) (Chunks czs)
| otherwise = yield (Just ln) (Chunks cys)
where
z = BL.head ys
zs = BL.tail ys
ln = toStrict . build $ xs
cys = BL.toChunks ys
czs = BL.toChunks zs
lf = 10
cr = 13
eol c = c == lf || c == cr
type Builder = BL.ByteString -> BL.ByteString
(+++) :: Builder -> Builder -> Builder
a +++ b = a . b
toB :: BL.ByteString -> Builder
toB b = (b `BL.append`)
toStrict :: BL.ByteString -> BS.ByteString
toStrict = BS.concat . BL.toChunks