{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

module Cardano.Ledger.Shelley.Metadata
  ( Metadatum (..),
    Metadata (Metadata),
    hashMetadata,
    validMetadatum,
  )
where

import Cardano.Binary
  ( Annotator (..),
    DecoderError (..),
    FromCBOR (fromCBOR),
    ToCBOR (toCBOR),
    encodePreEncoded,
    serializeEncoding,
    withSlice,
  )
import Cardano.Ledger.Era (Crypto, Era)
import Cardano.Ledger.Hashes (EraIndependentAuxiliaryData)
import Cardano.Ledger.SafeHash
  ( HashAnnotated,
    SafeHash,
    SafeToHash (..),
    hashAnnotated,
  )
import Cardano.Ledger.Serialization (mapFromCBOR, mapToCBOR)
import Codec.CBOR.Decoding (Decoder)
import qualified Codec.CBOR.Decoding as CBOR
import qualified Codec.CBOR.Encoding as CBOR
import Control.DeepSeq (NFData (rnf), deepseq)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import Data.Coders (cborError)
import Data.Map.Strict (Map)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Typeable (Typeable)
import Data.Word (Word64)
import GHC.Generics (Generic)
import NoThunks.Class (AllowThunksIn (..), NoThunks (..))

-- | A generic metadatum type.
data Metadatum
  = Map ![(Metadatum, Metadatum)]
  | List ![Metadatum]
  | I !Integer
  | B !BS.ByteString
  | S !T.Text
  deriving stock (Int -> Metadatum -> ShowS
[Metadatum] -> ShowS
Metadatum -> String
(Int -> Metadatum -> ShowS)
-> (Metadatum -> String)
-> ([Metadatum] -> ShowS)
-> Show Metadatum
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Metadatum] -> ShowS
$cshowList :: [Metadatum] -> ShowS
show :: Metadatum -> String
$cshow :: Metadatum -> String
showsPrec :: Int -> Metadatum -> ShowS
$cshowsPrec :: Int -> Metadatum -> ShowS
Show, Metadatum -> Metadatum -> Bool
(Metadatum -> Metadatum -> Bool)
-> (Metadatum -> Metadatum -> Bool) -> Eq Metadatum
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Metadatum -> Metadatum -> Bool
$c/= :: Metadatum -> Metadatum -> Bool
== :: Metadatum -> Metadatum -> Bool
$c== :: Metadatum -> Metadatum -> Bool
Eq, Eq Metadatum
Eq Metadatum
-> (Metadatum -> Metadatum -> Ordering)
-> (Metadatum -> Metadatum -> Bool)
-> (Metadatum -> Metadatum -> Bool)
-> (Metadatum -> Metadatum -> Bool)
-> (Metadatum -> Metadatum -> Bool)
-> (Metadatum -> Metadatum -> Metadatum)
-> (Metadatum -> Metadatum -> Metadatum)
-> Ord Metadatum
Metadatum -> Metadatum -> Bool
Metadatum -> Metadatum -> Ordering
Metadatum -> Metadatum -> Metadatum
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
min :: Metadatum -> Metadatum -> Metadatum
$cmin :: Metadatum -> Metadatum -> Metadatum
max :: Metadatum -> Metadatum -> Metadatum
$cmax :: Metadatum -> Metadatum -> Metadatum
>= :: Metadatum -> Metadatum -> Bool
$c>= :: Metadatum -> Metadatum -> Bool
> :: Metadatum -> Metadatum -> Bool
$c> :: Metadatum -> Metadatum -> Bool
<= :: Metadatum -> Metadatum -> Bool
$c<= :: Metadatum -> Metadatum -> Bool
< :: Metadatum -> Metadatum -> Bool
$c< :: Metadatum -> Metadatum -> Bool
compare :: Metadatum -> Metadatum -> Ordering
$ccompare :: Metadatum -> Metadatum -> Ordering
$cp1Ord :: Eq Metadatum
Ord, (forall x. Metadatum -> Rep Metadatum x)
-> (forall x. Rep Metadatum x -> Metadatum) -> Generic Metadatum
forall x. Rep Metadatum x -> Metadatum
forall x. Metadatum -> Rep Metadatum x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Metadatum x -> Metadatum
$cfrom :: forall x. Metadatum -> Rep Metadatum x
Generic)

