Skip to content

Commit

Permalink
Use little endian encoding of ByteStrings in Anoma (#2793)
Browse files Browse the repository at this point in the history
Anoma decodes integer atoms as bytes assuming a little endian layout.


https://github.com/anoma/anoma/blob/ea25f88cea52226d77c8392ae16bbfc5a7ffccee/lib/noun.ex#L182

This commit adds functions `byteStringToIntegerLE` and
`integerToByteStringLE` that makes it clear that little endian encoding
is being used.
  • Loading branch information
paulcadman authored May 31, 2024
1 parent e9afdad commit 88b4cb8
Showing 1 changed file with 18 additions and 16 deletions.
34 changes: 18 additions & 16 deletions src/Juvix/Compiler/Nockma/Encoding/ByteString.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module Juvix.Compiler.Nockma.Encoding.ByteString where

import Data.Bit
import Juvix.Compiler.Nockma.Encoding.Base
import Data.Bits
import Data.ByteString qualified as BS
import Data.ByteString.Builder qualified as BS
import Juvix.Compiler.Nockma.Language
import Juvix.Prelude.Base

Expand All @@ -12,33 +13,34 @@ byteStringToAtom :: (NockNatural a, Member (Error (ErrNockNatural a)) r) => Byte
byteStringToAtom = fmap mkEmptyAtom . fromNatural . byteStringToNatural

byteStringToNatural :: ByteString -> Natural
byteStringToNatural = bitsToNatural . cloneFromByteString
byteStringToNatural = fromInteger . byteStringToIntegerLE

naturalToByteString :: Natural -> ByteString
naturalToByteString = cloneToByteString . naturalToBits
naturalToByteString = integerToByteStringLE . toInteger

textToNatural :: Text -> Natural
textToNatural = byteStringToNatural . encodeUtf8
byteStringToIntegerLE :: ByteString -> Integer
byteStringToIntegerLE = BS.foldr (\b acc -> acc `shiftL` 8 .|. fromIntegral b) 0

bitsToNatural :: Vector Bit -> Natural
bitsToNatural = fromInteger . vectorBitsToInteger
integerToByteStringLE :: Integer -> ByteString
integerToByteStringLE = BS.toStrict . BS.toLazyByteString . go
where
go :: Integer -> BS.Builder
go = \case
0 -> mempty
n -> BS.word8 (fromIntegral n) <> go (n `shiftR` 8)

naturalToBits :: Natural -> Vector Bit
naturalToBits = integerToVectorBits . toInteger
textToNatural :: Text -> Natural
textToNatural = byteStringToNatural . encodeUtf8

atomToText :: (NockNatural a, Member (Error (ErrNockNatural a)) r) => Atom a -> Sem r Text
atomToText = fmap decodeUtf8Lenient . atomToByteString

-- | Construct an atom formed by concatenating the bits of two atoms, where each atom represents a sequence of bytes
atomConcatenateBytes :: forall a r. (NockNatural a, Member (Error (ErrNockNatural a)) r) => Atom a -> Atom a -> Sem r (Atom a)
atomConcatenateBytes l r = do
-- cloneToByteString ensures that the bytestring is zero-padded up to the byte boundary
lBs <- cloneToByteString <$> atomToBits l
rBs <- cloneToByteString <$> atomToBits r
lBs <- atomToByteString l
rBs <- atomToByteString r
byteStringToAtom (lBs <> rBs)
where
atomToBits :: Atom a -> Sem r (Vector Bit)
atomToBits = fmap naturalToBits . nockNatural

mkEmptyAtom :: a -> Atom a
mkEmptyAtom x =
Expand Down

0 comments on commit 88b4cb8

Please sign in to comment.