Skip to content

Instantly share code, notes, and snippets.

@jacobstanley
Created October 9, 2014 11:46
Show Gist options
  • Select an option

  • Save jacobstanley/e90f9908f01fd6956359 to your computer and use it in GitHub Desktop.

Select an option

Save jacobstanley/e90f9908f01fd6956359 to your computer and use it in GitHub Desktop.
hs-packer super inlinable varint decoding
getVarInt32 :: Unpacking Word32
getVarInt32 = go step (stepLast "getVarInt32: varint was larger than 32-bits") 0
where
go :: (Int -> b -> b) -> (Int -> b) -> b
go !s !sl = s 0 . s 7 . s 14 . s 21 $ sl 28
{-# INLINE go #-}
{-# INLINE getVarInt32 #-}
getVarInt64 :: Unpacking Word64
getVarInt64 = go step (stepLast "getVarInt64: varint was larger than 64-bits") 0
where
go :: (Int -> b -> b) -> (Int -> b) -> b
go !s !sl = s 0 . s 7 . s 14 . s 21 . s 28
. s 35 . s 42 . s 49 . s 56 $ sl 63
{-# INLINE go #-}
{-# INLINE getVarInt64 #-}
step :: (Bits a, Num a) => Int -> (a -> Unpacking a) -> a -> Unpacking a
step !shbits !next !val = do
x <- getWord8
if testBit x 7
then next (val .|. (fromIntegral (x .&. 0x7F) `shiftL` shbits))
else return $! val .|. (fromIntegral x `shiftL` shbits)
{-# INLINE step #-}
stepLast :: (Bits b, Num b) => String -> Int -> b -> Unpacking b
stepLast !failMsg !shbits !val = do
b <- getWord8
if testBit b 7
then fail failMsg
else return $! val .|. (fromIntegral b `shiftL` shbits)
{-# INLINE stepLast #-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment