{-# 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)