{-# language BangPatterns #-}
{-# language BlockArguments #-}
{-# language MagicHash #-}
{-# language NamedFieldPuns #-}
{-# language TypeApplications #-}
{-# language UnboxedTuples #-}
module Data.Bytes.Pure
( empty
, emptyPinned
, pin
, contents
, unsafeCopy
, toByteArray
, toByteArrayClone
, fromByteArray
, length
, foldl'
, fnv1a32
, fnv1a64
) where
import Prelude hiding (length)
import Control.Monad.Primitive (PrimState,PrimMonad)
import Control.Monad.ST.Run (runByteArrayST)
import Data.Bits (xor)
import Data.Bytes.Types (Bytes(Bytes))
import Data.Primitive (ByteArray,MutableByteArray)
import Data.Word (Word64,Word32,Word8)
import Foreign.Ptr (Ptr,plusPtr)
import qualified Data.Primitive as PM
empty :: Bytes
empty = Bytes mempty 0 0
emptyPinned :: Bytes
emptyPinned = Bytes
( runByteArrayST
(PM.newPinnedByteArray 0 >>= PM.unsafeFreezeByteArray)
) 0 0
pin :: Bytes -> Bytes
pin b@(Bytes arr _ len) = case PM.isByteArrayPinned arr of
True -> b
False -> Bytes
( runByteArrayST do
dst <- PM.newPinnedByteArray len
unsafeCopy dst 0 b
PM.unsafeFreezeByteArray dst
) 0 len
toByteArray :: Bytes -> ByteArray
toByteArray b@(Bytes arr off len)
| off == 0, PM.sizeofByteArray arr == len = arr
| otherwise = toByteArrayClone b
toByteArrayClone :: Bytes -> ByteArray
toByteArrayClone (Bytes arr off len) = runByteArrayST $ do
m <- PM.newByteArray len
PM.copyByteArray m 0 arr off len
PM.unsafeFreezeByteArray m
unsafeCopy :: PrimMonad m
=> MutableByteArray (PrimState m)
-> Int
-> Bytes
-> m ()
{-# inline unsafeCopy #-}
unsafeCopy dst dstIx (Bytes src srcIx len) =
PM.copyByteArray dst dstIx src srcIx len
fromByteArray :: ByteArray -> Bytes
fromByteArray b = Bytes b 0 (PM.sizeofByteArray b)
length :: Bytes -> Int
length (Bytes _ _ len) = len
fnv1a32 :: Bytes -> Word32
fnv1a32 = foldl'
(\acc w -> (fromIntegral @Word8 @Word32 w `xor` acc) * 0x01000193
) 0x811c9dc5
fnv1a64 :: Bytes -> Word64
fnv1a64 = foldl'
(\acc w -> (fromIntegral @Word8 @Word64 w `xor` acc) * 0x00000100000001B3
) 0xcbf29ce484222325
foldl' :: (a -> Word8 -> a) -> a -> Bytes -> a
{-# inline foldl' #-}
foldl' f a0 (Bytes arr off0 len0) = go a0 off0 len0 where
go !a !off !len = case len of
0 -> a
_ -> go (f a (PM.indexByteArray arr off)) (off + 1) (len - 1)
contents :: Bytes -> Ptr Word8
contents (Bytes arr off _) = plusPtr (PM.byteArrayContents arr) off