{-# LANGUAGE CPP          #-}
{-# LANGUAGE BangPatterns #-}

-- |
-- Module      : Codec.CBOR.Term
-- Copyright   : (c) Duncan Coutts 2015-2017
-- License     : BSD3-style (see LICENSE.txt)
--
-- Maintainer  : duncan@community.haskell.org
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--
-- This module provides an interface for decoding and encoding arbitrary
-- CBOR values (ones that, for example, may not have been generated by this
-- library).
--
-- Using 'decodeTerm', you can decode an arbitrary CBOR value given to you
-- into a 'Term', which represents a CBOR value as an AST.
--
-- Similarly, if you wanted to encode some value into a CBOR value directly,
-- you can wrap it in a 'Term' constructor and use 'encodeTerm'. This
-- would be useful, as an example, if you needed to serialise some value into
-- a CBOR term that is not compatible with that types 'Serialise' instance.
--
-- Because this interface gives you the ability to decode or encode any
-- arbitrary CBOR term, it can also be seen as an alternative interface to the
-- 'Codec.CBOR.Encoding' and
-- 'Codec.CBOR.Decoding' modules.
--
module Codec.CBOR.Term
  ( Term(..)    -- :: *
  , encodeTerm  -- :: Term -> Encoding
  , decodeTerm  -- :: Decoder Term
  ) where

#include "cbor.h"

import           Codec.CBOR.Encoding hiding (Tokens(..))
import           Codec.CBOR.Decoding

import           Data.Word
import qualified Data.Text as T
import qualified Data.Text.Lazy as LT
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import           Data.Monoid
import           Control.Applicative

import Prelude hiding (encodeFloat, decodeFloat)

--------------------------------------------------------------------------------
-- Types

-- | A general CBOR term, which can be used to serialise or deserialise
-- arbitrary CBOR terms for interoperability or debugging. This type is
-- essentially a direct reflection of the CBOR abstract syntax tree as a
-- Haskell data type.
--
-- The 'Term' type also comes with a 'Serialise' instance, so you can
-- easily use @'decode' :: 'Decoder' 'Term'@ to directly decode any arbitrary
-- CBOR value into Haskell with ease, and likewise with 'encode'.
--
-- @since 0.2.0.0
data Term
  = TInt     {-# UNPACK #-} !Int
  | TInteger                !Integer
  | TBytes                  !BS.ByteString
  | TBytesI                 !LBS.ByteString
  | TString                 !T.Text
  | TStringI                !LT.Text
  | TList                   ![Term]
  | TListI                  ![Term]
  | TMap                    ![(Term, Term)]
  | TMapI                   ![(Term, Term)]
  | TTagged  {-# UNPACK #-} !Word64 !Term
  | TBool                   !Bool
  | TNull
  | TSimple  {-# UNPACK #-} !Word8
  | THalf    {-# UNPACK #-} !Float
  | TFloat   {-# UNPACK #-} !Float
  | TDouble  {-# UNPACK #-} !Double
  deriving (Term -> Term -> Bool
(Term -> Term -> Bool) -> (Term -> Term -> Bool) -> Eq Term
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Term -> Term -> Bool
== :: Term -> Term -> Bool
$c/= :: Term -> Term -> Bool
/= :: Term -> Term -> Bool
Eq, Eq Term
Eq Term =>
(Term -> Term -> Ordering)
-> (Term -> Term -> Bool)
-> (Term -> Term -> Bool)
-> (Term -> Term -> Bool)
-> (Term -> Term -> Bool)
-> (Term -> Term -> Term)
-> (Term -> Term -> Term)
-> Ord Term
Term -> Term -> Bool
Term -> Term -> Ordering
Term -> Term -> Term
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Term -> Term -> Ordering
compare :: Term -> Term -> Ordering
$c< :: Term -> Term -> Bool
< :: Term -> Term -> Bool
$c<= :: Term -> Term -> Bool
<= :: Term -> Term -> Bool
$c> :: Term -> Term -> Bool
> :: Term -> Term -> Bool
$c>= :: Term -> Term -> Bool
>= :: Term -> Term -> Bool
$cmax :: Term -> Term -> Term
max :: Term -> Term -> Term
$cmin :: Term -> Term -> Term
min :: Term -> Term -> Term
Ord, Int -> Term -> ShowS
[Term] -> ShowS
Term -> String
(Int -> Term -> ShowS)
-> (Term -> String) -> ([Term] -> ShowS) -> Show Term
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Term -> ShowS
showsPrec :: Int -> Term -> ShowS
$cshow :: Term -> String
show :: Term -> String
$cshowList :: [Term] -> ShowS
showList :: [Term] -> ShowS
Show, ReadPrec [Term]
ReadPrec Term
Int -> ReadS Term
ReadS [Term]
(Int -> ReadS Term)
-> ReadS [Term] -> ReadPrec Term -> ReadPrec [Term] -> Read Term
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Term
readsPrec :: Int -> ReadS Term
$creadList :: ReadS [Term]
readList :: ReadS [Term]
$creadPrec :: ReadPrec Term
readPrec :: ReadPrec Term
$creadListPrec :: ReadPrec [Term]
readListPrec :: ReadPrec [Term]
Read)

--------------------------------------------------------------------------------
-- Main API

-- | Encode an arbitrary 'Term' into an 'Encoding' for later serialization.
--
-- @since 0.2.0.0
encodeTerm :: Term -> Encoding
encodeTerm :: Term -> Encoding
encodeTerm (TInt      Int
n)  = Int -> Encoding
encodeInt Int
n
encodeTerm (TInteger  Integer
n)  = Integer -> Encoding
encodeInteger Integer
n
encodeTerm (TBytes   ByteString
bs)  = ByteString -> Encoding
encodeBytes ByteString
bs
encodeTerm (TString  Text
st)  = Text -> Encoding
encodeString Text
st
encodeTerm (TBytesI ByteString
bss)  = Encoding
encodeBytesIndef
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [Encoding] -> Encoding
forall a. Monoid a => [a] -> a
mconcat [ ByteString -> Encoding
encodeBytes ByteString
bs
                                       | ByteString
bs <- ByteString -> [ByteString]
LBS.toChunks ByteString
bss ]
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Encoding
encodeBreak
encodeTerm (TStringI Text
sts) = Encoding
encodeStringIndef
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [Encoding] -> Encoding
forall a. Monoid a => [a] -> a
mconcat [ Text -> Encoding
encodeString Text
str
                                       | Text
str <- Text -> [Text]
LT.toChunks Text
sts ]
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Encoding
encodeBreak
encodeTerm (TList    [Term]
ts)  = Word -> Encoding
encodeListLen (Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word) -> Int -> Word
forall a b. (a -> b) -> a -> b
$ [Term] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Term]
ts)
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [Encoding] -> Encoding
forall a. Monoid a => [a] -> a
mconcat [ Term -> Encoding
encodeTerm Term
t | Term
t <- [Term]
ts ]
encodeTerm (TListI   [Term]
ts)  = Encoding
encodeListLenIndef
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [Encoding] -> Encoding
forall a. Monoid a => [a] -> a
mconcat [ Term -> Encoding
encodeTerm Term
t | Term
t <- [Term]
ts ]
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Encoding
encodeBreak
encodeTerm (TMap     [(Term, Term)]
ts)  = Word -> Encoding
encodeMapLen (Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word) -> Int -> Word
forall a b. (a -> b) -> a -> b
$ [(Term, Term)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Term, Term)]
ts)
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [Encoding] -> Encoding
forall a. Monoid a => [a] -> a
mconcat [ Term -> Encoding
encodeTerm Term
t Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Term -> Encoding
encodeTerm Term
t'
                                       | (Term
t, Term
t') <- [(Term, Term)]
ts ]
encodeTerm (TMapI [(Term, Term)]
ts)     = Encoding
encodeMapLenIndef
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [Encoding] -> Encoding
forall a. Monoid a => [a] -> a
mconcat [ Term -> Encoding
encodeTerm Term
t Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Term -> Encoding
encodeTerm Term
t'
                                       | (Term
t, Term
t') <- [(Term, Term)]
ts ]
                            Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Encoding
encodeBreak
encodeTerm (TTagged Word64
w Term
t)  = Word64 -> Encoding
encodeTag64 Word64
w Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Term -> Encoding
encodeTerm Term
t
encodeTerm (TBool     Bool
b)  = Bool -> Encoding
encodeBool Bool
b
encodeTerm  Term
TNull         = Encoding
encodeNull
encodeTerm (TSimple   Word8
w)  = Word8 -> Encoding
encodeSimple Word8
w
encodeTerm (THalf     Float
f)  = Float -> Encoding
encodeFloat16 Float
f
encodeTerm (TFloat    Float
f)  = Float -> Encoding
encodeFloat   Float
f
encodeTerm (TDouble   Double
f)  = Double -> Encoding
encodeDouble  Double
f

-- | Decode some arbitrary CBOR value into a 'Term'.
--
-- @since 0.2.0.0
decodeTerm :: Decoder s Term
decodeTerm :: forall s. Decoder s Term
decodeTerm = do
    TokenType
tkty <- Decoder s TokenType
forall s. Decoder s TokenType
peekTokenType
    case TokenType
tkty of
      TokenType
TypeUInt   -> do Word
w <- Decoder s Word
forall s. Decoder s Word
decodeWord
                       Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! Word -> Term
fromWord Word
w
                    where
                      fromWord :: Word -> Term
                      fromWord :: Word -> Term
fromWord Word
w
                        | Word
w Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
maxBound :: Int)
                                    = Int -> Term
TInt     (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
w)
                        | Bool
otherwise = Integer -> Term
TInteger (Word -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
w)

      TokenType
TypeUInt64 -> do Word64
w <- Decoder s Word64
forall s. Decoder s Word64
decodeWord64
                       Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! Word64 -> Term
forall {a}. Integral a => a -> Term
fromWord64 Word64
w
                    where
                      fromWord64 :: a -> Term
fromWord64 a
w
                        | a
w a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
maxBound :: Int)
                                    = Int -> Term
TInt     (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
w)
                        | Bool
otherwise = Integer -> Term
TInteger (a -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
w)

      TokenType
TypeNInt   -> do Word
w <- Decoder s Word
forall s. Decoder s Word
decodeNegWord
                       Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! Word -> Term
forall {a}. Integral a => a -> Term
fromNegWord Word
w
                    where
                      fromNegWord :: a -> Term
fromNegWord a
w
                        | a
w a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
maxBound :: Int)
                                    = Int -> Term
TInt     (-Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
w)
                        | Bool
otherwise = Integer -> Term
TInteger (-Integer
1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- a -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
w)

      TokenType
TypeNInt64 -> do Word64
w <- Decoder s Word64
forall s. Decoder s Word64
decodeNegWord64
                       Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! Word64 -> Term
forall {a}. Integral a => a -> Term
fromNegWord64 Word64
w
                    where
                      fromNegWord64 :: a -> Term
fromNegWord64 a
w
                        | a
w a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
maxBound :: Int)
                                    = Int -> Term
TInt     (-Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
w)
                        | Bool
otherwise = Integer -> Term
TInteger (-Integer
1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- a -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
w)

      TokenType
TypeInteger -> do !Integer
x <- Decoder s Integer
forall s. Decoder s Integer
decodeInteger
                        Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Term
TInteger Integer
x)
      TokenType
TypeFloat16 -> do !Float
x <- Decoder s Float
forall s. Decoder s Float
decodeFloat
                        Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Float -> Term
THalf Float
x)
      TokenType