instance NoThunks Metadatum

instance NFData Metadatum where
  rnf :: Metadatum -> ()
rnf = \case
    Map [(Metadatum, Metadatum)]
m -> [(Metadatum, Metadatum)] -> ()
forall a. NFData a => a -> ()
rnf [(Metadatum, Metadatum)]
m
    List [Metadatum]
l -> [Metadatum] -> ()
forall a. NFData a => a -> ()
rnf [Metadatum]
l
    I Integer
_ -> ()
    B ByteString
_ -> ()
    S Text
_ -> ()

data Metadata era = Metadata'
  { Metadata era -> Map Word64 Metadatum
mdMap :: Map Word64 Metadatum,
    Metadata era -> ByteString
mdBytes :: LBS.ByteString
  }
  deriving (Metadata era -> Metadata era -> Bool
(Metadata era -> Metadata era -> Bool)
-> (Metadata era -> Metadata era -> Bool) -> Eq (Metadata era)
forall era. Metadata era -> Metadata era -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Metadata era -> Metadata era -> Bool
$c/= :: forall era. Metadata era -> Metadata era -> Bool
== :: Metadata era -> Metadata era -> Bool
$c== :: forall era. Metadata era -> Metadata era -> Bool
Eq, Int -> Metadata era -> ShowS
[Metadata era] -> ShowS
Metadata era -> String
(Int -> Metadata era -> ShowS)
-> (Metadata era -> String)
-> ([Metadata era] -> ShowS)
-> Show (Metadata era)
forall era. Int -> Metadata era -> ShowS
forall era. [Metadata era] -> ShowS
forall era. Metadata era -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Metadata era] -> ShowS
$cshowList :: forall era. [Metadata era] -> ShowS
show :: Metadata era -> String
$cshow :: forall era. Metadata era -> String
showsPrec :: Int -> Metadata era -> ShowS
$cshowsPrec :: forall era. Int -> Metadata era -> ShowS
Show, Eq (Metadata era)
Eq (Metadata era)
-> (Metadata era -> Metadata era -> Ordering)
-> (Metadata era -> Metadata era -> Bool)
-> (Metadata era -> Metadata era -> Bool)
-> (Metadata era -> Metadata era -> Bool)
-> (Metadata era -> Metadata era -> Bool)
-> (Metadata era -> Metadata era -> Metadata era)
-> (Metadata era -> Metadata era -> Metadata era)
-> Ord (Metadata era)
Metadata era -> Metadata era -> Bool
Metadata era -> Metadata era -> Ordering
Metadata era -> Metadata era -> Metadata era
forall era. Eq (Metadata era)
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
forall era. Metadata era -> Metadata era -> Bool
forall era. Metadata era -> Metadata era -> Ordering
forall era. Metadata era -> Metadata era -> Metadata era
min :: Metadata era -> Metadata era -> Metadata era
$cmin :: forall era. Metadata era -> Metadata era -> Metadata era
max :: Metadata era -> Metadata era -> Metadata era
$cmax :: forall era. Metadata era -> Metadata era -> Metadata era
>= :: Metadata era -> Metadata era -> Bool
$c>= :: forall era. Metadata era -> Metadata era -> Bool
> :: Metadata era -> Metadata era -> Bool
$c> :: forall era. Metadata era -> Metadata era -> Bool
<= :: Metadata era -> Metadata era -> Bool
$c<= :: forall era. Metadata era -> Metadata era -> Bool
< :: Metadata era -> Metadata era -> Bool
$c< :: forall era. Metadata era -> Metadata era -> Bool
compare :: Metadata era -> Metadata era -> Ordering
$ccompare :: forall era. Metadata era -> Metadata era -> Ordering
$cp1Ord :: forall era. Eq (Metadata era)
Ord, (forall x. Metadata era -> Rep (Metadata era) x)
-> (forall x. Rep (Metadata era) x -> Metadata era)
-> Generic (Metadata era)
forall x. Rep (Metadata era) x -> Metadata era
forall x. Metadata era -> Rep (Metadata era) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall era x. Rep (Metadata era) x -> Metadata era
forall era x. Metadata era -> Rep (Metadata era) x
$cto :: forall era x. Rep (Metadata era) x -> Metadata era
$cfrom :: forall era x. Metadata era -> Rep (Metadata era) x
Generic)
  deriving (Context -> Metadata era -> IO (Maybe ThunkInfo)
Proxy (Metadata era) -> String
(Context -> Metadata era -> IO (Maybe ThunkInfo))
-> (Context -> Metadata era -> IO (Maybe ThunkInfo))
-> (Proxy (Metadata era) -> String)
-> NoThunks (Metadata era)
forall era.
Typeable era =>
Context -> Metadata era -> IO (Maybe ThunkInfo)
forall era. Typeable era => Proxy (Metadata era) -> String
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy (Metadata era) -> String
$cshowTypeOf :: forall era. Typeable era => Proxy (Metadata era) -> String
wNoThunks :: Context -> Metadata era -> IO (Maybe ThunkInfo)
$cwNoThunks :: forall era.
Typeable era =>
Context -> Metadata era -> IO (Maybe ThunkInfo)
noThunks :: Context -> Metadata era -> IO (Maybe ThunkInfo)
$cnoThunks :: forall era.
Typeable era =>
Context -> Metadata era -> IO (Maybe ThunkInfo)
NoThunks) via AllowThunksIn '["mdBytes"] (Metadata era)

