-- |
-- Module: M.LEB
-- Description: LEB128 encoding support for integers
-- Copyright: (c) axionbuster, 2025
-- License: BSD-3-Clause
--
-- Implements LEB128 (Little-Endian Base 128) variable-length encoding
-- for arbitrary finite-bit integers, used in the Minecraft protocol.
module M.LEB (LEB (..), VarInt, VarLong, decodeleb, encodeleb) where

import Control.DeepSeq
import Control.Monad.Fix
import Data.Bits
import Data.ByteString.Builder (Builder)
import Data.ByteString.Builder qualified as BB
import Data.Data
import Data.Function
import Data.Hashable
import Data.Int
import Data.Word
import GHC.Generics hiding (S)
import Language.Haskell.TH.Syntax (Lift)

-- | a LEB128 (unsigned) encoded integer. the integer itself may or
-- may not be signed
newtype LEB a = LEB {forall a. LEB a -> a
getleb :: a}
  deriving newtype
    ( Int -> LEB a -> ShowS
[LEB a] -> ShowS
LEB a -> String
(Int -> LEB a -> ShowS)
-> (LEB a -> String) -> ([LEB a] -> ShowS) -> Show (LEB a)
forall a. Show a => Int -> LEB a -> ShowS
forall a. Show a => [LEB a] -> ShowS
forall a. Show a => LEB a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> LEB a -> ShowS
showsPrec :: Int -> LEB a -> ShowS
$cshow :: forall a. Show a => LEB a -> String
show :: LEB a -> String
$cshowList :: forall a. Show a => [LEB a] -> ShowS
showList :: [LEB a] -> ShowS
Show,
      ReadPrec [LEB a]
ReadPrec (LEB a)
Int -> ReadS (LEB a)
ReadS [LEB a]
(Int -> ReadS (LEB a))
-> ReadS [LEB a]
-> ReadPrec (LEB a)
-> ReadPrec [LEB a]
-> Read (LEB a)
forall a. Read a => ReadPrec [LEB a]
forall a. Read a => ReadPrec (LEB a)
forall a. Read a => Int -> ReadS (LEB a)
forall a. Read a => ReadS [LEB a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: forall a. Read a => Int -> ReadS (LEB a)
readsPrec :: Int -> ReadS (LEB a)
$creadList :: forall a. Read a => ReadS [LEB a]
readList :: ReadS [LEB a]
$creadPrec :: forall a. Read a => ReadPrec (LEB a)
readPrec :: ReadPrec (LEB a)
$creadListPrec :: forall a. Read a => ReadPrec [LEB a]
readListPrec :: ReadPrec [LEB a]
Read,
      LEB a -> LEB a -> Bool
(LEB a -> LEB a -> Bool) -> (LEB a -> LEB a -> Bool) -> Eq (LEB a)
forall a. Eq a => LEB a -> LEB a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => LEB a -> LEB a -> Bool
== :: LEB a -> LEB a -> Bool
$c/= :: forall a. Eq a => LEB a -> LEB a -> Bool
/= :: LEB a -> LEB a -> Bool
Eq,
      Eq (LEB a)
Eq (LEB a) =>
(LEB a -> LEB a -> Ordering)
-> (LEB a -> LEB a -> Bool)
-> (LEB a -> LEB a -> Bool)
-> (LEB a -> LEB a -> Bool)
-> (LEB a -> LEB a -> Bool)
-> (LEB a -> LEB a -> LEB a)
-> (LEB a -> LEB a -> LEB a)
-> Ord (LEB a)
LEB a -> LEB a -> Bool
LEB a -> LEB a -> Ordering
LEB a -> LEB a -> LEB a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (LEB a)
forall a. Ord a => LEB a -> LEB a -> Bool
forall a. Ord a => LEB a -> LEB a -> Ordering
forall a. Ord a => LEB a -> LEB a -> LEB a
$ccompare :: forall a. Ord a => LEB a -> LEB a -> Ordering
compare :: LEB a -> LEB a -> Ordering
$c< :: forall a. Ord a => LEB a -> LEB a -> Bool
< :: LEB a -> LEB a -> Bool
$c<= :: forall a. Ord a => LEB a -> LEB a -> Bool
<= :: LEB a -> LEB a -> Bool
$c> :: forall a. Ord a => LEB a -> LEB a -> Bool
> :: LEB a -> LEB a -> Bool
$c>= :: forall a. Ord a => LEB a -> LEB a -> Bool
>= :: LEB a -> LEB a -> Bool
$cmax :: forall a. Ord a => LEB a -> LEB a -> LEB a
max :: LEB a -> LEB a -> LEB a
$cmin :: forall a. Ord a => LEB a -> LEB a -> LEB a
min :: LEB a -> LEB a -> LEB a
Ord,
      Int -> LEB a
LEB a -> Int
LEB a -> [LEB a]
LEB a -> LEB a
LEB a -> LEB a -> [LEB a]
LEB a -> LEB a -> LEB a -> [LEB a]
(LEB a -> LEB a)
-> (LEB a -> LEB a)
-> (Int -> LEB a)
-> (LEB a -> Int)
-> (LEB a -> [LEB a])
-> (LEB a -> LEB a -> [LEB a])
-> (LEB a -> LEB a -> [LEB a])
-> (LEB a -> LEB a -> LEB a -> [LEB a])
-> Enum (LEB a)
forall a. Enum a => Int -> LEB a
forall a. Enum a => LEB a -> Int
forall a. Enum a => LEB a -> [LEB a]
forall a. Enum a => LEB a -> LEB a
forall a. Enum a => LEB a -> LEB a -> [LEB a]
forall a. Enum a => LEB a -> LEB a -> LEB a -> [LEB a]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: forall a. Enum a => LEB a -> LEB a
succ :: LEB a -> LEB a
$cpred :: forall a. Enum a => LEB a -> LEB a
pred :: LEB a -> LEB a
$ctoEnum :: forall a. Enum a => Int -> LEB a
toEnum :: Int -> LEB a
$cfromEnum :: forall a. Enum a => LEB a -> Int
fromEnum :: LEB a -> Int
$cenumFrom :: forall a. Enum a => LEB a -> [LEB a]
enumFrom :: LEB a -> [LEB a]
$cenumFromThen :: forall a. Enum a => LEB a -> LEB a -> [LEB a]
enumFromThen :: LEB a -> LEB a -> [LEB a]
$cenumFromTo :: forall a. Enum a => LEB a -> LEB a -> [LEB a]
enumFromTo :: LEB a -> LEB a -> [LEB a]
$cenumFromThenTo :: forall a. Enum a => LEB a -> LEB a -> LEB a -> [LEB a]
enumFromThenTo :: LEB a -> LEB a -> LEB a -> [LEB a]
Enum,
      LEB a
LEB a -> LEB a -> Bounded (LEB a)
forall a. a -> a -> Bounded a
forall a. Bounded a => LEB a
$cminBound :: forall a. Bounded a => LEB a
minBound :: LEB a
$cmaxBound :: forall a. Bounded a => LEB a
maxBound :: LEB a
Bounded,
      Integer -> LEB a
LEB a -> LEB a
LEB a -> LEB a -> LEB a
(LEB a -> LEB a -> LEB a)
-> (LEB a -> LEB a -> LEB a)
-> (LEB a -> LEB a -> LEB a)
-> (LEB a -> LEB a)
-> (LEB a -> LEB a)
-> (LEB a -> LEB a)
-> (Integer -> LEB a)
-> Num (LEB a)
forall a. Num a => Integer -> LEB a
forall a. Num a => LEB a -> LEB a
forall a. Num a => LEB a -> LEB a -> LEB a
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: forall a. Num a => LEB a -> LEB a -> LEB a
+ :: LEB a -> LEB a -> LEB a
$c- :: forall a. Num a => LEB a -> LEB a -> LEB a
- :: LEB a -> LEB a -> LEB a
$c* :: forall a. Num a => LEB a -> LEB a -> LEB a
* :: LEB a -> LEB a -> LEB a
$cnegate :: forall a. Num a => LEB a -> LEB a
negate :: LEB a -> LEB a
$cabs :: forall a. Num a => LEB a -> LEB a
abs :: LEB a -> LEB a
$csignum :: forall a. Num a => LEB a -> LEB a
signum :: LEB a -> LEB a
$cfromInteger :: forall a. Num a => Integer -> LEB a
fromInteger :: Integer -> LEB a
Num,
      Num (LEB a)
Ord (LEB a)
(Num (LEB a), Ord (LEB a)) => (LEB a -> Rational) -> Real (LEB a)
LEB a -> Rational
forall a. (Num a, Ord a) => (a -> Rational) -> Real a
forall a. Real a => Num (LEB a)
forall a. Real a => Ord (LEB a)
forall a. Real a => LEB a -> Rational
$ctoRational :: forall a. Real a => LEB a -> Rational
toRational :: LEB a -> Rational
Real,
      Enum (LEB a)
Real (LEB a)
(Real (LEB a), Enum (LEB a)) =>
(LEB a -> LEB a -> LEB a)
-> (LEB a -> LEB a -> LEB a)
-> (LEB a -> LEB a -> LEB a)
-> (LEB a -> LEB a -> LEB a)
-> (LEB a -> LEB a -> (LEB a, LEB a))
-> (LEB a -> LEB a -> (LEB a, LEB a))
-> (LEB a -> Integer)
-> Integral (LEB a)
LEB a -> Integer
LEB a -> LEB a -> (LEB a, LEB a)
LEB a -> LEB a -> LEB a
forall a. Integral a => Enum (LEB a)
forall a. Integral a => Real (LEB a)
forall a. Integral a => LEB a -> Integer
forall a. Integral a => LEB a -> LEB a -> (LEB a, LEB a)
forall a. Integral a => LEB a -> LEB a -> LEB a
forall a.
(Real a, Enum a) =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
$cquot :: forall a. Integral a => LEB a -> LEB a -> LEB a
quot :: LEB a -> LEB a -> LEB a
$crem :: forall a. Integral a => LEB a -> LEB a -> LEB a
rem :: LEB a -> LEB a -> LEB a
$cdiv :: forall a. Integral a => LEB a -> LEB a -> LEB a
div :: LEB a -> LEB a -> LEB a
$cmod :: forall a. Integral a => LEB a -> LEB a -> LEB a
mod :: LEB a -> LEB a -> LEB a
$cquotRem :: forall a. Integral a => LEB a -> LEB a -> (LEB a, LEB a)
quotRem :: LEB a -> LEB a -> (LEB a, LEB a)
$cdivMod :: forall a. Integral a => LEB a -> LEB a -> (LEB a, LEB a)
divMod :: LEB a -> LEB a -> (LEB a, LEB a)
$ctoInteger :: forall a. Integral a => LEB a -> Integer
toInteger :: LEB a -> Integer
Integral,
      Eq (LEB a)
Eq (LEB a) =>
(Int -> LEB a -> Int) -> (LEB a -> Int) -> Hashable (LEB a)
Int -> LEB a -> Int
LEB a -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
forall a. Hashable a => Eq (LEB a)
forall a. Hashable a => Int -> LEB a -> Int
forall a. Hashable a => LEB a -> Int
$chashWithSalt :: forall a. Hashable a => Int -> LEB a -> Int
hashWithSalt :: Int -> LEB a -> Int
$chash :: forall a. Hashable a => LEB a -> Int
hash :: LEB a -> Int
Hashable
    )
  deriving stock ((forall x. LEB a -> Rep (LEB a) x)
-> (forall x. Rep (LEB a) x -> LEB a) -> Generic (LEB a)
forall x. Rep (LEB a) x -> LEB a
forall x. LEB a -> Rep (LEB a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (LEB a) x -> LEB a
forall a x. LEB a -> Rep (LEB a) x
$cfrom :: forall a x. LEB a -> Rep (LEB a) x
from :: forall x. LEB a -> Rep (LEB a) x
$cto :: forall a x. Rep (LEB a) x -> LEB a
to :: forall x. Rep (LEB a) x -> LEB a
Generic, Typeable, Typeable (LEB a)
Typeable (LEB a) =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> LEB a -> c (LEB a))
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (LEB a))
-> (LEB a -> Constr)
-> (LEB a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (LEB a)))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (LEB a)))
-> ((forall b. Data b => b -> b) -> LEB a -> LEB a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r)
-> (forall u. (forall d. Data d => d -> u) -> LEB a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> LEB a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> LEB a -> m (LEB a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> LEB a -> m (LEB a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> LEB a -> m (LEB a))
-> Data (LEB a)
LEB a -> Constr
LEB a -> DataType
(forall b. Data b => b -> b) -> LEB a -> LEB a
forall a. Data a => Typeable (LEB a)
forall a. Data a => LEB a -> Constr
forall a. Data a => LEB a -> DataType
forall a. Data a => (forall b. Data b => b -> b) -> LEB a -> LEB a
forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> LEB a -> u
forall a u. Data a => (forall d. Data d => d -> u) -> LEB a -> [u]
forall a r r'.
Data a =>
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r
forall a r r'.
Data a =>
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r
forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (LEB a)
forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> LEB a -> c (LEB a)
forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (LEB a))
forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (LEB a))
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> LEB a -> u
forall u. (forall d. Data d => d -> u) -> LEB a -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (LEB a)
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> LEB a -> c (LEB a)
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (LEB a))
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (LEB a))
$cgfoldl :: forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> LEB a -> c (LEB a)
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> LEB a -> c (LEB a)
$cgunfold :: forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (LEB a)
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (LEB a)
$ctoConstr :: forall a. Data a => LEB a -> Constr
toConstr :: LEB a -> Constr
$cdataTypeOf :: forall a. Data a => LEB a -> DataType
dataTypeOf :: LEB a -> DataType
$cdataCast1 :: forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (LEB a))
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (LEB a))
$cdataCast2 :: forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (LEB a))
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (LEB a))
$cgmapT :: forall a. Data a => (forall b. Data b => b -> b) -> LEB a -> LEB a
gmapT :: (forall b. Data b => b -> b) -> LEB a -> LEB a
$cgmapQl :: forall a r r'.
Data a =>
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r
$cgmapQr :: forall a r r'.
Data a =>
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> LEB a -> r
$cgmapQ :: forall a u. Data a => (forall d. Data d => d -> u) -> LEB a -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> LEB a -> [u]
$cgmapQi :: forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> LEB a -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> LEB a -> u
$cgmapM :: forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
$cgmapMp :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
$cgmapMo :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> LEB a -> m (LEB a)
Data, (forall a b. (a -> b) -> LEB a -> LEB b)
-> (forall a b. a -> LEB b -> LEB a) -> Functor LEB
forall a b. a -> LEB b -> LEB a
forall a b. (a -> b) -> LEB a -> LEB b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> LEB a -> LEB b
fmap :: forall a b. (a -> b) -> LEB a -> LEB b
$c<$ :: forall a b. a -> LEB b -> LEB a
<$ :: forall a b. a -> LEB b -> LEB a
Functor, (forall (m :: * -> *). Quote m => LEB a -> m Exp)
-> (forall (m :: * -> *). Quote m => LEB a -> Code m (LEB a))
-> Lift (LEB a)
forall a (m :: * -> *). (Lift a, Quote m) => LEB a -> m Exp
forall a (m :: * -> *).
(Lift a, Quote m) =>
LEB a -> Code m (LEB a)
forall t.
(forall (m :: * -> *). Quote m => t -> m Exp)
-> (forall (m :: * -> *). Quote m => t -> Code m t) -> Lift t
forall (m :: * -> *). Quote m => LEB a -> m Exp
forall (m :: * -> *). Quote m => LEB a -> Code m (LEB a)
$clift :: forall a (m :: * -> *). (Lift a, Quote m) => LEB a -> m Exp
lift :: forall (m :: * -> *). Quote m => LEB a -> m Exp
$cliftTyped :: forall a (m :: * -> *).
(Lift a, Quote m) =>
LEB a -> Code m (LEB a)
liftTyped :: forall (m :: * -> *). Quote m => LEB a -> Code m (LEB a)
Lift)
  deriving anyclass (LEB a -> ()
(LEB a -> ()) -> NFData (LEB a)
forall a. NFData a => LEB a -> ()
forall a. (a -> ()) -> NFData a
$crnf :: forall a. NFData a => LEB a -> ()
rnf :: LEB a -> ()
NFData)

