    {-# 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)