packages feed

bytesmith 0.3.4.0 → 0.3.5.0

raw patch · 7 files changed

+125/−6 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Bytes.Parser.BigEndian: word256 :: e -> Parser e s Word256
+ Data.Bytes.Parser.BigEndian: word256Array :: e -> Int -> Parser e s (PrimArray Word256)
+ Data.Bytes.Parser.Latin: hexFixedWord64 :: e -> Parser e s Word64
+ Data.Bytes.Parser.LittleEndian: word256 :: e -> Parser e s Word256
+ Data.Bytes.Parser.LittleEndian: word256Array :: e -> Int -> Parser e s (PrimArray Word256)

Files

CHANGELOG.md view
@@ -1,9 +1,16 @@ # Revision history for bytesmith +## 0.3.5.0 -- 2020-02-10++* Add big-endian and little-endian `word256` and `word256Array` parsers.+* Add `hexFixedWord64`.+ ## 0.3.4.0 -- 2020-02-03+ * Add `hexFixedWord32`.  ## 0.3.3.0 -- 2020-01-22+ * Add `hexWord8`, `hexWord16`, and `hexFixedWord8`.  ## 0.3.2.0 -- 2019-12-27
bytesmith.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: bytesmith-version: 0.3.4.0+version: 0.3.5.0 synopsis: Nonresumable byte parser description:   Parse bytes as fast as possible. This is a nonresumable parser
src/Data/Bytes/Parser/BigEndian.hs view
@@ -24,6 +24,7 @@   , word32   , word64   , word128+  , word256     -- * Signed   , int8   , int16@@ -35,6 +36,7 @@   , word32Array   , word64Array   , word128Array+  , word256Array   ) where  import Prelude hiding (length,any,fail,takeWhile)@@ -44,12 +46,12 @@ import Data.Bytes.Types (Bytes(..)) import Data.Bytes.Parser.Internal (Parser,uneffectful) import Data.Bytes.Parser.Internal (InternalResult(..))-import Data.Bytes.Parser.Internal (swapArray16,swapArray32,swapArray64)+import Data.Bytes.Parser.Internal (swapArray16,swapArray32,swapArray64,swapArray256) import Data.Bytes.Parser.Internal (swapArray128) import Data.Word (Word8,Word16,Word32,Word64) import Data.Int (Int8,Int16,Int32,Int64) import Data.Primitive (ByteArray(..),PrimArray(..))-import Data.WideWord (Word128(Word128))+import Data.WideWord (Word128(Word128),Word256(Word256)) import GHC.ByteOrder (ByteOrder(LittleEndian,BigEndian),targetByteOrder)  import qualified Data.Bytes as Bytes@@ -99,6 +101,18 @@     let r = swapArray64 bs     pure (asWord64s r) +-- | Parse an array of big-endian unsigned 256-bit words.+word256Array ::+     e -- ^ Error message if not enough bytes are present+  -> Int -- ^ Number of big-endian 256-bit words to consume+  -> Parser e s (PrimArray Word256) -- ^ Native-endian elements+word256Array e !n = case targetByteOrder of+  BigEndian -> fmap (asWord256s . Bytes.toByteArrayClone) (P.take e (n * 32))+  LittleEndian -> do+    bs <- P.take e (n * 32)+    let r = swapArray256 bs+    pure (asWord256s r)+ -- | Parse an array of big-endian unsigned 128-bit words. word128Array ::      e -- ^ Error message if not enough bytes are present@@ -123,6 +137,9 @@ asWord128s :: ByteArray -> PrimArray Word128 asWord128s (ByteArray x) = PrimArray x +asWord256s :: ByteArray -> PrimArray Word256+asWord256s (ByteArray x) = PrimArray x+ -- | Unsigned 16-bit word. word16 :: e -> Parser e s Word16 word16 e = uneffectful $ \chunk -> if length chunk >= 2@@ -181,6 +198,10 @@ -- | Unsigned 128-bit word. word128 :: e -> Parser e s Word128 word128 e = liftA2 Word128 (word64 e) (word64 e)++-- | Unsigned 256-bit word.+word256 :: e -> Parser e s Word256+word256 e = (\a b c d -> Word256 a b c d) <$> word64 e <*> word64 e <*> word64 e <*> word64 e  -- | Signed 8-bit integer. int8 :: e -> Parser e s Int8
src/Data/Bytes/Parser/Internal.hs view
@@ -38,6 +38,7 @@   , swapArray32   , swapArray64   , swapArray128+  , swapArray256   ) where  import Prelude hiding (length,any,fail,takeWhile)@@ -262,6 +263,23 @@           PM.writeByteArray dst (ixDst + 14) v1           PM.writeByteArray dst (ixDst + 15) v0           go (ixSrc + 16) (ixDst + 16) (len - 16)+        else pure ()+  go offset 0 length+  PM.unsafeFreezeByteArray dst++swapArray256 :: Bytes -> ByteArray+swapArray256 (Bytes{array,offset,length}) = runByteArrayST $ do+  dst <- PM.newByteArray length+  let go !ixSrc !ixDst !len = if len > 0+        then do+          let loop !i+                | i < 32 = do+                    let v = PM.indexByteArray array (ixSrc + i) :: Word8+                    PM.writeByteArray dst (ixDst + (31 - i)) v+                    loop (i + 1)+                | otherwise = pure ()+          loop 0+          go (ixSrc + 32) (ixDst + 32) (len - 32)         else pure ()   go offset 0 length   PM.unsafeFreezeByteArray dst
src/Data/Bytes/Parser/Latin.hs view
@@ -73,6 +73,7 @@   , hexFixedWord8   , hexFixedWord16   , hexFixedWord32+  , hexFixedWord64     -- *** Digit   , hexNibbleLower   , tryHexNibbleLower@@ -895,6 +896,9 @@     else (# | (# (), unI (offset c + 1), unI (length c - 1) #) #)  +-- | Parse exactly eight ASCII-encoded characters, interpreting them as the+-- hexadecimal encoding of a 32-bit number. Note that this rejects a sequence+-- such as @BC5A9@, requiring @000BC5A9@ instead. This is insensitive to case. hexFixedWord32 :: e -> Parser e s Word32 {-# inline hexFixedWord32 #-} hexFixedWord32 e = Parser@@ -931,7 +935,36 @@            | otherwise -> (# e | #)   else (# e | #) --- | Parse exactly four ASCII-encoded characters, interpretting+-- | Parse exactly 16 ASCII-encoded characters, interpreting them as the+-- hexadecimal encoding of a 64-bit number. Note that this rejects a sequence+-- such as @BC5A9@, requiring @00000000000BC5A9@ instead. This is insensitive+-- to case.+hexFixedWord64 :: e -> Parser e s Word64+{-# inline hexFixedWord64 #-}+hexFixedWord64 e = Parser+  (\x s0 -> case runParser (hexFixedWord64# e) x s0 of+    (# s1, r #) -> case r of+      (# err | #) -> (# s1, (# err | #) #)+      (# | (# a, b, c #) #) -> (# s1, (# | (# W64# a, b, c #) #) #)+  )++hexFixedWord64# :: e -> Parser e s Word#+{-# noinline hexFixedWord64# #-}+hexFixedWord64# e = uneffectfulWord# $ \chunk -> if length chunk >= 16+  then+    let go !off !len !acc = case len of+          0 -> case acc of+            W# r -> +              (# | (# r+              ,  unI off+              ,  unI (length chunk) -# 16# #) #)+          _ -> case oneHexMaybe (PM.indexByteArray (array chunk) off) of+            Nothing -> (# e | #)+            Just w -> go (off + 1) (len - 1) ((acc * 16) + w)+     in go (offset chunk) (16 :: Int) (0 :: Word)+  else (# e | #)++-- | Parse exactly four ASCII-encoded characters, interpreting -- them as the hexadecimal encoding of a 16-bit number. Note that -- this rejects a sequence such as @5A9@, requiring @05A9@ instead. -- This is insensitive to case. This is particularly useful when
src/Data/Bytes/Parser/LittleEndian.hs view
@@ -25,6 +25,7 @@   , word32   , word64   , word128+  , word256     -- ** Signed   , int8   , int16@@ -36,6 +37,7 @@   , word32Array   , word64Array   , word128Array+  , word256Array     -- ** Unsigned   , int64Array   ) where@@ -49,10 +51,10 @@ import Data.Bytes.Parser.Internal (Parser,uneffectful) import Data.Bytes.Parser.Internal (InternalResult(..)) import Data.Bytes.Parser.Internal (swapArray16,swapArray32)-import Data.Bytes.Parser.Internal (swapArray64,swapArray128)+import Data.Bytes.Parser.Internal (swapArray64,swapArray128,swapArray256) import Data.Word (Word8,Word16,Word32,Word64) import Data.Int (Int8,Int16,Int32,Int64)-import Data.WideWord (Word128(Word128))+import Data.WideWord (Word128(Word128),Word256(Word256)) import GHC.ByteOrder (ByteOrder(LittleEndian,BigEndian),targetByteOrder)  import qualified Data.Bytes as Bytes@@ -114,6 +116,18 @@     let r = swapArray128 bs     pure (asWord128s r) +-- | Parse an array of little-endian unsigned 256-bit words.+word256Array ::+     e -- ^ Error message if not enough bytes are present+  -> Int -- ^ Number of little-endian 256-bit words to consume+  -> Parser e s (PrimArray Word256) -- ^ Native-endian elements+word256Array e !n = case targetByteOrder of+  LittleEndian -> fmap (asWord256s . Bytes.toByteArrayClone) (P.take e (n * 32))+  BigEndian -> do+    bs <- P.take e (n * 32)+    let r = swapArray256 bs+    pure (asWord256s r)+ -- | Parse an array of little-endian signed 64-bit words. int64Array ::      e -- ^ Error message if not enough bytes are present@@ -135,6 +149,9 @@ asWord128s :: ByteArray -> PrimArray Word128 asWord128s (ByteArray x) = PrimArray x +asWord256s :: ByteArray -> PrimArray Word256+asWord256s (ByteArray x) = PrimArray x+ -- | Unsigned 16-bit word. word16 :: e -> Parser e s Word16 word16 e = uneffectful $ \chunk -> if length chunk >= 2@@ -189,6 +206,10 @@           )           (offset chunk + 8) (length chunk - 8)   else InternalFailure e++-- | Unsigned 256-bit word.+word256 :: e -> Parser e s Word256+word256 e = (\d c b a -> Word256 a b c d) <$> word64 e <*> word64 e <*> word64 e <*> word64 e  -- | Unsigned 128-bit word. word128 :: e -> Parser e s Word128
test/Main.hs view
@@ -105,6 +105,19 @@       P.parseBytes (replicateM (length xs) (BigEndian.word128 ())) bs       ===       P.parseBytes (fmap Exts.toList (BigEndian.word128Array () (length xs))) bs+  , testCase "big-endian-word256" $+      P.parseBytesMaybe (BigEndian.word256Array () 1) (Exts.fromList [+        0x12, 0x34, 0x56, 0x78, 0x90,+        0x12, 0x34, 0x56, 0x78, 0x90,+        0x12, 0x34, 0x56, 0x78, 0x90,+        0x12,+        0x12, 0x34, 0x56, 0x78, 0x90,+        0x12, 0x34, 0x56, 0x78, 0x90,+        0x12, 0x34, 0x56, 0x78, 0x90,+        0x12+      ])+      @=?+      Just (Exts.fromList [0x1234567890123456789012345678901212345678901234567890123456789012])   , testProperty "big-endian-word64" bigEndianWord64   , testProperty "big-endian-word32" bigEndianWord32   , testProperty "little-endian-word32" littleEndianWord32@@ -338,6 +351,12 @@         P.parseBytes (Latin.hexFixedWord32 ()) (bytes "") @=? P.Failure ()     , testCase "D" $         P.parseBytes (Latin.hexFixedWord32 ()) (bytes "A!A0A0A0") @=? P.Failure ()+    ]+  , testGroup "hexFixedWord64"+    [ testCase "A" $+        P.parseBytes (Latin.hexFixedWord64 ()) (bytes "ABCD01235678BCDE")+        @=? P.Success+        (Slice 17 0 0xABCD01235678BCDE)     ]   ]