byteslice 0.2.9.0 → 0.2.10.0
raw patch · 8 files changed
+218/−26 lines, 8 filesdep ~primitivedep ~primitive-unliftedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: primitive, primitive-unlifted
API changes (from Hackage documentation)
+ Data.Bytes.Encode.BigEndian: int16 :: Int16 -> Bytes
+ Data.Bytes.Encode.BigEndian: int32 :: Int32 -> Bytes
+ Data.Bytes.Encode.BigEndian: int64 :: Int64 -> Bytes
+ Data.Bytes.Encode.BigEndian: word16 :: Word16 -> Bytes
+ Data.Bytes.Encode.BigEndian: word32 :: Word32 -> Bytes
+ Data.Bytes.Encode.BigEndian: word64 :: Word64 -> Bytes
+ Data.Bytes.Text.Ascii: equalsCStringCaseInsensitive :: CString -> Bytes -> Bool
+ Data.Bytes.Text.Latin1: equals13 :: Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Bytes -> Bool
+ Data.Bytes.Text.Latin1: equals14 :: Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Bytes -> Bool
+ Data.Bytes.Text.Latin1: equals15 :: Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Bytes -> Bool
+ Data.Bytes.Types: instance GHC.TypeNats.KnownNat n => GHC.Show.Show (Data.Bytes.Types.ByteArrayN n)
+ Data.Bytes.Types: instance GHC.TypeNats.KnownNat n => GHC.Show.Show (Data.Bytes.Types.BytesN n)
Files
- CHANGELOG.md +6/−0
- byteslice.cabal +4/−2
- src/Data/Bytes/Encode/BigEndian.hs +77/−0
- src/Data/Bytes/Internal.hs +2/−23
- src/Data/Bytes/Internal/Show.hs +35/−0
- src/Data/Bytes/Text/Ascii.hs +21/−0
- src/Data/Bytes/Text/Latin1.hs +57/−0
- src/Data/Bytes/Types.hs +16/−1
CHANGELOG.md view
@@ -1,5 +1,11 @@ # Revision history for byteslice +## 0.2.10.0 -- 2023-05-01++* Add `equals13`, `equals14`, `equals15`.+* Add `Show` instances for `BytesN` and `ByteArrayN`.+* Add `equalsCStringCaseInsensitive` for ascii text.+ ## 0.2.9.0 -- 2022-12-08 * Add `toShortText`, `toShortTextU`, and `toText` to `Data.Byte.Text.Ascii`.
byteslice.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: byteslice-version: 0.2.9.0+version: 0.2.10.0 synopsis: Slicing managed and unmanaged memory description: This library provides types that allow the user to talk about a slice of@@ -25,6 +25,7 @@ exposed-modules: Data.Bytes Data.Bytes.Chunks+ Data.Bytes.Encode.BigEndian Data.Bytes.Internal Data.Bytes.Mutable Data.Bytes.Text.Ascii@@ -38,12 +39,13 @@ Data.Bytes.Byte Data.Bytes.Pure Data.Bytes.IO+ Data.Bytes.Internal.Show Reps Cstrlen build-depends: , base >=4.14 && <5 , bytestring >=0.10.8 && <0.12- , primitive >=0.7.4 && <0.8+ , primitive >=0.7.4 && <0.10 , primitive-unlifted >=0.1.2 && <0.2 , primitive-addr >=0.1 && <0.2 , run-st >=0.1.1 && <0.2
+ src/Data/Bytes/Encode/BigEndian.hs view
@@ -0,0 +1,77 @@+{-# language BangPatterns #-}+{-# language TypeApplications #-}++module Data.Bytes.Encode.BigEndian+ ( 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 0 (fromIntegral @Word32 @Word8 (unsafeShiftR w 24))+ PM.writeByteArray arr 1 (fromIntegral @Word32 @Word8 (unsafeShiftR w 16))+ PM.writeByteArray arr 2 (fromIntegral @Word32 @Word8 (unsafeShiftR w 8))+ PM.writeByteArray arr 3 (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 0 (fromIntegral @Word16 @Word8 (unsafeShiftR w 8))+ PM.writeByteArray arr 1 (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 0 (fromIntegral @Word64 @Word8 (unsafeShiftR w 56))+ PM.writeByteArray arr 1 (fromIntegral @Word64 @Word8 (unsafeShiftR w 48))+ PM.writeByteArray arr 2 (fromIntegral @Word64 @Word8 (unsafeShiftR w 40))+ PM.writeByteArray arr 3 (fromIntegral @Word64 @Word8 (unsafeShiftR w 32))+ PM.writeByteArray arr 4 (fromIntegral @Word64 @Word8 (unsafeShiftR w 24))+ PM.writeByteArray arr 5 (fromIntegral @Word64 @Word8 (unsafeShiftR w 16))+ PM.writeByteArray arr 6 (fromIntegral @Word64 @Word8 (unsafeShiftR w 8))+ PM.writeByteArray arr 7 (fromIntegral @Word64 @Word8 w)+ PM.unsafeFreezeByteArray arr
src/Data/Bytes/Internal.hs view
@@ -12,13 +12,11 @@ import Control.Monad.ST (runST) import Control.Monad.ST.Run (runByteArrayST)-import Data.Bits ((.&.),unsafeShiftR)-import Data.Char (ord) import Data.Primitive (ByteArray(..)) import Data.Word (Word8)-import GHC.Base (unsafeChr) import GHC.Exts (Int(I#),unsafeCoerce#,sameMutableByteArray#) import GHC.Exts (isTrue#,compareByteArrays#,IsList(..))+import Data.Bytes.Internal.Show (showsSlice) import qualified Data.List as L import qualified Data.Foldable as F@@ -43,26 +41,7 @@ else [] instance Show Bytes where- showsPrec _ (Bytes arr off len) s = if len == 0- then showString "[]" s- else showString "[0x"- $ showHexDigits (PM.indexByteArray arr off)- $ showLoop (off + 1) (len - 1) arr- $ showChar ']'- $ s--showLoop :: Int -> Int -> ByteArray -> String -> String-showLoop !ix !len !arr s = if len > 0- then ',':'0':'x':showHexDigits (PM.indexByteArray arr ix) (showLoop (ix + 1) (len - 1) arr s)- else s--showHexDigits :: Word8 -> String -> String-showHexDigits !w s = word4ToChar (unsafeShiftR w 4) : word4ToChar (0x0F .&. w) : s--word4ToChar :: Word8 -> Char-word4ToChar w = if w < 10- then unsafeChr (ord '0' + fromIntegral w)- else unsafeChr (ord 'a' + (fromIntegral w) - 10)+ showsPrec _ (Bytes arr off len) s = showsSlice arr off len s instance Eq Bytes where Bytes arr1 off1 len1 == Bytes arr2 off2 len2
+ src/Data/Bytes/Internal/Show.hs view
@@ -0,0 +1,35 @@+{-# language BangPatterns #-}++module Data.Bytes.Internal.Show+ ( showsSlice+ ) where++import Data.Bits ((.&.),unsafeShiftR)+import Data.Char (ord)+import Data.Primitive (ByteArray)+import Data.Word (Word8)+import GHC.Base (unsafeChr)++import qualified Data.Primitive as PM++showsSlice :: ByteArray -> Int -> Int -> String -> String+showsSlice arr off len s = if len == 0+ then showString "[]" s+ else showString "[0x"+ $ showHexDigitsWord8 (PM.indexByteArray arr off)+ $ showHexLoop (off + 1) (len - 1) arr+ $ showChar ']'+ $ s++showHexLoop :: Int -> Int -> ByteArray -> String -> String+showHexLoop !ix !len !arr s = if len > 0+ then ',':'0':'x':showHexDigitsWord8 (PM.indexByteArray arr ix) (showHexLoop (ix + 1) (len - 1) arr s)+ else s++showHexDigitsWord8 :: Word8 -> String -> String+showHexDigitsWord8 !w s = word4ToChar (unsafeShiftR w 4) : word4ToChar (0x0F .&. w) : s++word4ToChar :: Word8 -> Char+word4ToChar w = if w < 10+ then unsafeChr (ord '0' + fromIntegral w)+ else unsafeChr (ord 'a' + (fromIntegral w) - 10)
src/Data/Bytes/Text/Ascii.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE BinaryLiterals #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE TypeApplications #-} -- | This module treats 'Bytes' data as holding ASCII text. Providing bytes@@ -11,6 +13,7 @@ module Data.Bytes.Text.Ascii ( fromString , decodeDecWord+ , equalsCStringCaseInsensitive , toShortText , toShortTextU #if MIN_VERSION_text(2,0,0)@@ -18,6 +21,7 @@ #endif ) where +import Data.Bits ((.&.)) import Data.ByteString.Short.Internal (ShortByteString(SBS)) import Data.Bytes.Text.Latin1 (decodeDecWord) import Data.Bytes.Types (Bytes(Bytes))@@ -26,9 +30,12 @@ import Data.Text (Text) import Data.Text.Short (ShortText) import Data.Word (Word8)+import Foreign.C.String (CString)+import Foreign.Ptr (Ptr,plusPtr,castPtr) import qualified Data.Bytes.Pure as Bytes import qualified Data.Primitive as PM+import qualified Data.Primitive.Ptr as PM import qualified Data.Text.Array as A import qualified Data.Text.Internal as I import qualified Data.Text.Short.Unsafe as TS@@ -67,3 +74,17 @@ True -> Just (I.Text (A.ByteArray arr) off len) False -> Nothing #endif++-- | Is the byte sequence equal to the @NUL@-terminated C String?+-- The C string must be a constant.+equalsCStringCaseInsensitive :: CString -> Bytes -> Bool+{-# inline equalsCStringCaseInsensitive #-}+equalsCStringCaseInsensitive !ptr0 (Bytes arr off0 len0) = go (castPtr ptr0 :: Ptr Word8) off0 len0 where+ go !ptr !off !len = case len of+ 0 -> PM.indexOffPtr ptr 0 == (0 :: Word8)+ _ -> case PM.indexOffPtr ptr 0 of+ 0 -> False+ c ->+ (c .&. 0b1101_1111) == (PM.indexByteArray arr off .&. 0b1101_1111)+ &&+ go (plusPtr ptr 1) (off + 1) (len - 1)
src/Data/Bytes/Text/Latin1.hs view
@@ -35,6 +35,9 @@ , equals10 , equals11 , equals12+ , equals13+ , equals14+ , equals15 ) where import Prelude hiding (length)@@ -215,6 +218,60 @@ c9 == indexCharArray arr (off + 9) && c10 == indexCharArray arr (off + 10) && c11 == indexCharArray arr (off + 11)+ _ -> False++equals13 :: Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Bytes -> Bool+equals13 !c0 !c1 !c2 !c3 !c4 !c5 !c6 !c7 !c8 !c9 !c10 !c11 !c12 (Bytes arr off len) = case len of+ 13 -> c0 == indexCharArray arr off &&+ c1 == indexCharArray arr (off + 1) &&+ c2 == indexCharArray arr (off + 2) &&+ c3 == indexCharArray arr (off + 3) &&+ c4 == indexCharArray arr (off + 4) &&+ c5 == indexCharArray arr (off + 5) &&+ c6 == indexCharArray arr (off + 6) &&+ c7 == indexCharArray arr (off + 7) &&+ c8 == indexCharArray arr (off + 8) &&+ c9 == indexCharArray arr (off + 9) &&+ c10 == indexCharArray arr (off + 10) &&+ c11 == indexCharArray arr (off + 11) &&+ c12 == indexCharArray arr (off + 12)+ _ -> False++equals14 :: Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Bytes -> Bool+equals14 !c0 !c1 !c2 !c3 !c4 !c5 !c6 !c7 !c8 !c9 !c10 !c11 !c12 !c13 (Bytes arr off len) = case len of+ 14 -> c0 == indexCharArray arr off &&+ c1 == indexCharArray arr (off + 1) &&+ c2 == indexCharArray arr (off + 2) &&+ c3 == indexCharArray arr (off + 3) &&+ c4 == indexCharArray arr (off + 4) &&+ c5 == indexCharArray arr (off + 5) &&+ c6 == indexCharArray arr (off + 6) &&+ c7 == indexCharArray arr (off + 7) &&+ c8 == indexCharArray arr (off + 8) &&+ c9 == indexCharArray arr (off + 9) &&+ c10 == indexCharArray arr (off + 10) &&+ c11 == indexCharArray arr (off + 11) &&+ c12 == indexCharArray arr (off + 12) &&+ c13 == indexCharArray arr (off + 13)+ _ -> False++equals15 :: Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Char -> Bytes -> Bool+equals15 !c0 !c1 !c2 !c3 !c4 !c5 !c6 !c7 !c8 !c9 !c10 !c11 !c12 !c13 !c14 (Bytes arr off len) = case len of+ 15 -> c0 == indexCharArray arr off &&+ c1 == indexCharArray arr (off + 1) &&+ c2 == indexCharArray arr (off + 2) &&+ c3 == indexCharArray arr (off + 3) &&+ c4 == indexCharArray arr (off + 4) &&+ c5 == indexCharArray arr (off + 5) &&+ c6 == indexCharArray arr (off + 6) &&+ c7 == indexCharArray arr (off + 7) &&+ c8 == indexCharArray arr (off + 8) &&+ c9 == indexCharArray arr (off + 9) &&+ c10 == indexCharArray arr (off + 10) &&+ c11 == indexCharArray arr (off + 11) &&+ c12 == indexCharArray arr (off + 12) &&+ c13 == indexCharArray arr (off + 13) &&+ c14 == indexCharArray arr (off + 14) _ -> False indexCharArray :: ByteArray -> Int -> Char
src/Data/Bytes/Types.hs view
@@ -1,8 +1,10 @@ {-# language BangPatterns #-} {-# language DataKinds #-}+{-# language PolyKinds #-} {-# language MagicHash #-} {-# language TypeFamilies #-} {-# language DuplicateRecordFields #-}+{-# language ScopedTypeVariables #-} module Data.Bytes.Types ( Bytes(..)@@ -16,8 +18,11 @@ import Data.Bytes.Internal (Bytes(..)) import Data.Primitive (ByteArray(..),MutableByteArray(..)) import Data.Primitive.Addr (Addr)-import GHC.TypeNats (Nat)+import GHC.TypeNats (Nat,KnownNat,natVal) import Reps (Bytes#(..))+import Data.Bytes.Internal.Show (showsSlice)+import Data.Proxy (Proxy(Proxy))+import GHC.Natural (naturalToInteger) -- | A slice of a 'ByteArray' whose compile-time-known length is represented -- by a phantom type variable. Consumers of this data constructor must be@@ -27,12 +32,22 @@ , offset :: {-# UNPACK #-} !Int } +instance KnownNat n => Show (BytesN n) where+ showsPrec _ (BytesN arr off) s =+ let len = fromInteger (naturalToInteger (natVal (Proxy :: Proxy n)))+ in showsSlice arr off len s+ -- | A 'ByteArray' whose compile-time-known length is represented -- by a phantom type variable. Consumers of this data constructor must be -- careful to preserve the expected invariant. newtype ByteArrayN (n :: Nat) = ByteArrayN { array :: ByteArray }++instance KnownNat n => Show (ByteArrayN n) where+ showsPrec _ (ByteArrayN arr) s =+ let len = fromInteger (naturalToInteger (natVal (Proxy :: Proxy n)))+ in showsSlice arr 0 len s -- | A slice of a 'MutableByteArray'. data MutableBytes s = MutableBytes