{-# LANGUAGE FlexibleContexts #-}

module Cardano.Ledger.Binary (
  module Cardano.Ledger.Binary.Decoding,
  module Cardano.Ledger.Binary.Encoding,
  module Cardano.Ledger.Binary.Group,
  module Cardano.Ledger.Binary.Version,
  module Cardano.Ledger.Binary.Plain,
  Term (..),
  C.DeserialiseFailure (..),
  translateViaCBORAnnotator,
)
where

import Cardano.Ledger.Binary.Decoding
import Cardano.Ledger.Binary.Encoding
import Cardano.Ledger.Binary.Group
import Cardano.Ledger.Binary.Plain (FromCBOR (fromCBOR), ToCBOR (toCBOR))
import qualified Cardano.Ledger.Binary.Plain as Plain
import Cardano.Ledger.Binary.Version
import qualified Codec.CBOR.Read as C (DeserialiseFailure (..))
import Codec.CBOR.Term (Term (..))
import Control.Monad.Except (Except, MonadError (throwError))
import Data.Text (Text)

-- | Translation function between values through a related binary representation. This
-- function allows you to translate one type into another (or the same one) through their
-- common binary format. It is possible for the source type to be encoded with a different
-- version than the version that will be used for decoding. This is useful for types that
-- build upon one another and are "upgradeable" through their binary representation. It is
-- important to note that the deserialization will happen with `Annotator`, since that is
-- usually the way we deserialize upgradeable types that live on chain. Moreover, encoding
-- does not require a version, because memoized types that were decoded with annotation
-- will have the bytes retained and thus will have the `ToCBOR` instance.
translateViaCBORAnnotator ::
  (ToCBOR a, DecCBOR (Annotator b)) =>
  -- | Version that will be used for deserialization
  Version ->
  Text ->
  a ->
  Except DecoderError b
translateViaCBORAnnotator :: forall a b.
(ToCBOR a, DecCBOR (Annotator b)) =>
Version -> Text -> a -> Except DecoderError b
translateViaCBORAnnotator Version
versionDeserialize Text
name a
x =
  case forall a.
Version
-> Text
-> (forall s. Decoder s (Annotator a))
-> ByteString
-> Either DecoderError a
decodeFullAnnotator Version
versionDeserialize Text
name forall a s. DecCBOR a => Decoder s a
decCBOR (forall a. ToCBOR a => a -> ByteString
Plain.serialize a
x) of
    Right b
newx -> forall (f :: * -> *) a. Applicative f => a -> f a
pure b
newx
    Left DecoderError
decoderError -> forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError DecoderError
decoderError