-- | VarInt
type VarInt = LEB Int32

-- | VarLong
type VarLong = LEB Int64

-- internal state
data S a = S !Int !a -- shift, accumulator

-- | decode an unsigned LEB128 encoded integer
--
-- the actual integer may or may not be signed; the encoding itself is
-- \"unsigned\"
decodeleb ::
  forall m a.
  (Monad m, FiniteBits a, Num a) =>
  -- | accept any 'Word8' value
  m Word8 ->
  -- | LEB128 encoded integer
  m (LEB a)
decodeleb :: forall (m :: * -> *) a.
(Monad m, FiniteBits a, Num a) =>
m Word8 -> m (LEB a)
decodeleb m Word8
word8 =
  Int -> a -> S a
forall a. Int -> a -> S a
S Int
0 a
0 S a -> (S a -> m (LEB a)) -> m (LEB a)
forall a b. a -> (a -> b) -> b
& ((S a -> m (LEB a)) -> S a -> m (LEB a)) -> S a -> m (LEB a)
forall a. (a -> a) -> a
fix \S a -> m (LEB a)
f -> \case
    S Int
s a
n | Int
s Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= a -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize (a
forall a. HasCallStack => a
undefined :: a) -> LEB a -> m (LEB a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> LEB a
forall a. a -> LEB a
LEB a
n)
    S Int
