{-# LANGUAGE MagicHash #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnboxedTuples #-}
module Basement.Block.Mutable
( Block(..)
, MutableBlock(..)
, mutableLengthSize
, mutableLength
, mutableLengthBytes
, mutableWithPtr
, withMutablePtr
, withMutablePtrHint
, new
, newPinned
, mutableEmpty
, iterSet
, read
, write
, unsafeNew
, unsafeWrite
, unsafeRead
, unsafeFreeze
, unsafeThaw
, unsafeCopyElements
, unsafeCopyElementsRO
, unsafeCopyBytes
, unsafeCopyBytesRO
, unsafeCopyBytesPtr
, copyFromPtr
, copyToPtr
) where
import GHC.Prim
import GHC.Types
import Basement.Compat.Base
import Data.Proxy
import Basement.Exception
import Basement.Types.OffsetSize
import Basement.Monad
import Basement.Numerical.Additive
import Basement.PrimType
import Basement.Block.Base
iterSet :: (PrimType ty, PrimMonad prim)
=> (Offset ty -> ty)
-> MutableBlock ty (PrimState prim)
-> prim ()
iterSet :: (Offset ty -> ty) -> MutableBlock ty (PrimState prim) -> prim ()
iterSet Offset ty -> ty
f MutableBlock ty (PrimState prim)
ma = Offset ty -> prim ()
loop Offset ty
0
where
!sz :: CountOf ty
sz = MutableBlock ty (PrimState prim) -> CountOf ty
forall ty st. PrimType ty => MutableBlock ty st -> CountOf ty
mutableLength MutableBlock ty (PrimState prim)
ma
loop :: Offset ty -> prim ()
loop Offset ty
i
| Offset ty
i Offset ty -> CountOf ty -> Bool
forall ty. Offset ty -> CountOf ty -> Bool
.==# CountOf ty
sz = () -> prim ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = MutableBlock ty (PrimState prim) -> Offset ty -> ty -> prim ()
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MutableBlock ty (PrimState prim) -> Offset ty -> ty -> prim ()
unsafeWrite MutableBlock ty (PrimState prim)
ma Offset ty
i (Offset ty -> ty
f Offset ty
i) prim () -> prim () -> prim ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Offset ty -> prim ()
loop (Offset ty
iOffset ty -> Offset ty -> Offset ty
forall a. Additive a => a -> a -> a
+Offset ty
1)
{-# INLINE loop #-}
mutableLengthSize :: PrimType ty => MutableBlock ty st -> CountOf ty
mutableLengthSize :: MutableBlock ty st -> CountOf ty
mutableLengthSize = MutableBlock ty st -> CountOf ty
forall ty st. PrimType ty => MutableBlock ty st -> CountOf ty
mutableLength
{-# DEPRECATED mutableLengthSize "use mutableLength" #-}
read :: (PrimMonad prim, PrimType ty) => MutableBlock ty (PrimState prim) -> Offset ty -> prim ty
read :: MutableBlock ty (PrimState prim) -> Offset ty -> prim ty
read MutableBlock ty (PrimState prim)
array Offset ty
n
| Offset ty -> CountOf ty -> Bool
forall ty. Offset ty -> CountOf ty -> Bool
isOutOfBound Offset ty
n CountOf ty
len = OutOfBoundOperation -> Offset ty -> CountOf ty -> prim ty
forall (prim :: * -> *) ty a.
PrimMonad prim =>
OutOfBoundOperation -> Offset ty -> CountOf ty -> prim a
primOutOfBound OutOfBoundOperation
OOB_Read Offset ty
n CountOf ty
len
| Bool
otherwise = MutableBlock ty (PrimState prim) -> Offset ty -> prim ty
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MutableBlock ty (PrimState prim) -> Offset ty -> prim ty
unsafeRead MutableBlock ty (PrimState prim)
array Offset ty
n
where len :: CountOf ty
len = MutableBlock ty (PrimState prim) -> CountOf ty
forall ty st. PrimType ty => MutableBlock ty st -> CountOf ty
mutableLength MutableBlock ty (PrimState prim)
array
{-# INLINE read #-}
write :: (PrimMonad prim, PrimType ty) => MutableBlock ty (PrimState prim) -> Offset ty -> ty -> prim ()
write :: MutableBlock ty (PrimState prim) -> Offset ty -> ty -> prim ()
write MutableBlock ty (PrimState prim)
array Offset ty
n ty
val
| Offset ty -> CountOf ty -> Bool
forall ty. Offset ty -> CountOf ty -> Bool
isOutOfBound Offset ty
n CountOf ty
len = OutOfBoundOperation -> Offset ty -> CountOf ty -> prim ()
forall (prim :: * -> *) ty a.
PrimMonad prim =>
OutOfBoundOperation -> Offset ty -> CountOf ty -> prim a
primOutOfBound OutOfBoundOperation
OOB_Write Offset ty
n CountOf ty
len
| Bool
otherwise = MutableBlock ty (PrimState prim) -> Offset ty -> ty -> prim ()
forall (prim :: * -> *) ty.
(PrimMonad prim, PrimType ty) =>
MutableBlock ty (PrimState prim) -> Offset ty -> ty -> prim ()
unsafeWrite MutableBlock ty (PrimState prim)
array Offset ty
n ty
val
where
len :: CountOf ty
len = MutableBlock ty (PrimState prim) -> CountOf ty
forall ty st. PrimType ty => MutableBlock ty st -> CountOf ty
mutableLengthSize MutableBlock ty (PrimState prim)
array
{-# INLINE write #-}
copyFromPtr :: forall prim ty . (PrimMonad prim, PrimType ty)
=> Ptr ty
-> MutableBlock ty (PrimState prim)
-> Offset ty
-> CountOf ty
-> prim ()
copyFromPtr :: Ptr ty
-> MutableBlock ty (PrimState prim)
-> Offset ty
-> CountOf ty
-> prim ()
copyFromPtr src :: Ptr ty
src@(Ptr Addr#
src#) mb :: MutableBlock ty (PrimState prim)
mb@(MutableBlock MutableByteArray# (PrimState prim)
mba) Offset ty
ofs CountOf ty
count
| Offset Word8
end Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> CountOf Word8 -> Offset Word8
forall a. CountOf a -> Offset a
sizeAsOffset CountOf Word8
arrSz = OutOfBoundOperation -> Offset Word8 -> CountOf Word8 -> prim ()
forall (prim :: * -> *) ty a.
PrimMonad prim =>
OutOfBoundOperation -> Offset ty -> CountOf ty -> prim a
primOutOfBound OutOfBoundOperation
OOB_MemCopy Offset Word8
end CountOf Word8
arrSz
| Bool
otherwise = (State# (PrimState prim) -> (# State# (PrimState prim), () #))
-> prim ()
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive ((State# (PrimState prim) -> (# State# (PrimState prim), () #))
-> prim ())
-> (State# (PrimState prim) -> (# State# (PrimState prim), () #))
-> prim ()
forall a b. (a -> b) -> a -> b
$ \State# (PrimState prim)
st -> (# Addr#
-> MutableByteArray# (PrimState prim)
-> Int#
-> Int#
-> State# (PrimState prim)
-> State# (PrimState prim)
forall d.
Addr#
-> MutableByteArray# d -> Int# -> Int# -> State# d -> State# d
copyAddrToByteArray# Addr#
src# MutableByteArray# (PrimState prim)
mba Int#
od# Int#
bytes# State# (PrimState prim)
st, () #)
where
end :: Offset Word8
end = Offset Word8
od Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` CountOf Word8
arrSz
sz :: CountOf Word8
sz = Proxy ty -> CountOf Word8
forall ty. PrimType ty => Proxy ty -> CountOf Word8
primSizeInBytes (Proxy ty
forall k (t :: k). Proxy t
Proxy :: Proxy ty)
!arrSz :: CountOf Word8
arrSz@(CountOf (I# Int#
bytes#)) = CountOf Word8 -> CountOf ty -> CountOf Word8
forall ty. CountOf Word8 -> CountOf ty -> CountOf Word8
sizeOfE CountOf Word8
sz CountOf ty
count
!od :: Offset Word8
od@(Offset (I# Int#
od#)) = CountOf Word8 -> Offset ty -> Offset Word8
forall ty. CountOf Word8 -> Offset ty -> Offset Word8
offsetOfE CountOf Word8
sz Offset ty
ofs
copyToPtr :: forall ty prim . (PrimType ty, PrimMonad prim)
=> MutableBlock ty (PrimState prim)
-> Offset ty
-> Ptr ty
-> CountOf ty
-> prim ()
copyToPtr :: MutableBlock ty (PrimState prim)
-> Offset ty -> Ptr ty -> CountOf ty -> prim ()
copyToPtr mb :: MutableBlock ty (PrimState prim)
mb@(MutableBlock MutableByteArray# (PrimState prim)
mba) Offset ty
ofs dst :: Ptr ty
dst@(Ptr Addr#
dst#) CountOf ty
count
| Offset Word8
srcEnd Offset Word8 -> Offset Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> CountOf Word8 -> Offset Word8
forall a. CountOf a -> Offset a
sizeAsOffset CountOf Word8
arrSz = OutOfBoundOperation -> Offset Word8 -> CountOf Word8 -> prim ()
forall (prim :: * -> *) ty a.
PrimMonad prim =>
OutOfBoundOperation -> Offset ty -> CountOf ty -> prim a
primOutOfBound OutOfBoundOperation
OOB_MemCopy Offset Word8
srcEnd CountOf Word8
arrSz
| Bool
otherwise = do
Block ty
blk <- MutableBlock ty (PrimState prim) -> prim (Block ty)
forall (prim :: * -> *) ty.
PrimMonad prim =>
MutableBlock ty (PrimState prim) -> prim (Block ty)
unsafeFreeze MutableBlock ty (PrimState prim)
mb
let !(Block ByteArray#
ba) = Block ty
blk
(State# (PrimState prim) -> (# State# (PrimState prim), () #))
-> prim ()
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive ((State# (PrimState prim) -> (# State# (PrimState prim), () #))
-> prim ())
-> (State# (PrimState prim) -> (# State# (PrimState prim), () #))
-> prim ()
forall a b. (a -> b) -> a -> b
$ \State# (PrimState prim)
s1 -> (# ByteArray#
-> Int#
-> Addr#
-> Int#
-> State# (PrimState prim)
-> State# (PrimState prim)
forall d.
ByteArray# -> Int# -> Addr# -> Int# -> State# d -> State# d
copyByteArrayToAddr# ByteArray#
ba Int#
os# Addr#
dst# Int#
szBytes# State# (PrimState prim)
s1, () #)
where
srcEnd :: Offset Word8
srcEnd = Offset Word8
os Offset Word8 -> CountOf Word8 -> Offset Word8
forall ty. Offset ty -> CountOf ty -> Offset ty
`offsetPlusE` CountOf Word8
arrSz
!os :: Offset Word8
os@(Offset (I# Int#
os#)) = Offset ty -> Offset Word8
forall a. PrimType a => Offset a -> Offset Word8
offsetInBytes Offset ty
ofs
!arrSz :: CountOf Word8
arrSz@(CountOf (I# Int#
szBytes#)) = MutableBlock ty (PrimState prim) -> CountOf Word8
forall ty st. MutableBlock ty st -> CountOf Word8
mutableLengthBytes MutableBlock ty (PrimState prim)
mb