module Data.Serialize.Varint
( Varint(..)
, getVarint
, putVarint
) where
import Data.Bits
import GHC.Word (Word8)
import Data.Serialize (Serialize(..), Get, Put, putWord8, getWord8)
newtype Varint a = Varint a
deriving (Eq, Num, Ord, Real, Integral, Enum, Show, Bits)
getVarint :: (Num a, Bits a) => Word8 -> Get (Varint a)
getVarint n
| testBit n 7 = do
Varint m <- getWord8 >>= getVarint
pure (shiftL m 7 .|. clearBit (fromIntegral n) 7)
| otherwise = pure (fromIntegral n)
putVarint :: (Integral a, Bits a) => a -> Put
putVarint n
| n < 0x80 = putWord8 (fromIntegral n)
| otherwise = do
putWord8 (setBit (fromIntegral n) 7)
putVarint (shiftR n 7)
instance (Bits a, Integral a) => Serialize (Varint a) where
get = getWord8 >>= getVarint
put = putVarint