TypeFloat32 -> do !Float
x <- Decoder s Float
forall s. Decoder s Float
decodeFloat
                        Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Float -> Term
TFloat Float
x)
      TokenType
TypeFloat64 -> do !Double
x <- Decoder s Double
forall s. Decoder s Double
decodeDouble
                        Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> Term
TDouble Double
x)

      TokenType
TypeBytes        -> do !ByteString
x <- Decoder s ByteString
forall s. Decoder s ByteString
decodeBytes
                             Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> Term
TBytes ByteString
x)
      TokenType
TypeBytesIndef   -> Decoder s ()
forall s. Decoder s ()
decodeBytesIndef Decoder s () -> Decoder s Term -> Decoder s Term
forall a b. Decoder s a -> Decoder s b -> Decoder s b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [ByteString] -> Decoder s Term
forall s. [ByteString] -> Decoder s Term
decodeBytesIndefLen []
      TokenType
TypeString       -> do !Text
x <- Decoder s Text
forall s. Decoder s Text
decodeString
                             Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Term
TString Text
x)
      TokenType
TypeStringIndef  -> Decoder s ()
forall s. Decoder s ()
decodeStringIndef Decoder s () -> Decoder s Term -> Decoder s Term
forall a b. Decoder s a -> Decoder s b -> Decoder s b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Text] -> Decoder s Term
forall s. [Text] -> Decoder s Term
decodeStringIndefLen []

      TokenType