instance NFData (Metadata era) where
  rnf :: Metadata era -> ()
rnf Metadata era
m = Metadata era -> Map Word64 Metadatum
forall era. Metadata era -> Map Word64 Metadatum
mdMap Metadata era
m Map Word64 Metadatum -> () -> ()
forall a b. NFData a => a -> b -> b
`deepseq` ByteString -> ()
forall a. NFData a => a -> ()
rnf (Metadata era -> ByteString
forall era. Metadata era -> ByteString
mdBytes Metadata era
m)

-- Usually we derive SafetToHash instances, but since Metadata preserves its serialisation
-- bytes we can just extract them here, and make an explicit SafeToHash instance.

instance SafeToHash (Metadata era) where
  originalBytes :: Metadata era -> ByteString
originalBytes = ByteString -> ByteString
LBS.toStrict (ByteString -> ByteString)
-> (Metadata era -> ByteString) -> Metadata era -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Metadata era -> ByteString
forall era. Metadata era -> ByteString
mdBytes

instance c ~ Crypto era => HashAnnotated (Metadata era) EraIndependentAuxiliaryData c

hashMetadata :: Era era => Metadata era -> SafeHash (Crypto era) EraIndependentAuxiliaryData
hashMetadata :: Metadata era -> SafeHash (Crypto era) EraIndependentAuxiliaryData
hashMetadata = Metadata era -> SafeHash (Crypto era) EraIndependentAuxiliaryData
forall c i x.
(HasAlgorithm c, HashAnnotated x i c) =>
x -> SafeHash c i
hashAnnotated

