packages feed

flatparse 0.3.2.0 → 0.3.3.0

raw patch · 6 files changed

+697/−159 lines, 6 filesdep +QuickCheckPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: QuickCheck

API changes (from Hackage documentation)

- FlatParse.Internal: indexWord16OffAddr :: Addr# -> Int# -> Word#
- FlatParse.Internal: indexWord32OffAddr :: Addr# -> Int# -> Word#
- FlatParse.Internal: indexWord64OffAddr :: Addr# -> Int# -> Word#
- FlatParse.Internal: indexWord8OffAddr :: Addr# -> Int# -> Word#
+ FlatParse.Basic: anyInt :: Parser e Int
+ FlatParse.Basic: anyInt16 :: Parser e Int16
+ FlatParse.Basic: anyInt16be :: Parser e Int16
+ FlatParse.Basic: anyInt16le :: Parser e Int16
+ FlatParse.Basic: anyInt32 :: Parser e Int32
+ FlatParse.Basic: anyInt32be :: Parser e Int32
+ FlatParse.Basic: anyInt32le :: Parser e Int32
+ FlatParse.Basic: anyInt64 :: Parser e Int64
+ FlatParse.Basic: anyInt64be :: Parser e Int64
+ FlatParse.Basic: anyInt64le :: Parser e Int64
+ FlatParse.Basic: anyInt8 :: Parser e Int8
+ FlatParse.Basic: anyWord16be :: Parser e Word16
+ FlatParse.Basic: anyWord16le :: Parser e Word16
+ FlatParse.Basic: anyWord32be :: Parser e Word32
+ FlatParse.Basic: anyWord32le :: Parser e Word32
+ FlatParse.Basic: anyWord64 :: Parser e Word64
+ FlatParse.Basic: anyWord64_ :: Parser e ()
+ FlatParse.Basic: anyWord64be :: Parser e Word64
+ FlatParse.Basic: anyWord64le :: Parser e Word64
+ FlatParse.Basic: withAnyInt16# :: (Int16'# -> Parser e a) -> Parser e a
+ FlatParse.Basic: withAnyInt32# :: (Int32'# -> Parser e a) -> Parser e a
+ FlatParse.Basic: withAnyInt64# :: (Int# -> Parser e a) -> Parser e a
+ FlatParse.Basic: withAnyInt8# :: (Int8'# -> Parser e a) -> Parser e a
+ FlatParse.Basic: withAnyWord16# :: (Word16'# -> Parser e a) -> Parser e a
+ FlatParse.Basic: withAnyWord32# :: (Word32'# -> Parser e a) -> Parser e a
+ FlatParse.Basic: withAnyWord64# :: (Word# -> Parser e a) -> Parser e a
+ FlatParse.Basic: withAnyWord8# :: (Word8'# -> Parser e a) -> Parser e a
+ FlatParse.Internal.UnboxedNumerics: byteSwap16'# :: Word16'# -> Word16'#
+ FlatParse.Internal.UnboxedNumerics: byteSwap32'# :: Word32'# -> Word32'#
+ FlatParse.Internal.UnboxedNumerics: eqWord16'# :: Word16'# -> Word16'# -> Int#
+ FlatParse.Internal.UnboxedNumerics: eqWord32'# :: Word32'# -> Word32'# -> Int#
+ FlatParse.Internal.UnboxedNumerics: eqWord8'# :: Word8'# -> Word8'# -> Int#
+ FlatParse.Internal.UnboxedNumerics: indexWord8OffAddr''# :: Addr# -> Int# -> Word8#
+ FlatParse.Internal.UnboxedNumerics: type Int16'# = Int#
+ FlatParse.Internal.UnboxedNumerics: type Int32'# = Int#
+ FlatParse.Internal.UnboxedNumerics: type Int8'# = Int#
+ FlatParse.Internal.UnboxedNumerics: type Word16'# = Word#
+ FlatParse.Internal.UnboxedNumerics: type Word32'# = Word#
+ FlatParse.Internal.UnboxedNumerics: type Word8'# = Word#
+ FlatParse.Internal.UnboxedNumerics: word16ToInt16# :: Word16'# -> Int#
+ FlatParse.Internal.UnboxedNumerics: word32ToInt32# :: Word32'# -> Int#
+ FlatParse.Internal.UnboxedNumerics: word8ToWord''# :: Word8# -> Word#
+ FlatParse.Internal.UnboxedNumerics: wordToWord8''# :: Word# -> Word8#
+ FlatParse.Stateful: anyInt :: Parser e Int
+ FlatParse.Stateful: anyInt16 :: Parser e Int16
+ FlatParse.Stateful: anyInt16be :: Parser e Int16
+ FlatParse.Stateful: anyInt16le :: Parser e Int16
+ FlatParse.Stateful: anyInt32 :: Parser e Int32
+ FlatParse.Stateful: anyInt32be :: Parser e Int32
+ FlatParse.Stateful: anyInt32le :: Parser e Int32
+ FlatParse.Stateful: anyInt64 :: Parser e Int64
+ FlatParse.Stateful: anyInt64be :: Parser e Int64
+ FlatParse.Stateful: anyInt64le :: Parser e Int64
+ FlatParse.Stateful: anyInt8 :: Parser e Int8
+ FlatParse.Stateful: anyWord16be :: Parser e Word16
+ FlatParse.Stateful: anyWord16le :: Parser e Word16
+ FlatParse.Stateful: anyWord32be :: Parser e Word32
+ FlatParse.Stateful: anyWord32le :: Parser e Word32
+ FlatParse.Stateful: anyWord64 :: Parser e Word64
+ FlatParse.Stateful: anyWord64_ :: Parser e ()
+ FlatParse.Stateful: anyWord64be :: Parser e Word64
+ FlatParse.Stateful: anyWord64le :: Parser e Word64
+ FlatParse.Stateful: withAnyInt16# :: (Int16'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyInt32# :: (Int32'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyInt64# :: (Int# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyInt8# :: (Int8'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyWord16# :: (Word16'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyWord32# :: (Word32'# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyWord64# :: (Word# -> Parser e a) -> Parser e a
+ FlatParse.Stateful: withAnyWord8# :: (Word8'# -> Parser e a) -> Parser e a
- FlatParse.Basic: anyWord16 :: Parser e Word
+ FlatParse.Basic: anyWord16 :: Parser e Word16
- FlatParse.Basic: anyWord32 :: Parser e Word
+ FlatParse.Basic: anyWord32 :: Parser e Word32
- FlatParse.Basic: byte :: Word -> Parser e ()
+ FlatParse.Basic: byte :: Word8 -> Parser e ()
- FlatParse.Basic: scan16# :: Word -> Parser e ()
+ FlatParse.Basic: scan16# :: Word16 -> Parser e ()
- FlatParse.Basic: scan32# :: Word -> Parser e ()
+ FlatParse.Basic: scan32# :: Word32 -> Parser e ()
- FlatParse.Basic: scan8# :: Word -> Parser e ()
+ FlatParse.Basic: scan8# :: Word8 -> Parser e ()
- FlatParse.Basic: scanAny8# :: Parser e Word
+ FlatParse.Basic: scanAny8# :: Parser e Word8
- FlatParse.Stateful: anyWord16 :: Parser e Word
+ FlatParse.Stateful: anyWord16 :: Parser e Word16
- FlatParse.Stateful: anyWord32 :: Parser e Word
+ FlatParse.Stateful: anyWord32 :: Parser e Word32
- FlatParse.Stateful: anyWord8 :: Parser e Word
+ FlatParse.Stateful: anyWord8 :: Parser e Word8
- FlatParse.Stateful: byte :: Word -> Parser e ()
+ FlatParse.Stateful: byte :: Word8 -> Parser e ()
- FlatParse.Stateful: scan16# :: Word -> Parser e ()
+ FlatParse.Stateful: scan16# :: Word16 -> Parser e ()
- FlatParse.Stateful: scan32# :: Word -> Parser e ()
+ FlatParse.Stateful: scan32# :: Word32 -> Parser e ()
- FlatParse.Stateful: scan8# :: Word -> Parser e ()
+ FlatParse.Stateful: scan8# :: Word8 -> Parser e ()
- FlatParse.Stateful: scanAny8# :: Parser e Word
+ FlatParse.Stateful: scanAny8# :: Parser e Word8

