module Text.Delimited.ByteString.Lazy (
encode, decode, interact
) where
import Data.Binary.Put (Put, putByteString, runPut)
import Data.ByteString.Lazy (ByteString, toChunks)
import qualified Data.ByteString as BS
import Prelude hiding (interact)
import Text.Show.ByteString (putAscii, showp, unlinesP)
import qualified Data.ParserCombinators.Attoparsec.Char8 as P
import Text.Delimited.Types
intersperseP :: Put -> [Put] -> Put
intersperseP _ [] = return ()
intersperseP _ (x:[]) = showp x
intersperseP d (x:xs) = x >> d >> intersperseP d xs
putContent :: Char -> Content -> Put
putContent delim = unlinesP . map (intersperseP (putAscii delim) . map putByteString)
encode :: Char -> Content -> ByteString
encode delim = runPut . putContent delim
fromLazy :: ByteString -> BS.ByteString
fromLazy = BS.concat . toChunks
endBy :: P.Parser a -> P.Parser b -> P.Parser a
a `endBy` b = do
r <- a
b
return r
parser :: [Char] -> P.Parser Content
parser delims = line `P.manyTill` P.eof
where
line = (field `P.sepBy` sep) `endBy` eol
field = fromLazy `fmap` P.takeWhile (P.notInClass (delims ++ nls))
sep = P.skipMany1 (P.satisfy $ P.inClass delims)
eol = P.skipMany1 (P.satisfy $ P.inClass nls)
nls = "\n\r"
decode :: [Char] -> ByteString -> Result Content
decode delims = snd . P.parse (parser delims)
interact :: (Record -> Record) -> [Char] -> ByteString -> Result ByteString
interact f delims s =
case decode delims s of
Right c -> Right (encode (head delims) (map f c))
Left e -> Left e