Skip to content

Commit 177d9ed

Browse files
committed
Introduce forceCanonical function to create canonical encoding
1 parent 1db5ab2 commit 177d9ed

File tree

1 file changed

+23
-0
lines changed
  • scls-cbor/src/Cardano/SCLS/CBOR/Canonical

1 file changed

+23
-0
lines changed

scls-cbor/src/Cardano/SCLS/CBOR/Canonical/Encoder.hs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ module Cardano.SCLS.CBOR.Canonical.Encoder (
1515
encodeAsMap,
1616
SomeEncodablePair (..),
1717
mkEncodablePair,
18+
forceCanonical,
1819
) where
1920

2021
import Cardano.SCLS.CBOR.Canonical (CanonicalEncoding (getRawEncoding), assumeCanonicalEncoding)
2122
import Codec.CBOR.ByteArray.Sliced qualified as BAS
2223
import Codec.CBOR.Encoding qualified as E
24+
import Codec.CBOR.FlatTerm (fromFlatTerm, toFlatTerm)
2325
import Codec.CBOR.Term
2426
import Codec.CBOR.Write (toStrictByteString)
2527
import Data.Array.Byte qualified as Prim
@@ -38,6 +40,7 @@ import Data.Text (Text)
3840
import Data.Text.Lazy qualified as TL
3941
import Data.Traversable (mapAccumL)
4042
import Data.Word
43+
import GHC.Stack (HasCallStack)
4144
import GHC.TypeLits
4245

4346
-- | Encode data to CBOR corresponding with the SCLS format.
@@ -361,3 +364,23 @@ in the canonical format
361364
toCanonicalTagged :: proxy (v :: Symbol) -> Word64 -> Term -> CanonicalEncoding
362365
toCanonicalTagged v 258 (TList ns) = toCanonicalCBOR v (Set.fromList ns)
363366
toCanonicalTagged 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

Comments
 (0)