{- | Encode numbers to and from bytestrings using the (S)LEB128 encoding. The implementation is backed by the generic algorithms defined in "Codec.LEB128.Generic". -} module Codec.LEB128 ( -- * Encode values as bytestring builder. toULEB128Builder , toSLEB128Builder -- * Encode value as bytestring. , toULEB128ByteString , toSLEB128ByteString -- * Encode value from bytestring. , fromULEB128ByteString , fromSLEB128ByteString , fromULEB128ByteStringN , fromSLEB128ByteStringI -- * Encode value from bytestring. Throws an error if not enough bytes are provided. , fromULEB128ByteStringUnsafe , fromSLEB128ByteStringUnsafe , fromULEB128ByteStringNUnsafe , fromSLEB128ByteStringIUnsafe ) where import Numeric.Natural import Data.Word import Data.Int import Data.ByteString.Builder.Extra (toLazyByteStringWith, safeStrategy, AllocationStrategy) import Data.ByteString.Builder as B(Builder) import Data.ByteString.Lazy (toStrict) import Data.ByteString (ByteString) import Codec.LEB128.Constraints import Codec.LEB128.Internal.BS as B -- Builders {-# SPECIALIZE toULEB128Builder :: Natural -> Builder #-} {-# SPECIALIZE toULEB128Builder :: Word -> Builder #-} {-# SPECIALIZE toULEB128Builder :: Word64 -> Builder #-} {-# SPECIALIZE toULEB128Builder :: Word32 -> Builder #-} -- | Encode values as bytestring builder. {-# INLINEABLE toULEB128Builder #-} toULEB128Builder :: LEB128 a => a -> B.Builder toULEB128Builder = B.toULEB128 {-# SPECIALIZE toSLEB128Builder :: Integer -> Builder #-} {-# SPECIALIZE toSLEB128Builder :: Int -> Builder #-} {-# SPECIALIZE toSLEB128Builder :: Int64 -> Builder #-} {-# SPECIALIZE toSLEB128Builder :: Int32 -> Builder #-} {-# INLINEABLE toSLEB128Builder #-} toSLEB128Builder :: SLEB128 a => a -> B.Builder toSLEB128Builder = B.toSLEB128 smallChunks :: AllocationStrategy smallChunks = safeStrategy 12 64 -- Conversion to encodede ByteString {-# SPECIALIZE toULEB128ByteString :: Natural -> ByteString #-} {-# SPECIALIZE toULEB128ByteString :: Word -> ByteString #-} {-# SPECIALIZE toULEB128ByteString :: Word64 -> ByteString #-} {-# SPECIALIZE toULEB128ByteString :: Word32 -> ByteString #-} {-# INLINEABLE toULEB128ByteString #-} toULEB128ByteString :: LEB128 a => a -> ByteString toULEB128ByteString = toStrict . toLazyByteStringWith smallChunks mempty . toULEB128Builder {-# SPECIALIZE toSLEB128ByteString :: Integer -> ByteString #-} {-# SPECIALIZE toSLEB128ByteString :: Int -> ByteString #-} {-# SPECIALIZE toSLEB128ByteString :: Int64 -> ByteString #-} {-# SPECIALIZE toSLEB128ByteString :: Int32 -> ByteString #-} {-# INLINEABLE toSLEB128ByteString #-} toSLEB128ByteString :: SLEB128 a => a -> ByteString toSLEB128ByteString = toStrict . toLazyByteStringWith smallChunks mempty . toSLEB128Builder -- Conversion from encoded ByteString {-# SPECIALIZE fromULEB128ByteString :: ByteString-> (Maybe Natural,ByteString) #-} {-# SPECIALIZE fromULEB128ByteString :: ByteString-> (Maybe Word,ByteString) #-} {-# SPECIALIZE fromULEB128ByteString :: ByteString-> (Maybe Word64,ByteString) #-} {-# SPECIALIZE fromULEB128ByteString :: ByteString-> (Maybe Word32,ByteString) #-} {-# INLINEABLE fromULEB128ByteString #-} fromULEB128ByteString :: LEB128 a => ByteString -> (Maybe a,ByteString) fromULEB128ByteString = B.fromULEB128 {-# SPECIALIZE fromSLEB128ByteString :: ByteString-> (Maybe Integer,ByteString) #-} {-# SPECIALIZE fromSLEB128ByteString :: ByteString-> (Maybe Int,ByteString) #-} {-# SPECIALIZE fromSLEB128ByteString :: ByteString-> (Maybe Int64,ByteString) #-} {-# SPECIALIZE fromSLEB128ByteString :: ByteString-> (Maybe Int32,ByteString) #-} {-# INLINEABLE fromSLEB128ByteString #-} fromSLEB128ByteString :: SLEB128 a => ByteString -> (Maybe a,ByteString) fromSLEB128ByteString = B.fromSLEB128 {-# NOINLINE fromULEB128ByteStringN #-} fromULEB128ByteStringN :: ByteString -> (Maybe Natural,ByteString) fromULEB128ByteStringN = B.fromULEB128 {-# NOINLINE fromSLEB128ByteStringI #-} fromSLEB128ByteStringI :: ByteString -> (Maybe Integer,ByteString) fromSLEB128ByteStringI = B.fromSLEB128 -- Be partial if not enough bytes are provided. {-# SPECIALIZE fromULEB128ByteStringUnsafe :: ByteString-> (Natural,ByteString) #-} {-# SPECIALIZE fromULEB128ByteStringUnsafe :: ByteString-> (Word,ByteString) #-} {-# SPECIALIZE fromULEB128ByteStringUnsafe :: ByteString-> (Word64,ByteString) #-} {-# SPECIALIZE fromULEB128ByteStringUnsafe :: ByteString-> (Word32,ByteString) #-} {-# INLINEABLE fromULEB128ByteStringUnsafe #-} fromULEB128ByteStringUnsafe :: LEB128 a => ByteString -> (a,ByteString) fromULEB128ByteStringUnsafe = B.fromULEB128Unsafe {-# SPECIALIZE fromSLEB128ByteStringUnsafe :: ByteString-> (Integer,ByteString) #-} {-# SPECIALIZE fromSLEB128ByteStringUnsafe :: ByteString-> (Int,ByteString) #-} {-# SPECIALIZE fromSLEB128ByteStringUnsafe :: ByteString-> (Int64,ByteString) #-} {-# SPECIALIZE fromSLEB128ByteStringUnsafe :: ByteString-> (Int32,ByteString) #-} {-# INLINEABLE fromSLEB128ByteStringUnsafe #-} fromSLEB128ByteStringUnsafe :: SLEB128 a => ByteString -> (a,ByteString) fromSLEB128ByteStringUnsafe = B.fromSLEB128Unsafe {-# NOINLINE fromULEB128ByteStringNUnsafe #-} fromULEB128ByteStringNUnsafe :: ByteString -> (Natural,ByteString) fromULEB128ByteStringNUnsafe = B.fromULEB128Unsafe {-# NOINLINE fromSLEB128ByteStringIUnsafe #-} fromSLEB128ByteStringIUnsafe :: ByteString -> (Integer,ByteString) fromSLEB128ByteStringIUnsafe = B.fromSLEB128Unsafe