s a
n -> do
      Word8
c <- m Word8
word8
      let d :: a
d = a
n a -> a -> a
forall a. Bits a => a -> a -> a
.|. a -> Int -> a
forall a. Bits a => a -> Int -> a
shift (a -> Int -> a
forall a. Bits a => a -> Int -> a
clearBit (Word8 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
c) Int
7) Int
s
      if Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word8
c Int
7
        then S a -> m (LEB a)
f (Int -> a -> S a
forall a. Int -> a -> S a
S (Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
7) a
d)
        else LEB a -> m (LEB a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> LEB a
forall a. a -> LEB a
LEB a
d)
{-# INLINEABLE decodeleb #-}

-- | encode an LEB128 encoded integer into a 'Builder'
encodeleb :: (FiniteBits a, Integral a) => LEB a -> Builder
encodeleb :: forall a. (FiniteBits a, Integral a) => LEB a -> Builder
encodeleb (LEB a
n) =
  let m :: a
m = a -> a
forall a. Bits a => a -> a
complement (a
0x7f a -> Int -> a
forall a. Bits a => a -> Int -> a
`rotate` (-Int
7))
      l :: Word8
l = Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
clearBit (a -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n) Int
7
      r :: a
r = a -> Int -> a
forall a. Bits a => a -> Int -> a
shift a
n (-Int
7) a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
m -- force unsigned shift
      (Word8
o, Builder
next)
        | a
n a -> a -> a
forall a. Bits a => a -> a -> a
.&. a -> a
forall a. Bits a => a -> a
complement a
0x7f a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0 = (Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
setBit Word8
l Int
7, LEB a -> Builder
forall a. (FiniteBits a, Integral a) => LEB a -> Builder
encodeleb (a -> LEB a
forall a. a -> LEB a
LEB a
r))
        | Bool
otherwise = (Word8
l, Builder
forall a. Monoid a => a
mempty)
   in Word8 -> Builder
BB.word8 Word8
o Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
next
{-# INLINEABLE encodeleb #-}
{-# SPECIALIZE encodeleb :: LEB Int32 -> Builder #-}
{-# SPECIALIZE encodeleb :: LEB Int64 -> Builder #-}