First attempt at implementing VLQ encoding, fails for large negative numbers when Int > 32 bits.

This commit is contained in:
Robin Heggelund Hansen 2023-05-24 23:08:52 +02:00
parent 56dc275d6f
commit 5f9c114b4b
No known key found for this signature in database
3 changed files with 54 additions and 4 deletions

View File

@ -2,6 +2,55 @@ module Generate.VLQ
( encode
) where
import Data.Bits ((.|.), (.&.))
import Data.Bits qualified as Bit
import Data.List qualified as List
import Data.Map (Map, (!))
import Data.Map qualified as Map
import Data.Function ((&))
import Data.Foldable.WithIndex (ifoldr)
{- Ported from the Elm package Janiczek/elm-vlq
-}
encode :: Int -> String
encode _num =
""
encode num =
let
numWithSign =
if num < 0
then (negate num `Bit.shiftL` 1) .|. 1
else num `Bit.shiftL` 1
in
encodeHelp numWithSign ""
encodeHelp :: Int -> String -> String
encodeHelp num acc =
let
clamped =
num .&. 31
newNum =
num `Bit.shiftR` 5
newClamped =
if newNum > 0 then
clamped .|. 32
else
clamped
newAcc =
base64Table ! newClamped : acc
in
if newNum > 0 then
encodeHelp newNum newAcc
else
List.reverse newAcc
base64Table :: Map Int Char
base64Table =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='"
& ifoldr Map.insert Map.empty

View File

@ -225,7 +225,8 @@ Common gren-common
utf8-string,
vector,
text >= 2 && < 3,
base64-bytestring >= 1.2 && < 2
base64-bytestring >= 1.2 && < 2,
indexed-traversable
Executable gren
Import:

View File

@ -16,4 +16,4 @@ spec = do
encode 123456789 `shouldBe` "qxmvrH"
-- limits:
encode (-2147483648) `shouldBe` "B"
encode 2147483647 `shouldBe` "+/////D"
encode 2147483647 `shouldBe` "+/////D"