{-# language BangPatterns #-} {-# language TypeApplications #-} module Data.Bytes.Parser.Base128 ( -- * Unsigned word16 , word32 , word64 ) where import Control.Monad (when) import Data.Bits (testBit,unsafeShiftL,(.|.),bit,clearBit) import Data.Bytes.Parser (Parser) import Data.Word (Word8,Word16,Word32,Word64) import qualified Data.Bytes.Parser as P word16 :: e -> Parser e s Word16 word16 e = fromIntegral @Word64 @Word16 <$> stepBoundedWord e 16 0 word32 :: e -> Parser e s Word32 word32 e = fromIntegral @Word64 @Word32 <$> stepBoundedWord e 32 0 word64 :: e -> Parser e s Word64 word64 e = fromIntegral @Word64 @Word64 <$> stepBoundedWord e 64 0 stepBoundedWord :: e -> Int -> Word64 -> Parser e s Word64 stepBoundedWord e !bitLimit !acc = do when (acc >= bit (bitLimit - 7)) $ P.fail e raw <- P.any e let content = clearBit raw 7 acc' = unsafeShiftL acc 7 .|. fromIntegral @Word8 @Word64 content if testBit raw 7 then stepBoundedWord e bitLimit acc' else pure acc'