leb128-0.1.0.0: src/Codec/LEB128/List.hs
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE InstanceSigs #-}
{- |
Module : Codec.LEB128.Generic
Description : Encode values via (S)LEB128 to/from lists.
Copyright : (c) Andreas Klebinger 2020
License : BSD3
Maintainer : Andreas Klebinger
Portability : GHC >= 7.10
The implementation is backed by the generic algorithms defined
in "Codec.LEB128.Generic".
The code is quite fast but does not fuse.
-}
module Codec.LEB128.List
( fromULEB128
, fromSLEB128
, toULEB128
, toSLEB128
)
where
import Data.Word
import GHC.Magic
import Control.Monad.Trans.State.Strict
import Codec.LEB128.Constraints
import Codec.LEB128.Generic as G
-- | Encode a __unsigned__ value in LEB128.
{-# INLINEABLE toULEB128 #-}
toULEB128 :: LEB128 a => a -> [Word8]
toULEB128 = (inline G.encodeLEB128) pure
-- | Encode a __signed__ value in LEB128.
{-# INLINEABLE toSLEB128 #-}
toSLEB128 :: SLEB128 a => a -> [Word8]
toSLEB128 = (inline G.encodeSLEB128) pure
type ByteProvider a = State [Word8] a
{-# INLINE getByte #-}
getByte :: ByteProvider Word8
getByte = do
wds <- get
case wds of
[] -> error "decode LEB128: Not enough bytes"
(x:xs) -> put xs >> return x
{-# INLINEABLE fromULEB128 #-}
-- | Decode a __unsigned__ value from LEB128 encoding.
fromULEB128 :: LEB128 a => [Word8] -> (a,[Word8])
fromULEB128 = runState ((inline G.decodeLEB128) getByte)
{-# INLINEABLE fromSLEB128 #-}
-- | Decode a __signed__ value from SLEB128 encoding.
fromSLEB128 :: SLEB128 a => [Word8] -> (a,[Word8])
fromSLEB128 = runState ((inline G.decodeSLEB128) getByte)