{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE ScopedTypeVariables #-}

module DSV.AttoPipe
  ( attoPipe
  , handleAttoProducer
  ) where

import DSV.AttoParser
import DSV.ByteString
import DSV.IO
import DSV.ParseError
import DSV.ParseStop
import DSV.Pipes
import DSV.Prelude

-- attoparsec
import qualified Data.Attoparsec.ByteString as Atto

-- pipes-bytestring
import qualified Pipes.ByteString

attoPipe :: forall a m .
    Monad m
    => AttoParser a
    -> Pipe ByteString a m ParseError

attoPipe :: AttoParser a -> Pipe ByteString a m ParseError
attoPipe AttoParser a
p =
  do
    ByteString
x <- Proxy () ByteString () a m ByteString
forall (m :: * -> *) a. Functor m => Consumer' a m a
await
    IResult ByteString a -> Pipe ByteString a m ParseError
forall (m :: * -> *).
Functor m =>
IResult ByteString a -> Proxy () ByteString () a m ParseError
proceed (AttoParser a -> ByteString -> IResult ByteString a
forall a. Parser a -> ByteString -> Result a
Atto.parse AttoParser a
p ByteString
x)

  where
    proceed :: IResult ByteString a -> Proxy () ByteString () a m ParseError
proceed (Atto.Partial ByteString -> IResult ByteString a
c) =
      do
        ByteString
x <- Proxy () ByteString () a m ByteString
forall (m :: * -> *) a. Functor m => Consumer' a m a
await
        IResult ByteString a -> Proxy () ByteString () a m ParseError
proceed (ByteString -> IResult ByteString a
c ByteString
x)

    proceed (Atto.Done ByteString
remainingInput a
x) =
      do
        a -> Proxy () ByteString () a m ()
forall (m :: * -> *) a x' x. Functor m => a -> Proxy x' x () a m ()
yield a
x
        IResult ByteString a -> Proxy () ByteString () a m ParseError
proceed (AttoParser a -> ByteString -> IResult ByteString a
forall a. Parser a -> ByteString -> Result a
Atto.parse AttoParser a
p ByteString
remainingInput)

    proceed (Atto.Fail ByteString
_remainingInput [String]
_ctxs String
_msg) =
        ParseError -> Proxy () ByteString () a m ParseError
forall (m :: * -> *) a. Monad m => a -> m a
return ParseError
ParseError

handleAttoProducer ::
    forall a m .
    MonadIO m
    => AttoParser a
    -> Handle         -- ^ File handle to read parser input from
    -> Producer a m ParseStop

handleAttoProducer :: AttoParser a -> Handle -> Producer a m ParseStop
handleAttoProducer AttoParser a
p Handle
h = Proxy X () () ByteString m ParseStop
forall x' x. Proxy x' x () ByteString m ParseStop
readBytes Proxy X () () ByteString m ParseStop
-> Proxy () ByteString () a m ParseStop -> Producer a m ParseStop
forall (m :: * -> *) a' a b r c' c.
Monad m =>
Proxy a' a () b m r -> Proxy () b c' c m r -> Proxy a' a c' c m r
>-> Proxy () ByteString () a m ParseStop
parseRows
  where
    readBytes :: Proxy x' x () ByteString m ParseStop
readBytes =
      do  Handle -> Producer' ByteString m ()
forall (m :: * -> *).
MonadIO m =>
Handle -> Producer' ByteString m ()
Pipes.ByteString.fromHandle Handle
h
          ParseStop -> Proxy x' x () ByteString m ParseStop
forall (m :: * -> *) a. Monad m => a -> m a
return ParseStop
ParseComplete
    parseRows :: Proxy () ByteString () a m ParseStop
parseRows =
      do  ParseError
_ <- AttoParser a -> Pipe ByteString a m ParseError
forall a (m :: * -> *).
Monad m =>
AttoParser a -> Pipe ByteString a m ParseError
attoPipe AttoParser a
p
          ParseStop -> Proxy () ByteString () a m ParseStop
forall (m :: * -> *) a. Monad m => a -> m a
return ParseStop
ParseIncomplete