pattern Metadata :: Map Word64 Metadatum -> Metadata era
pattern $bMetadata :: Map Word64 Metadatum -> Metadata era
$mMetadata :: forall r era.
Metadata era -> (Map Word64 Metadatum -> r) -> (Void# -> r) -> r
Metadata m <-
  Metadata' m _
  where
    Metadata Map Word64 Metadatum
m =
      let bytes :: ByteString
bytes = Encoding -> ByteString
serializeEncoding (Encoding -> ByteString) -> Encoding -> ByteString
forall a b. (a -> b) -> a -> b
$ Map Word64 Metadatum -> Encoding
forall a b. (ToCBOR a, ToCBOR b) => Map a b -> Encoding
mapToCBOR Map Word64 Metadatum
m
       in Map Word64 Metadatum -> ByteString -> Metadata era
forall era. Map Word64 Metadatum -> ByteString -> Metadata era
Metadata' Map Word64 Metadatum
m ByteString
bytes

{-# COMPLETE Metadata #-}

instance Typeable era => ToCBOR (Metadata era) where
  toCBOR :: Metadata era -> Encoding
toCBOR = ByteString -> Encoding
encodePreEncoded (ByteString -> Encoding)
-> (Metadata era -> ByteString) -> Metadata era -> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
LBS.toStrict (ByteString -> ByteString)
-> (Metadata era -> ByteString) -> Metadata era -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Metadata era -> ByteString
forall era. Metadata era -> ByteString
mdBytes

instance Typeable era => FromCBOR (Annotator (Metadata era)) where
  fromCBOR :: Decoder s (Annotator (Metadata era))
fromCBOR = do
    (Map Word64 Metadatum
m, Annotator ByteString
bytesAnn) <- Decoder s (Map Word64 Metadatum)
-> Decoder s (Map Word64 Metadatum, Annotator ByteString)
forall s a. Decoder s a -> Decoder s (a, Annotator ByteString)
withSlice Decoder s (Map Word64 Metadatum)
forall a b s.
(Ord a, FromCBOR a, FromCBOR b) =>
Decoder s (Map a b)
mapFromCBOR
    Annotator (Metadata era) -> Decoder s (Annotator (Metadata era))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Annotator (Metadata era) -> Decoder s (Annotator (Metadata era)))
-> Annotator (Metadata era) -> Decoder s (Annotator (Metadata era))
forall a b. (a -> b) -> a -> b
$ Map Word64 Metadatum -> ByteString -> Metadata era
forall era. Map Word64 Metadatum -> ByteString -> Metadata era
Metadata' Map Word64 Metadatum
m (ByteString -> Metadata era)
-> Annotator ByteString -> Annotator (Metadata era)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Annotator ByteString
bytesAnn

instance ToCBOR Metadatum where
  toCBOR :: Metadatum -> Encoding
toCBOR = Metadatum -> Encoding
encodeMetadatum

instance FromCBOR Metadatum where
  fromCBOR :: Decoder s Metadatum
fromCBOR = Decoder s Metadatum
forall s. Decoder s Metadatum
decodeMetadatum

-- Validation of sizes

validMetadatum :: Metadatum -> Bool
-- The integer size/representation checks are enforced in the decoder.
validMetadatum :: Metadatum -> Bool
validMetadatum (I Integer
_) = Bool
True
validMetadatum (B ByteString
b) = ByteString -> Int
BS.length ByteString
b Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
64
validMetadatum (S Text
s) = ByteString -> Int
BS.length (Text -> ByteString
T.encodeUtf8 Text
s) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
64
validMetadatum (List [Metadatum]
xs) = (Metadatum -> Bool) -> [Metadatum] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Metadatum -> Bool
validMetadatum [Metadatum]
xs
validMetadatum (Map [(Metadatum, Metadatum)]
kvs) =
  ((Metadatum, Metadatum) -> Bool)
-> [(Metadatum, Metadatum)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all
    ( \(Metadatum
k, Metadatum
v) ->
        Metadatum -> Bool
validMetadatum Metadatum
k
          Bool -> Bool -> Bool
&& Metadatum -> Bool
validMetadatum Metadatum
v
    )
    [(Metadatum, Metadatum)]
kvs

-------------------------------------------------------------------------------
-- CBOR encoding and decoding

encodeMetadatum :: Metadatum -> CBOR.Encoding
encodeMetadatum :: Metadatum -> Encoding
encodeMetadatum (I Integer
n) = Integer -> Encoding
CBOR.encodeInteger Integer
n
encodeMetadatum (B ByteString
b) = ByteString -> Encoding
CBOR.encodeBytes ByteString
b
encodeMetadatum (S Text
s) = Text -> Encoding
CBOR.encodeString Text
s
encodeMetadatum (List [Metadatum]
xs) =
  Word -> Encoding
CBOR.encodeListLen (Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Metadatum] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Metadatum]
xs))
    Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [Encoding] -> Encoding
