morley-1.9: src/Michelson/Interpret/Utils.hs
-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ
-- | General utilities used by interpreter.
--
-- This is not supposed to import any Michelson modules.
module Michelson.Interpret.Utils
( encodeZarithNumber
) where
import Control.Exception (assert)
import qualified Data.Bits as Bits
-- | Encode a number as tezos does this.
--
-- In the Tezos reference implementation this encoding is called @zarith@.
encodeZarithNumber :: Integer -> NonEmpty Word8
encodeZarithNumber = doEncode True
where
{- Numbers, when packed by tezos, are represented as follows:
byte 0: 1 _ ______ || lowest digits
has continuation is negative payload ||
||
byte 1: 1 _______ ||
... 1 _______ ||
byte n: 0 _______ ||
has continuation payload \/ highest digits
-}
doEncode :: Bool -> Integer -> NonEmpty Word8
doEncode isFirst a
| a >= byteWeight =
let (hi, lo) = a `divMod` byteWeight
byte = Bits.setBit (fromIntegral @_ @Word8 lo) 7
in byte :| toList (doEncode False hi)
| a >= 0 =
one (fromIntegral @_ @Word8 a)
| otherwise = assert isFirst $
let h :| t = doEncode True (-a)
in Bits.setBit h 6 :| t
where
byteWeight = if isFirst then 64 else 128