    {-# LANGUAGE ScopedTypeVariables #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Data.Aeson.Extra.Stream
    -- Copyright   :  (C) 2015-2016 Oleg Grenrus
    -- License     :  BSD3
    -- Maintainer  :  Oleg Grenrus <oleg.grenrus@iki.fi>
    --
    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 a b. a -> Parser ByteString b -> Parser ByteString a
    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 a.
    Parser ByteString a -> Parser ByteString a -> Parser ByteString a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Bool
    False Bool -> Parser Char -> Parser ByteString Bool
    forall a b. a -> Parser ByteString b -> Parser ByteString a
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
    <$ Char -> Parser Char
    lexemeChar Char
    ']'
            (Value, Bool) -> Parser (Value, Bool)
    forall a. a -> Parser ByteString a
    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 a. Parser ByteString a -> Parser ByteString [a]
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    many Parser Char
    A8.space Parser ByteString String -> Parser Char -> Parser Char
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString b
    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 a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Parser Char -> Parser ByteString String
    forall a. Parser ByteString a -> Parser ByteString [a]
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    many Parser Char
    A8.space

    -- | Lazyly parse 'LBS.ByteString' with top-level JSON array.
    --
    -- /Note:/ inspecting result's second field will force the list!
    --
    -- @
    -- let ~(values, err) = 'streamDecode' bs
    -- traverse_ processValue values
    -- maybe (pure ()) printError err
    -- @
    --
    -- @since 0.3.2.0
    streamDecode :: forall a. FromJSON a => LBS.ByteString -> ([a], Maybe String)
    streamDecode :: forall a. FromJSON a => 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')