forall a. Monoid a => [a] -> a
mconcat
      [ Metadatum -> Encoding
encodeMetadatum Metadatum
x
        | Metadatum
x <- [Metadatum]
xs
      ]
encodeMetadatum (Map [(Metadatum, Metadatum)]
kvs) =
  Word -> Encoding
CBOR.encodeMapLen (Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([(Metadatum, Metadatum)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Metadatum, Metadatum)]
kvs))
    Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [Encoding] -> Encoding
forall a. Monoid a => [a] -> a
mconcat
      [ Metadatum -> Encoding
encodeMetadatum Metadatum
k Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Metadatum -> Encoding
encodeMetadatum Metadatum
v
        | (Metadatum
k, Metadatum
v) <- [(Metadatum, Metadatum)]
kvs
      ]

-- | Decode a transaction matadatum value from its CBOR representation.
--
-- The CDDL for the CBOR is
--
-- > transaction_metadatum =
-- >     int
-- >   / bytes .size (0..64)
-- >   / text .size (0..64)
-- >   / [ * transaction_metadatum ]
-- >   / { * transaction_metadatum => transaction_metadatum }
--
-- We do not require canonical representations, just like everywhere else
-- on the chain. We accept both definte and indefinite representations.
--
-- The byte and string length checks are not enforced in this decoder, but
decodeMetadatum :: Decoder s Metadatum
decodeMetadatum :: Decoder s Metadatum
decodeMetadatum = do
  TokenType
tkty <- Decoder s TokenType
forall s. Decoder s TokenType
CBOR.peekTokenType
  case TokenType
tkty of
    -- We support -(2^64-1) .. 2^64-1, but not big integers
    -- not even big integer representation of values within range
    TokenType
CBOR.TypeUInt -> Integer -> Metadatum
I (Integer -> Metadatum) -> Decoder s Integer -> Decoder s Metadatum
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Integer
forall s. Decoder s Integer
CBOR.decodeInteger
    TokenType
CBOR.TypeUInt64 -> Integer -> Metadatum
I (Integer -> Metadatum) -> Decoder s Integer -> Decoder s Metadatum
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Integer
forall s. Decoder s Integer
CBOR.decodeInteger
    TokenType
CBOR.TypeNInt -> Integer -> Metadatum
I (Integer -> Metadatum) -> Decoder s Integer -> Decoder s Metadatum
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Integer
forall s. Decoder s Integer
CBOR.decodeInteger
    TokenType
CBOR.TypeNInt64 -> Integer -> Metadatum
I (Integer -> Metadatum) -> Decoder s Integer -> Decoder s Metadatum
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Integer
forall s. Decoder s Integer
CBOR.decodeInteger
    -- Note that we do not enforce byte and string lengths here in the
    -- decoder. We enforce that in the tx validation rules.
    TokenType
CBOR.TypeBytes -> do
      !ByteString
x <- Decoder s ByteString
forall s. Decoder s ByteString
CBOR.decodeBytes
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> Metadatum
B ByteString
x)
    TokenType
CBOR.TypeBytesIndef -> do
      Decoder s ()
forall s. Decoder s ()
CBOR.decodeBytesIndef
      !ByteString
x <- [ByteString] -> Decoder s ByteString
forall s. [ByteString] -> Decoder s ByteString
decodeBytesIndefLen []
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> Metadatum
B ByteString
x)
    TokenType
CBOR.TypeString -> do
      !Text
x <- Decoder s Text
forall s. Decoder s Text
CBOR.decodeString
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Metadatum
S Text
x)
    TokenType
CBOR.TypeStringIndef -> do
      Decoder s ()
forall s. Decoder s ()
CBOR.decodeStringIndef
      !Text
