{-# OPTIONS_GHC -fno-specialize #-}
{-# OPTIONS_HADDOCK prune #-}

-- | An on-chain implementation of [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949): Concise Binary Object Representation (CBOR).
--
-- This is generally something one would want to avoid as the memory and CPU
-- budgets on-chain are heavily limited. However, there are scenarios when one
-- needs to serialise some higher level data-type into binary. This library
-- provides an efficient way of doing it.
--
-- = How to use
--
-- Let's start with some relatively simple type:
--
-- @
-- data Foo = Foo
--  { bar :: Bool
--  , baz :: Integer
--  }
-- @
--
-- From there, one can define an 'Encoding' for the @Foo@ data-type. This is a
-- simple record of unary constructors, so using a 2-tuple should do. Note that
-- 'Encoding' is a 'Semigroup', and thus, they are easily composed using the
-- concatenation operator ('<>').
--
-- @
-- encodeFoo :: Foo -> Encoding
-- encodeFoo Foo{bar,baz} =
--   encodeListLen 2
--     <> encodeBool bar
--     <> encodeInteger baz
-- @
--
-- Then, any 'Encoding' can be turned into a 'BuiltinByteString' using: 'encodingToBuiltinByteString'.
-- For instance, one could define:
--
-- @
-- serialiseFoo :: Foo -> BuiltinByteString
-- serialiseFoo = encodingToBuiltinByteString . encodeFoo
-- @
module Plutus.Codec.CBOR.Encoding (
  -- * Encoding
  Encoding,
  encodingToBuiltinByteString,

  -- * Basic Types
  encodeBool,
  encodeInteger,
  encodeByteString,
  encodeString,
  encodeNull,

  -- * Data-Structures

  -- ** Finite Structures
  encodeMaybe,
  encodeListLen,
  encodeList,
  encodeMapLen,
  encodeMap,

  -- ** Indefinite Structures
  encodeBreak,
  encodeBeginList,
  encodeListIndef,
  encodeBeginMap,
  encodeMapIndef,

  -- * Tags
  encodeTag,

  -- * Backdoor / Unsafe
  unsafeEncodeRaw,
) where

import PlutusTx.Prelude

import PlutusTx.AssocMap (Map)
import PlutusTx.AssocMap qualified as Map
import PlutusTx.Builtins (subtractInteger)

-- * Encoding

-- | An opaque 'Encoding' type. See also 'encodingToBuiltinByteString'.
newtype Encoding = Encoding (BuiltinByteString -> BuiltinByteString)

instance Semigroup Encoding where
  (Encoding BuiltinByteString -> BuiltinByteString
a) <> :: Encoding -> Encoding -> Encoding
<> (Encoding BuiltinByteString -> BuiltinByteString
b) = (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (BuiltinByteString -> BuiltinByteString
a (BuiltinByteString -> BuiltinByteString)
-> (BuiltinByteString -> BuiltinByteString)
-> BuiltinByteString
-> BuiltinByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinByteString -> BuiltinByteString
b)

instance Monoid Encoding where
  mempty :: Encoding
mempty = (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding BuiltinByteString -> BuiltinByteString
forall a. a -> a
id

-- | Runs an encoder and produce a 'BuiltinByteString'.
encodingToBuiltinByteString :: Encoding -> BuiltinByteString
encodingToBuiltinByteString :: Encoding -> BuiltinByteString
encodingToBuiltinByteString (Encoding BuiltinByteString -> BuiltinByteString
runEncoder) =
  BuiltinByteString -> BuiltinByteString
runEncoder BuiltinByteString
emptyByteString
{-# INLINEABLE encodingToBuiltinByteString #-}

-- * Basic types

-- | Encode a 'Bool' as a CBOR type-07 major type.
encodeBool :: Bool -> Encoding
encodeBool :: Bool -> Encoding
encodeBool = \case
  Bool
False ->
    (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned8 Integer
244)
  Bool
True ->
    (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned8 Integer
245)
{-# INLINEABLE encodeBool #-}

-- | Encode an 'Integer' as a CBOR type-00 or type-01 (negative) number.
--
-- Note (1): The 'Encoding' is of variable-length, larger numbers are larger to
-- encode.
--
-- Note (2): This can only encode numbers up to @2^64 - 1@ and down to @-2^63@
encodeInteger :: Integer -> Encoding
encodeInteger :: Integer -> Encoding
encodeInteger Integer
n
  | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 =
      (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned Integer
1 (Integer -> Integer -> Integer
subtractInteger Integer
0 Integer
n Integer -> Integer -> Integer
forall a. AdditiveGroup a => a -> a -> a
- Integer
1))
  | Bool
otherwise =
      (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned Integer
0 Integer
n)
{-# INLINEABLE encodeInteger #-}

-- | Encode a 'BuiltinByteString' as a CBOR type-02 major type.
encodeByteString :: BuiltinByteString -> Encoding
encodeByteString :: BuiltinByteString -> Encoding
encodeByteString BuiltinByteString
bytes =
  (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned Integer
2 (BuiltinByteString -> Integer
lengthOfByteString BuiltinByteString
bytes) (BuiltinByteString -> BuiltinByteString)
-> (BuiltinByteString -> BuiltinByteString)
-> BuiltinByteString
-> BuiltinByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinByteString -> BuiltinByteString -> BuiltinByteString
appendByteString BuiltinByteString
bytes)
{-# INLINEABLE encodeByteString #-}

-- | Encode a 'BuiltinString' as a CBOR type-03 major type.
encodeString :: BuiltinString -> Encoding
encodeString :: BuiltinString -> Encoding
encodeString (BuiltinString -> BuiltinByteString
encodeUtf8 -> BuiltinByteString
bytes) =
  (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned Integer
3 (BuiltinByteString -> Integer
lengthOfByteString BuiltinByteString
bytes) (BuiltinByteString -> BuiltinByteString)
-> (BuiltinByteString -> BuiltinByteString)
-> BuiltinByteString
-> BuiltinByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinByteString -> BuiltinByteString -> BuiltinByteString
appendByteString BuiltinByteString
bytes)
{-# INLINEABLE encodeString #-}

-- | Encode a null character, useful to encode optional values.
encodeNull :: Encoding
encodeNull :: Encoding
encodeNull =
  (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> BuiltinByteString -> BuiltinByteString
consByteString Integer
246)
{-# INLINEABLE encodeNull #-}

-- * Data-Structure

-- | Encode a indefinite list or map termination. This must come (not
-- necessarily immediately) after an 'encodeListIndef' or 'encodeMapIndef'
encodeBreak :: Encoding
encodeBreak :: Encoding
encodeBreak = (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> BuiltinByteString -> BuiltinByteString
consByteString Integer
0xFF)
{-# INLINEABLE encodeBreak #-}

-- | Declare a list of fixed size. Each element of the list must then be
-- separately provided via appending them ('Encoding' is a 'Semigroup').
--
-- This is useful to construct non-uniform arrays where elements may have
-- different types. For uniform list, see 'encodeList'.
--
-- @
-- -- Encoding (14, 42) as a finite list...
-- encodeListLen 2
--   <> encodeInteger 14
--   <> encodeInteger 42
-- @
encodeListLen :: Integer -> Encoding
encodeListLen :: Integer -> Encoding
encodeListLen = (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding ((BuiltinByteString -> BuiltinByteString) -> Encoding)
-> (Integer -> BuiltinByteString -> BuiltinByteString)
-> Integer
-> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned Integer
4
{-# INLINEABLE encodeListLen #-}

-- | Declare a list of indefinite size. Each element of the list must then be
-- separately provided via appending them ('Encoding' is a 'Semigroup').
--
-- This is useful to construct non-uniform arrays where elements may have
-- different types. For uniform list, see 'encodeListIndef'.
--
-- @
-- -- Encoding (14, 42) as an indefinite list...
-- encodeBeginList
--   <> encodeInteger 14
--   <> encodeInteger 42
--   <> encodeBreak
-- @
encodeBeginList :: Encoding
encodeBeginList :: Encoding
encodeBeginList = (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> Integer -> BuiltinByteString -> BuiltinByteString
withMajorType Integer
4 Integer
31)
{-# INLINEABLE encodeBeginList #-}

-- | Shorthand for encoding a uniform list. Note that CBOR supports non-uniform
-- lists (i.e. n-tuples) for which one should use 'encodeListLen' or
-- 'encodeBeginList' / 'encodeBreak'.
encodeList :: (a -> Encoding) -> [a] -> Encoding
encodeList :: forall a. (a -> Encoding) -> [a] -> Encoding
encodeList a -> Encoding
encodeElem =
  Integer -> Encoding -> [a] -> Encoding
step Integer
0 Encoding
forall a. Monoid a => a
mempty
 where
  step :: Integer -> Encoding -> [a] -> Encoding
step Integer
n Encoding
bs = \case
    [] -> Integer -> Encoding
encodeListLen Integer
n Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Encoding
bs
    (a
e : [a]
q) -> Integer -> Encoding -> [a] -> Encoding
step (Integer
n Integer -> Integer -> Integer
forall a. AdditiveSemigroup a => a -> a -> a
+ Integer
1) (Encoding
bs Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> a -> Encoding
encodeElem a
e) [a]
q
{-# INLINEABLE encodeList #-}

-- | Shorthand for encoding uniform list of indefinite sizes. Note that CBOR
-- supports non-uniform indefinite list (i.e. n-tuples) for which one should use
-- 'encodeListLen' or 'encodeBeginList' / 'encodeBreak'.
encodeListIndef :: (a -> Encoding) -> [a] -> Encoding
encodeListIndef :: forall a. (a -> Encoding) -> [a] -> Encoding
encodeListIndef a -> Encoding
encodeElem [a]
es =
  Encoding
encodeBeginList Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [a] -> Encoding
step [a]
es
 where
  step :: [a] -> Encoding
step = \case
    [] -> Encoding
encodeBreak
    (a
e : [a]
q) -> a -> Encoding
encodeElem a
e Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [a] -> Encoding
step [a]
q
{-# INLINEABLE encodeListIndef #-}

-- | Declare a map of fixed size. Each key/value pair of the map must then
-- be separately provided via appending them ('Encoding' is a 'Semigroup').
--
-- This is useful to construct non-uniform maps where keys and values may have
-- different types. For uniform maps, see 'encodeMap'.
--
-- @
-- -- Encoding { 14: b'1abc', 42: b'0000' } as a finite map...
-- encodeMapLen 2
--   <> encodeInteger 14 <> encodeByteString "1abc"
--   <> encodeInteger 42 <> encodeByteString "0000"
-- @
encodeMapLen :: Integer -> Encoding
encodeMapLen :: Integer -> Encoding
encodeMapLen = (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding ((BuiltinByteString -> BuiltinByteString) -> Encoding)
-> (Integer -> BuiltinByteString -> BuiltinByteString)
-> Integer
-> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned Integer
5
{-# INLINEABLE encodeMapLen #-}

-- | Declare a map of indefinite size. Each key/value pair of the map must then
-- be separately provided via appending them ('Encoding' is a 'Semigroup').
--
-- This is useful to construct non-uniform maps where keys and values may have
-- different types. For uniform maps, see 'encodeMap'.
--
-- @
-- -- Encoding { 14: b'1abc', 42: b'0000' } as a finite map...
-- encodeBeginMap
--   <> encodeInteger 14 <> encodeByteString "1abc"
--   <> encodeInteger 42 <> encodeByteString "0000"
--   <> encodeBreak
-- @
encodeBeginMap :: Encoding
encodeBeginMap :: Encoding
encodeBeginMap = (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding (Integer -> Integer -> BuiltinByteString -> BuiltinByteString
withMajorType Integer
5 Integer
31)
{-# INLINEABLE encodeBeginMap #-}

-- | Shorthand for encoding a uniform map of fixed size.
--
-- see also: 'encodeMapLen' / 'encodeBreak' for non-uniform maps.
encodeMap :: (k -> Encoding) -> (v -> Encoding) -> Map k v -> Encoding
encodeMap :: forall k v.
(k -> Encoding) -> (v -> Encoding) -> Map k v -> Encoding
encodeMap k -> Encoding
encodeKey v -> Encoding
encodeValue =
  Integer -> Encoding -> [(k, v)] -> Encoding
step Integer
0 Encoding
forall a. Monoid a => a
mempty ([(k, v)] -> Encoding)
-> (Map k v -> [(k, v)]) -> Map k v -> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map k v -> [(k, v)]
forall k v. Map k v -> [(k, v)]
Map.toList
 where
  step :: Integer -> Encoding -> [(k, v)] -> Encoding
step Integer
n Encoding
bs = \case
    [] -> Integer -> Encoding
encodeMapLen Integer
n Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> Encoding
bs
    ((k
k, v
v) : [(k, v)]
q) -> Integer -> Encoding -> [(k, v)] -> Encoding
step (Integer
n Integer -> Integer -> Integer
forall a. AdditiveSemigroup a => a -> a -> a
+ Integer
1) (Encoding
bs Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> k -> Encoding
encodeKey k
k Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> v -> Encoding
encodeValue v
v) [(k, v)]
q
{-# INLINEABLE encodeMap #-}

-- | Shorthand for encoding a uniform map of indefinite size.
--
-- see also: 'encodeBeginMap' / 'encodeBreak' for non-uniform maps.
encodeMapIndef :: (k -> Encoding) -> (v -> Encoding) -> Map k v -> Encoding
encodeMapIndef :: forall k v.
(k -> Encoding) -> (v -> Encoding) -> Map k v -> Encoding
encodeMapIndef k -> Encoding
encodeKey v -> Encoding
encodeValue Map k v
m =
  Encoding
encodeBeginMap Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [(k, v)] -> Encoding
step (Map k v -> [(k, v)]
forall k v. Map k v -> [(k, v)]
Map.toList Map k v
m)
 where
  step :: [(k, v)] -> Encoding
step = \case
    [] -> Encoding
encodeBreak
    ((k
k, v
v) : [(k, v)]
q) -> k -> Encoding
encodeKey k
k Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> v -> Encoding
encodeValue v
v Encoding -> Encoding -> Encoding
forall a. Semigroup a => a -> a -> a
<> [(k, v)] -> Encoding
step [(k, v)]
q
{-# INLINEABLE encodeMapIndef #-}

-- | Helper for optionally encoding a type. Note that in the @Nothing@ case,
-- this is a no-op.
encodeMaybe :: (a -> Encoding) -> Maybe a -> Encoding
encodeMaybe :: forall a. (a -> Encoding) -> Maybe a -> Encoding
encodeMaybe a -> Encoding
encode = \case
  Maybe a
Nothing -> (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding BuiltinByteString -> BuiltinByteString
forall a. a -> a
id
  Just a
a -> a -> Encoding
encode a
a
{-# INLINEABLE encodeMaybe #-}

-- * Tags

-- | Encode a CBOR-tag as a major type-06.
--
-- Well known tags:
--
-- +-----+-------------------------------------+--------------+
-- | Tag | Description                         | Type         |
-- +-----+-------------------------------------+--------------+
-- |  0  | Standard date/time string           | text string  |
-- +-----+-------------------------------------+--------------+
-- |  1  | Epoch-based date/time               | number       |
-- +-----+-------------------------------------+--------------+
-- |  2  | Positive bignum                     | byte string  |
-- +-----+-------------------------------------+--------------+
-- |  3  | Negative bignum                     | byte string  |
-- +-----+-------------------------------------+--------------+
-- |  4  | Decimal fraction                    | array        |
-- +-----+-------------------------------------+--------------+
-- | 24  | Encoded CBOR data item              | byte string  |
-- +-----+-------------------------------------+--------------+
--
-- For more tags, have a look at [iana's Concise Binary Object Representation (CBOR) Tags list](https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml).
encodeTag :: Integer -> Encoding
encodeTag :: Integer -> Encoding
encodeTag =
  (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding ((BuiltinByteString -> BuiltinByteString) -> Encoding)
-> (Integer -> BuiltinByteString -> BuiltinByteString)
-> Integer
-> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned Integer
6

-- * Backdoor

-- | Inject an already CBOR-encoded bytestring into an 'Encoding'. Do not use
-- unless you know what you're doing, this may creates an 'Encoding' not
-- compliant with the CBOR specification.
unsafeEncodeRaw :: BuiltinByteString -> Encoding
unsafeEncodeRaw :: BuiltinByteString -> Encoding
unsafeEncodeRaw =
  (BuiltinByteString -> BuiltinByteString) -> Encoding
Encoding ((BuiltinByteString -> BuiltinByteString) -> Encoding)
-> (BuiltinByteString -> BuiltinByteString -> BuiltinByteString)
-> BuiltinByteString
-> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BuiltinByteString -> BuiltinByteString -> BuiltinByteString
appendByteString
{-# INLINEABLE unsafeEncodeRaw #-}

-- * Internal

withMajorType :: Integer -> Integer -> BuiltinByteString -> BuiltinByteString
withMajorType :: Integer -> Integer -> BuiltinByteString -> BuiltinByteString
withMajorType Integer
major Integer
n =
  Integer -> BuiltinByteString -> BuiltinByteString
consByteString (Integer
32 Integer -> Integer -> Integer
forall a. MultiplicativeSemigroup a => a -> a -> a
* Integer
major Integer -> Integer -> Integer
forall a. AdditiveSemigroup a => a -> a -> a
+ Integer
n)
{-# INLINEABLE withMajorType #-}

encodeUnsigned :: Integer -> Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned :: Integer -> Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned Integer
major Integer
n BuiltinByteString
next
  | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
24 =
      Integer -> Integer -> BuiltinByteString -> BuiltinByteString
withMajorType Integer
major Integer
n BuiltinByteString
next
  | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
256 =
      Integer -> Integer -> BuiltinByteString -> BuiltinByteString
withMajorType Integer
major Integer
24 (Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned8 Integer
n BuiltinByteString
next)
  | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
65536 =
      Integer -> Integer -> BuiltinByteString -> BuiltinByteString
withMajorType Integer
major Integer
25 (Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned16 Integer
n BuiltinByteString
next)
  | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
4294967296 =
      Integer -> Integer -> BuiltinByteString -> BuiltinByteString
withMajorType Integer
major Integer
26 (Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned32 Integer
n BuiltinByteString
next)
  | Bool
otherwise =
      Integer -> Integer -> BuiltinByteString -> BuiltinByteString
withMajorType Integer
major Integer
27 (Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned64 Integer
n BuiltinByteString
next)
{-# INLINEABLE encodeUnsigned #-}

encodeUnsigned8 :: Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned8 :: Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned8 = Integer -> BuiltinByteString -> BuiltinByteString
consByteString
{-# INLINEABLE encodeUnsigned8 #-}

encodeUnsigned16 :: Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned16 :: Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned16 Integer
n =
  Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned8 (Integer -> Integer -> Integer
quotient Integer
n Integer
256) (BuiltinByteString -> BuiltinByteString)
-> (BuiltinByteString -> BuiltinByteString)
-> BuiltinByteString
-> BuiltinByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned8 (Integer -> Integer -> Integer
remainder Integer
n Integer
256)
{-# INLINEABLE encodeUnsigned16 #-}

encodeUnsigned32 :: Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned32 :: Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned32 Integer
n =
  Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned16 (Integer -> Integer -> Integer
quotient Integer
n Integer
65536) (BuiltinByteString -> BuiltinByteString)
-> (BuiltinByteString -> BuiltinByteString)
-> BuiltinByteString
-> BuiltinByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned16 (Integer -> Integer -> Integer
remainder Integer
n Integer
65536)
{-# INLINEABLE encodeUnsigned32 #-}

encodeUnsigned64 :: Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned64 :: Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned64 Integer
n =
  Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned32 (Integer -> Integer -> Integer
quotient Integer
n Integer
4294967296) (BuiltinByteString -> BuiltinByteString)
-> (BuiltinByteString -> BuiltinByteString)
-> BuiltinByteString
-> BuiltinByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> BuiltinByteString -> BuiltinByteString
encodeUnsigned32 (Integer -> Integer -> Integer
remainder Integer
n Integer
4294967296)
{-# INLINEABLE encodeUnsigned64 #-}