module Pipes.Csv (
feedParser,
feedHeaderParser,
decode,
decodeWith,
decodeByName,
decodeByNameWith
) where
import qualified Data.Csv.Incremental as CI
import qualified Data.ByteString as B
import Data.Csv.Incremental (Parser(..), HeaderParser(..))
import Data.Csv (DecodeOptions, FromRecord,
FromNamedRecord, defaultDecodeOptions)
import Data.ByteString (ByteString)
import Pipes
feedParser :: Monad m
=> Parser a
-> Producer ByteString m ()
-> Producer (Either String a) m ()
feedParser parser source = case parser of
Fail _ e -> yield (Left e)
Done es -> each es
Some es k -> each es >> cont k source
Partial k -> cont k source
where
cont = continue feedParser
feedHeaderParser :: (Monad m, FromNamedRecord a)
=> HeaderParser (Parser a)
-> Producer ByteString m ()
-> Producer (Either String a) m ()
feedHeaderParser headerParser source = case headerParser of
FailH bs e -> yield (Left e)
PartialH k -> cont k source
DoneH _ p -> feedParser p source
where
cont = continue feedHeaderParser
continue :: (Monad (t m), Monad m, MonadTrans t)
=> (a -> Producer ByteString m () -> t m b)
-> (ByteString -> a)
-> Producer ByteString m ()
-> t m b
continue feed k producer = do
x <- lift (next producer)
case x of
Left () -> feed (k B.empty) (return ())
Right (bs, producer') ->
if (B.null bs)
then continue feed k producer'
else feed (k bs) producer'
decode :: (Monad m, FromRecord a)
=> Bool
-> Producer ByteString m ()
-> Producer (Either String a) m ()
decode = decodeWith defaultDecodeOptions
decodeWith :: (Monad m, FromRecord a)
=> DecodeOptions
-> Bool
-> Producer ByteString m ()
-> Producer (Either String a) m ()
decodeWith opts skipHeader src = feedParser (CI.decodeWith opts skipHeader) src
decodeByName :: (Monad m, FromNamedRecord a)
=> Producer ByteString m ()
-> Producer (Either String a) m ()
decodeByName = decodeByNameWith defaultDecodeOptions
decodeByNameWith :: (Monad m, FromNamedRecord a)
=> DecodeOptions
-> Producer ByteString m ()
-> Producer (Either String a) m ()
decodeByNameWith opts src = feedHeaderParser (CI.decodeByNameWith opts) src