TypeListLen      -> Decoder s Int
forall s. Decoder s Int
decodeListLen      Decoder s Int -> (Int -> Decoder s Term) -> Decoder s Term
forall a b. Decoder s a -> (a -> Decoder s b) -> Decoder s b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Int -> [Term] -> Decoder s Term)
-> [Term] -> Int -> Decoder s Term
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> [Term] -> Decoder s Term
forall s. Int -> [Term] -> Decoder s Term
decodeListN []
      TokenType
TypeListLen64    -> Decoder s Int
forall s. Decoder s Int
decodeListLen      Decoder s Int -> (Int -> Decoder s Term) -> Decoder s Term
forall a b. Decoder s a -> (a -> Decoder s b) -> Decoder s b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Int -> [Term] -> Decoder s Term)
-> [Term] -> Int -> Decoder s Term
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> [Term] -> Decoder s Term
forall s. Int -> [Term] -> Decoder s Term
decodeListN []
      TokenType
TypeListLenIndef -> Decoder s ()
forall s. Decoder s ()
decodeListLenIndef Decoder s () -> Decoder s Term -> Decoder s Term
forall a b. Decoder s a -> Decoder s b -> Decoder s b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  [Term] -> Decoder s Term
forall s. [Term] -> Decoder s Term
decodeListIndefLen []
      TokenType
