{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
module Pipes.Aeson.Internal
( DecodingError(..)
, consecutively
, decodeL
) where
import Control.Exception (Exception)
import Control.Monad.Trans.Error (Error)
import qualified Control.Monad.Trans.State.Strict as S
import qualified Data.Aeson as Ae
import qualified Data.Attoparsec.Types as Attoparsec
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as B (isSpaceWord8)
import Data.Data (Data, Typeable)
import Pipes
import qualified Pipes.Attoparsec as PA
import qualified Pipes.Parse as Pipes
data DecodingError
= AttoparsecError PA.ParsingError
| FromJSONError String
deriving (Show, Eq, Data, Typeable)
instance Exception DecodingError
instance Error DecodingError
instance Error (DecodingError, Producer a m r)
consecutively
:: (Monad m)
=> Pipes.Parser B.ByteString m (Maybe (Either e a))
-> Producer B.ByteString m r
-> Producer a m (Either (e, Producer B.ByteString m r) r)
consecutively parser = step where
step p0 = do
x <- lift $ nextSkipBlank p0
case x of
Left r -> return (Right r)
Right (bs, p1) -> do
(mea, p2) <- lift $ S.runStateT parser (yield bs >> p1)
case mea of
Just (Right a) -> yield a >> step p2
Just (Left e) -> return (Left (e, p2))
Nothing -> error "Pipes.Aeson.Internal.consecutively: impossible"
decodeL
:: (Monad m, Ae.FromJSON a)
=> Attoparsec.Parser B.ByteString Ae.Value
-> Pipes.Parser B.ByteString m (Maybe (Either DecodingError (Int, a)))
decodeL parser = do
mev <- PA.parseL parser
return $ case mev of
Nothing -> Nothing
Just (Left l) -> Just (Left (AttoparsecError l))
Just (Right (n, v)) -> case Ae.fromJSON v of
Ae.Error e -> Just (Left (FromJSONError e))
Ae.Success a -> Just (Right (n, a))
nextSkipBlank
:: (Monad m)
=> Producer B.ByteString m r
-> m (Either r (B.ByteString, Producer B.ByteString m r))
nextSkipBlank = go where
go p0 = do
x <- next p0
case x of
Left _ -> return x
Right (a,p1) -> do
let a' = B.dropWhile B.isSpaceWord8 a
if B.null a' then go p1
else return (Right (a', p1))