module Pipes.KeyValueCsv.Internal where
import Pipes.KeyValueCsv.Internal.Types
import Control.Lens
import Control.Monad.State.Strict
import Data.Char
import Data.Monoid
import Data.Text (Text)
import qualified Data.Text.Lazy as Lazy
import Data.Text.Lazy.Builder
import Pipes
import qualified Pipes.Prelude as Pipes
import Pipes.Group (FreeT(..), FreeF(..))
import Pipes.Parse (Parser)
import qualified Pipes.Parse as Parse
import qualified Pipes.Text as PipesText
build :: Monad m => Parser Text m Lazy.Text
build =
Parse.foldAll
(\b t -> b <> fromText t)
mempty
toLazyText
skipSpace :: Monad m => Parser Text m ()
skipSpace = zoom (PipesText.span isSpace) Parse.skipAll
drawText :: Monad m => Parser Text m Lazy.Text
drawText = do
skipSpace
quote'm <- PipesText.peekChar
case quote'm of
Just '"' -> do
drawn <- Parse.draw *> zoom (PipesText.break isQuote) build
pure drawn
Just _ -> zoom (PipesText.break isSpace) build
Nothing -> pure $ Lazy.empty
where
isQuote = (== '"')
breakLines'
:: Monad m
=> (Text -> Bool)
-> FreeT (Line m) m r
-> FreeT (Line m) m (FreeT (Line m) m r)
breakLines' predicate ls = FreeT $ do
ft <- runFreeT ls
case ft of
p@(Pure _) -> pure . Pure . FreeT $ pure p
Free (Line line) -> do
(text, leftovers) <- runStateT (Lazy.toStrict <$> build) line
r <- runEffect $ leftovers >-> Pipes.drain
pure $ if predicate text
then Pure r
else Free . Line $ do
yield text
pure $ breakLines' predicate r