TypeMapLen       -> Decoder s Int
forall s. Decoder s Int
decodeMapLen       Decoder s Int -> (Int -> Decoder s Term) -> Decoder s Term
forall a b. Decoder s a -> (a -> Decoder s b) -> Decoder s b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Int -> [(Term, Term)] -> Decoder s Term)
-> [(Term, Term)] -> Int -> Decoder s Term
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> [(Term, Term)] -> Decoder s Term
forall s. Int -> [(Term, Term)] -> Decoder s Term
decodeMapN []
      TokenType
TypeMapLen64     -> Decoder s Int
forall s. Decoder s Int
decodeMapLen       Decoder s Int -> (Int -> Decoder s Term) -> Decoder s Term
forall a b. Decoder s a -> (a -> Decoder s b) -> Decoder s b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Int -> [(Term, Term)] -> Decoder s Term)
-> [(Term, Term)] -> Int -> Decoder s Term
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> [(Term, Term)] -> Decoder s Term
forall s. Int -> [(Term, Term)] -> Decoder s Term
decodeMapN []
      TokenType
TypeMapLenIndef  -> Decoder s ()
forall s. Decoder s ()
decodeMapLenIndef  Decoder s () -> Decoder s Term -> Decoder s Term
forall a b. Decoder s a -> Decoder s b -> Decoder s b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>  [(Term, Term)] -> Decoder s Term
forall s. [(Term, Term)] -> Decoder s Term
decodeMapIndefLen []
      TokenType
TypeTag          -> do !Word64
x <- Decoder s Word64
forall s. Decoder s Word64
decodeTag64
                             !Term
y <- Decoder s Term
forall s. Decoder s Term
decodeTerm
                             Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Word64 -> Term -> Term
TTagged Word64
x Term
y)
      TokenType
TypeTag64        -> do !Word64
x <- Decoder s Word64
forall s. Decoder s Word64
decodeTag64
                             !Term
y <- Decoder s Term
forall s. Decoder s Term
decodeTerm
                             Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Word64 -> Term -> Term
TTagged Word64
x Term
y)

      TokenType
TypeBool    -> do !Bool
x <- Decoder s Bool
forall s. Decoder s Bool
decodeBool
                        Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Term
TBool Bool
x)
      TokenType
TypeNull    -> Term
TNull   Term -> Decoder s () -> Decoder s Term
forall a b. a -> Decoder s b -> Decoder s a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$  Decoder s ()
forall s. Decoder s ()
decodeNull
      TokenType
TypeSimple  -> do !Word8
x <- Decoder s Word8
forall s. Decoder s Word8
decodeSimple
                        Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Word8 -> Term
TSimple Word8
x)
      TokenType
TypeBreak   -> String -> Decoder s Term
forall a. String -> Decoder s a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"unexpected break"
      TokenType
TypeInvalid -> String -> Decoder s Term
forall a. String -> Decoder s a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalid token encoding"

--------------------------------------------------------------------------------
-- Internal utilities

decodeBytesIndefLen :: [BS.ByteString] -> Decoder s Term
decodeBytesIndefLen :: forall s. [ByteString] -> Decoder s Term
decodeBytesIndefLen [ByteString]
acc = do
    Bool
stop <- Decoder s Bool
forall s. Decoder s Bool
decodeBreakOr
    if Bool
stop then Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! ByteString -> Term
TBytesI ([ByteString] -> ByteString
LBS.fromChunks ([ByteString] -> [ByteString]
forall a. [a] -> [a]
reverse [ByteString]
acc))
            else do !ByteString
bs <- Decoder s ByteString
forall s. Decoder s ByteString
decodeBytes
                    [ByteString] -> Decoder s Term