Files

flatparse.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           flatparse-version:        0.3.2.0+version:        0.3.3.0 synopsis:       High-performance parsing from strict bytestrings description:    @Flatparse@ is a high-performance parsing library, focusing on programming languages and                 human-readable data formats. See the README for more information:@@ -23,7 +23,8 @@     GHC == 8.6.5   , GHC == 8.8.4   , GHC == 8.10.7-  , GHC == 9.0.1+  , GHC == 9.0.2+  , GHC == 9.2.2 extra-source-files:     README.md @@ -47,6 +48,7 @@       FlatParse.Examples.BasicLambda.Lexer       FlatParse.Examples.BasicLambda.Parser       FlatParse.Internal+      FlatParse.Internal.UnboxedNumerics       FlatParse.Stateful   other-modules:       Paths_flatparse@@ -98,6 +100,7 @@   ghc-options: -Wall -Wno-missing-signatures -Wno-name-shadowing -Wno-unused-binds -Wno-unused-matches -O2 -Wno-type-defaults   build-depends:       HUnit+    , QuickCheck     , base >=4.7 && <5     , bytestring     , flatparse
src/FlatParse/Basic.hs view
@@ -52,8 +52,15 @@   , anyWord16_   , anyWord32   , anyWord32_+  , anyWord64+  , anyWord64_   , anyWord   , anyWord_+  , anyInt8+  , anyInt16+  , anyInt32+  , anyInt64+  , anyInt   , anyChar   , anyChar_   , anyCharASCII@@ -64,6 +71,20 @@   , FlatParse.Basic.readInt   , FlatParse.Basic.readInteger +  -- ** Explicit-endianness machine integers+  , anyWord16le+  , anyWord16be+  , anyWord32le+  , anyWord32be+  , anyWord64le+  , anyWord64be+  , anyInt16le+  , anyInt16be+  , anyInt32le+  , anyInt32be+  , anyInt64le+  , anyInt64be+   -- * Combinators   , (<|>)   , branch@@ -115,6 +136,15 @@   , scanBytes#   , setBack# +  , withAnyWord8#+  , withAnyWord16#+  , withAnyWord32#+  , withAnyWord64#+  , withAnyInt8#+  , withAnyInt16#+  , withAnyInt32#+  , withAnyInt64#+   ) where  import Control.Monad@@ -125,6 +155,7 @@ import Data.Word import GHC.Exts import GHC.Word+import GHC.Int import GHC.ForeignPtr import Language.Haskell.TH import System.IO.Unsafe@@ -135,6 +166,7 @@ import qualified Data.Map.Strict as M  import FlatParse.Internal+import FlatParse.Internal.UnboxedNumerics  -------------------------------------------------------------------------------- @@ -334,8 +366,8 @@ char c = string [c]  -- | Read a `Word8`.-byte :: Word -> Parser e ()-byte (W# w) = ensureBytes# 1 >> scan8# (W# w)+byte :: Word8 -> Parser e ()+byte w = ensureBytes# 1 >> scan8# w {-# inline byte #-}  -- | Read a sequence of bytes. This is a template function, you can use it as @$(bytes [3, 4, 5])@,@@ -507,58 +539,6 @@ fusedSatisfy_ f1 f2 f3 f4 = () <$ fusedSatisfy f1 f2 f3 f4 {-# inline fusedSatisfy_ #-} --- | Parse any `Word8`.-anyWord8 :: Parser e Word8-anyWord8 = Parser \fp eob buf -> case eqAddr# eob buf of-  1# -> Fail#-  _  -> case indexWord8OffAddr# buf 0# of-    w -> OK# (W8# w) (plusAddr# buf 1#)-{-# inline anyWord8 #-}---- | Skip any `Word8`.-anyWord8_ :: Parser e ()-anyWord8_ = () <$ anyWord8-{-# inline anyWord8_ #-}---- | Parse any `Word16`.-anyWord16 :: Parser e Word-anyWord16 = Parser \fp eob buf -> case 2# <=# minusAddr# eob buf of-  0# -> Fail#-  _  -> case indexWord16OffAddr buf 0# of-    w -> OK# (W# w) (plusAddr# buf 2#)-{-# inline anyWord16 #-}---- | Skip any `Word16`.-anyWord16_ :: Parser e ()-anyWord16_ = () <$ anyWord16-{-# inline anyWord16_ #-}---- | Parse any `Word32`.-anyWord32 :: Parser e Word-anyWord32 = Parser \fp eob buf -> case 4# <=# minusAddr# eob buf of-  0# -> Fail#-  _  -> case indexWord32OffAddr buf 0# of-    w -> OK# (W# w) (plusAddr# buf 4#)-{-# inline anyWord32 #-}---- | Skip any `Word32`.-anyWord32_ :: Parser e ()-anyWord32_ = () <$ anyWord32-{-# inline anyWord32_ #-}---- | Parse any `Word`.-anyWord :: Parser e Word-anyWord = Parser \fp eob buf -> case 8# <=# minusAddr# eob buf of-  0# -> Fail#-  _  -> case indexWordOffAddr# buf 0# of-    w -> OK# (W# w) (plusAddr# buf 8#)-{-# inline anyWord #-}---- | Skip any `Word`.-anyWord_ :: Parser e ()-anyWord_ = () <$ anyWord-{-# inline anyWord_ #-}- -- | Parse any UTF-8-encoded `Char`. anyChar :: Parser e Char anyChar = Parser \fp eob buf -> case eqAddr# eob buf of@@ -902,30 +882,30 @@  -- | Unsafely read a concrete byte from the input. It's not checked that the input has --   enough bytes.-scan8# :: Word -> Parser e ()-scan8# (W# c) = Parser \fp eob s ->-  case indexWord8OffAddr s 0# of-    c' -> case eqWord# c c' of+scan8# :: Word8 -> Parser e ()+scan8# (W8# c) = Parser \fp eob s ->+  case indexWord8OffAddr# s 0# of+    c' -> case eqWord8'# c c' of       1# -> OK# () (plusAddr# s 1#)       _  -> Fail# {-# inline scan8# #-}  -- | Unsafely read two concrete bytes from the input. It's not checked that the input has --   enough bytes.-scan16# :: Word -> Parser e ()-scan16# (W# c) = Parser \fp eob s ->-  case indexWord16OffAddr s 0# of-    c' -> case eqWord# c c' of+scan16# :: Word16 -> Parser e ()+scan16# (W16# c) = Parser \fp eob s ->+  case indexWord16OffAddr# s 0# of+    c' -> case eqWord16'# c c' of       1# -> OK# () (plusAddr# s 2#)       _  -> Fail# {-# inline scan16# #-}  -- | Unsafely read four concrete bytes from the input. It's not checked that the input has --   enough bytes.-scan32# :: Word -> Parser e ()-scan32# (W# c) = Parser \fp eob s ->-  case indexWord32OffAddr s 0# of-    c' -> case eqWord# c c' of+scan32# :: Word32 -> Parser e ()+scan32# (W32# c) = Parser \fp eob s ->+  case indexWord32OffAddr# s 0# of+    c' -> case eqWord32'# c c' of       1# -> OK# () (plusAddr# s 4#)       _  -> Fail# {-# inline scan32# #-}@@ -934,15 +914,15 @@ --   enough bytes. scan64# :: Word -> Parser e () scan64# (W# c) = Parser \fp eob s ->-  case indexWord64OffAddr s 0# of+  case indexWord64OffAddr# s 0# of     c' -> case eqWord# c c' of       1# -> OK# () (plusAddr# s 8#)       _  -> Fail# {-# inline scan64# #-}  -- | Unsafely read and return a byte from the input. It's not checked that the input is non-empty.-scanAny8# :: Parser e Word-scanAny8# = Parser \fp eob s -> OK# (W# (indexWord8OffAddr s 0#)) (plusAddr# s 1#)+scanAny8# :: Parser e Word8+scanAny8# = Parser \fp eob s -> OK# (W8# (indexWord8OffAddr# s 0#)) (plusAddr# s 1#) {-# inline scanAny8# #-}  scanPartial64# :: Int -> Word -> Parser e ()@@ -1076,3 +1056,204 @@       !m    = M.fromList ((Nothing, maybe (VarE 'empty) id fallback) : branches)       !trie = compileTrie strings   in (m , trie)++--------------------------------------------------------------------------------++withAnyWord8# :: (Word8'# -> Parser e a) -> Parser e a+withAnyWord8# p = Parser \fp eob buf -> case eqAddr# eob buf of+  1# -> Fail#+  _  -> case indexWord8OffAddr# buf 0# of+    w# -> runParser# (p w#) fp eob (plusAddr# buf 1#)+{-# inline withAnyWord8# #-}++withAnyWord16# :: (Word16'# -> Parser e a) -> Parser e a+withAnyWord16# p = Parser \fp eob buf -> case 2# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexWord16OffAddr# buf 0# of+    w# -> runParser# (p w#) fp eob (plusAddr# buf 2#)+{-# inline withAnyWord16# #-}++withAnyWord32# :: (Word32'# -> Parser e a) -> Parser e a+withAnyWord32# p = Parser \fp eob buf -> case 4# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexWord32OffAddr# buf 0# of+    w# -> runParser# (p w#) fp eob (plusAddr# buf 4#)+{-# inline withAnyWord32# #-}++withAnyWord64# :: (Word# -> Parser e a) -> Parser e a+withAnyWord64# p = Parser \fp eob buf -> case 8# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexWordOffAddr# buf 0# of+    w# -> runParser# (p w#) fp eob (plusAddr# buf 8#)+{-# inline withAnyWord64# #-}++withAnyInt8# :: (Int8'# -> Parser e a) -> Parser e a+withAnyInt8# p = Parser \fp eob buf -> case eqAddr# eob buf of+  1# -> Fail#+  _  -> case indexInt8OffAddr# buf 0# of+    i# -> runParser# (p i#) fp eob (plusAddr# buf 1#)+{-# inline withAnyInt8# #-}++withAnyInt16# :: (Int16'# -> Parser e a) -> Parser e a+withAnyInt16# p = Parser \fp eob buf -> case 2# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexInt16OffAddr# buf 0# of+    i# -> runParser# (p i#) fp eob (plusAddr# buf 2#)+{-# inline withAnyInt16# #-}++withAnyInt32# :: (Int32'# -> Parser e a) -> Parser e a+withAnyInt32# p = Parser \fp eob buf -> case 4# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexInt32OffAddr# buf 0# of+    i# -> runParser# (p i#) fp eob (plusAddr# buf 4#)+{-# inline withAnyInt32# #-}++withAnyInt64# :: (Int# -> Parser e a) -> Parser e a+withAnyInt64# p = Parser \fp eob buf -> case 8# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexInt64OffAddr# buf 0# of+    i# -> runParser# (p i#) fp eob (plusAddr# buf 8#)+{-# inline withAnyInt64# #-}++--------------------------------------------------------------------------------++-- | Parse any 'Word8' (byte).+anyWord8 :: Parser e Word8+anyWord8 = withAnyWord8# (\w# -> pure (W8# w#))+{-# inline anyWord8 #-}++-- | Skip any 'Word8' (byte).+anyWord8_ :: Parser e ()+anyWord8_ = () <$ anyWord8+{-# inline anyWord8_ #-}++-- | Parse any 'Word16'.+anyWord16 :: Parser e Word16+anyWord16 = withAnyWord16# (\w# -> pure (W16# w#))+{-# inline anyWord16 #-}++-- | Skip any 'Word16'.+anyWord16_ :: Parser e ()+anyWord16_ = () <$ anyWord16+{-# inline anyWord16_ #-}++-- | Parse any 'Word32'.+anyWord32 :: Parser e Word32+anyWord32 = withAnyWord32# (\w# -> pure (W32# w#))+{-# inline anyWord32 #-}++-- | Skip any 'Word32'.+anyWord32_ :: Parser e ()+anyWord32_ = () <$ anyWord32+{-# inline anyWord32_ #-}++-- | Parse any 'Word64'.+anyWord64 :: Parser e Word64+anyWord64 = withAnyWord64# (\w# -> pure (W64# w#))+{-# inline anyWord64 #-}++-- | Skip any 'Word64'.+anyWord64_ :: Parser e ()+anyWord64_ = () <$ anyWord64+{-# inline anyWord64_ #-}++-- | Parse any 'Word'.+anyWord :: Parser e Word+anyWord = withAnyWord64# (\w# -> pure (W# w#))+{-# inline anyWord #-}++-- | Skip any 'Word'.+anyWord_ :: Parser e ()+anyWord_ = () <$ anyWord+{-# inline anyWord_ #-}++--------------------------------------------------------------------------------++-- | Parse any 'Int8'.+anyInt8 :: Parser e Int8+anyInt8 = withAnyInt8# (\i# -> pure (I8# i#))+{-# inline anyInt8 #-}++-- | Parse any 'Int16'.+anyInt16 :: Parser e Int16+anyInt16 = withAnyInt16# (\i# -> pure (I16# i#))+{-# inline anyInt16 #-}++-- | Parse any 'Int32'.+anyInt32 :: Parser e Int32+anyInt32 = withAnyInt32# (\i# -> pure (I32# i#))+{-# inline anyInt32 #-}++-- | Parse any 'Int64'.+anyInt64 :: Parser e Int64+anyInt64 = withAnyInt64# (\i# -> pure (I64# i#))+{-# inline anyInt64 #-}++-- | Parse any 'Int'.+anyInt :: Parser e Int+anyInt = withAnyInt64# (\i# -> pure (I# i#))+{-# inline anyInt #-}++--------------------------------------------------------------------------------++-- | Parse any 'Word16' (little-endian).+anyWord16le :: Parser e Word16+anyWord16le = anyWord16+{-# inline anyWord16le #-}++-- | Parse any 'Word16' (big-endian).+anyWord16be :: Parser e Word16+anyWord16be = withAnyWord16# (\w# -> pure (W16# (byteSwap16'# w#)))+{-# inline anyWord16be #-}++-- | Parse any 'Word32' (little-endian).+anyWord32le :: Parser e Word32+anyWord32le = anyWord32+{-# inline anyWord32le #-}++-- | Parse any 'Word32' (big-endian).+anyWord32be :: Parser e Word32+anyWord32be = withAnyWord32# (\w# -> pure (W32# (byteSwap32'# w#)))+{-# inline anyWord32be #-}++-- | Parse any 'Word64' (little-endian).+anyWord64le :: Parser e Word64+anyWord64le = anyWord64+{-# inline anyWord64le #-}++-- | Parse any 'Word64' (big-endian).+anyWord64be :: Parser e Word64+anyWord64be = withAnyWord64# (\w# -> pure (W64# (byteSwap# w#)))+{-# inline anyWord64be #-}++--------------------------------------------------------------------------------++-- | Parse any 'Int16' (little-endian).+anyInt16le :: Parser e Int16+anyInt16le = anyInt16+{-# inline anyInt16le #-}++-- | Parse any 'Int16' (big-endian).+anyInt16be :: Parser e Int16+anyInt16be = withAnyWord16# (\w# -> pure (I16# (word16ToInt16# (byteSwap16'# w#))))+{-# inline anyInt16be #-}++-- | Parse any 'Int32' (little-endian).+anyInt32le :: Parser e Int32+anyInt32le = anyInt32+{-# inline anyInt32le #-}++-- | Parse any 'Int32' (big-endian).+anyInt32be :: Parser e Int32+anyInt32be = withAnyWord32# (\w# -> pure (I32# (word32ToInt32# (byteSwap32'# w#))))+{-# inline anyInt32be #-}++-- | Parse any 'Int64' (little-endian).+anyInt64le :: Parser e Int64+anyInt64le = anyInt64+{-# inline anyInt64le #-}++-- | Parse any 'Int64' (big-endian).+anyInt64be :: Parser e Int64+anyInt64be = withAnyWord64# (\w# -> pure (I64# (word2Int# (byteSwap# w#))))+{-# inline anyInt64be #-}
src/FlatParse/Internal.hs view
@@ -2,6 +2,8 @@  module FlatParse.Internal where +import FlatParse.Internal.UnboxedNumerics+ import Data.Bits import Data.Char import Data.Foldable (foldl')@@ -31,23 +33,7 @@ #endif {-# inline shortInteger #-} -#if MIN_VERSION_base(4,16,0)-indexWord8OffAddr s x = word8ToWord# (indexWord8OffAddr# s x)-indexWord16OffAddr s x = word16ToWord# (indexWord16OffAddr# s x)-indexWord32OffAddr s x = word32ToWord# (indexWord32OffAddr# s x)-indexWord64OffAddr s x = indexWord64OffAddr# s x-#else-indexWord8OffAddr  = indexWord8OffAddr#-indexWord16OffAddr = indexWord16OffAddr#-indexWord32OffAddr = indexWord32OffAddr#-indexWord64OffAddr = indexWord64OffAddr#-#endif-{-# inline indexWord8OffAddr #-}-{-# inline indexWord16OffAddr #-}-{-# inline indexWord32OffAddr #-}-{-# inline indexWord64OffAddr #-} - -- Char predicates -------------------------------------------------------------------------------- @@ -76,9 +62,9 @@ readInt' :: Int# -> Addr# -> Addr# -> (# Int#, Addr# #) readInt' acc s end = case eqAddr# s end of   1# -> (# acc, s #)-  _  -> case indexWord8OffAddr s 0# of-    w | 1# <- leWord# 48## w, 1# <- leWord# w 57## ->-      readInt' (mul10 acc +# (word2Int# w -# 48#)) (plusAddr# s 1#) end+  _  -> case indexWord8OffAddr''# s 0# of+    w | 1# <- leWord8# (wordToWord8''# 0x30##) w, 1# <- leWord8# w (wordToWord8''# 0x39##) ->+      readInt' (mul10 acc +# (word2Int# (word8ToWord''# w) -# 0x30#)) (plusAddr# s 1#) end     _ -> (# acc, s #)  
+ src/FlatParse/Internal/UnboxedNumerics.hs view
@@ -0,0 +1,113 @@+{- | Compatibility layer for numeric primops.++GHC 9.2 standardized unboxed numeric primops. Prior, it was quite asymmetric.+Many primop functions used the native unboxed numerics 'Word#' and 'Int#' even+if a sized unboxed numeric was in the name, e.g. 'indexWord8OffAddr#' returning+'Word#' pre-9.2. All boxed machine integers only stored 'Word#' internally!++We target GHC 9.2's better handling. In order to maintain compatibility with+older GHCs, we define missing primops and wrap ones that changed type. Usually,+we can write a few wrappers so that 9.2 uses sized unboxed numerics everywhere,+and pre-9.2 uses native unboxed numerics everywhere. Sometimes we really want to+work with sized unboxed numerics on both, in which case we have to do more+involved primop wrapping.++The general pattern is as follows:++  * A ticked primop means it's sized on >=9.2, native on <9.2+  * A double-ticked primop means it's sized on all+  * An unticked primop should mean the same as a ticked primop (no guarantees)++Also see: https://gitlab.haskell.org/ghc/ghc/-/wikis/Unboxed-Numerics+-}++module FlatParse.Internal.UnboxedNumerics where++import GHC.Exts++-- "Switch" wrappers: sized on >=9.2, native on <9.2+byteSwap16'# :: Word16'# -> Word16'#+byteSwap32'# :: Word32'# -> Word32'#+eqWord8'# :: Word8'# -> Word8'# -> Int#+eqWord16'# :: Word16'# -> Word16'# -> Int#+eqWord32'# :: Word32'# -> Word32'# -> Int#+{-# inline byteSwap16'# #-}+{-# inline byteSwap32'# #-}+{-# inline eqWord8'#    #-}+{-# inline eqWord16'#   #-}+{-# inline eqWord32'#   #-}++-- "Sized" wrappers: sized on all+indexWord8OffAddr''# :: Addr# -> Int# -> Word8#+wordToWord8''# :: Word# -> Word8#+word8ToWord''# :: Word8# -> Word#+{-# inline indexWord8OffAddr''#  #-}+{-# inline wordToWord8''# #-}+{-# inline word8ToWord''# #-}++#if MIN_VERSION_base(4,16,0)+-- GHC >=9.2++type Word8'#  = Word8#+type Word16'# = Word16#+type Word32'# = Word32#+type Int8'#   = Int8#+type Int16'#  = Int16#+type Int32'#  = Int32#++-- "Switch" wrappers: sized on >=9.2, native on <9.2+byteSwap16'# w# = wordToWord16# (byteSwap16# (word16ToWord# w#))+byteSwap32'# w# = wordToWord32# (byteSwap32# (word32ToWord# w#))+eqWord8'# = eqWord8#+eqWord16'# = eqWord16#+eqWord32'# = eqWord32#++-- "Sized" wrappers: sized on all+indexWord8OffAddr''# = indexWord8OffAddr#+wordToWord8''# = wordToWord8#+word8ToWord''# = word8ToWord#++#else+-- GHC <9.2++type Word8'#  = Word#+type Word16'# = Word#+type Word32'# = Word#+type Int8'#   = Int#+type Int16'#  = Int#+type Int32'#  = Int#++-- "Switch" wrappers: sized on >=9.2, native on <9.2+byteSwap16'# = byteSwap16#+byteSwap32'# = byteSwap32#+eqWord8'# = eqWord#+eqWord16'# = eqWord#+eqWord32'# = eqWord#++-- No need to tick wrap these, they didn't exist <9.2+word16ToInt16# :: Word16'# -> Int#+word16ToInt16# w = narrow16Int# (word2Int# w)+word32ToInt32# :: Word32'# -> Int#+word32ToInt32# w = narrow32Int# (word2Int# w)+{-# inline word16ToInt16# #-}+{-# inline word32ToInt32# #-}++-- "Sized" wrappers: sized on all+indexWord8OffAddr''# a# i# = narrowWord8# (indexWord8OffAddr# a# i#)+wordToWord8''# = narrowWord8#+word8ToWord''# = extendWord8#++#endif++#if !MIN_VERSION_base(4,13,0)+-- GHC <8.8++type Word8# = Word#+narrowWord8# :: Word# -> Word8#+narrowWord8# = narrow8Word#+extendWord8# :: Word# -> Word8#+extendWord8# w# = w#+leWord8# :: Word8# -> Word8# -> Int#+leWord8# w1# w2# = leWord# w1# w2#++#endif
src/FlatParse/Stateful.hs view
@@ -58,8 +58,15 @@   , anyWord16_   , anyWord32   , anyWord32_+  , anyWord64+  , anyWord64_   , anyWord   , anyWord_+  , anyInt8+  , anyInt16+  , anyInt32+  , anyInt64+  , anyInt   , anyChar   , anyChar_   , anyCharASCII@@ -70,6 +77,20 @@   , FlatParse.Stateful.readInt   , FlatParse.Stateful.readInteger +  -- ** Explicit-endianness machine integers+  , anyWord16le+  , anyWord16be+  , anyWord32le+  , anyWord32be+  , anyWord64le+  , anyWord64be+  , anyInt16le+  , anyInt16be+  , anyInt32le+  , anyInt32be+  , anyInt64le+  , anyInt64be+   -- * Combinators   , (<|>)   , branch@@ -121,12 +142,23 @@   , scanBytes#   , setBack# +  , withAnyWord8#+  , withAnyWord16#+  , withAnyWord32#+  , withAnyWord64#+  , withAnyInt8#+  , withAnyInt16#+  , withAnyInt32#+  , withAnyInt64#+   ) where  import Control.Monad import Data.Foldable import Data.Map (Map) import GHC.Exts+import GHC.Word+import GHC.Int import Language.Haskell.TH import System.IO.Unsafe import GHC.ForeignPtr@@ -137,6 +169,7 @@ import qualified Data.Map.Strict as M  import FlatParse.Internal+import FlatParse.Internal.UnboxedNumerics  import qualified FlatParse.Basic as Basic @@ -367,8 +400,8 @@ char c = string [c]  -- | Read a byte.-byte :: Word -> Parser e ()-byte (W# w) = ensureBytes# 1 >> scan8# (W# w)+byte :: Word8 -> Parser e ()+byte w = ensureBytes# 1 >> scan8# w {-# inline byte #-}  -- | Read a sequence of bytes. This is a template function, you can use it as @$(bytes [3, 4, 5])@,@@ -536,58 +569,6 @@ fusedSatisfy_ f1 f2 f3 f4 = () <$ fusedSatisfy f1 f2 f3 f4 {-# inline fusedSatisfy_ #-} --- | Parse any byte.-anyWord8 :: Parser e Word-anyWord8 = Parser \fp !r eob buf n -> case eqAddr# eob buf of-  1# -> Fail#-  _  -> case indexWord8OffAddr buf 0# of-    w -> OK# (W# w) (plusAddr# buf 1#) n-{-# inline anyWord8 #-}---- | Skip any byte.-anyWord8_ :: Parser e ()-anyWord8_ = () <$ anyWord8-{-# inline anyWord8_ #-}---- | Parse any `Word16`.-anyWord16 :: Parser e Word-anyWord16 = Parser \fp !r eob buf n -> case 2# <=# minusAddr# eob buf of-  0# -> Fail#-  _  -> case indexWord16OffAddr buf 0# of-    w -> OK# (W# w) (plusAddr# buf 2#) n-{-# inline anyWord16 #-}---- | Skip any `Word16`.-anyWord16_ :: Parser e ()-anyWord16_ = () <$ anyWord16-{-# inline anyWord16_ #-}---- | Parse any `Word32`.-anyWord32 :: Parser e Word-anyWord32 = Parser \fp !r eob buf n -> case 4# <=# minusAddr# eob buf of-  0# -> Fail#-  _  -> case indexWord32OffAddr buf 0# of-    w -> OK# (W# w) (plusAddr# buf 4#) n-{-# inline anyWord32 #-}---- | Skip any `Word32`.-anyWord32_ :: Parser e ()-anyWord32_ = () <$ anyWord32-{-# inline anyWord32_ #-}---- | Parse any `Word`.-anyWord :: Parser e Word-anyWord = Parser \fp !r eob buf n -> case 8# <=# minusAddr# eob buf of-  0# -> Fail#-  _  -> case indexWordOffAddr# buf 0# of-    w -> OK# (W# w) (plusAddr# buf 8#) n-{-# inline anyWord #-}---- | Skip any `Word`.-anyWord_ :: Parser e ()-anyWord_ = () <$ anyWord-{-# inline anyWord_ #-}- -- | Parse any UTF-8-encoded `Char`. anyChar :: Parser e Char anyChar = Parser \fp !r eob buf n -> case eqAddr# eob buf of@@ -876,30 +857,30 @@  -- | Unsafely read a concrete byte from the input. It's not checked that the input has --   enough bytes.-scan8# :: Word -> Parser e ()-scan8# (W# c) = Parser \fp !r eob s n ->-  case indexWord8OffAddr s 0# of-    c' -> case eqWord# c c' of+scan8# :: Word8 -> Parser e ()+scan8# (W8# c) = Parser \fp !r eob s n ->+  case indexWord8OffAddr# s 0# of+    c' -> case eqWord8'# c c' of       1# -> OK# () (plusAddr# s 1#) n       _  -> Fail# {-# inline scan8# #-}  -- | Unsafely read two concrete bytes from the input. It's not checked that the input has --   enough bytes.-scan16# :: Word -> Parser e ()-scan16# (W# c) = Parser \fp !r eob s n ->-  case indexWord16OffAddr s 0# of-    c' -> case eqWord# c c' of+scan16# :: Word16 -> Parser e ()+scan16# (W16# c) = Parser \fp !r eob s n ->+  case indexWord16OffAddr# s 0# of+    c' -> case eqWord16'# c c' of       1# -> OK# () (plusAddr# s 2#) n       _  -> Fail# {-# inline scan16# #-}  -- | Unsafely read four concrete bytes from the input. It's not checked that the input has --   enough bytes.-scan32# :: Word -> Parser e ()-scan32# (W# c) = Parser \fp !r eob s n ->-  case indexWord32OffAddr s 0# of-    c' -> case eqWord# c c' of+scan32# :: Word32 -> Parser e ()+scan32# (W32# c) = Parser \fp !r eob s n ->+  case indexWord32OffAddr# s 0# of+    c' -> case eqWord32'# c c' of       1# -> OK# () (plusAddr# s 4#) n       _  -> Fail# {-# inline scan32# #-}@@ -908,15 +889,15 @@ --   enough bytes. scan64# :: Word -> Parser e () scan64# (W# c) = Parser \fp !r eob s n ->-  case indexWord64OffAddr s 0# of+  case indexWord64OffAddr# s 0# of     c' -> case eqWord# c c' of       1# -> OK# () (plusAddr# s 8#) n       _  -> Fail# {-# inline scan64# #-}  -- | Unsafely read and return a byte from the input. It's not checked that the input is non-empty.-scanAny8# :: Parser e Word-scanAny8# = Parser \fp !r eob s n -> OK# (W# (indexWord8OffAddr s 0#)) (plusAddr# s 1#) n+scanAny8# :: Parser e Word8+scanAny8# = Parser \fp !r eob s n -> OK# (W8# (indexWord8OffAddr# s 0#)) (plusAddr# s 1#) n {-# inline scanAny8# #-}  scanPartial64# :: Int -> Word -> Parser e ()@@ -1050,3 +1031,204 @@       !m    =  M.fromList ((Nothing, maybe (VarE 'empty) id fallback) : branches)       !trie = compileTrie strings   in (m , trie)++--------------------------------------------------------------------------------++withAnyWord8# :: (Word8'# -> Parser e a) -> Parser e a+withAnyWord8# p = Parser \fp !r eob buf n -> case eqAddr# eob buf of+  1# -> Fail#+  _  -> case indexWord8OffAddr# buf 0# of+    w# -> runParser# (p w#) fp r eob (plusAddr# buf 1#) n+{-# inline withAnyWord8# #-}++withAnyWord16# :: (Word16'# -> Parser e a) -> Parser e a+withAnyWord16# p = Parser \fp !r eob buf n -> case 2# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexWord16OffAddr# buf 0# of+    w# -> runParser# (p w#) fp r eob (plusAddr# buf 2#) n+{-# inline withAnyWord16# #-}++withAnyWord32# :: (Word32'# -> Parser e a) -> Parser e a+withAnyWord32# p = Parser \fp !r eob buf n -> case 4# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexWord32OffAddr# buf 0# of+    w# -> runParser# (p w#) fp r eob (plusAddr# buf 4#) n+{-# inline withAnyWord32# #-}++withAnyWord64# :: (Word# -> Parser e a) -> Parser e a+withAnyWord64# p = Parser \fp !r eob buf n -> case 8# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexWordOffAddr# buf 0# of+    w# -> runParser# (p w#) fp r eob (plusAddr# buf 8#) n+{-# inline withAnyWord64# #-}++withAnyInt8# :: (Int8'# -> Parser e a) -> Parser e a+withAnyInt8# p = Parser \fp !r eob buf n -> case eqAddr# eob buf of+  1# -> Fail#+  _  -> case indexInt8OffAddr# buf 0# of+    i# -> runParser# (p i#) fp r eob (plusAddr# buf 1#) n+{-# inline withAnyInt8# #-}++withAnyInt16# :: (Int16'# -> Parser e a) -> Parser e a+withAnyInt16# p = Parser \fp !r eob buf n -> case 2# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexInt16OffAddr# buf 0# of+    i# -> runParser# (p i#) fp r eob (plusAddr# buf 2#) n+{-# inline withAnyInt16# #-}++withAnyInt32# :: (Int32'# -> Parser e a) -> Parser e a+withAnyInt32# p = Parser \fp !r eob buf n -> case 4# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexInt32OffAddr# buf 0# of+    i# -> runParser# (p i#) fp r eob (plusAddr# buf 4#) n+{-# inline withAnyInt32# #-}++withAnyInt64# :: (Int# -> Parser e a) -> Parser e a+withAnyInt64# p = Parser \fp !r eob buf n -> case 8# <=# minusAddr# eob buf of+  0# -> Fail#+  _  -> case indexInt64OffAddr# buf 0# of+    i# -> runParser# (p i#) fp r eob (plusAddr# buf 8#) n+{-# inline withAnyInt64# #-}++--------------------------------------------------------------------------------++-- | Parse any 'Word8' (byte).+anyWord8 :: Parser e Word8+anyWord8 = withAnyWord8# (\w# -> pure (W8# w#))+{-# inline anyWord8 #-}++-- | Skip any 'Word8' (byte).+anyWord8_ :: Parser e ()+anyWord8_ = () <$ anyWord8+{-# inline anyWord8_ #-}++-- | Parse any 'Word16'.+anyWord16 :: Parser e Word16+anyWord16 = withAnyWord16# (\w# -> pure (W16# w#))+{-# inline anyWord16 #-}++-- | Skip any 'Word16'.+anyWord16_ :: Parser e ()+anyWord16_ = () <$ anyWord16+{-# inline anyWord16_ #-}++-- | Parse any 'Word32'.+anyWord32 :: Parser e Word32+anyWord32 = withAnyWord32# (\w# -> pure (W32# w#))+{-# inline anyWord32 #-}++-- | Skip any 'Word32'.+anyWord32_ :: Parser e ()+anyWord32_ = () <$ anyWord32+{-# inline anyWord32_ #-}++-- | Parse any 'Word64'.+anyWord64 :: Parser e Word64+anyWord64 = withAnyWord64# (\w# -> pure (W64# w#))+{-# inline anyWord64 #-}++-- | Skip any 'Word64'.+anyWord64_ :: Parser e ()+anyWord64_ = () <$ anyWord64+{-# inline anyWord64_ #-}++-- | Parse any 'Word'.+anyWord :: Parser e Word+anyWord = withAnyWord64# (\w# -> pure (W# w#))+{-# inline anyWord #-}++-- | Skip any 'Word'.+anyWord_ :: Parser e ()+anyWord_ = () <$ anyWord+{-# inline anyWord_ #-}++--------------------------------------------------------------------------------++-- | Parse any 'Int8'.+anyInt8 :: Parser e Int8+anyInt8 = withAnyInt8# (\i# -> pure (I8# i#))+{-# inline anyInt8 #-}++-- | Parse any 'Int16'.+anyInt16 :: Parser e Int16+anyInt16 = withAnyInt16# (\i# -> pure (I16# i#))+{-# inline anyInt16 #-}++-- | Parse any 'Int32'.+anyInt32 :: Parser e Int32+anyInt32 = withAnyInt32# (\i# -> pure (I32# i#))+{-# inline anyInt32 #-}++-- | Parse any 'Int64'.+anyInt64 :: Parser e Int64+anyInt64 = withAnyInt64# (\i# -> pure (I64# i#))+{-# inline anyInt64 #-}++-- | Parse any 'Int'.+anyInt :: Parser e Int+anyInt = withAnyInt64# (\i# -> pure (I# i#))+{-# inline anyInt #-}++--------------------------------------------------------------------------------++-- | Parse any 'Word16' (little-endian).+anyWord16le :: Parser e Word16+anyWord16le = anyWord16+{-# inline anyWord16le #-}++-- | Parse any 'Word16' (big-endian).+anyWord16be :: Parser e Word16+anyWord16be = withAnyWord16# (\w# -> pure (W16# (byteSwap16'# w#)))+{-# inline anyWord16be #-}++-- | Parse any 'Word32' (little-endian).+anyWord32le :: Parser e Word32+anyWord32le = anyWord32+{-# inline anyWord32le #-}++-- | Parse any 'Word32' (big-endian).+anyWord32be :: Parser e Word32+anyWord32be = withAnyWord32# (\w# -> pure (W32# (byteSwap32'# w#)))+{-# inline anyWord32be #-}++-- | Parse any 'Word64' (little-endian).+anyWord64le :: Parser e Word64+anyWord64le = anyWord64+{-# inline anyWord64le #-}++-- | Parse any 'Word64' (big-endian).+anyWord64be :: Parser e Word64+anyWord64be = withAnyWord64# (\w# -> pure (W64# (byteSwap# w#)))+{-# inline anyWord64be #-}++--------------------------------------------------------------------------------++-- | Parse any 'Int16' (little-endian).+anyInt16le :: Parser e Int16+anyInt16le = anyInt16+{-# inline anyInt16le #-}++-- | Parse any 'Int16' (big-endian).+anyInt16be :: Parser e Int16+anyInt16be = withAnyWord16# (\w# -> pure (I16# (word16ToInt16# (byteSwap16'# w#))))+{-# inline anyInt16be #-}++-- | Parse any 'Int32' (little-endian).+anyInt32le :: Parser e Int32+anyInt32le = anyInt32+{-# inline anyInt32le #-}++-- | Parse any 'Int32' (big-endian).+anyInt32be :: Parser e Int32+anyInt32be = withAnyWord32# (\w# -> pure (I32# (word32ToInt32# (byteSwap32'# w#))))+{-# inline anyInt32be #-}++-- | Parse any 'Int64' (little-endian).+anyInt64le :: Parser e Int64+anyInt64le = anyInt64+{-# inline anyInt64le #-}++-- | Parse any 'Int64' (big-endian).+anyInt64be :: Parser e Int64+anyInt64be = withAnyWord64# (\w# -> pure (I64# (word2Int# (byteSwap# w#))))+{-# inline anyInt64be #-}
test/Test.hs view
@@ -1,9 +1,16 @@+{-# LANGUAGE ScopedTypeVariables #-}+ module Main where  import Data.ByteString (ByteString)+import qualified Data.ByteString as B import FlatParse.Basic import Test.HUnit import Test.Hspec+import Test.Hspec.QuickCheck+import Data.Word+import Data.Int+import Data.Bits  main :: IO () main = hspec $ do@@ -201,6 +208,39 @@     describe "readInteger" $ do       pure () +    describe "Explicit-endianness machine integers" $ do+      describe "Unsigned" $ do+        prop "parses Word8s" $ do+          \(w :: Word8)  -> anyWord8    `shouldParseWith` (w8AsByteString w, w)+        prop "parses Word16s (LE)" $ do+          \(w :: Word16) -> anyWord16le `shouldParseWith` (w16leAsByteString w, w)+        prop "parses Word16s (BE)" $ do+          \(w :: Word16) -> anyWord16be `shouldParseWith` (B.reverse (w16leAsByteString w), w)+        prop "parses Word32s (LE)" $ do+          \(w :: Word32) -> anyWord32le `shouldParseWith` (w32leAsByteString w, w)+        prop "parses Word32s (BE)" $ do+          \(w :: Word32) -> anyWord32be `shouldParseWith` (B.reverse (w32leAsByteString w), w)+        prop "parses Word64s (LE)" $ do+          \(w :: Word64) -> anyWord64le `shouldParseWith` (w64leAsByteString w, w)+        prop "parses Word64s (BE)" $ do+          \(w :: Word64) -> anyWord64be `shouldParseWith` (B.reverse (w64leAsByteString w), w)++      describe "Signed" $ do+        prop "parses Int8s" $ do+          \(i :: Int8)   -> anyInt8     `shouldParseWith` (w8AsByteString i, i)+        prop "parses Int16s (LE)" $ do+          \(i :: Int16)  -> anyInt16le  `shouldParseWith` (w16leAsByteString i, i)+        prop "parses Int16s (BE)" $ do+          \(i :: Int16)  -> anyInt16be  `shouldParseWith` (B.reverse (w16leAsByteString i), i)+        prop "parses Int32s (LE)" $ do+          \(i :: Int32)  -> anyInt32le  `shouldParseWith` (w32leAsByteString i, i)+        prop "parses Int32s (BE)" $ do+          \(i :: Int32)  -> anyInt32be  `shouldParseWith` (B.reverse (w32leAsByteString i), i)+        prop "parses Int64s (LE)" $ do+          \(i :: Int64)  -> anyInt64le  `shouldParseWith` (w64leAsByteString i, i)+        prop "parses Int64s (BE)" $ do+          \(i :: Int64)  -> anyInt64be  `shouldParseWith` (B.reverse (w64leAsByteString i), i)+   describe "Combinators" $ do     describe "(<|>)" $ do       pure ()@@ -295,3 +335,36 @@      describe "unpackUTF8" $ do       pure ()++--------------------------------------------------------------------------------++w8AsByteString :: (Bits w, Num w, Integral w) => w -> ByteString+w8AsByteString w = B.pack [b1]+  where+    b1 = fromIntegral $  w .&. 0x00FF++w16leAsByteString :: (Bits w, Num w, Integral w) => w -> ByteString+w16leAsByteString w = B.pack [b1, b2]+  where+    b1 = fromIntegral $  w .&. 0x00FF+    b2 = fromIntegral $ (w .&. 0xFF00) `shiftR` 8++w32leAsByteString :: (Bits w, Num w, Integral w) => w -> ByteString+w32leAsByteString w = B.pack [b1, b2, b3, b4]+  where+    b1 = fromIntegral $  w .&. 0x000000FF+    b2 = fromIntegral $ (w .&. 0x0000FF00) `shiftR` 8+    b3 = fromIntegral $ (w .&. 0x00FF0000) `shiftR` 16+    b4 = fromIntegral $ (w .&. 0xFF000000) `shiftR` 24++w64leAsByteString :: (Bits w, Num w, Integral w) => w -> ByteString+w64leAsByteString w = B.pack [b1, b2, b3, b4, b5, b6, b7, b8]+  where+    b1 = fromIntegral $  w .&. 0x00000000000000FF+    b2 = fromIntegral $ (w .&. 0x000000000000FF00) `shiftR` 8+    b3 = fromIntegral $ (w .&. 0x0000000000FF0000) `shiftR` 16+    b4 = fromIntegral $ (w .&. 0x00000000FF000000) `shiftR` 24+    b5 = fromIntegral $ (w .&. 0x000000FF00000000) `shiftR` 32+    b6 = fromIntegral $ (w .&. 0x0000FF0000000000) `shiftR` 40+    b7 = fromIntegral $ (w .&. 0x00FF000000000000) `shiftR` 48+    b8 = fromIntegral $ (w .&. 0xFF00000000000000) `shiftR` 56