{-# LANGUAGE ScopedTypeVariables #-}
module Data.Aeson.Extra.Stream (
streamDecode,
) where
import Prelude ()
import Prelude.Compat
import Control.Applicative (many, (<|>))
import Data.Aeson (FromJSON, Result (..), Value, fromJSON)
import Data.Aeson.Parser (value)
import qualified Data.Attoparsec.ByteString.Char8 as A8
import qualified Data.Attoparsec.ByteString.Lazy as A
import qualified Data.ByteString.Lazy as LBS
streamParse :: LBS.ByteString -> ([Value], Maybe String)
streamParse :: ByteString -> ([Value], Maybe String)
streamParse = ByteString -> ([Value], Maybe String)
start
where
start :: ByteString -> ([Value], Maybe String)
start ByteString
bs = case Parser Char -> ByteString -> Result Char
forall a. Parser a -> ByteString -> Result a
A.parse (Char -> Parser Char
lexemeChar Char
'[') ByteString
bs of
A.Done ByteString
bs' Char
_ -> ByteString -> ([Value], Maybe String)
first ByteString
bs'
A.Fail ByteString
_ [String]
_ String
err -> ([], String -> Maybe String
forall a. a -> Maybe a
Just String
err)
first :: ByteString -> ([Value], Maybe String)
first ByteString
bs = case Parser Char -> ByteString -> Result Char
forall a. Parser a -> ByteString -> Result a
A.parse (Char -> Parser Char
lexemeChar Char
']') ByteString
bs of
A.Done {} -> ([], Maybe String
forall a. Maybe a
Nothing)
A.Fail {} -> ByteString -> ([Value], Maybe String)
go ByteString
bs
go :: ByteString -> ([Value], Maybe String)
go ByteString
bs = case Parser (Value, Bool) -> ByteString -> Result (Value, Bool)
forall a. Parser a -> ByteString -> Result a
A.parse Parser (Value, Bool)
valueEnd ByteString
bs of
A.Done ByteString
_ (Value
r, Bool
False) -> ([Value
r], Maybe String
forall a. Maybe a
Nothing)
A.Done ByteString
bs' (Value
r, Bool
True) -> case ByteString -> ([Value], Maybe String)
go ByteString
bs' of
~([Value]
rs, Maybe String
end) -> (Value
rValue -> [Value] -> [Value]
forall a. a -> [a] -> [a]
:[Value]
rs, Maybe String
end)
A.Fail ByteString
_ [String]
_ String
err -> ([], String -> Maybe String
forall a. a -> Maybe a
Just String
err)
valueEnd :: Parser (Value, Bool)
valueEnd = do
Value
v <- Parser Value
value
Bool
c <- Bool
True Bool -> Parser Char -> Parser ByteString Bool
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Char -> Parser Char
lexemeChar Char
',' Parser ByteString Bool
-> Parser ByteString Bool -> Parser ByteString Bool
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Bool
False Bool -> Parser Char -> Parser ByteString Bool
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Char -> Parser Char
lexemeChar Char
']'
(Value, Bool) -> Parser (Value, Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Value
v, Bool
c)
lexemeChar :: Char -> Parser Char
lexemeChar Char
c = Parser Char -> Parser ByteString String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser Char
A8.space Parser ByteString String -> Parser Char -> Parser Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Char -> Parser Char
A8.char Char
c Parser Char -> Parser ByteString String -> Parser Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Char -> Parser ByteString String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser Char
A8.space
streamDecode :: forall a. FromJSON a => LBS.ByteString -> ([a], Maybe String)
streamDecode :: ByteString -> ([a], Maybe String)
streamDecode ByteString
bs = [Value] -> ([a], Maybe String)
go [Value]
values
where
([Value]
values, Maybe String
err) = ByteString -> ([Value], Maybe String)
streamParse ByteString
bs
go :: [Value] -> ([a], Maybe String)
go :: [Value] -> ([a], Maybe String)
go [] = ([], Maybe String
err)
go (Value
v:[Value]
vs) = case Value -> Result a
forall a. FromJSON a => Value -> Result a
fromJSON Value
v of
Error String
err' -> ([], String -> Maybe String
forall a. a -> Maybe a
Just String
err')
Success a
x -> case [Value] -> ([a], Maybe String)
go [Value]
vs of
~([a]
xs, Maybe String
err') -> (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs, Maybe String
err')