{-# LANGUAGE RankNTypes #-}

-- | This module allows you to encode and decode JSON values flowing downstream
-- through Pipes streams.
--
-- This module builds on top of the @aeson@, @pipes@ and @pipes-parse@
-- libraries, and assumes you know how to use them. Please read the examples
-- in "Pipes.Parse.Tutorial" to understand how to use these functions.
--
-- In this module, the following type synonym compatible with the @lens@,
-- @lens-family@ and @lens-family-core@ libraries is used but not exported:
--
-- @
-- type Lens' s a = forall f . 'Functor' f => (a -> f a) -> (s -> f s)
-- @

module Pipes.Aeson
  ( -- * Encoding
    -- $encoding
    encodeArray
  , encodeObject

    -- * Decoding
    -- $decoding
  , decode
  , decoded
  , loop
    -- ** Including lengths
  , decodeL
  , decodedL
  , loopL

    -- * Types
  , I.DecodingError(..)
  ) where

import qualified Data.Aeson            as Ae
import qualified Data.Aeson.Parser     as Ae
import qualified Data.ByteString.Char8 as B
import           Pipes
import qualified Pipes.Aeson.Internal  as I
import qualified Pipes.Aeson.Unchecked as U
import qualified Pipes.Parse           as Pipes

--------------------------------------------------------------------------------
-- $encoding
--
-- Encode 'Ae.Array' or 'Ae.Object' values as JSON and send them downstream,
-- possibly in more than one 'B.ByteString' chunk.
--
-- /Note:/ The JSON RFC-4627 standard only allows arrays or objects as top-level
-- entities, which is why these functions restrict their input to them. If you
-- prefer to ignore the standard and encode any 'Ae.Value', then use 'U.encode'
-- from the "Pipes.Aeson.Unchecked" module.
--

-- | Encode an 'Ae.Object' as JSON and send it downstream,
--
-- /Hint:/ You can easily turn this 'Producer'' into a 'Pipe' that encodes
-- 'Ae.Object' values as JSON as they flow downstream using:
--
-- @
-- 'for' 'cat' 'encodeObject' :: 'Monad' m => 'Pipe' 'Ae.Object' 'B.ByteString' m r
-- @
encodeObject :: Monad m => Ae.Object -> Proxy x' x () B.ByteString m ()
encodeObject :: forall (m :: * -> *) x' x.
Monad m =>
Object -> Proxy x' x () ByteString m ()
encodeObject = Object -> Proxy x' x () ByteString m ()
forall (m :: * -> *) a x' x.
(Monad m, ToJSON a) =>
a -> Proxy x' x () ByteString m ()
U.encode
{-# INLINABLE encodeObject #-}
{-# RULES "p >-> for cat encodeObject" forall p .
    p >-> for cat encodeObject = for p encodeObject
  #-}

-- | Encode an 'Ae.Array' as JSON and send it downstream,
--
-- /Hint:/ You can easily turn this 'Producer'' into a 'Pipe' that encodes
-- 'Ae.Array' values as JSON as they flow downstream using:
--
-- @
-- 'for' 'cat' 'encodeArray' :: 'Monad' m => 'Pipe' 'Ae.Array' 'B.ByteString' m r
-- @
encodeArray :: Monad m => Ae.Array -> Proxy x' x () B.ByteString m ()
encodeArray :: forall (m :: * -> *) x' x.
Monad m =>
Array -> Proxy x' x () ByteString m ()
encodeArray = Array -> Proxy x' x () ByteString m ()
forall (m :: * -> *) a x' x.
(Monad m, ToJSON a) =>
a -> Proxy x' x () ByteString m ()
U.encode
{-# INLINABLE encodeArray #-}
{-# RULES "p >-> for cat encodeArray" forall p .
    p >-> for cat encodeArray = for p encodeArray
  #-}

--------------------------------------------------------------------------------
-- $decoding
--
-- Decoding JSON as a Haskell value involves two different steps:
--
-- * Parsing a raw JSON 'B.ByteString' into an 'Ae.Object' or an 'Ae.Array'.
--
-- * Converting the obtained 'Ae.Object' or 'Ae.Array' to the desired
-- 'Ae.FromJSON' instance.
--
-- Any of those steps can fail, in which case a 'I.DecodingError' will report
-- the precise error and at which step it happened.


-- | Decodes an 'Ae.Object' or 'Ae.Array' JSON value from the underlying state.
--
-- It returns 'Nothing' if the underlying 'Producer' is exhausted, otherwise
-- it returns either the decoded entity or a 'I.DecodingError' in case of error.
--
-- /Note:/ The JSON RFC-4627 standard only allows arrays or objects as top-level
-- entities, which is why this 'Pipes.Parser' restricts its output to them. If
-- you prefer to ignore the standard and decode any 'Ae.Value', then use
-- 'U.decode' from the "Pipes.Aeson.Unchecked" module.
decode
  :: (Monad m, Ae.FromJSON a)
  => Pipes.Parser B.ByteString m (Maybe (Either I.DecodingError a))
decode :: forall (m :: * -> *) a.
(Monad m, FromJSON a) =>
Parser ByteString m (Maybe (Either DecodingError a))
decode = (Maybe (Either DecodingError (Int, a))
 -> Maybe (Either DecodingError a))
-> StateT
     (Producer ByteString m x) m (Maybe (Either DecodingError (Int, a)))
-> StateT
     (Producer ByteString m x) m (Maybe (Either DecodingError a))
forall a b.
(a -> b)
-> StateT (Producer ByteString m x) m a
-> StateT (Producer ByteString m x) m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Either DecodingError (Int, a) -> Either DecodingError a)
-> Maybe (Either DecodingError (Int, a))
-> Maybe (Either DecodingError a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((Int, a) -> a)
-> Either DecodingError (Int, a) -> Either DecodingError a
forall a b.
(a -> b) -> Either DecodingError a -> Either DecodingError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int, a) -> a
forall a b. (a, b) -> b
snd)) StateT
  (Producer ByteString m x) m (Maybe (Either DecodingError (Int, a)))
Parser ByteString m (Maybe (Either DecodingError (Int, a)))
forall (m :: * -> *) a.
(Monad m, FromJSON a) =>
Parser ByteString m (Maybe (Either DecodingError (Int, a)))
decodeL
{-# INLINABLE decode #-}

-- | Like 'decode', except it also returns the length of JSON input that was
-- consumed in order to obtain the value, not including the length of whitespace
-- before nor after the parsed JSON input.
decodeL
  :: (Monad m, Ae.FromJSON a)
  => Pipes.Parser B.ByteString m (Maybe (Either I.DecodingError (Int, a)))
decodeL :: forall (m :: * -> *) a.
(Monad m, FromJSON a) =>
Parser ByteString m (Maybe (Either DecodingError (Int, a)))
decodeL = Parser ByteString Value
-> Parser ByteString m (Maybe (Either DecodingError (Int, a)))
forall (m :: * -> *) a.
(Monad m, FromJSON a) =>
Parser ByteString Value
-> Parser ByteString m (Maybe (Either DecodingError (Int, a)))
I.decodeL Parser ByteString Value
Ae.json'
{-# INLINABLE decodeL #-}


-- | /Improper lens/ that turns a stream of raw JSON input into a stream of
-- 'Ae.FromJSON' and back.
--
-- By /improper lens/ we mean that in practice you can't expect the
-- /Monad Morphism Laws/ to be true when using 'decoded' with
-- 'Control.Lens.zoom'.
--
-- @
-- 'Control.Lens.zoom' 'decoded' ('return' r) /= 'return' r
-- 'Control.Lens.zoom' 'decoded' (m >>= k)  /= 'Control.Lens.zoom' m >>= 'Control.Lens.zoom' . f
-- @
--
-- /Note:/ The JSON RFC-4627 standard only allows arrays or objects as top-level
-- entities, which is why this function restricts its stream values to them. If
-- you prefer to ignore the standard and encode or decode any 'Ae.Value', then
-- use 'U.decoded' from the "Pipes.Aeson.Unchecked" module.
decoded
  :: (Monad m, Ae.FromJSON a, Ae.ToJSON a)
  => (Ae.Value -> Either Ae.Object Ae.Array)
     -- ^ A witness that @a@ can be represented either as an 'Ae.Object' or as
     -- an 'Ae.Array'. The passed in 'Ae.Value' is @'Ae.toJSON' a@
  -> Lens' (Producer B.ByteString m r)
           (Producer a m (Either (I.DecodingError, Producer B.ByteString m r) r))
decoded :: forall (m :: * -> *) a r.
(Monad m, FromJSON a, ToJSON a) =>
(Value -> Either Object Array)
-> Lens'
     (Producer ByteString m r)
     (Producer a m (Either (DecodingError, Producer ByteString m r) r))
decoded Value -> Either Object Array
f Producer a m (Either (DecodingError, Producer ByteString m r) r)
-> f (Producer
        a m (Either (DecodingError, Producer ByteString m r) r))
k Producer ByteString m r
p0 = (Producer a m (Either (DecodingError, Producer ByteString m r) r)
 -> Producer ByteString m r)
-> f (Producer
        a m (Either (DecodingError, Producer ByteString m r) r))
-> f (Producer ByteString m r)
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Producer a m (Either (DecodingError, Producer ByteString m r) r)
-> Producer ByteString m r
forall {x'} {x} {a} {b}.
Proxy x' x () a m (Either (a, Proxy x' x () ByteString m b) b)
-> Proxy x' x () ByteString m b
_encode (Producer a m (Either (DecodingError, Producer ByteString m r) r)
-> f (Producer
        a m (Either (DecodingError, Producer ByteString m r) r))
k (Parser ByteString m (Maybe (Either DecodingError a))
-> Producer ByteString m r
-> Producer a m (Either (DecodingError, Producer ByteString m r) r)
forall (m :: * -> *) e a r.
Monad m =>
Parser ByteString m (Maybe (Either e a))
-> Producer ByteString m r
-> Producer a m (Either (e, Producer ByteString m r) r)
I.consecutively StateT (Producer ByteString m x) m (Maybe (Either DecodingError a))
Parser ByteString m (Maybe (Either DecodingError a))
forall (m :: * -> *) a.
(Monad m, FromJSON a) =>
Parser ByteString m (Maybe (Either DecodingError a))
decode Producer ByteString m r
p0))
  where
    _encode :: Proxy x' x () a m (Either (a, Proxy x' x () ByteString m b) b)
-> Proxy x' x () ByteString m b
_encode = \Proxy x' x () a m (Either (a, Proxy x' x () ByteString m b) b)
p -> do
       Either (a, Proxy x' x () ByteString m b) b
er <- Proxy x' x () a m (Either (a, Proxy x' x () ByteString m b) b)
-> (a -> Proxy x' x () ByteString m ())
-> Proxy
     x' x () ByteString m (Either (a, Proxy x' x () ByteString m b) b)
