@@ -15,11 +15,13 @@ module Cardano.SCLS.CBOR.Canonical.Encoder (
1515 encodeAsMap ,
1616 SomeEncodablePair (.. ),
1717 mkEncodablePair ,
18+ forceCanonical ,
1819) where
1920
2021import Cardano.SCLS.CBOR.Canonical (CanonicalEncoding (getRawEncoding ), assumeCanonicalEncoding )
2122import Codec.CBOR.ByteArray.Sliced qualified as BAS
2223import Codec.CBOR.Encoding qualified as E
24+ import Codec.CBOR.FlatTerm (fromFlatTerm , toFlatTerm )
2325import Codec.CBOR.Term
2426import Codec.CBOR.Write (toStrictByteString )
2527import Data.Array.Byte qualified as Prim
@@ -38,6 +40,7 @@ import Data.Text (Text)
3840import Data.Text.Lazy qualified as TL
3941import Data.Traversable (mapAccumL )
4042import Data.Word
43+ import GHC.Stack (HasCallStack )
4144import GHC.TypeLits
4245
4346-- | Encode data to CBOR corresponding with the SCLS format.
@@ -361,3 +364,23 @@ in the canonical format
361364toCanonicalTagged :: proxy (v :: Symbol ) -> Word64 -> Term -> CanonicalEncoding
362365toCanonicalTagged v 258 (TList ns) = toCanonicalCBOR v (Set. fromList ns)
363366toCanonicalTagged v t term = assumeCanonicalEncoding (E. encodeTag64 t) <> toCanonicalCBOR v term
367+
368+ {- |
369+ Converts any CBOR encoding to its canonical form by first decoding it to a generic
370+ CBOR 'Term' and then re-encoding it canonically according to the Cardano specification.
371+
372+ **When to use:**
373+
374+ Use this function as a last resort when you have a CBOR encoding ('E.Encoding') that may not
375+ be in canonical form and you need to ensure canonicalization. It is primarily intended for
376+ situations where you do not have a more direct or efficient way to produce canonical CBOR.
377+
378+ **Caveats:**
379+
380+ This function is slow because it fully decodes the input encoding and then re-encodes it.
381+ Avoid using it in performance-critical code paths.
382+ -}
383+ forceCanonical :: (HasCallStack ) => proxy (v :: Symbol ) -> E. Encoding -> CanonicalEncoding
384+ forceCanonical p x = case fromFlatTerm decodeTerm (toFlatTerm x) of
385+ Left e -> error $ " forceCanonical: unable to decode term, generated by Encoding: " <> show e
386+ Right y -> toCanonicalCBOR p y
0 commit comments