x <- [Text] -> Decoder s Text
forall s. [Text] -> Decoder s Text
decodeStringIndefLen []
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Metadatum
S Text
x)

    -- Why does it work to do the same thing here for 32 and 64bit list len
    -- tokens? On 32bit systems the decodeListLen will fail if the value
    -- really is bigger than maxBound :: Int, and on 64bit systems if a value
    -- that big is provided, then it'll fail when it runs out of input for
    -- such a big list. Hence we can do exactly the same for the 32bit and
    -- 64bit cases.
    TokenType
CBOR.TypeListLen -> do
      Int
n <- Decoder s Int
forall s. Decoder s Int
CBOR.decodeListLen
      [Metadatum]
xs <- Int -> [Metadatum] -> Decoder s [Metadatum]
forall s. Int -> [Metadatum] -> Decoder s [Metadatum]
decodeListN Int
n []
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return ([Metadatum] -> Metadatum
List [Metadatum]
xs)
    TokenType
CBOR.TypeListLen64 -> do
      Int
n <- Decoder s Int
forall s. Decoder s Int
CBOR.decodeListLen
      [Metadatum]
xs <- Int -> [Metadatum] -> Decoder s [Metadatum]
forall s. Int -> [Metadatum] -> Decoder s [Metadatum]
decodeListN Int
n []
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return ([Metadatum] -> Metadatum
List [Metadatum]
xs)
    TokenType
CBOR.TypeListLenIndef -> do
      Decoder s ()
forall s. Decoder s ()
CBOR.decodeListLenIndef
      [Metadatum]
xs <- [Metadatum] -> Decoder s [Metadatum]
forall s. [Metadatum] -> Decoder s [Metadatum]
decodeListIndefLen []
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return ([Metadatum] -> Metadatum
List [Metadatum]
xs)

    -- Same logic applies as above for large lists.
    TokenType
CBOR.TypeMapLen -> do
      Int
n <- Decoder s Int
forall s. Decoder s Int
CBOR.decodeMapLen
      [(Metadatum, Metadatum)]
xs <- Int
-> [(Metadatum, Metadatum)] -> Decoder s [(Metadatum, Metadatum)]
forall s.
Int
-> [(Metadatum, Metadatum)] -> Decoder s [(Metadatum, Metadatum)]
decodeMapN Int
n []
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Metadatum, Metadatum)] -> Metadatum
Map [(Metadatum, Metadatum)]
xs)
    TokenType
CBOR.TypeMapLen64 -> do
      Int
n <- Decoder s Int
forall s. Decoder s Int
CBOR.decodeMapLen
      [(Metadatum, Metadatum)]
xs <- Int
-> [(Metadatum, Metadatum)] -> Decoder s [(Metadatum, Metadatum)]
forall s.
Int
-> [(Metadatum, Metadatum)] -> Decoder s [(Metadatum, Metadatum)]
decodeMapN Int
n []
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Metadatum, Metadatum)] -> Metadatum
Map [(Metadatum, Metadatum)]
xs)
    TokenType
CBOR.TypeMapLenIndef -> do
      Decoder s ()
forall s. Decoder s ()
CBOR.decodeMapLenIndef
      [(Metadatum, Metadatum)]
xs <- [(Metadatum, Metadatum)] -> Decoder s [(Metadatum, Metadatum)]
forall s.
[(Metadatum, Metadatum)] -> Decoder s [(Metadatum, Metadatum)]
decodeMapIndefLen []
      Metadatum -> Decoder s Metadatum
forall (m :: * -> *) a. Monad m => a -> m a
return ([(Metadatum, Metadatum)] -> Metadatum
Map [(Metadatum, Metadatum)]
xs)
    TokenType
_ -> Text -> Decoder s Metadatum
forall s a. Text -> Decoder s a
decodeError (Text
"Unsupported CBOR token type " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (TokenType -> String
forall a. Show a => a -> String
show TokenType
tkty))
  where
    decodeError :: Text -> Decoder s a
decodeError Text
msg = DecoderError -> Decoder s a
forall e s a. Buildable e => e -> Decoder s a
cborError (Text -> Text -> DecoderError
DecoderErrorCustom Text
"metadata" Text
msg)

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

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

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

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

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

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