byteslice 0.2.10.0 → 0.2.11.0
raw patch · 7 files changed
+202/−6 lines, 7 filesdep +natural-arithmetic
Dependencies added: natural-arithmetic
Files
- CHANGELOG.md +5/−0
- byteslice.cabal +4/−2
- src/Data/Bytes.hs +86/−2
- src/Data/Bytes/Chunks.hs +1/−1
- src/Data/Bytes/Encode/LittleEndian.hs +77/−0
- src/Data/Bytes/Pure.hs +1/−1
- test/Main.hs +28/−0
CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for byteslice +## 0.2.11.0 -- 2023-07-25++* Add `Data.Bytes.Encode.LittleEndian`.+* Add `splitTetragram1`.+ ## 0.2.10.0 -- 2023-05-01 * Add `equals13`, `equals14`, `equals15`.
byteslice.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: byteslice-version: 0.2.10.0+version: 0.2.11.0 synopsis: Slicing managed and unmanaged memory description: This library provides types that allow the user to talk about a slice of@@ -26,6 +26,7 @@ Data.Bytes Data.Bytes.Chunks Data.Bytes.Encode.BigEndian+ Data.Bytes.Encode.LittleEndian Data.Bytes.Internal Data.Bytes.Mutable Data.Bytes.Text.Ascii@@ -45,9 +46,10 @@ build-depends: , base >=4.14 && <5 , bytestring >=0.10.8 && <0.12+ , natural-arithmetic >=0.1.4 , primitive >=0.7.4 && <0.10- , primitive-unlifted >=0.1.2 && <0.2 , primitive-addr >=0.1 && <0.2+ , primitive-unlifted >=0.1.2 && <2.2 , run-st >=0.1.1 && <0.2 , text >=1.2.5 , text-short >=0.1.3 && <0.2
src/Data/Bytes.hs view
@@ -1,6 +1,7 @@ {-# language BangPatterns #-} {-# language BlockArguments #-} {-# language DuplicateRecordFields #-}+{-# language KindSignatures #-} {-# language MagicHash #-} {-# language NamedFieldPuns #-} {-# language RankNTypes #-}@@ -72,6 +73,7 @@ , Byte.splitStream -- ** Fixed from Beginning , Byte.split1+ , splitTetragram1 , Byte.split2 , Byte.split3 , Byte.split4@@ -85,6 +87,7 @@ -- * Searching , replace , findIndices+ , findTetragramIndex -- * Counting , Byte.count -- * Prefix and Suffix@@ -158,6 +161,9 @@ -- * Unlifted Types , lift , unlift+ -- * Length Indexed+ , withLength+ , withLengthU ) where import Prelude hiding (length,takeWhile,dropWhile,null,foldl,foldr,elem,replicate,any,all,readFile,map)@@ -165,20 +171,24 @@ import Control.Monad.Primitive (PrimMonad,primitive_,unsafeIOToPrim) import Control.Monad.ST.Run (runByteArrayST) import Cstrlen (cstringLength#)+import Data.Bits (unsafeShiftL,(.|.)) import Data.ByteString.Short.Internal (ShortByteString(SBS)) import Data.Bytes.Pure (length,fromByteArray,foldr,unsafeDrop) import Data.Bytes.Pure (unsafeIndex,toShortByteString)-import Data.Bytes.Types (Bytes(Bytes,array,offset))+import Data.Bytes.Types (Bytes(Bytes,array,offset),BytesN(BytesN))+import Data.Bytes.Types (ByteArrayN(ByteArrayN)) import Data.Primitive (Array,ByteArray(ByteArray)) import Data.Text.Short (ShortText) import Foreign.C.String (CString) import Foreign.Ptr (Ptr,plusPtr,castPtr) import GHC.Exts (Addr#,Word#,Int#) import GHC.Exts (Int(I#),Ptr(Ptr))-import GHC.Word (Word8(W8#))+import GHC.Word (Word8(W8#),Word32) import Reps (Bytes#(..),word8ToWord#) import Data.Bytes.Search (findIndices,replace,isInfixOf) +import qualified Arithmetic.Nat as Nat+import qualified Arithmetic.Types as Arithmetic import qualified Data.Bytes.Byte as Byte import qualified Data.Bytes.Chunks as Chunks import qualified Data.Bytes.IO as BIO@@ -193,6 +203,7 @@ import qualified Data.Primitive.Ptr as PM import qualified Data.Text.Short as TS import qualified GHC.Exts as Exts+import qualified GHC.TypeNats as GHC -- | Extract the head and tail of the 'Bytes', returning 'Nothing' if -- it is empty.@@ -671,3 +682,76 @@ concatArray :: Array Bytes -> Bytes {-# inline concatArray #-} concatArray !xs = Pure.fromByteArray (concatArrayU xs)++-- | Convert 'Bytes' to 'BytesN', exposing the length in a type-safe+-- way in the callback.+withLength ::+ Bytes+ -> (forall (n :: GHC.Nat). Arithmetic.Nat n -> BytesN n -> a)+ -> a+{-# inline withLength #-}+withLength Bytes{array,offset,length=len} f = Nat.with+ len+ (\n -> f n BytesN{array,offset})++withLengthU ::+ ByteArray+ -> (forall (n :: GHC.Nat). Arithmetic.Nat n -> ByteArrayN n -> a)+ -> a+{-# inline withLengthU #-}+withLengthU !arr f = Nat.with+ (PM.sizeofByteArray arr)+ (\n -> f n (ByteArrayN arr))++findTetragramIndex ::+ Word8+ -> Word8+ -> Word8+ -> Word8+ -> Bytes+ -> Maybe Int+findTetragramIndex !w0 !w1 !w2 !w3 (Bytes arr off len) = if len < 4+ then Nothing+ else+ let !target = + unsafeShiftL (fromIntegral w0 :: Word32) 24+ .|.+ unsafeShiftL (fromIntegral w1 :: Word32) 16+ .|.+ unsafeShiftL (fromIntegral w2 :: Word32) 8+ .|.+ unsafeShiftL (fromIntegral w3 :: Word32) 0+ !end = off + len+ go !ix !acc = if acc == target+ then+ let n = ix - off+ in Just (n - 4)+ else if ix < end+ then+ let !w = PM.indexByteArray arr ix :: Word8+ acc' =+ (fromIntegral w :: Word32)+ .|.+ unsafeShiftL acc 8+ in go (ix + 1) acc'+ else Nothing+ !acc0 =+ unsafeShiftL (fromIntegral (PM.indexByteArray arr 0 :: Word8) :: Word32) 24+ .|.+ unsafeShiftL (fromIntegral (PM.indexByteArray arr 1 :: Word8) :: Word32) 16+ .|.+ unsafeShiftL (fromIntegral (PM.indexByteArray arr 2 :: Word8) :: Word32) 8+ .|.+ unsafeShiftL (fromIntegral (PM.indexByteArray arr 3 :: Word8) :: Word32) 0+ in go 4 acc0++splitTetragram1 ::+ Word8+ -> Word8+ -> Word8+ -> Word8+ -> Bytes+ -> Maybe (Bytes,Bytes)+splitTetragram1 !w0 !w1 !w2 !w3 !b = case findTetragramIndex w0 w1 w2 w3 b of+ Nothing -> Nothing+ Just n -> Just (Pure.unsafeTake n b, Pure.unsafeDrop (n + 4) b)
src/Data/Bytes/Chunks.hs view
@@ -47,7 +47,7 @@ , writeFile ) where -import Prelude hiding (length,concat,reverse,readFile,writeFile,null)+import Prelude hiding (Foldable(..),concat,reverse,readFile,writeFile) import Control.Exception (IOException,catch) import Control.Monad.ST.Run (runIntByteArrayST)
+ src/Data/Bytes/Encode/LittleEndian.hs view
@@ -0,0 +1,77 @@+{-# language BangPatterns #-}+{-# language TypeApplications #-}++module Data.Bytes.Encode.LittleEndian+ ( word16+ , word32+ , word64+ , int16+ , int32+ , int64+ ) where++import Control.Monad.ST.Run (runByteArrayST)+import Data.Bits (unsafeShiftR)+import Data.Bytes.Types (Bytes)+import Data.Int (Int16,Int32,Int64)+import Data.Primitive (ByteArray)+import Data.Word (Word8,Word16,Word32,Word64)++import qualified Data.Bytes.Pure as Pure+import qualified Data.Primitive as PM++-- | Encode a 32-bit signed integer as 4 bytes.+int32 :: Int32 -> Bytes+{-# inline int32 #-}+int32 = word32 . fromIntegral @Int32 @Word32 ++-- | Encode a 32-bit unsigned integer as 4 bytes.+word32 :: Word32 -> Bytes+word32 !w = Pure.fromByteArray (word32U w)++word32U :: Word32 -> ByteArray+word32U !w = runByteArrayST $ do+ arr <- PM.newByteArray 4+ PM.writeByteArray arr 3 (fromIntegral @Word32 @Word8 (unsafeShiftR w 24))+ PM.writeByteArray arr 2 (fromIntegral @Word32 @Word8 (unsafeShiftR w 16))+ PM.writeByteArray arr 1 (fromIntegral @Word32 @Word8 (unsafeShiftR w 8))+ PM.writeByteArray arr 0 (fromIntegral @Word32 @Word8 w)+ PM.unsafeFreezeByteArray arr++-- | Encode a 16-bit signed integer as 4 bytes.+int16 :: Int16 -> Bytes+{-# inline int16 #-}+int16 = word16 . fromIntegral @Int16 @Word16 ++-- | Encode a 16-bit unsigned integer as 4 bytes.+word16 :: Word16 -> Bytes+word16 !w = Pure.fromByteArray (word16U w)++word16U :: Word16 -> ByteArray+word16U !w = runByteArrayST $ do+ arr <- PM.newByteArray 2+ PM.writeByteArray arr 1 (fromIntegral @Word16 @Word8 (unsafeShiftR w 8))+ PM.writeByteArray arr 0 (fromIntegral @Word16 @Word8 w)+ PM.unsafeFreezeByteArray arr++-- | Encode a 16-bit signed integer as 4 bytes.+int64 :: Int64 -> Bytes+{-# inline int64 #-}+int64 = word64 . fromIntegral @Int64 @Word64 ++-- | Encode a 16-bit unsigned integer as 4 bytes.+word64 :: Word64 -> Bytes+word64 !w = Pure.fromByteArray (word64U w)++word64U :: Word64 -> ByteArray+word64U !w = runByteArrayST $ do+ arr <- PM.newByteArray 8+ PM.writeByteArray arr 7 (fromIntegral @Word64 @Word8 (unsafeShiftR w 56))+ PM.writeByteArray arr 6 (fromIntegral @Word64 @Word8 (unsafeShiftR w 48))+ PM.writeByteArray arr 5 (fromIntegral @Word64 @Word8 (unsafeShiftR w 40))+ PM.writeByteArray arr 4 (fromIntegral @Word64 @Word8 (unsafeShiftR w 32))+ PM.writeByteArray arr 3 (fromIntegral @Word64 @Word8 (unsafeShiftR w 24))+ PM.writeByteArray arr 2 (fromIntegral @Word64 @Word8 (unsafeShiftR w 16))+ PM.writeByteArray arr 1 (fromIntegral @Word64 @Word8 (unsafeShiftR w 8))+ PM.writeByteArray arr 0 (fromIntegral @Word64 @Word8 w)+ PM.unsafeFreezeByteArray arr
src/Data/Bytes/Pure.hs view
@@ -41,7 +41,7 @@ , toShortByteString ) where -import Prelude hiding (length,foldl,foldr,map,null)+import Prelude hiding (Foldable(..),map) import Control.Monad.Primitive (PrimState,PrimMonad) import Control.Monad.ST.Run (runByteArrayST)
test/Main.hs view
@@ -265,6 +265,34 @@ Nothing -> property False Just (y2,z2) -> (y1,z1) === (bytesToByteString y2, bytesToByteString z2) _ -> property Discard+ , testProperty "splitTetragram1A" $ \(w0 :: Word8) (w1 :: Word8) (w2 :: Word8) (w3 :: Word8) (xs :: [Word8]) ->+ (w0 /= 0xEF && w1 /= 0xEF && w2 /= 0xEF && w3 /= 0xEF)+ ==>+ case Bytes.splitTetragram1 w0 w1 w2 w3 (slicedPack (0xEF : w0 : w1 : w2 : w3 : xs)) of+ Nothing -> property False+ Just (pre,post) ->+ (pre,post) === (Exts.fromList [0xEF], Exts.fromList xs) + , testProperty "splitTetragram1B" $ \(w0 :: Word8) (w1 :: Word8) (w2 :: Word8) (w3 :: Word8) (xs :: [Word8]) ->+ (w0 /= 0xEF && w1 /= 0xEF && w2 /= 0xEF && w3 /= 0xEF)+ ==>+ case Bytes.splitTetragram1 w0 w1 w2 w3 (slicedPack (0xEF : 0xEF : 0xEF : 0xEF : w0 : w1 : w2 : w3 : xs)) of+ Nothing -> property False+ Just (pre,post) ->+ (pre,post) === (Exts.fromList (List.replicate 4 0xEF), Exts.fromList xs) + , testProperty "splitTetragram1C" $ \(w0 :: Word8) (w1 :: Word8) (w2 :: Word8) (xs :: [Word8]) ->+ (w0 /= 0xEF && w1 /= 0xEF && w2 /= 0xEF)+ ==>+ case Bytes.splitTetragram1 w0 w1 w2 0xEF (slicedPack (xs ++ [w0, w1, w2, 0xEF])) of+ Nothing -> property False+ Just (pre,post) ->+ (pre,post) === (Exts.fromList xs, mempty)+ , testProperty "splitTetragram1D" $ \(w0 :: Word8) (w1 :: Word8) (w2 :: Word8) (xs :: [Word8]) ->+ (w0 /= 0xEF && w1 /= 0xEF && w2 /= 0xEF)+ ==>+ case Bytes.splitTetragram1 w0 w1 w2 0xEF (slicedPack (xs ++ [w0, w1, w2, 0xEF, 0xEF])) of+ Nothing -> property False+ Just (pre,post) ->+ (pre,post) === (Exts.fromList xs, Exts.fromList [0xEF]) , testProperty "split2" $ \(xs :: [Word8]) (ys :: [Word8]) (zs :: [Word8]) -> (all (/=0xEF) xs && all (/=0xEF) ys && all (/=0xEF) zs) ==>