forall (m :: * -> *) x' x b' b a' c' c.
Functor m =>
Proxy x' x b' b m a'
-> (b -> Proxy x' x c' c m b') -> Proxy x' x c' c m a'
for Proxy x' x () a m (Either (a, Proxy x' x () ByteString m b) b)
p (\a
a -> (Object -> Proxy x' x () ByteString m ())
-> (Array -> Proxy x' x () ByteString m ())
-> Either Object Array
-> Proxy x' x () ByteString m ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Object -> Proxy x' x () ByteString m ()
forall (m :: * -> *) x' x.
Monad m =>
Object -> Proxy x' x () ByteString m ()
encodeObject Array -> Proxy x' x () ByteString m ()
forall (m :: * -> *) x' x.
Monad m =>
Array -> Proxy x' x () ByteString m ()
encodeArray (Value -> Either Object Array
f (a -> Value
forall a. ToJSON a => a -> Value
Ae.toJSON a
a)))
       case Either (a, Proxy x' x () ByteString m b) b
er of
          Left (a
_, Proxy x' x () ByteString m b
p') -> Proxy x' x () ByteString m b
p'
          Right b
r      -> b -> Proxy x' x () ByteString m b
forall a. a -> Proxy x' x () ByteString m a
forall (m :: * -> *) a. Monad m => a -> m a
return b
r
{-# INLINABLE decoded #-}

-- | Like 'decoded', except it also tags each decoded entity with the length of
-- JSON input that was consumed in order to obtain the value, not including the
-- length of whitespace between each parsed JSON input.
decodedL
  :: (Monad m, Ae.FromJSON a, Ae.ToJSON a)
  => (Ae.Value -> Either Ae.Object Ae.Array)
     -- ^ A witness that @a@ can be represented either as an 'Ae.Object' or as
     -- an 'Ae.Array'. The passed in 'Ae.Value' is @'Ae.toJSON' a@
  -> Lens' (Producer B.ByteString m r)
           (Producer (Int, a) m (Either (I.DecodingError, Producer B.ByteString m r) r))
decodedL :: forall (m :: * -> *) a r.
(Monad m, FromJSON a, ToJSON a) =>
(Value -> Either Object Array)
-> Lens'
     (Producer ByteString m r)
     (Producer
        (Int, a) m (Either (DecodingError, Producer ByteString m r) r))
decodedL Value -> Either Object Array
f Producer
  (Int, a) m (Either (DecodingError, Producer ByteString m r) r)
-> f (Producer
        (Int, a) m (Either (DecodingError, Producer ByteString m r) r))
k Producer ByteString m r
p0 = (Producer
   (Int, a) m (Either (DecodingError, Producer ByteString m r) r)
 -> Producer ByteString m r)
-> f (Producer
        (Int, a) m (Either (DecodingError, Producer ByteString m r) r))
-> f (Producer ByteString m r)
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Producer
  (Int, a) m (Either (DecodingError, Producer ByteString m r) r)
-> Producer ByteString m r
forall {x'} {x} {a} {a} {b}.
Proxy x' x () (a, a) m (Either (a, Proxy x' x () ByteString m b) b)
-> Proxy x' x () ByteString m b
_encode (Producer
  (Int, a) m (Either (DecodingError, Producer ByteString m r) r)
-> f (Producer
        (Int, a) m (Either (DecodingError, Producer ByteString m r) r))
k (Parser ByteString m (Maybe (Either DecodingError (Int, a)))
-> Producer ByteString m r
-> Producer
     (Int, a) m (Either (DecodingError, Producer ByteString m r) r)
forall (m :: * -> *) e a r.
Monad m =>
Parser ByteString m (Maybe (Either e a))
-> Producer ByteString m r
-> Producer a m (Either (e, Producer ByteString m r) r)
I.consecutively StateT
  (Producer ByteString m x) m (Maybe (Either DecodingError (Int, a)))
Parser ByteString m (Maybe (Either DecodingError (Int, a)))
forall (m :: * -> *) a.
(Monad m, FromJSON a) =>
Parser ByteString m (Maybe (Either DecodingError a))
decode Producer ByteString m r
p0))
  where
    _encode :: Proxy x' x () (a, a) m (Either (a, Proxy x' x () ByteString m b) b)
-> Proxy x' x () ByteString m b
_encode = \Proxy x' x () (a, a) m (Either (a, Proxy x' x () ByteString m b) b)
p -> do
      Either (a, Proxy x' x () ByteString m b) b
er <- Proxy x' x () (a, a) m (Either (a, Proxy x' x () ByteString m b) b)
-> ((a, a) -> Proxy x' x () ByteString m ())
-> Proxy
     x' x () ByteString m (Either (a, Proxy x' x () ByteString m b) b)