forall s. [ByteString] -> Decoder s Term
decodeBytesIndefLen (ByteString
bs ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc)


decodeStringIndefLen :: [T.Text] -> Decoder s Term
decodeStringIndefLen :: forall s. [Text] -> Decoder s Term
decodeStringIndefLen [Text]
acc = do
    Bool
stop <- Decoder s Bool
forall s. Decoder s Bool
decodeBreakOr
    if Bool
stop then Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! Text -> Term
TStringI ([Text] -> Text
LT.fromChunks ([Text] -> [Text]
forall a. [a] -> [a]
reverse [Text]
acc))
            else do !Text
str <- Decoder s Text
forall s. Decoder s Text
decodeString
                    [Text] -> Decoder s Term
forall s. [Text] -> Decoder s Term
decodeStringIndefLen (Text
str Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
acc)


decodeListN :: Int -> [Term] -> Decoder s Term
decodeListN :: forall s. Int -> [Term] -> Decoder s Term
decodeListN !Int
n [Term]
acc =
    case Int
n of
      Int
0 -> Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! [Term] -> Term
TList ([Term] -> [Term]
forall a. [a] -> [a]
reverse [Term]
acc)
      Int
_ -> do !Term
t <- Decoder s Term
forall s. Decoder s Term
decodeTerm
              Int -> [Term] -> Decoder s Term
forall s. Int -> [Term] -> Decoder s Term
decodeListN (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Term
t Term -> [Term] -> [Term]
forall a. a -> [a] -> [a]
: [Term]
acc)


decodeListIndefLen :: [Term] -> Decoder s Term
decodeListIndefLen :: forall s. [Term] -> Decoder s Term
decodeListIndefLen [Term]
acc = do
    Bool
stop <- Decoder s Bool
forall s. Decoder s Bool
decodeBreakOr
    if Bool
stop then Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! [Term] -> Term
TListI ([Term] -> [Term]
forall a. [a] -> [a]
reverse [Term]
acc)
            else do !Term
tm <- Decoder s Term
forall s. Decoder s Term
decodeTerm
                    [Term] -> Decoder s Term
forall s. [Term] -> Decoder s Term
decodeListIndefLen (Term
tm Term -> [Term] -> [Term]
forall a. a -> [a] -> [a]
: [Term]
acc)


decodeMapN :: Int -> [(Term, Term)] -> Decoder s Term
decodeMapN :: forall s. Int -> [(Term, Term)] -> Decoder s Term
decodeMapN !Int
n [(Term, Term)]
acc =
    case Int
n of
      Int
0 -> Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! [(Term, Term)] -> Term
TMap ([(Term, Term)] -> [(Term, Term)]
forall a. [a] -> [a]
reverse [(Term, Term)]
acc)
      Int
_ -> do !Term
tm   <- Decoder s Term
forall s. Decoder s Term
decodeTerm
              !Term
tm'  <- Decoder s Term
forall s. Decoder s Term
decodeTerm
              Int -> [(Term, Term)] -> Decoder s Term
forall s. Int -> [(Term, Term)] -> Decoder s Term
decodeMapN (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) ((Term
tm, Term
tm') (Term, Term) -> [(Term, Term)] -> [(Term, Term)]
forall a. a -> [a] -> [a]
: [(Term, Term)]
acc)


decodeMapIndefLen :: [(Term, Term)] -> Decoder s Term
decodeMapIndefLen :: forall s. [(Term, Term)] -> Decoder s Term
decodeMapIndefLen [(Term, Term)]
acc = do
    Bool
stop <- Decoder s Bool
forall s. Decoder s Bool
decodeBreakOr
    if Bool
stop then Term -> Decoder s Term
forall a. a -> Decoder s a
forall (m :: * -> *) a. Monad m => a -> m a
return (Term -> Decoder s Term) -> Term -> Decoder s Term
forall a b. (a -> b) -> a -> b
$! [(Term, Term)] -> Term
TMapI ([(Term, Term)] -> [(Term, Term)]
forall a. [a] -> [a]
reverse [(Term, Term)]
acc)
            else do !Term
tm  <- Decoder s Term
forall s. Decoder s Term
decodeTerm
                    !Term
tm' <- Decoder s Term
forall s. Decoder s Term
decodeTerm
                    [(Term, Term)] -> Decoder s Term
forall s. [(Term, Term)] -> Decoder s Term
decodeMapIndefLen ((Term
tm, Term
tm') (Term, Term) -> [(Term, Term)] -> [(Term, Term)]
forall a. a -> [a] -> [a]
: [(Term, Term)]
acc)