forall (m :: * -> *) x' x b' b a' c' c.
Functor m =>
Proxy x' x b' b m a'
-> (b -> Proxy x' x c' c m b') -> Proxy x' x c' c m a'
for Proxy x' x () (a, a) m (Either (a, Proxy x' x () ByteString m b) b)
p (\(a
_, a
a) -> (Object -> Proxy x' x () ByteString m ())
-> (Array -> Proxy x' x () ByteString m ())
-> Either Object Array
-> Proxy x' x () ByteString m ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Object -> Proxy x' x () ByteString m ()
forall (m :: * -> *) x' x.
Monad m =>
Object -> Proxy x' x () ByteString m ()
encodeObject Array -> Proxy x' x () ByteString m ()
forall (m :: * -> *) x' x.
Monad m =>
Array -> Proxy x' x () ByteString m ()
encodeArray (Value -> Either Object Array
f (a -> Value
forall a. ToJSON a => a -> Value
Ae.toJSON a
a)))
      case Either (a, Proxy x' x () ByteString m b) b
er of
         Left (a
_, Proxy x' x () ByteString m b
p') -> Proxy x' x () ByteString m b
p'
         Right b
r      -> b -> Proxy x' x () ByteString m b
forall a. a -> Proxy x' x () ByteString m a
forall (m :: * -> *) a. Monad m => a -> m a
return b
r
{-# INLINABLE decodedL #-}

-- | Repeteadly try to parse raw JSON bytes into @a@ values, reporting any
-- 'I.DecodingError's downstream as they happen.
--
-- /Note:/ The JSON RFC-4627 standard only allows arrays or objects as top-level
-- entities, which is why these functions restrict their input to them. If you
-- prefer to ignore the standard and encode any 'Ae.Value', then use 'U.encode'
-- from the "Pipes.Aeson.Unchecked" module.
loop
  :: (Monad m, Ae.FromJSON a)
  => (Pipes.Producer B.ByteString m r -> Pipes.Producer B.ByteString m r)
  -- ^ In case of 'I.AttoparsecError', this function will be called to modify
  -- the leftovers 'Pipes.Producer' before using it.
  --
  -- Ideally you will want to drop everything until the beginning of the next
  -- JSON element. This is easy to accomplish if there is a clear whitespace
  -- delimiter between the JSON elements, such as a newline (i.e.,
  -- @'Pipes.ByteString.drop' 1 . 'Pipes.ByteString.dropWhile' (/= 0xA)@).
  -- However, it can be hard to do correctly is there is no such delimiter.
  -- Skipping the first character (i.e., @'Pipes.ByteString.drop' 1@) should be
  -- sufficient in most cases, but not when parsing recursive data structures
  -- because you can accidentally parse a child in its parent's stead.
  --
  -- Notice that unless you advance the 'Pipes.Producer' somehow, 'loop'
  -- will never terminate.
  -> Pipes.Producer B.ByteString m r
  -- ^ Raw JSON input.
  -> Pipes.Producer' (Either I.DecodingError a) m r
{-# INLINABLE loop #-}
loop :: forall (m :: * -> *) a r.
(Monad m, FromJSON a) =>
(Producer ByteString m r -> Producer ByteString m r)
-> Producer ByteString m r
-> Producer' (Either DecodingError a) m r
loop Producer ByteString m r -> Producer ByteString m r
fp Producer ByteString m r
p0 = Proxy x' x () (Either DecodingError (Int, a)) m r
-> (Either DecodingError (Int, a)
    -> Proxy x' x () (Either DecodingError a) m ())
-> Proxy x' x () (Either DecodingError a) m r
forall (m :: * -> *) x' x b' b a' c' c.
Functor m =>
Proxy x' x b' b m a'
-> (b -> Proxy x' x c' c m b') -> Proxy x' x c' c m a'
Pipes.for ((Producer ByteString m r -> Producer ByteString m r)
-> Producer ByteString m r
-> Proxy x' x () (Either DecodingError (Int, a)) m r
forall (m :: * -> *) a r x' x.
(Monad m, FromJSON a) =>
(Producer ByteString m r -> Producer ByteString m r)
-> Producer ByteString m r
-> Proxy x' x () (Either DecodingError (Int, a)) m r
loopL Producer ByteString m r -> Producer ByteString m r
fp Producer ByteString m r
p0) (Either DecodingError a
-> Proxy x' x () (Either DecodingError a) m ()
forall (m :: * -> *) a x' x. Functor m => a -> Proxy x' x () a m ()
Pipes.yield (Either DecodingError a
 -> Proxy x' x () (Either DecodingError a) m ())
-> (Either DecodingError (Int, a) -> Either DecodingError a)
-> Either DecodingError (Int, a)
-> Proxy x' x () (Either DecodingError a) m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, a) -> a)
-> Either DecodingError (Int, a) -> Either DecodingError a
forall a b.
(a -> b) -> Either DecodingError a -> Either DecodingError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int, a) -> a
forall a b. (a, b) -> b
snd)

-- | Like 'loop', except it also outputs the length of JSON input that was
-- consumed in order to obtain the value, not including the length of whitespace
-- before nor after the parsed JSON input.
loopL
  :: (Monad m, Ae.FromJSON a)
  => (Pipes.Producer B.ByteString m r -> Pipes.Producer B.ByteString m r)
  -- ^ In case of 'I.AttoparsecError', this function will be called to modify
  -- the leftovers 'Pipes.Producer' before using it.
  --
  -- Ideally you will want to drop everything until the beginning of the next
  -- JSON element. This is easy to accomplish if there is a clear whitespace
  -- delimiter between the JSON elements, such as a newline (i.e.,
  -- @'Pipes.ByteString.drop' 1 . 'Pipes.ByteString.dropWhile' (/= 0xA)@).
  -- However, it can be hard to do correctly is there is no such delimiter.
  -- Skipping the first character (i.e., @'Pipes.ByteString.drop' 1@) should be
  -- sufficient in most cases, but not when parsing recursive data structures
  -- because you can accidentally parse a child in its parent's stead.
  --
  -- Notice that unless you advance the 'Pipes.Producer' somehow, 'loopL'
  -- will never terminate.
  -> Pipes.Producer B.ByteString m r
  -- ^ Raw JSON input.
  -> Pipes.Proxy x' x () (Either I.DecodingError (Int, a)) m r
{-# INLINABLE loopL #-}
loopL :: forall (m :: * -> *) a r x' x.
(Monad m, FromJSON a) =>
(Producer ByteString m r -> Producer ByteString m r)
-> Producer ByteString m r
-> Proxy x' x () (Either DecodingError (Int, a)) m r
loopL = Parser ByteString Value
-> (Producer ByteString m r -> Producer ByteString m r)
-> Producer ByteString m r
-> Proxy x' x () (Either DecodingError (Int, a)) m r
forall (m :: * -> *) a r x' x.
(Monad m, FromJSON a) =>
Parser ByteString Value
-> (Producer ByteString m r -> Producer ByteString m r)
-> Producer ByteString m r
-> Proxy x' x () (Either DecodingError (Int, a)) m r
I.loopL Parser ByteString Value
Ae.json'

--------------------------------------------------------------------------------
-- Internal tools --------------------------------------------------------------

type Lens' s a = forall f . Functor f => (a -> f a) -> s -> f s