packages feed

primal-memory 0.1.0.0 → 0.2.0.0

raw patch · 16 files changed

+3100/−1565 lines, 16 filesdep +QuickCheckdep +doctestdep +template-haskelldep ~basedep ~bytestringdep ~primalPVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck, doctest, template-haskell, text

Dependency ranges changed: base, bytestring, primal

API changes (from Hackage documentation)

- Data.Prim.Memory: allocByteCountMem :: (MemAlloc a, MonadPrim s m) => Count Word8 -> m (a s)
- Data.Prim.Memory.ByteArray: ByteArray :: Bytes p -> ByteArray e
- Data.Prim.Memory.ByteArray: Inc :: Pinned
- Data.Prim.Memory.ByteArray: MByteArray :: MBytes p s -> MByteArray e s
- Data.Prim.Memory.ByteArray: Pin :: Pinned
- Data.Prim.Memory.ByteArray: allocAlignedMByteArray :: (MonadPrim s m, Prim e) => Count e -> m (MByteArray 'Pin e s)
- Data.Prim.Memory.ByteArray: allocMByteArray :: forall e p m s. (Typeable p, Prim e, MonadPrim s m) => Size -> m (MByteArray p e s)
- Data.Prim.Memory.ByteArray: allocPinnedMByteArray :: forall e m s. (MonadPrim s m, Prim e) => Size -> m (MByteArray 'Pin e s)
- Data.Prim.Memory.ByteArray: allocUnpinnedMByteArray :: forall e m s. (MonadPrim s m, Prim e) => Size -> m (MByteArray 'Inc e s)
- Data.Prim.Memory.ByteArray: castByteArray :: ByteArray p e' -> ByteArray p e
- Data.Prim.Memory.ByteArray: castMByteArray :: MByteArray p e' s -> MByteArray p e s
- Data.Prim.Memory.ByteArray: copyByteArrayToMByteArray :: (MonadPrim s m, Prim e) => ByteArray p e -> Int -> MByteArray p e s -> Int -> Size -> m ()
- Data.Prim.Memory.ByteArray: data Pinned
- Data.Prim.Memory.ByteArray: freezeMByteArray :: MonadPrim s m => MByteArray p e s -> m (ByteArray p e)
- Data.Prim.Memory.ByteArray: fromBytesByteArray :: Bytes p -> ByteArray p e
- Data.Prim.Memory.ByteArray: fromMBytesMByteArray :: MBytes p s -> MByteArray p e s
- Data.Prim.Memory.ByteArray: getSizeMByteArray :: forall e p m s. (MonadPrim s m, Prim e) => MByteArray p e s -> m Size
- Data.Prim.Memory.ByteArray: instance (Data.Typeable.Internal.Typeable p, Data.Prim.Class.Prim e) => GHC.Exts.IsList (Data.Prim.Memory.ByteArray.ByteArray p e)
- Data.Prim.Memory.ByteArray: instance (GHC.Show.Show e, Data.Prim.Class.Prim e) => GHC.Show.Show (Data.Prim.Memory.ByteArray.ByteArray p e)
- Data.Prim.Memory.ByteArray: instance Control.DeepSeq.NFData (Data.Prim.Memory.ByteArray.ByteArray p e)
- Data.Prim.Memory.ByteArray: instance Control.DeepSeq.NFData (Data.Prim.Memory.ByteArray.MByteArray p e s)
- Data.Prim.Memory.ByteArray: instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.ByteArray.ByteArray 'Data.Prim.Memory.Bytes.Internal.Pin e)
- Data.Prim.Memory.ByteArray: instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.ByteArray.MByteArray 'Data.Prim.Memory.Bytes.Internal.Pin e s)
- Data.Prim.Memory.ByteArray: instance Data.Prim.Memory.Internal.MemRead (Data.Prim.Memory.ByteArray.ByteArray p e)
- Data.Prim.Memory.ByteArray: instance Data.Prim.Memory.Internal.MemWrite (Data.Prim.Memory.ByteArray.MByteArray p e)
- Data.Prim.Memory.ByteArray: instance Data.Typeable.Internal.Typeable p => Data.Prim.Memory.Internal.MemAlloc (Data.Prim.Memory.ByteArray.MByteArray p e)
- Data.Prim.Memory.ByteArray: instance Data.Typeable.Internal.Typeable p => Data.String.IsString (Data.Prim.Memory.ByteArray.ByteArray p GHC.Types.Char)
- Data.Prim.Memory.ByteArray: instance Data.Typeable.Internal.Typeable p => GHC.Base.Monoid (Data.Prim.Memory.ByteArray.ByteArray p e)
- Data.Prim.Memory.ByteArray: instance Data.Typeable.Internal.Typeable p => GHC.Base.Semigroup (Data.Prim.Memory.ByteArray.ByteArray p e)
- Data.Prim.Memory.ByteArray: isPinnedByteArray :: ByteArray p e -> Bool
- Data.Prim.Memory.ByteArray: isPinnedMByteArray :: MByteArray p e s -> Bool
- Data.Prim.Memory.ByteArray: moveMByteArrayToMByteArray :: forall e p m s. (MonadPrim s m, Prim e) => MByteArray p e s -> Int -> MByteArray p e s -> Int -> Size -> m ()
- Data.Prim.Memory.ByteArray: newtype ByteArray (p :: Pinned) e
- Data.Prim.Memory.ByteArray: newtype MByteArray (p :: Pinned) e s
- Data.Prim.Memory.ByteArray: readMByteArray :: (MonadPrim s m, Prim e) => MByteArray p e s -> Int -> m e
- Data.Prim.Memory.ByteArray: reallocMByteArray :: forall e p m s. (MonadPrim s m, Typeable p, Prim e) => MByteArray p e s -> Size -> m (MByteArray p e s)
- Data.Prim.Memory.ByteArray: resizeMByteArray :: forall e p m s. (MonadPrim s m, Prim e) => MByteArray p e s -> Size -> m (MByteArray 'Inc e s)
- Data.Prim.Memory.ByteArray: setMByteArray :: (MonadPrim s m, Prim e) => MByteArray p e s -> Int -> Size -> e -> m ()
- Data.Prim.Memory.ByteArray: shrinkMByteArray :: forall e p m s. (MonadPrim s m, Prim e) => MByteArray p e s -> Size -> m ()
- Data.Prim.Memory.ByteArray: sizeByteArray :: forall e p. Prim e => ByteArray p e -> Size
- Data.Prim.Memory.ByteArray: thawByteArray :: MonadPrim s m => ByteArray p e -> m (MByteArray p e s)
- Data.Prim.Memory.ByteArray: toBytesByteArray :: ByteArray p e -> Bytes p
- Data.Prim.Memory.ByteArray: toMBytesMByteArray :: MByteArray p e s -> MBytes p s
- Data.Prim.Memory.ByteArray: writeMByteArray :: (MonadPrim s m, Prim e) => MByteArray p e s -> Int -> e -> m ()
- Data.Prim.Memory.Internal: Bytes :: ByteArray# -> Bytes
- Data.Prim.Memory.Internal: Inc :: Pinned
- Data.Prim.Memory.Internal: MBytes :: MutableByteArray# s -> MBytes s
- Data.Prim.Memory.Internal: MMemView :: {-# UNPACK #-} !Off Word8 -> {-# UNPACK #-} !Count Word8 -> !a s -> MMemView a s
- Data.Prim.Memory.Internal: MemState :: a -> MemState a s
- Data.Prim.Memory.Internal: MemView :: {-# UNPACK #-} !Off Word8 -> {-# UNPACK #-} !Count Word8 -> !a -> MemView a
- Data.Prim.Memory.Internal: Pin :: Pinned
- Data.Prim.Memory.Internal: [mmvCount] :: MMemView a s -> {-# UNPACK #-} !Count Word8
- Data.Prim.Memory.Internal: [mmvMem] :: MMemView a s -> !a s
- Data.Prim.Memory.Internal: [mmvOffset] :: MMemView a s -> {-# UNPACK #-} !Off Word8
- Data.Prim.Memory.Internal: [mvCount] :: MemView a -> {-# UNPACK #-} !Count Word8
- Data.Prim.Memory.Internal: [mvMem] :: MemView a -> !a
- Data.Prim.Memory.Internal: [mvOffset] :: MemView a -> {-# UNPACK #-} !Off Word8
- Data.Prim.Memory.Internal: [unMemState] :: MemState a s -> a
- Data.Prim.Memory.Internal: allocByteCountMem :: (MemAlloc a, MonadPrim s m) => Count Word8 -> m (a s)
- Data.Prim.Memory.Internal: allocMem :: (MemAlloc a, MonadPrim s m, Prim e) => Count e -> m (a s)
- Data.Prim.Memory.Internal: allocZeroMem :: (MemAlloc a, MonadPrim s m, Prim e) => Count e -> m (a s)
- Data.Prim.Memory.Internal: appendMem :: (MemRead r1, MemRead r2, MemAlloc a) => r1 -> r2 -> FrozenMem a
- Data.Prim.Memory.Internal: byteCountMem :: MemRead r => r -> Count Word8
- Data.Prim.Memory.Internal: class (MemRead (FrozenMem a), MemWrite a) => MemAlloc a where {
- Data.Prim.Memory.Internal: class MemRead r
- Data.Prim.Memory.Internal: class MemWrite w
- Data.Prim.Memory.Internal: clone :: (MemAlloc r, MonadPrim s m) => r s -> m (r s)
- Data.Prim.Memory.Internal: compareByteOffMem :: (MemRead r, MemRead r', Prim e) => r' -> Off Word8 -> r -> Off Word8 -> Count e -> Ordering
- Data.Prim.Memory.Internal: compareByteOffToBytesMem :: (MemRead r, MonadPrim s m, Prim e) => r -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> m Ordering
- Data.Prim.Memory.Internal: compareByteOffToPtrMem :: (MemRead r, MonadPrim s m, Prim e) => r -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m Ordering
- Data.Prim.Memory.Internal: compareMem :: (MemRead r1, MemRead r2, Prim e) => r1 -> Off e -> r2 -> Off e -> Count e -> Ordering
- Data.Prim.Memory.Internal: concatMem :: (MemRead r, MemAlloc a) => [r] -> FrozenMem a
- Data.Prim.Memory.Internal: convertMem :: (MemRead r, MemAlloc a) => r -> FrozenMem a
- Data.Prim.Memory.Internal: copyByteOffMem :: (MemWrite w, MonadPrim s m, MemRead r, Prim e) => r -> Off Word8 -> w s -> Off Word8 -> Count e -> m ()
- Data.Prim.Memory.Internal: copyByteOffToMBytesMem :: (MemRead r, MonadPrim s m, Prim e) => r -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m ()
- Data.Prim.Memory.Internal: copyByteOffToPtrMem :: (MemRead r, MonadPrim s m, Prim e) => r -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m ()
- Data.Prim.Memory.Internal: copyMem :: (MonadPrim s m, MemRead r, MemWrite w, Prim e) => r -> Off e -> w s -> Off e -> Count e -> m ()
- Data.Prim.Memory.Internal: countMem :: forall e r. (MemRead r, Prim e) => r -> Count e
- Data.Prim.Memory.Internal: countRemMem :: forall e r. (MemRead r, Prim e) => r -> (Count e, Count Word8)
- Data.Prim.Memory.Internal: createMemST :: (MemAlloc a, Prim e) => Count e -> (forall s. a s -> ST s b) -> (b, FrozenMem a)
- Data.Prim.Memory.Internal: createMemST_ :: (MemAlloc a, Prim e) => Count e -> (forall s. a s -> ST s b) -> FrozenMem a
- Data.Prim.Memory.Internal: createZeroMemST :: (MemAlloc a, Prim e) => Count e -> (forall s. a s -> ST s b) -> (b, FrozenMem a)
- Data.Prim.Memory.Internal: createZeroMemST_ :: (MemAlloc a, Prim e) => Count e -> (forall s. a s -> ST s b) -> FrozenMem a
- Data.Prim.Memory.Internal: cycleMemN :: (MemAlloc a, MemRead r) => Int -> r -> FrozenMem a
- Data.Prim.Memory.Internal: data Bytes (p :: Pinned)
- Data.Prim.Memory.Internal: data MBytes (p :: Pinned) s
- Data.Prim.Memory.Internal: data MMemView a s
- Data.Prim.Memory.Internal: data MemView a
- Data.Prim.Memory.Internal: data Pinned
- Data.Prim.Memory.Internal: defaultResizeMem :: (Prim e, MemAlloc a, MonadPrim s m) => a s -> Count e -> m (a s)
- Data.Prim.Memory.Internal: emptyMem :: MemAlloc a => FrozenMem a
- Data.Prim.Memory.Internal: eqMem :: (MemRead r1, MemRead r2) => r1 -> r2 -> Bool
- Data.Prim.Memory.Internal: foldrCountMem :: (MemRead r, Prim e) => Count e -> (e -> b -> b) -> b -> r -> b
- Data.Prim.Memory.Internal: forByteOffMemM_ :: (MemRead r, MonadPrim s m, Prim e) => r -> Off Word8 -> Count e -> (Off Word8 -> e -> m b) -> m (Off Word8)
- Data.Prim.Memory.Internal: freezeCloneMem :: (MemAlloc a, MonadPrim s m) => a s -> m (FrozenMem a)
- Data.Prim.Memory.Internal: freezeCopyMem :: (MemAlloc a, MonadPrim s m, Prim e) => a s -> Off e -> Count e -> m (FrozenMem a)
- Data.Prim.Memory.Internal: freezeMem :: (MemAlloc a, MonadPrim s m) => a s -> m (FrozenMem a)
- Data.Prim.Memory.Internal: fromByteListMem :: MemAlloc a => [Word8] -> FrozenMem a
- Data.Prim.Memory.Internal: fromListMem :: (MemAlloc a, Prim e) => [e] -> FrozenMem a
- Data.Prim.Memory.Internal: fromListMemN :: (MemAlloc a, Prim e) => Count e -> [e] -> (Ordering, FrozenMem a)
- Data.Prim.Memory.Internal: fromListMemN_ :: (MemAlloc a, Prim e) => Count e -> [e] -> FrozenMem a
- Data.Prim.Memory.Internal: getByteCountMem :: (MemAlloc a, MonadPrim s m) => a s -> m (Count Word8)
- Data.Prim.Memory.Internal: getCountMem :: (MemAlloc r, MonadPrim s m, Prim e) => r s -> m (Count e)
- Data.Prim.Memory.Internal: getCountRemMem :: (MemAlloc r, MonadPrim s m, Prim e) => r s -> m (Count e, Count Word8)
- Data.Prim.Memory.Internal: indexByteOffMem :: (MemRead r, Prim e) => r -> Off Word8 -> e
- Data.Prim.Memory.Internal: indexOffMem :: (MemRead r, Prim e) => r -> Off e -> e
- Data.Prim.Memory.Internal: instance Data.Prim.Memory.Internal.MemAlloc Data.Prim.Memory.ByteString.MByteString
- Data.Prim.Memory.Internal: instance Data.Prim.Memory.Internal.MemRead (Data.Prim.Memory.Bytes.Internal.Bytes p)
- Data.Prim.Memory.Internal: instance Data.Prim.Memory.Internal.MemRead Data.ByteString.Internal.ByteString
- Data.Prim.Memory.Internal: instance Data.Prim.Memory.Internal.MemRead Data.ByteString.Short.Internal.ShortByteString
- Data.Prim.Memory.Internal: instance Data.Prim.Memory.Internal.MemWrite (Data.Prim.Memory.Bytes.Internal.MBytes p)
- Data.Prim.Memory.Internal: instance Data.Prim.Memory.Internal.MemWrite (Data.Prim.Memory.Internal.MemState (GHC.ForeignPtr.ForeignPtr a))
- Data.Prim.Memory.Internal: instance Data.Prim.Memory.Internal.MemWrite Data.Prim.Memory.ByteString.MByteString
- Data.Prim.Memory.Internal: instance Data.Typeable.Internal.Typeable p => Data.Prim.Memory.Internal.MemAlloc (Data.Prim.Memory.Bytes.Internal.MBytes p)
- Data.Prim.Memory.Internal: instance Data.Typeable.Internal.Typeable p => GHC.Base.Monoid (Data.Prim.Memory.Bytes.Internal.Bytes p)
- Data.Prim.Memory.Internal: instance Data.Typeable.Internal.Typeable p => GHC.Base.Semigroup (Data.Prim.Memory.Bytes.Internal.Bytes p)
- Data.Prim.Memory.Internal: instance Data.Typeable.Internal.Typeable p => GHC.Exts.IsList (Data.Prim.Memory.Bytes.Internal.Bytes p)
- Data.Prim.Memory.Internal: instance GHC.Classes.Eq (Data.Prim.Memory.Bytes.Internal.Bytes p)
- Data.Prim.Memory.Internal: instance GHC.Classes.Ord (Data.Prim.Memory.Bytes.Internal.Bytes p)
- Data.Prim.Memory.Internal: instance GHC.Show.Show (Data.Prim.Memory.Bytes.Internal.Bytes p)
- Data.Prim.Memory.Internal: izipWithByteOffMemM_ :: (MemRead r1, MemRead r2, MonadPrim s m, Prim e) => r1 -> Off Word8 -> r2 -> Off Word8 -> Count e -> (Off Word8 -> e -> Off Word8 -> e -> m b) -> m (Off Word8)
- Data.Prim.Memory.Internal: izipWithOffMemM_ :: (MemRead r1, MemRead r2, MonadPrim s m, Prim e1, Prim e2) => r1 -> Off e1 -> r2 -> Off e2 -> Int -> (Off e1 -> e1 -> Off e2 -> e2 -> m b) -> m ()
- Data.Prim.Memory.Internal: loadListMem :: (MonadPrim s m, MemAlloc r, Prim e) => [e] -> r s -> m Ordering
- Data.Prim.Memory.Internal: loadListMemN :: (MemWrite r, MonadPrim s m, Prim e) => Count e -> Count Word8 -> [e] -> r s -> m Ordering
- Data.Prim.Memory.Internal: loadListMemN_ :: (MemWrite r, MonadPrim s m, Prim e) => Count e -> [e] -> r s -> m ()
- Data.Prim.Memory.Internal: loadListMem_ :: (MonadPrim s m, MemAlloc r, Prim e) => [e] -> r s -> m ()
- Data.Prim.Memory.Internal: loopShortM :: Monad m => Int -> (Int -> a -> Bool) -> (Int -> Int) -> a -> (Int -> a -> m a) -> m a
- Data.Prim.Memory.Internal: loopShortM' :: Monad m => Int -> (Int -> a -> m Bool) -> (Int -> Int) -> a -> (Int -> a -> m a) -> m a
- Data.Prim.Memory.Internal: mapByteMem :: (MemRead r, MemAlloc a, Prim e) => (Word8 -> e) -> r -> FrozenMem a
- Data.Prim.Memory.Internal: mapByteMemM :: (MemRead r, MemAlloc a, MonadPrim s m, Prim e) => (Word8 -> m e) -> r -> m (FrozenMem a)
- Data.Prim.Memory.Internal: mapByteOffMem :: (MemRead r, MemAlloc a, Prim e) => (Off Word8 -> Word8 -> e) -> r -> FrozenMem a
- Data.Prim.Memory.Internal: mapByteOffMemM :: (MemRead r, MemAlloc a, MonadPrim s m, Prim e) => (Off Word8 -> Word8 -> m e) -> r -> m (FrozenMem a)
- Data.Prim.Memory.Internal: modifyFetchNewMem :: (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> b) -> m b
- Data.Prim.Memory.Internal: modifyFetchNewMemM :: (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> m b) -> m b
- Data.Prim.Memory.Internal: modifyFetchOldMem :: (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> b) -> m b
- Data.Prim.Memory.Internal: modifyFetchOldMemM :: (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> m b) -> m b
- Data.Prim.Memory.Internal: moveByteOffMem :: (MemWrite w, MonadPrim s m, MemWrite w', Prim e) => w' s -> Off Word8 -> w s -> Off Word8 -> Count e -> m ()
- Data.Prim.Memory.Internal: moveByteOffToMBytesMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m ()
- Data.Prim.Memory.Internal: moveByteOffToPtrMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m ()
- Data.Prim.Memory.Internal: moveMem :: (MonadPrim s m, MemWrite w1, MemWrite w2, Prim e) => w1 s -> Off e -> w2 s -> Off e -> Count e -> m ()
- Data.Prim.Memory.Internal: newtype MemState a s
- Data.Prim.Memory.Internal: readByteOffMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off Word8 -> m e
- Data.Prim.Memory.Internal: readOffMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off e -> m e
- Data.Prim.Memory.Internal: resizeMem :: (MemAlloc a, MonadPrim s m, Prim e) => a s -> Count e -> m (a s)
- Data.Prim.Memory.Internal: setMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off e -> Count e -> e -> m ()
- Data.Prim.Memory.Internal: showsHexMem :: MemRead r => r -> [ShowS]
- Data.Prim.Memory.Internal: singletonMem :: forall e a. (MemAlloc a, Prim e) => e -> FrozenMem a
- Data.Prim.Memory.Internal: thawCloneMem :: (MemRead r, MemAlloc a, MonadPrim s m) => r -> m (a s)
- Data.Prim.Memory.Internal: thawCopyMem :: (MemRead r, MemAlloc a, MonadPrim s m, Prim e) => r -> Off e -> Count e -> m (a s)
- Data.Prim.Memory.Internal: thawMem :: (MemAlloc a, MonadPrim s m) => FrozenMem a -> m (a s)
- Data.Prim.Memory.Internal: toByteListMem :: MemAlloc a => FrozenMem a -> [Word8]
- Data.Prim.Memory.Internal: toListMem :: (MemRead r, Prim e) => r -> [e]
- Data.Prim.Memory.Internal: toListSlackMem :: forall e r. (MemRead r, Prim e) => r -> ([e], [Word8])
- Data.Prim.Memory.Internal: type family FrozenMem a = (fa :: Type) | fa -> a;
- Data.Prim.Memory.Internal: withScrubbedMem :: (MonadUnliftPrim RW m, Prim e, MemAlloc mem) => Count e -> (mem RW -> m a) -> m a
- Data.Prim.Memory.Internal: writeByteOffMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off Word8 -> e -> m ()
- Data.Prim.Memory.Internal: writeOffMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off e -> e -> m ()
- Data.Prim.Memory.Internal: }
+ Data.Prim.Memory: -- <tt>ma <a>-</a> FrozeMem ma</tt> will always uniquely identify each
+ Data.Prim.Memory: -- inference.
+ Data.Prim.Memory: -- other, which is an extremely useful property when it comes to type
+ Data.Prim.Memory: -- states of memory region are in one-to-one correspondence, therefore
+ Data.Prim.Memory: -- | Memory region in the immutable state. Types for frozen and thawed
+ Data.Prim.Memory: cloneMem :: forall ma. MemAlloc ma => FrozenMem ma -> FrozenMem ma
+ Data.Prim.Memory: compareByteOffToBytesMem :: (MemRead mr, Prim e) => mr -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> Ordering
+ Data.Prim.Memory: compareByteOffToPtrMem :: (MemRead mr, MonadPrim s m, Prim e) => mr -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m Ordering
+ Data.Prim.Memory: copyByteOffToMBytesMem :: (MemRead mr, MonadPrim s m, Prim e) => mr -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m ()
+ Data.Prim.Memory: copyByteOffToPtrMem :: (MemRead mr, MonadPrim s m, Prim e) => mr -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m ()
+ Data.Prim.Memory: fromListZeroMemN :: forall e ma. (Prim e, MemAlloc ma) => Count e -> [e] -> (Either [e] (Count e), FrozenMem ma)
+ Data.Prim.Memory: fromListZeroMemN_ :: forall e ma. (Prim e, MemAlloc ma) => Count e -> [e] -> FrozenMem ma
+ Data.Prim.Memory: loadListByteOffMem :: (MemAlloc ma, MonadPrim s m, Prim e) => [e] -> ma s -> Off Word8 -> m ([e], Count e)
+ Data.Prim.Memory: loadListByteOffMemN :: (MemWrite mw, MonadPrim s m, Prim e) => Count e -> [e] -> mw s -> Off Word8 -> m ([e], Count e)
+ Data.Prim.Memory: loadListOffMem :: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) => [e] -> ma s -> Off e -> m ([e], Count e)
+ Data.Prim.Memory: loadListOffMemN :: (MemWrite mw, MonadPrim s m, Prim e) => Count e -> [e] -> mw s -> Off e -> m ([e], Count e)
+ Data.Prim.Memory: moveByteOffToMBytesMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m ()
+ Data.Prim.Memory: moveByteOffToPtrMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m ()
+ Data.Prim.Memory: resizeMem :: (MemAlloc ma, MonadPrim s m, Prim e) => ma s -> Count e -> m (ma s)
+ Data.Prim.Memory: showsHexMem :: MemRead mr => mr -> [ShowS]
+ Data.Prim.Memory: withScrubbedMem :: forall e ma m a. (MonadUnliftPrim RW m, Prim e, MemAlloc ma, PtrAccess RW (ma RW)) => Count e -> (ma RW -> m a) -> m a
+ Data.Prim.Memory.Bytes: toInconclusiveBytes :: Bytes p -> Bytes 'Inc
+ Data.Prim.Memory.Bytes: toInconclusiveMBytes :: MBytes p e -> MBytes 'Inc e
+ Data.Prim.Memory.PrimArray: Inc :: Pinned
+ Data.Prim.Memory.PrimArray: MPrimArray :: MBytes p s -> MPrimArray e s
+ Data.Prim.Memory.PrimArray: Pin :: Pinned
+ Data.Prim.Memory.PrimArray: PrimArray :: Bytes p -> PrimArray e
+ Data.Prim.Memory.PrimArray: allocAlignedMPrimArray :: (MonadPrim s m, Prim e) => Count e -> m (MPrimArray 'Pin e s)
+ Data.Prim.Memory.PrimArray: allocMPrimArray :: forall e p m s. (Typeable p, Prim e, MonadPrim s m) => Size -> m (MPrimArray p e s)
+ Data.Prim.Memory.PrimArray: allocPinnedMPrimArray :: forall e m s. (MonadPrim s m, Prim e) => Size -> m (MPrimArray 'Pin e s)
+ Data.Prim.Memory.PrimArray: allocUnpinnedMPrimArray :: forall e m s. (MonadPrim s m, Prim e) => Size -> m (MPrimArray 'Inc e s)
+ Data.Prim.Memory.PrimArray: castMPrimArray :: MPrimArray p e' s -> MPrimArray p e s
+ Data.Prim.Memory.PrimArray: castPrimArray :: PrimArray p e' -> PrimArray p e
+ Data.Prim.Memory.PrimArray: copyPrimArrayToMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => PrimArray p e -> Int -> MPrimArray p e s -> Int -> Size -> m ()
+ Data.Prim.Memory.PrimArray: data Pinned
+ Data.Prim.Memory.PrimArray: freezeMPrimArray :: MonadPrim s m => MPrimArray p e s -> m (PrimArray p e)
+ Data.Prim.Memory.PrimArray: fromBytesPrimArray :: Bytes p -> PrimArray p e
+ Data.Prim.Memory.PrimArray: fromMBytesMPrimArray :: MBytes p s -> MPrimArray p e s
+ Data.Prim.Memory.PrimArray: getSizeMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> m Size
+ Data.Prim.Memory.PrimArray: instance (Data.Typeable.Internal.Typeable p, Data.Prim.Class.Prim e) => GHC.Exts.IsList (Data.Prim.Memory.PrimArray.PrimArray p e)
+ Data.Prim.Memory.PrimArray: instance (GHC.Show.Show e, Data.Prim.Class.Prim e) => GHC.Show.Show (Data.Prim.Memory.PrimArray.PrimArray p e)
+ Data.Prim.Memory.PrimArray: instance Control.DeepSeq.NFData (Data.Prim.Memory.PrimArray.MPrimArray p e s)
+ Data.Prim.Memory.PrimArray: instance Control.DeepSeq.NFData (Data.Prim.Memory.PrimArray.PrimArray p e)
+ Data.Prim.Memory.PrimArray: instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.PrimArray.MPrimArray 'Data.Prim.Memory.Bytes.Internal.Pin e s)
+ Data.Prim.Memory.PrimArray: instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.PrimArray.PrimArray 'Data.Prim.Memory.Bytes.Internal.Pin e)
+ Data.Prim.Memory.PrimArray: instance Data.Prim.Memory.Internal.MemRead (Data.Prim.Memory.PrimArray.PrimArray p e)
+ Data.Prim.Memory.PrimArray: instance Data.Prim.Memory.Internal.MemWrite (Data.Prim.Memory.PrimArray.MPrimArray p e)
+ Data.Prim.Memory.PrimArray: instance Data.Typeable.Internal.Typeable p => Data.Prim.Memory.Internal.MemAlloc (Data.Prim.Memory.PrimArray.MPrimArray p e)
+ Data.Prim.Memory.PrimArray: instance Data.Typeable.Internal.Typeable p => Data.String.IsString (Data.Prim.Memory.PrimArray.PrimArray p GHC.Types.Char)
+ Data.Prim.Memory.PrimArray: instance Data.Typeable.Internal.Typeable p => GHC.Base.Monoid (Data.Prim.Memory.PrimArray.PrimArray p e)
+ Data.Prim.Memory.PrimArray: instance Data.Typeable.Internal.Typeable p => GHC.Base.Semigroup (Data.Prim.Memory.PrimArray.PrimArray p e)
+ Data.Prim.Memory.PrimArray: isPinnedMPrimArray :: MPrimArray p e s -> Bool
+ Data.Prim.Memory.PrimArray: isPinnedPrimArray :: PrimArray p e -> Bool
+ Data.Prim.Memory.PrimArray: moveMPrimArrayToMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> MPrimArray p e s -> Int -> Size -> m ()
+ Data.Prim.Memory.PrimArray: newtype MPrimArray (p :: Pinned) e s
+ Data.Prim.Memory.PrimArray: newtype PrimArray (p :: Pinned) e
+ Data.Prim.Memory.PrimArray: readMPrimArray :: (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> m e
+ Data.Prim.Memory.PrimArray: reallocMPrimArray :: forall e p m s. (MonadPrim s m, Typeable p, Prim e) => MPrimArray p e s -> Size -> m (MPrimArray p e s)
+ Data.Prim.Memory.PrimArray: resizeMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> Size -> m (MPrimArray 'Inc e s)
+ Data.Prim.Memory.PrimArray: setMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> Size -> e -> m ()
+ Data.Prim.Memory.PrimArray: shrinkMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> Size -> m ()
+ Data.Prim.Memory.PrimArray: sizePrimArray :: forall e p. Prim e => PrimArray p e -> Size
+ Data.Prim.Memory.PrimArray: thawPrimArray :: MonadPrim s m => PrimArray p e -> m (MPrimArray p e s)
+ Data.Prim.Memory.PrimArray: toBytesPrimArray :: PrimArray p e -> Bytes p
+ Data.Prim.Memory.PrimArray: toMBytesMPrimArray :: MPrimArray p e s -> MBytes p s
+ Data.Prim.Memory.PrimArray: writeMPrimArray :: (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> e -> m ()
+ Data.Prim.Memory.Text: Array :: ByteArray# -> Array
+ Data.Prim.Memory.Text: MArray :: MutableByteArray# s -> MArray s
+ Data.Prim.Memory.Text: MText :: {-# UNPACK #-} !MArray s -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> MText s
+ Data.Prim.Memory.Text: Text :: {-# UNPACK #-} !Array -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Text
+ Data.Prim.Memory.Text: [aBA] :: Array -> ByteArray#
+ Data.Prim.Memory.Text: [maBA] :: MArray s -> MutableByteArray# s
+ Data.Prim.Memory.Text: data Array
+ Data.Prim.Memory.Text: data MArray s
+ Data.Prim.Memory.Text: data MText s
+ Data.Prim.Memory.Text: data Text
+ Data.Prim.Memory.Text: fromBytesArray :: Bytes p -> Array
+ Data.Prim.Memory.Text: fromMBytesMArray :: MBytes p s -> MArray s
+ Data.Prim.Memory.Text: toBytesArray :: Array -> Bytes 'Inc
+ Data.Prim.Memory.Text: toMBytesMArray :: MArray s -> MBytes 'Inc s
- Data.Prim.Memory: allocMem :: (MemAlloc a, MonadPrim s m, Prim e) => Count e -> m (a s)
+ Data.Prim.Memory: allocMem :: (MemAlloc ma, Prim e, MonadPrim s m) => Count e -> m (ma s)
- Data.Prim.Memory: allocZeroMem :: (MemAlloc a, MonadPrim s m, Prim e) => Count e -> m (a s)
+ Data.Prim.Memory: allocZeroMem :: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) => Count e -> m (ma s)
- Data.Prim.Memory: byteCountMem :: MemRead r => r -> Count Word8
+ Data.Prim.Memory: byteCountMem :: MemRead mr => mr -> Count Word8
- Data.Prim.Memory: class (MemRead (FrozenMem a), MemWrite a) => MemAlloc a where {
+ Data.Prim.Memory: class (MemRead (FrozenMem ma), MemWrite ma) => MemAlloc ma where {
- Data.Prim.Memory: class MemRead r
+ Data.Prim.Memory: class MemRead mr
- Data.Prim.Memory: class MemWrite w
+ Data.Prim.Memory: class MemWrite mw
- Data.Prim.Memory: compareByteOffMem :: (MemRead r, MemRead r', Prim e) => r' -> Off Word8 -> r -> Off Word8 -> Count e -> Ordering
+ Data.Prim.Memory: compareByteOffMem :: (MemRead mr, MemRead mr', Prim e) => mr' -> Off Word8 -> mr -> Off Word8 -> Count e -> Ordering
- Data.Prim.Memory: compareMem :: (MemRead r1, MemRead r2, Prim e) => r1 -> Off e -> r2 -> Off e -> Count e -> Ordering
+ Data.Prim.Memory: compareMem :: forall e mr1 mr2. (MemRead mr1, MemRead mr2, Prim e) => mr1 -> Off e -> mr2 -> Off e -> Count e -> Ordering
- Data.Prim.Memory: convertMem :: (MemRead r, MemAlloc a) => r -> FrozenMem a
+ Data.Prim.Memory: convertMem :: (MemRead mr, MemAlloc ma) => mr -> FrozenMem ma
- Data.Prim.Memory: copyByteOffMem :: (MemWrite w, MonadPrim s m, MemRead r, Prim e) => r -> Off Word8 -> w s -> Off Word8 -> Count e -> m ()
+ Data.Prim.Memory: copyByteOffMem :: (MemWrite mw, MonadPrim s m, MemRead mr, Prim e) => mr -> Off Word8 -> mw s -> Off Word8 -> Count e -> m ()
- Data.Prim.Memory: copyMem :: (MonadPrim s m, MemRead r, MemWrite w, Prim e) => r -> Off e -> w s -> Off e -> Count e -> m ()
+ Data.Prim.Memory: copyMem :: (MonadPrim s m, MemRead mr, MemWrite mw, Prim e) => mr -> Off e -> mw s -> Off e -> Count e -> m ()
- Data.Prim.Memory: countMem :: forall e r. (MemRead r, Prim e) => r -> Count e
+ Data.Prim.Memory: countMem :: forall e mr. (MemRead mr, Prim e) => mr -> Count e
- Data.Prim.Memory: countRemMem :: forall e r. (MemRead r, Prim e) => r -> (Count e, Count Word8)
+ Data.Prim.Memory: countRemMem :: forall e mr. (MemRead mr, Prim e) => mr -> (Count e, Count Word8)
- Data.Prim.Memory: createMemST :: (MemAlloc a, Prim e) => Count e -> (forall s. a s -> ST s b) -> (b, FrozenMem a)
+ Data.Prim.Memory: createMemST :: forall e b ma. (MemAlloc ma, Prim e) => Count e -> (forall s. ma s -> ST s b) -> (b, FrozenMem ma)
- Data.Prim.Memory: createMemST_ :: (MemAlloc a, Prim e) => Count e -> (forall s. a s -> ST s b) -> FrozenMem a
+ Data.Prim.Memory: createMemST_ :: (MemAlloc ma, Prim e) => Count e -> (forall s. ma s -> ST s b) -> FrozenMem ma
- Data.Prim.Memory: createZeroMemST :: (MemAlloc a, Prim e) => Count e -> (forall s. a s -> ST s b) -> (b, FrozenMem a)
+ Data.Prim.Memory: createZeroMemST :: forall e ma b. (MemAlloc ma, Prim e) => Count e -> (forall s. ma s -> ST s b) -> (b, FrozenMem ma)
- Data.Prim.Memory: createZeroMemST_ :: (MemAlloc a, Prim e) => Count e -> (forall s. a s -> ST s b) -> FrozenMem a
+ Data.Prim.Memory: createZeroMemST_ :: forall e ma b. (MemAlloc ma, Prim e) => Count e -> (forall s. ma s -> ST s b) -> FrozenMem ma
- Data.Prim.Memory: cycleMemN :: (MemAlloc a, MemRead r) => Int -> r -> FrozenMem a
+ Data.Prim.Memory: cycleMemN :: forall ma mr. (MemAlloc ma, MemRead mr) => Int -> mr -> FrozenMem ma
- Data.Prim.Memory: emptyMem :: MemAlloc a => FrozenMem a
+ Data.Prim.Memory: emptyMem :: forall ma. MemAlloc ma => FrozenMem ma
- Data.Prim.Memory: eqMem :: (MemRead r1, MemRead r2) => r1 -> r2 -> Bool
+ Data.Prim.Memory: eqMem :: (MemRead mr1, MemRead mr2) => mr1 -> mr2 -> Bool
- Data.Prim.Memory: foldrCountMem :: (MemRead r, Prim e) => Count e -> (e -> b -> b) -> b -> r -> b
+ Data.Prim.Memory: foldrCountMem :: forall e b mr. (MemRead mr, Prim e) => Count e -> (e -> b -> b) -> b -> mr -> b
- Data.Prim.Memory: freezeCloneMem :: (MemAlloc a, MonadPrim s m) => a s -> m (FrozenMem a)
+ Data.Prim.Memory: freezeCloneMem :: forall ma m s. (MemAlloc ma, MonadPrim s m) => ma s -> m (FrozenMem ma)
- Data.Prim.Memory: freezeCopyMem :: (MemAlloc a, MonadPrim s m, Prim e) => a s -> Off e -> Count e -> m (FrozenMem a)
+ Data.Prim.Memory: freezeCopyMem :: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) => ma s -> Off e -> Count e -> m (FrozenMem ma)
- Data.Prim.Memory: freezeMem :: (MemAlloc a, MonadPrim s m) => a s -> m (FrozenMem a)
+ Data.Prim.Memory: freezeMem :: (MemAlloc ma, MonadPrim s m) => ma s -> m (FrozenMem ma)
- Data.Prim.Memory: fromByteListMem :: MemAlloc a => [Word8] -> FrozenMem a
+ Data.Prim.Memory: fromByteListMem :: forall ma. MemAlloc ma => [Word8] -> FrozenMem ma
- Data.Prim.Memory: fromListMem :: (MemAlloc a, Prim e) => [e] -> FrozenMem a
+ Data.Prim.Memory: fromListMem :: forall e ma. (Prim e, MemAlloc ma) => [e] -> FrozenMem ma
- Data.Prim.Memory: fromListMemN :: (MemAlloc a, Prim e) => Count e -> [e] -> (Ordering, FrozenMem a)
+ Data.Prim.Memory: fromListMemN :: forall e ma. (Prim e, MemAlloc ma) => Count e -> [e] -> (Either [e] (Count e), FrozenMem ma)
- Data.Prim.Memory: getByteCountMem :: (MemAlloc a, MonadPrim s m) => a s -> m (Count Word8)
+ Data.Prim.Memory: getByteCountMem :: (MemAlloc ma, MonadPrim s m) => ma s -> m (Count Word8)
- Data.Prim.Memory: getCountMem :: (MemAlloc r, MonadPrim s m, Prim e) => r s -> m (Count e)
+ Data.Prim.Memory: getCountMem :: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) => ma s -> m (Count e)
- Data.Prim.Memory: getCountRemMem :: (MemAlloc r, MonadPrim s m, Prim e) => r s -> m (Count e, Count Word8)
+ Data.Prim.Memory: getCountRemMem :: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) => ma s -> m (Count e, Count Word8)
- Data.Prim.Memory: indexByteOffMem :: (MemRead r, Prim e) => r -> Off Word8 -> e
+ Data.Prim.Memory: indexByteOffMem :: (MemRead mr, Prim e) => mr -> Off Word8 -> e
- Data.Prim.Memory: indexOffMem :: (MemRead r, Prim e) => r -> Off e -> e
+ Data.Prim.Memory: indexOffMem :: (MemRead mr, Prim e) => mr -> Off e -> e
- Data.Prim.Memory: loadListMem :: (MonadPrim s m, MemAlloc r, Prim e) => [e] -> r s -> m Ordering
+ Data.Prim.Memory: loadListMem :: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) => [e] -> ma s -> m ([e], Count e)
- Data.Prim.Memory: loadListMemN :: (MemWrite r, MonadPrim s m, Prim e) => Count e -> Count Word8 -> [e] -> r s -> m Ordering
+ Data.Prim.Memory: loadListMemN :: forall e mw m s. (MemWrite mw, MonadPrim s m, Prim e) => Count e -> [e] -> mw s -> m ([e], Count e)
- Data.Prim.Memory: loadListMemN_ :: (MemWrite r, MonadPrim s m, Prim e) => Count e -> [e] -> r s -> m ()
+ Data.Prim.Memory: loadListMemN_ :: forall e mw m s. (Prim e, MemWrite mw, MonadPrim s m) => Count e -> [e] -> mw s -> m ()
- Data.Prim.Memory: loadListMem_ :: (MonadPrim s m, MemAlloc r, Prim e) => [e] -> r s -> m ()
+ Data.Prim.Memory: loadListMem_ :: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) => [e] -> ma s -> m ()
- Data.Prim.Memory: modifyFetchNewMem :: (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> b) -> m b
+ Data.Prim.Memory: modifyFetchNewMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> e) -> m e
- Data.Prim.Memory: modifyFetchNewMemM :: (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> m b) -> m b
+ Data.Prim.Memory: modifyFetchNewMemM :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> m e) -> m e
- Data.Prim.Memory: modifyFetchOldMem :: (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> b) -> m b
+ Data.Prim.Memory: modifyFetchOldMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> e) -> m e
- Data.Prim.Memory: modifyFetchOldMemM :: (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> m b) -> m b
+ Data.Prim.Memory: modifyFetchOldMemM :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> m e) -> m e
- Data.Prim.Memory: moveByteOffMem :: (MemWrite w, MonadPrim s m, MemWrite w', Prim e) => w' s -> Off Word8 -> w s -> Off Word8 -> Count e -> m ()
+ Data.Prim.Memory: moveByteOffMem :: (MemWrite mw, MonadPrim s m, MemWrite mw', Prim e) => mw' s -> Off Word8 -> mw s -> Off Word8 -> Count e -> m ()
- Data.Prim.Memory: moveMem :: (MonadPrim s m, MemWrite w1, MemWrite w2, Prim e) => w1 s -> Off e -> w2 s -> Off e -> Count e -> m ()
+ Data.Prim.Memory: moveMem :: (MonadPrim s m, MemWrite mw1, MemWrite mw2, Prim e) => mw1 s -> Off e -> mw2 s -> Off e -> Count e -> m ()
- Data.Prim.Memory: readByteOffMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off Word8 -> m e
+ Data.Prim.Memory: readByteOffMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off Word8 -> m e
- Data.Prim.Memory: readOffMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off e -> m e
+ Data.Prim.Memory: readOffMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> m e
- Data.Prim.Memory: setMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off e -> Count e -> e -> m ()
+ Data.Prim.Memory: setMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> Count e -> e -> m ()
- Data.Prim.Memory: singletonMem :: forall e a. (MemAlloc a, Prim e) => e -> FrozenMem a
+ Data.Prim.Memory: singletonMem :: forall e ma. (MemAlloc ma, Prim e) => e -> FrozenMem ma
- Data.Prim.Memory: thawCloneMem :: (MemRead r, MemAlloc a, MonadPrim s m) => r -> m (a s)
+ Data.Prim.Memory: thawCloneMem :: forall mr ma m s. (MemRead mr, MemAlloc ma, MonadPrim s m) => mr -> m (ma s)
- Data.Prim.Memory: thawCopyMem :: (MemRead r, MemAlloc a, MonadPrim s m, Prim e) => r -> Off e -> Count e -> m (a s)
+ Data.Prim.Memory: thawCopyMem :: forall e mr ma m s. (Prim e, MemRead mr, MemAlloc ma, MonadPrim s m) => mr -> Off e -> Count e -> m (ma s)
- Data.Prim.Memory: thawMem :: (MemAlloc a, MonadPrim s m) => FrozenMem a -> m (a s)
+ Data.Prim.Memory: thawMem :: (MemAlloc ma, MonadPrim s m) => FrozenMem ma -> m (ma s)
- Data.Prim.Memory: toByteListMem :: MemAlloc a => FrozenMem a -> [Word8]
+ Data.Prim.Memory: toByteListMem :: forall ma. MemAlloc ma => FrozenMem ma -> [Word8]
- Data.Prim.Memory: toListMem :: (MemRead r, Prim e) => r -> [e]
+ Data.Prim.Memory: toListMem :: forall e mr. (MemRead mr, Prim e) => mr -> [e]
- Data.Prim.Memory: toListSlackMem :: forall e r. (MemRead r, Prim e) => r -> ([e], [Word8])
+ Data.Prim.Memory: toListSlackMem :: forall e mr. (MemRead mr, Prim e) => mr -> ([e], [Word8])
- Data.Prim.Memory: type family FrozenMem a = (fa :: Type) | fa -> a;
+ Data.Prim.Memory: type family FrozenMem ma = (fm :: Type) | fm -> ma;
- Data.Prim.Memory: writeByteOffMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off Word8 -> e -> m ()
+ Data.Prim.Memory: writeByteOffMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off Word8 -> e -> m ()
- Data.Prim.Memory: writeOffMem :: (MemWrite w, MonadPrim s m, Prim e) => w s -> Off e -> e -> m ()
+ Data.Prim.Memory: writeOffMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> e -> m ()
- Data.Prim.Memory.Bytes: fromListBytesN :: (Prim e, Typeable p) => Count e -> [e] -> (Ordering, Bytes p)
+ Data.Prim.Memory.Bytes: fromListBytesN :: (Prim e, Typeable p) => Count e -> [e] -> (Either [e] (Count e), Bytes p)
- Data.Prim.Memory.Bytes: loadListMBytes :: (MonadPrim s m, Prim e) => [e] -> MBytes p s -> m Ordering
+ Data.Prim.Memory.Bytes: loadListMBytes :: (Prim e, Typeable p, MonadPrim s m) => [e] -> MBytes p s -> m ([e], Count e)
- Data.Prim.Memory.Bytes: loadListMBytes_ :: (MonadPrim s m, Prim e) => [e] -> MBytes p s -> m ()
+ Data.Prim.Memory.Bytes: loadListMBytes_ :: (Prim e, Typeable p, MonadPrim s m) => [e] -> MBytes p s -> m ()
- Data.Prim.Memory.Bytes: relaxPinnedBytes :: Bytes p -> Bytes 'Inc
+ Data.Prim.Memory.Bytes: relaxPinnedBytes :: Bytes 'Pin -> Bytes p
- Data.Prim.Memory.Bytes: relaxPinnedMBytes :: MBytes p e -> MBytes 'Inc e
+ Data.Prim.Memory.Bytes: relaxPinnedMBytes :: MBytes 'Pin e -> MBytes p e

Files

CHANGELOG.md view
@@ -1,5 +1,11 @@ # Changelog for primal-memory -## 0.1.0.0+## 0.2.0++* Rename `ByteArray` -> `PrimArray`+* Improve `fromList` conversion+* Get rid of `allocByteCountMem` in favor of more general `allocMem`++## 0.1.0  * Initial release
bench/Bench.hs view
@@ -24,11 +24,11 @@   mb1 <- allocAlignedMBytes n64   mb2 <- allocAlignedMBytes n64   b1 <- freezeMBytes mb1-  mba <- BA.newAlignedPinnedByteArray (fromCount (n :: Count Word64)) 8+  mba <- BA.newAlignedPinnedByteArray (unCountBytes (n :: Count Word64)) 8   ba <- BA.unsafeFreezeByteArray mba   -- Ensure that arrays are equal by filling them with zeros-  mbaEq1 <- BA.newAlignedPinnedByteArray (fromCount (n :: Count Word64)) 8-  mbaEq2 <- BA.newAlignedPinnedByteArray (fromCount (n :: Count Word64)) 8+  mbaEq1 <- BA.newAlignedPinnedByteArray (unCountBytes (n :: Count Word64)) 8+  mbaEq2 <- BA.newAlignedPinnedByteArray (unCountBytes (n :: Count Word64)) 8   BA.setByteArray mbaEq1 0 (unCount n64) (0 :: Word64)   BA.setByteArray mbaEq2 0 (unCount n64) (0 :: Word64)   defaultMain
bench/Conversion.hs view
@@ -13,7 +13,6 @@ import qualified Foreign.ForeignPtr as GHC import Foreign.Storable import Data.Prim.Memory.ForeignPtr-import Data.Semigroup import qualified Data.Primitive.ByteArray as BA  main :: IO ()@@ -26,13 +25,13 @@   mb2 <- allocAlignedMBytes n64   mb3 <- allocAlignedMBytes n64   let fp = toForeignPtrMBytes mb3-  mba <- BA.newAlignedPinnedByteArray (fromCount (n :: Count Word64)) 8+  mba <- BA.newAlignedPinnedByteArray (unCountBytes (n :: Count Word64)) 8   ba <- BA.unsafeFreezeByteArray mba   -- Ensure that arrays are equal by filling them with zeros   bEq1 <- freezeMBytes =<< callocAlignedMBytes n64   bEq2 <- freezeMBytes =<< callocAlignedMBytes n64-  mbaEq1 <- BA.newAlignedPinnedByteArray (fromCount (n :: Count Word64)) 8-  mbaEq2 <- BA.newAlignedPinnedByteArray (fromCount (n :: Count Word64)) 8+  mbaEq1 <- BA.newAlignedPinnedByteArray (unCountBytes (n :: Count Word64)) 8+  mbaEq2 <- BA.newAlignedPinnedByteArray (unCountBytes (n :: Count Word64)) 8   BA.setByteArray mbaEq1 0 (unCount n64) (0 :: Word64)   BA.setByteArray mbaEq2 0 (unCount n64) (0 :: Word64)   baEq1 <- BA.unsafeFreezeByteArray mbaEq1
primal-memory.cabal view
@@ -1,5 +1,5 @@ name:                primal-memory-version:             0.1.0.0+version:             0.2.0.0 synopsis:            Unified interface for memory managemenet. description:         Please see the README on GitHub at <https://github.com/lehins/primal#readme> homepage:            https://github.com/lehins/primal@@ -25,33 +25,39 @@ library   hs-source-dirs:      src   exposed-modules:     Data.Prim.Memory-                     , Data.Prim.Memory.ByteArray-                     , Data.Prim.Memory.Bytes                      , Data.Prim.Memory.Addr                      , Data.Prim.Memory.ByteString+                     , Data.Prim.Memory.Bytes+                     , Data.Prim.Memory.ForeignPtr+                     , Data.Prim.Memory.PrimArray                      , Data.Prim.Memory.Ptr+                     , Data.Prim.Memory.Text                      , Data.Prim.Memory.Internal-                     , Data.Prim.Memory.ForeignPtr   other-modules:       Data.Prim.Memory.Bytes.Internal-  build-depends:       base >= 4.8 && < 5-                     , bytestring+  build-depends:       base >= 4.9 && < 5+                     , bytestring >= 0.10.4                      , deepseq-                     , primal+                     , primal >= 0.2+                     , text >= 1.1.1.3    default-language:    Haskell2010   ghc-options:         -Wall--- test-suite doctests---   type:             exitcode-stdio-1.0---   hs-source-dirs:   tests---   main-is:          doctests.hs---   build-depends: base---                , doctest >=0.15---                , prim-bytes---                , template-haskell---   default-language:    Haskell2010---   ghc-options:        -Wall---                       -fno-warn-orphans---                       -threaded++test-suite doctests+  type:             exitcode-stdio-1.0+  hs-source-dirs:   tests+  main-is:          doctests.hs+  build-depends: base+               , bytestring+               , doctest >=0.15+               , primal+               , primal-memory+               , QuickCheck+               , template-haskell+  default-language:    Haskell2010+  ghc-options:        -Wall+                      -threaded+  benchmark bench   type:                exitcode-stdio-1.0
src/Data/Prim/Memory.hs view
@@ -7,83 +7,100 @@ -- Portability : non-portable -- module Data.Prim.Memory-  ( Pinned(..)+  ( module Data.Prim+  , Pinned(..)   -- * Immutable   , Bytes   , MemRead-  , countMem-  , countRemMem-  , indexOffMem-  , eqMem-  , compareMem+  -- ** Size+  , countMem                  -- DOC: [x], DOCTEST [x], TEST: [ ]+  , countRemMem               -- DOC: [x], DOCTEST [x], TEST: [ ]+  , byteCountMem              -- DOC: [x], DOCTEST [ ], TEST: [x]+  -- ** Index+  , indexOffMem               -- DOC: [x], DOCTEST [ ], TEST: [x]+  , indexByteOffMem           -- DOC: [x], DOCTEST [ ], TEST: [x]+  -- ** Construct+  , emptyMem                  -- DOC: [x], DOCTEST [x], TEST: [x]+  , singletonMem              -- DOC: [x], DOCTEST [x], TEST: [ ]+  , cycleMemN                 -- DOC: [x], DOCTEST [x], TEST: [ ]+  , createMemST               -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , createMemST_              -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , createZeroMemST           -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , createZeroMemST_          -- DOC: [x], DOCTEST [x], TEST: [ ]+  -- ** Copy+  , cloneMem                  -- DOC: [x], DOCTEST [x], TEST: [ ]+  , copyMem                   -- DOC: [x], DOCTEST [ ], TEST: [x]+  , copyByteOffMem            -- DOC: [x], DOCTEST [ ], TEST: [ ]+  , copyByteOffToMBytesMem    -- DOC: [x], DOCTEST [ ], TEST: [x]+  , copyByteOffToPtrMem       -- DOC: [x], DOCTEST [ ], TEST: [x]+  -- ** Compare+  , eqMem                     -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , compareMem                -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , compareByteOffMem         -- DOC: [x], DOCTEST [ ], TEST: [ ]+  , compareByteOffToPtrMem    -- DOC: [x], DOCTEST [ ], TEST: [x]+  , compareByteOffToBytesMem  -- DOC: [x], DOCTEST [ ], TEST: [x]+  -- ** Convert+  , convertMem                -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  -- *** To list+  , toListMem                 -- DOC: [x], DOCTEST [x], TEST: [x]+  , toListSlackMem            -- DOC: [x], DOCTEST [x], TEST: [x]+  , toByteListMem             -- DOC: [x], DOCTEST [x], TEST: [x]+  , foldrCountMem             -- DOC: [x], DOCTEST [-], TEST: [-]+  , showsHexMem               -- DOC: [x], DOCTEST [x], TEST: [ ]++  -- *** From list+  , fromListMem               -- DOC: [x], DOCTEST [x], TEST: [x]+  , fromByteListMem           -- DOC: [x], DOCTEST [x], TEST: [x]+  , fromListMemN              -- DOC: [x], DOCTEST [x], TEST: [x]+  , fromListZeroMemN          -- DOC: [x], DOCTEST [x], TEST: [ ]+  , fromListZeroMemN_         -- DOC: [x], DOCTEST [x], TEST: [ ]   -- * Mutable   , MBytes-  , MemAlloc(FrozenMem)   , MemWrite-  , getCountMem-  , getCountRemMem-  , readOffMem-  , writeOffMem-  , modifyFetchOldMem-  , modifyFetchOldMemM-  , modifyFetchNewMem-  , modifyFetchNewMemM-  , setMem-  , copyMem-  , moveMem-+  , MemAlloc(FrozenMem)   , MemState(..)-  , allocMem-  , allocZeroMem-  , thawMem-  , thawCloneMem-  , thawCopyMem-  , freezeMem-  , freezeCloneMem-  , freezeCopyMem-  , createMemST-  , createMemST_-  , createZeroMemST-  , createZeroMemST_-  , emptyMem-  , singletonMem-  , cycleMemN-  -- * Byte operations-  -- $byteOperations-  -- ** Immutable-  , byteCountMem-  , indexByteOffMem-  , compareByteOffMem-  -- ** Mutable-  , allocByteCountMem-  , getByteCountMem-  , readByteOffMem-  , writeByteOffMem-  , copyByteOffMem-  , moveByteOffMem-  -- * Conversion-  , convertMem-  -- ** List-  , toListMem-  , toListSlackMem-  , toByteListMem-  , fromByteListMem--  , fromListMem-  , fromListMemN-  , loadListMem-  , loadListMem_-  , loadListMemN-  , loadListMemN_-  -- *** Helpers-  , foldrCountMem+  -- ** Size+  , getCountMem               -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , getCountRemMem            -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , getByteCountMem           -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  -- ** Read+  , readOffMem                -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , readByteOffMem            -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  -- ** Write+  , writeOffMem               -- DOC: [x], DOCTEST [ ], TEST: [x]+  , writeByteOffMem           -- DOC: [x], DOCTEST [ ], TEST: [x]+  , setMem                    -- DOC: [x], DOCTEST [ ], TEST: [x]+  , modifyFetchOldMem         -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , modifyFetchOldMemM        -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , modifyFetchNewMem         -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , modifyFetchNewMemM        -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  -- ** Allocate+  , allocMem                  -- DOC: [x], DOCTEST [ ], TEST: [ ]+  , allocZeroMem              -- DOC: [x], DOCTEST [x], TEST: [ ]+  , thawMem                   -- DOC: [x], DOCTEST [ ], TEST: [ ]+  , thawCloneMem              -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , thawCopyMem               -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , freezeMem                 -- DOC: [x], DOCTEST [ ], TEST: [ ]+  , freezeCloneMem            -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , freezeCopyMem             -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , resizeMem                 -- DOC: [x], DOCTEST [ ], TEST: [ ]+  , withScrubbedMem           -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  -- ** Move+  , moveMem                   -- DOC: [ ], DOCTEST [ ], TEST: [x]+  , moveByteOffMem            -- DOC: [x], DOCTEST [ ], TEST: [ ]+  , moveByteOffToMBytesMem    -- DOC: [x], DOCTEST [ ], TEST: [x]+  , moveByteOffToPtrMem       -- DOC: [x], DOCTEST [ ], TEST: [x]+  -- ** Load list+  , loadListMem               -- DOC: [x], DOCTEST [x], TEST: [x]+  , loadListMem_              -- DOC: [x], DOCTEST [x], TEST: [ ]+  , loadListMemN              -- DOC: [x], DOCTEST [ ], TEST: [ ]+  , loadListMemN_             -- DOC: [x], DOCTEST [ ], TEST: [ ]+  -- *** With offset+  , loadListOffMem            -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , loadListOffMemN           -- DOC: [ ], DOCTEST [ ], TEST: [ ]+  , loadListByteOffMem        -- DOC: [x], DOCTEST [x], TEST: [ ]+  , loadListByteOffMemN       -- DOC: [x], DOCTEST [x], TEST: [ ]   ) where +import Data.Prim import Data.Prim.Memory.Internal----- $byteOperations------ More often than not it is desired to operate on the offset and count of the actual type--- of intereset we are dealing with in memory. But sometimes it is necessary to specify--- things in 8bit steps, this is where byte size offsets and counts will come in handy.
src/Data/Prim/Memory/Addr.hs view
@@ -134,26 +134,29 @@ import Data.Prim.Atomic import Data.Prim.Class import Data.Prim.Memory.Bytes+import Data.Prim.Memory.Bytes.Internal import Data.Prim.Memory.ByteString import Data.Prim.Memory.ForeignPtr import Data.Prim.Memory.Internal import Data.Prim.Memory.Ptr import qualified Data.Semigroup as Semigroup import Foreign.Prim+import Unsafe.Coerce  +-- | Immutable read-only address data Addr e = Addr   { addrAddr# :: Addr#   , addrBytes :: {-# UNPACK #-}!(Bytes 'Pin)   }-type role Addr representational-+type role Addr nominal +-- | Mutable address data MAddr e s = MAddr   { mAddrAddr#  :: Addr#   , mAddrMBytes :: {-# UNPACK #-}!(MBytes 'Pin s)   }-type role MAddr representational nominal+type role MAddr nominal nominal   @@ -169,7 +172,7 @@ instance Prim e => IsList (Addr e) where   type Item (Addr e) = e   fromList = fromListMem-  fromListN n = fromListMemN_ (Count n)+  fromListN n = fromListZeroMemN_ (Count n)   toList = toListMem  instance Semigroup.Semigroup (Addr e) where@@ -189,6 +192,9 @@ castMAddr :: MAddr e s -> MAddr b s castMAddr (MAddr a mb) = MAddr a mb +castStateMAddr :: MAddr e s' -> MAddr b s+castStateMAddr = unsafeCoerce+ isSameAddr :: Addr e -> Addr e -> Bool isSameAddr (Addr a1# _) (Addr a2# _) = isTrue# (a1# `eqAddr#` a2#) @@ -245,13 +251,13 @@   plusOffAddr :: Prim e => Addr e -> Off e -> Addr e-plusOffAddr (Addr addr# b) off = Addr (addr# `plusAddr#` fromOff# off) b+plusOffAddr (Addr addr# b) off = Addr (addr# `plusAddr#` unOffBytes# off) b  plusOffMAddr :: Prim e => MAddr e s -> Off e -> MAddr e s-plusOffMAddr (MAddr addr# mb) off = MAddr (addr# `plusAddr#` fromOff# off) mb+plusOffMAddr (MAddr addr# mb) off = MAddr (addr# `plusAddr#` unOffBytes# off) mb  curOffAddr :: Prim e => Addr e -> Off e-curOffAddr a@(Addr addr# b) = offAsProxy a (Ptr addr# `minusOffPtr` toPtrBytes b)+curOffAddr a@(Addr addr# b) = (Ptr addr# `minusOffPtr` toPtrBytes b) `offForProxyTypeOf` a  curByteOffAddr :: Addr e -> Off Word8 curByteOffAddr (Addr addr# b) = Ptr addr# `minusByteOffPtr` toPtrBytes b@@ -314,32 +320,40 @@ toForeignPtrMAddr :: MAddr e s -> ForeignPtr e toForeignPtrMAddr (MAddr addr# (MBytes mba#)) = ForeignPtr addr# (PlainPtr (unsafeCoerce# mba#)) --- | Discarding the original `ForeignPtr` will trigger finalizers that were attached to--- it, because `Addr` does not retain any finalizers. This is a unsafe cast therefore--- modification of `ForeignPtr` will be reflected in resulting immutable `Addr`. Pointer--- created with @malloc@ cannot be converted to `Addr` and will result in `Nothing`+-- | This is a unsafe cast therefore modification of `ForeignPtr` will be reflected in+-- resulting immutable `Addr`. Pointer created with @malloc@ cannot be converted to `Addr`+-- and will result in `Nothing` -- -- @since 0.1.0 fromForeignPtrAddr :: ForeignPtr e -> Maybe (Addr e)-fromForeignPtrAddr (ForeignPtr addr# c) =-  case c of-    PlainPtr mba#    -> Just (Addr addr# (unsafePerformIO (freezeMBytes (MBytes mba#))))-    MallocPtr mba# _ -> Just (Addr addr# (unsafePerformIO (freezeMBytes (MBytes mba#))))-    _                -> Nothing+fromForeignPtrAddr fptr =+  unsafePerformIO $ fromForeignPtrIO fptr >>= traverse freezeMAddr + -- | Discarding the original ForeignPtr will trigger finalizers that were attached to it, -- because `MAddr` does not retain any finalizers. Pointer created with @malloc@ cannot be -- converted to `MAddr` and will result in `Nothing` -- -- @since 0.1.0 fromForeignPtrMAddr :: ForeignPtr e -> Maybe (MAddr e s)-fromForeignPtrMAddr (ForeignPtr addr# c) =-  case c of-    PlainPtr mba#    -> Just (MAddr addr# (MBytes (unsafeCoerce# mba#)))-    MallocPtr mba# _ -> Just (MAddr addr# (MBytes (unsafeCoerce# mba#)))-    _                -> Nothing+fromForeignPtrMAddr fptr =+  unsafePerformIO (fmap castStateMAddr <$> fromForeignPtrIO fptr)+  -- case c of+  --   PlainPtr mba#    -> Just (MAddr addr# (MBytes (unsafeCoerce# mba#)))+  --   MallocPtr mba# _ -> Just (MAddr addr# (MBytes (unsafeCoerce# mba#)))+  --   _                -> Nothing  +fromForeignPtrIO :: ForeignPtr e -> IO (Maybe (MAddr e RW))+fromForeignPtrIO fptr =+  onForeignPtrContents fptr checkConvert $ \_ -> pure Nothing+  where+    checkConvert addr# mba# checkFinalizers = do+      hasFinalizers <- checkFinalizers+      pure $+        if hasFinalizers+          then Nothing+          else Just (MAddr addr# (MBytes mba#))  withAddrMAddr# :: MonadPrim s m => MAddr e s -> (Addr# -> m b) -> m b withAddrMAddr# (MAddr addr# mb) f = do@@ -374,11 +388,10 @@  instance MemAlloc (MAddr e) where   type FrozenMem (MAddr e) = Addr e-   getByteCountMem = getByteCountMAddr   {-# INLINE getByteCountMem #-}-  allocByteCountMem = fmap castMAddr . allocMAddr-  {-# INLINE allocByteCountMem #-}+  allocMem = fmap castMAddr . allocMAddr+  {-# INLINE allocMem #-}   thawMem = thawAddr   {-# INLINE thawMem #-}   freezeMem = freezeMAddr@@ -404,7 +417,8 @@     withPtrAccess addr $ \ptr1 -> pure $ compareByteOffPtrToPtr ptr1 off1 ptr2 off2 c   {-# INLINE compareByteOffToPtrMem #-}   compareByteOffToBytesMem addr off1 bytes off2 c =-    withPtrAccess addr $ \ptr1 -> pure $ compareByteOffPtrToBytes ptr1 off1 bytes off2 c+    unsafeInlineIO $ withPtrAccess addr $ \ptr1 ->+      pure $! compareByteOffPtrToBytes ptr1 off1 bytes off2 c   {-# INLINE compareByteOffToBytesMem #-}   compareByteOffMem mem1 off1 addr off2 c =     unsafeInlineIO $ withPtrAccess addr $ \ptr2 -> compareByteOffToPtrMem mem1 off1 ptr2 off2 c@@ -533,7 +547,7 @@ toShortByteStringAddr :: Addr Word8 -> (ShortByteString, Off Word8) toShortByteStringAddr = first toShortByteStringBytes . toBytesAddr --- | /O(1)/ - Cast an immutable `ShortByteString` to an immutable `Addr`. In a most common+-- | /O(n)/ - Convert an immutable `ShortByteString` to an immutable `Addr`. In a most common -- case when `ShortByteString` is not backed by pinned memory, this function will return -- `Nothing`. --@@ -549,7 +563,7 @@ fromByteStringAddr (PS fptr i n) =   case fromForeignPtrAddr fptr of     Just addr -> (addr `plusOffAddr` Off i, Count n)-    Nothing -> byteStringConvertError "It was allocated outside of 'bytestring' package"+    Nothing -> byteStringConvertError "ByteString was allocated outside of 'bytestring' package"  -- | /O(1)/ - Cast an immutable `ByteString` to a mutable `MAddr`. Also returns the -- original length of ByteString, which will be less or equal to `getCountOfMAddr` in the@@ -1026,33 +1040,33 @@   prefetchOffAddr0 :: (MonadPrim s m, Prim e) => Addr e -> Off e -> m ()-prefetchOffAddr0 (Addr addr# _) off = prim_ (prefetchAddr0# addr# (fromOff# off))+prefetchOffAddr0 (Addr addr# _) off = prim_ (prefetchAddr0# addr# (unOffBytes# off)) {-# INLINE prefetchOffAddr0 #-}  prefetchOffMAddr0 :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> m ()-prefetchOffMAddr0 (MAddr maddr# _) off = prim_ (prefetchAddr0# maddr# (fromOff# off))+prefetchOffMAddr0 (MAddr maddr# _) off = prim_ (prefetchAddr0# maddr# (unOffBytes# off)) {-# INLINE prefetchOffMAddr0 #-}  prefetchOffAddr1 :: (MonadPrim s m, Prim e) => Addr e -> Off e -> m ()-prefetchOffAddr1 (Addr addr# _) off = prim_ (prefetchAddr1# addr# (fromOff# off))+prefetchOffAddr1 (Addr addr# _) off = prim_ (prefetchAddr1# addr# (unOffBytes# off)) {-# INLINE prefetchOffAddr1 #-}  prefetchOffMAddr1 :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> m ()-prefetchOffMAddr1 (MAddr maddr# _) off = prim_ (prefetchAddr1# maddr# (fromOff# off))+prefetchOffMAddr1 (MAddr maddr# _) off = prim_ (prefetchAddr1# maddr# (unOffBytes# off)) {-# INLINE prefetchOffMAddr1 #-}  prefetchOffAddr2 :: (MonadPrim s m, Prim e) => Addr e -> Off e -> m ()-prefetchOffAddr2 (Addr addr# _) off = prim_ (prefetchAddr2# addr# (fromOff# off))+prefetchOffAddr2 (Addr addr# _) off = prim_ (prefetchAddr2# addr# (unOffBytes# off)) {-# INLINE prefetchOffAddr2 #-}  prefetchOffMAddr2 :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> m ()-prefetchOffMAddr2 (MAddr maddr# _) off = prim_ (prefetchAddr2# maddr# (fromOff# off))+prefetchOffMAddr2 (MAddr maddr# _) off = prim_ (prefetchAddr2# maddr# (unOffBytes# off)) {-# INLINE prefetchOffMAddr2 #-}  prefetchOffAddr3 :: (MonadPrim s m, Prim e) => Addr e -> Off e -> m ()-prefetchOffAddr3 (Addr addr# _) off = prim_ (prefetchAddr3# addr# (fromOff# off))+prefetchOffAddr3 (Addr addr# _) off = prim_ (prefetchAddr3# addr# (unOffBytes# off)) {-# INLINE prefetchOffAddr3 #-}  prefetchOffMAddr3 :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> m ()-prefetchOffMAddr3 (MAddr maddr# _) off = prim_ (prefetchAddr3# maddr# (fromOff# off))+prefetchOffMAddr3 (MAddr maddr# _) off = prim_ (prefetchAddr3# maddr# (unOffBytes# off)) {-# INLINE prefetchOffMAddr3 #-}
− src/Data/Prim/Memory/ByteArray.hs
@@ -1,311 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RoleAnnotations #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}--- |--- Module      : Data.Prim.Memory.ByteArray--- Copyright   : (c) Alexey Kuleshevich 2020--- License     : BSD3--- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>--- Stability   : experimental--- Portability : non-portable----module Data.Prim.Memory.ByteArray-  ( ByteArray(..)-  , MByteArray(..)-  , Pinned(..)-  , fromBytesByteArray-  , toBytesByteArray-  , castByteArray-  , fromMBytesMByteArray-  , toMBytesMByteArray-  , castMByteArray-  , allocMByteArray-  , allocPinnedMByteArray-  , allocAlignedMByteArray-  , allocUnpinnedMByteArray-  , shrinkMByteArray-  , resizeMByteArray-  , reallocMByteArray-  , isPinnedByteArray-  , isPinnedMByteArray--  , thawByteArray-  , freezeMByteArray-  , sizeByteArray-  , getSizeMByteArray-  , readMByteArray-  , writeMByteArray--  , setMByteArray-  , copyByteArrayToMByteArray-  , moveMByteArrayToMByteArray-  ) where--import Control.DeepSeq-import Control.Prim.Monad-import Foreign.Prim-import Data.Prim-import Data.Prim.Memory.Bytes-import Data.Prim.Memory.Internal-import Data.Prim.Memory.ForeignPtr----- | An immutable array of bytes of type @e@-newtype ByteArray (p :: Pinned) e = ByteArray (Bytes p)-  deriving (NFData, Semigroup, Monoid, MemRead)-type role ByteArray nominal nominal---- | A mutable array of bytes of type @e@-newtype MByteArray (p :: Pinned) e s = MByteArray (MBytes p s)-  deriving (NFData, MemWrite)-type role MByteArray nominal nominal nominal---- | Read-only access, but it is not enforced.-instance PtrAccess s (ByteArray 'Pin e) where-  toForeignPtr = pure . toForeignPtrBytes . toBytesByteArray-  {-# INLINE toForeignPtr #-}-  withPtrAccess b = withPtrBytes (toBytesByteArray b)-  {-# INLINE withPtrAccess #-}-  withNoHaltPtrAccess b = withNoHaltPtrBytes (toBytesByteArray b)-  {-# INLINE withNoHaltPtrAccess #-}--instance PtrAccess s (MByteArray 'Pin e s) where-  toForeignPtr = pure . toForeignPtrMBytes . toMBytesMByteArray-  {-# INLINE toForeignPtr #-}-  withPtrAccess mb = withPtrMBytes (toMBytesMByteArray mb)-  {-# INLINE withPtrAccess #-}-  withNoHaltPtrAccess mb = withNoHaltPtrMBytes (toMBytesMByteArray mb)-  {-# INLINE withNoHaltPtrAccess #-}--instance Typeable p => MemAlloc (MByteArray p e) where-  type FrozenMem (MByteArray p e) = ByteArray p e-  getByteCountMem = getByteCountMem . toMBytesMByteArray-  {-# INLINE getByteCountMem #-}-  allocByteCountMem = fmap fromMBytesMByteArray . allocMBytes-  {-# INLINE allocByteCountMem #-}-  thawMem = thawByteArray-  {-# INLINE thawMem #-}-  freezeMem = freezeMByteArray-  {-# INLINE freezeMem #-}-  resizeMem mba = fmap fromMBytesMByteArray . reallocMBytes (toMBytesMByteArray mba)-  {-# INLINE resizeMem #-}--instance (Typeable p, Prim e) => IsList (ByteArray p e) where-  type Item (ByteArray p e) = e-  fromList = fromListMem-  fromListN n = fromListMemN_ (Count n)-  toList = toListMem--instance Typeable p => IsString (ByteArray p Char) where-  fromString = fromListMem--instance (Show e, Prim e) => Show (ByteArray p e) where-  show = show . toListByteArray---toListByteArray :: Prim e => ByteArray p e -> [e]-toListByteArray = toListMem--castByteArray :: ByteArray p e' -> ByteArray p e-castByteArray = coerce--fromBytesByteArray :: Bytes p -> ByteArray p e-fromBytesByteArray = coerce--toBytesByteArray :: ByteArray p e -> Bytes p-toBytesByteArray = coerce--castMByteArray :: MByteArray p e' s -> MByteArray p e s-castMByteArray = coerce--fromMBytesMByteArray :: MBytes p s -> MByteArray p e s-fromMBytesMByteArray = coerce--toMBytesMByteArray :: MByteArray p e s -> MBytes p s-toMBytesMByteArray = coerce--sizeByteArray :: forall e p. Prim e => ByteArray p e -> Size-sizeByteArray = (coerce :: Count e -> Size) . countBytes . toBytesByteArray-{-# INLINE sizeByteArray #-}--getSizeMByteArray :: forall e p m s. (MonadPrim s m, Prim e) => MByteArray p e s -> m Size-getSizeMByteArray = fmap (coerce :: Count e -> Size) . getCountMBytes . toMBytesMByteArray-{-# INLINE getSizeMByteArray #-}--allocMByteArray ::-     forall e p m s . (Typeable p, Prim e, MonadPrim s m) => Size -> m (MByteArray p e s)-allocMByteArray sz = fromMBytesMByteArray <$> allocMBytes (coerce sz :: Count e)-{-# INLINE allocMByteArray #-}--allocUnpinnedMByteArray :: forall e m s . (MonadPrim s m, Prim e) => Size -> m (MByteArray 'Inc e s)-allocUnpinnedMByteArray sz = fromMBytesMByteArray <$> allocUnpinnedMBytes (coerce sz :: Count e)-{-# INLINE allocUnpinnedMByteArray #-}--allocPinnedMByteArray :: forall e m s . (MonadPrim s m, Prim e) => Size -> m (MByteArray 'Pin e s)-allocPinnedMByteArray sz = fromMBytesMByteArray <$> allocPinnedMBytes (coerce sz :: Count e)-{-# INLINE allocPinnedMByteArray #-}--allocAlignedMByteArray ::-     (MonadPrim s m, Prim e)-  => Count e -- ^ Size in number of bytes-  -> m (MByteArray 'Pin e s)-allocAlignedMByteArray = fmap fromMBytesMByteArray . allocAlignedMBytes-{-# INLINE allocAlignedMByteArray #-}--freezeMByteArray :: MonadPrim s m => MByteArray p e s -> m (ByteArray p e)-freezeMByteArray = fmap fromBytesByteArray . freezeMBytes . toMBytesMByteArray-{-# INLINE freezeMByteArray #-}--thawByteArray :: MonadPrim s m => ByteArray p e -> m (MByteArray p e s)-thawByteArray = fmap fromMBytesMByteArray . thawBytes . toBytesByteArray-{-# INLINE thawByteArray #-}---- | Shrink mutable bytes to new specified count of elements. The new count must be less--- than or equal to the current count as reported by `getCountMByteArray`.-shrinkMByteArray ::-     forall e p m s. (MonadPrim s m, Prim e)-  => MByteArray p e s-  -> Size-  -> m ()-shrinkMByteArray mba sz = shrinkMBytes (toMBytesMByteArray mba) (coerce sz :: Count e)-{-# INLINE shrinkMByteArray #-}----- | Attempt to resize mutable bytes in place.------ * New bytes might be allocated, with the copy of an old one.--- * Old references should not be kept around to allow GC to claim it--- * Old references should not be used to avoid undefined behavior-resizeMByteArray ::-     forall e p m s. (MonadPrim s m, Prim e)-  => MByteArray p e s-  -> Size-  -> m (MByteArray 'Inc e s)-resizeMByteArray mba sz =-  fromMBytesMByteArray <$>-  resizeMBytes (toMBytesMByteArray mba) (coerce sz :: Count e)-{-# INLINE resizeMByteArray #-}--reallocMByteArray ::-     forall e p m s. (MonadPrim s m, Typeable p,  Prim e)-  => MByteArray p e s-  -> Size-  -> m (MByteArray p e s)-reallocMByteArray mba sz =-  fromMBytesMByteArray <$>-  reallocMBytes (toMBytesMByteArray mba) (coerce sz :: Count e)-{-# INLINABLE reallocMByteArray #-}---isPinnedByteArray :: ByteArray p e -> Bool-isPinnedByteArray (ByteArray b) = isPinnedBytes b-{-# INLINE isPinnedByteArray #-}--isPinnedMByteArray :: MByteArray p e s -> Bool-isPinnedMByteArray (MByteArray mb) = isPinnedMBytes mb-{-# INLINE isPinnedMByteArray #-}--readMByteArray :: (MonadPrim s m, Prim e) => MByteArray p e s -> Int -> m e-readMByteArray (MByteArray mb) = readOffMBytes mb . coerce-{-# INLINE readMByteArray #-}--writeMByteArray :: (MonadPrim s m, Prim e) => MByteArray p e s -> Int -> e -> m ()-writeMByteArray (MByteArray mb) o = writeOffMBytes mb (coerce o)-{-# INLINE writeMByteArray #-}----setMByteArray ::-     (MonadPrim s m, Prim e)-  => MByteArray p e s -- ^ Chunk of memory to fill-  -> Int -- ^ Offset in number of elements-  -> Size -- ^ Number of cells to fill-  -> e -- ^ A value to fill the cells with-  -> m ()-setMByteArray (MByteArray mb) off sz = setMBytes mb (coerce off) (coerce sz)-{-# INLINE setMByteArray #-}--copyByteArrayToMByteArray ::-     (MonadPrim s m, Prim e)-  => ByteArray p e-  -> Int-  -> MByteArray p e s-  -> Int-  -> Size-  -> m ()-copyByteArrayToMByteArray ba srcOff mba dstOff sz =-  copyMem ba (coerce srcOff) mba (coerce dstOff) (countAsProxy ba (coerce sz))-{-# INLINE copyByteArrayToMByteArray #-}--moveMByteArrayToMByteArray ::-     forall e p m s. (MonadPrim s m, Prim e)-  => MByteArray p e s-  -> Int-  -> MByteArray p e s-  -> Int-  -> Size-  -> m ()-moveMByteArrayToMByteArray ba srcOff mba dstOff sz =-  moveMem ba (coerce srcOff) mba (coerce dstOff) (coerce sz :: Count e)-{-# INLINE moveMByteArrayToMByteArray #-}------ toPtrByteArray :: ByteArray Pin e -> Ptr e--- toPtrByteArray (ByteArray ba#) = Ptr (byteArrayContents# ba#)--- {-# INLINE toPtrByteArray #-}---- toPtrMByteArray :: MByteArray Pin e s -> Ptr e--- toPtrMByteArray (MByteArray mba#) = Ptr (mutableByteArrayContents# mba#)--- {-# INLINE toPtrMByteArray #-}---- -- | Pointer access to immutable `ByteArray` should be for read only purposes, but it is--- -- not enforced. Any mutation will break referential transparency--- withPtrByteArray :: MonadPrim s m => ByteArray Pin e -> (Ptr e -> m b) -> m b--- withPtrByteArray b f = do---   res <- f (toPtrByteArray b)---   res <$ touch b--- {-# INLINE withPtrByteArray #-}---- -- | Same as `withPtrByteArray`, but is suitable for actions that don't terminate--- withNoHaltPtrByteArray :: MonadUnliftPrim s m => ByteArray Pin e -> (Ptr e -> m b) -> m b--- withNoHaltPtrByteArray b f = withAliveUnliftPrim b $ f (toPtrByteArray b)--- {-# INLINE withNoHaltPtrByteArray #-}---- withPtrMByteArray :: MonadPrim s m => MByteArray Pin e s -> (Ptr e -> m b) -> m b--- withPtrMByteArray mb f = do---   res <- f (toPtrMByteArray mb)---   res <$ touch mb--- {-# INLINE withPtrMByteArray #-}---- withNoHaltPtrMByteArray :: MonadUnliftPrim s m => MByteArray Pin e s -> (Ptr e -> m b) -> m b--- withNoHaltPtrMByteArray mb f = withAliveUnliftPrim mb $ f (toPtrMByteArray mb)--- {-# INLINE withNoHaltPtrMByteArray #-}----- -- -- | Check if two byte arrays refer to pinned memory and compare their pointers.--- -- isSameByteArray :: ByteArray p1 e -> ByteArray p2 e -> Bool--- -- isSameByteArray (ByteArray b1#) (ByteArray b2#) = isTrue# (isSameByteArray# b1# b2#)--- -- {-# INLINE[0] isSameByteArray #-}--- -- {-# RULES--- -- "isSamePinnedByteArray" isSameByteArray = isSamePinnedByteArray--- --   #-}---- -- -- | Perform pointer equality on pinned `ByteArray`.--- -- isSamePinnedByteArray :: ByteArray Pin e -> ByteArray Pin e -> Bool--- -- isSamePinnedByteArray pb e1 pb2 = toPtrByteArray pb e1 == toPtrByteArray pb e2--- -- {-# INLINE isSamePinnedByteArray #-}------ -- byteStringConvertError :: String -> a--- -- byteStringConvertError msg = error $ "Cannot convert 'ByteString'. " ++ msg--- -- {-# NOINLINE byteStringConvertError #-}-
src/Data/Prim/Memory/ByteString.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE MagicHash #-} -- |@@ -34,6 +35,7 @@ import Data.ByteString.Builder import Data.ByteString.Internal import Data.ByteString.Short.Internal+import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL import Data.Prim import Foreign.Prim@@ -46,8 +48,9 @@   , allocMBytes   , freezeMBytes   , byteCountBytes+  , relaxPinnedBytes   , toForeignPtrBytes-  , fromForeignPtrBytes+  , castForeignPtrToBytes   , byteStringConvertError   ) @@ -55,13 +58,39 @@ newtype MByteString s = MByteString ByteString  --- | /O(1)/ - Cast an immutable `Bytes` to an immutable `ByteString`+-- | /O(1)/ - Cast immutable `Bytes` to an immutable `ByteString` -- -- @since 0.1.0 toByteStringBytes :: Bytes 'Pin -> ByteString-toByteStringBytes b = PS (toForeignPtrBytes b) 0 (coerce (byteCountBytes b)) {-# INLINE toByteStringBytes #-}+toByteStringBytes b =+#if MIN_VERSION_bytestring(0,11,0)+  BS (toForeignPtrBytes b) (coerce (byteCountBytes b))+#else+  PS (toForeignPtrBytes b) 0 (coerce (byteCountBytes b))+#endif ++-- | /O(1)/ - Cast an immutable `ByteString` to immutable `Bytes`. Only unsliced+-- `ByteString`s that are backed by a `ForeignPtr` allocated on Haskell heap without+-- finilizers can be converted without copy.+--+-- @since 0.2.0+castByteStringBytes :: ByteString -> Either String (Bytes 'Pin)+#if MIN_VERSION_bytestring(0,11,0)+castByteStringBytes (BS fptr n) = do+#else+castByteStringBytes (PS fptr o n) = do+  unless (o == 0) sliceError+#endif+  b <- castForeignPtrToBytes fptr+  unless (unCount (byteCountBytes b) == n) sliceError+  Right b+  where+    sliceError = Left "ByteString was sliced"+{-# INLINE castByteStringBytes #-}++ -- | /O(1)/ - Cast an immutable `Bytes` to an immutable `ShortByteString` -- -- @since 0.1.0@@ -92,32 +121,43 @@  -- | /O(n)/ - Allocate `Bytes` and fill them with the contents of a lazy `BSL.ByteString` fromLazyByteStringBytes :: BSL.ByteString -> Bytes 'Pin-fromLazyByteStringBytes bsl =-  case BSL.toStrict bsl of-    PS fptr _ _ -> either byteStringConvertError id $ fromForeignPtrBytes fptr+fromLazyByteStringBytes = fromByteStringBytes . BSL.toStrict {-# INLINE fromLazyByteStringBytes #-}  --- | /O(n)/ - Allocate `Bytes` and fill them with the contents of a strict `ByteString`+-- | /O(n)/ - Convert a strict `ByteString` to `Bytes`. fromByteStringBytes :: Typeable p => ByteString -> Bytes p-fromByteStringBytes bs@(PS _ _ n) =-  runST $-  withPtrByteString bs $ \ptr -> do-    let c = Count n :: Count Word8-    mb <- allocMBytes c-    movePtrToMBytes ptr 0 mb 0 c-    freezeMBytes mb+fromByteStringBytes bs =+  case castByteStringBytes bs of+    Right b -> relaxPinnedBytes b+    Left _ ->+      runST $+      withPtrByteString bs $ \ptr -> do+        let c = Count (BS.length bs) :: Count Word8+        mb <- allocMBytes c+        copyPtrToMBytes ptr 0 mb 0 c+        freezeMBytes mb {-# INLINE fromByteStringBytes #-}   withPtrByteString :: MonadPrim s m => ByteString -> (Ptr a -> m b) -> m b-withPtrByteString (PS (ForeignPtr addr# ptrContents) (I# o#) _) f = do-  r <- f (Ptr (addr# `plusAddr#` o#))+#if MIN_VERSION_bytestring(0,11,0)+withPtrByteString (BS (ForeignPtr addr# ptrContents) _) f = do+#else+withPtrByteString (PS (ForeignPtr addr'# ptrContents) (I# o#) _) f = do+  let addr# = addr'# `plusAddr#` o#+#endif+  r <- f (Ptr addr#)   r <$ touch ptrContents {-# INLINE withPtrByteString #-}   withNoHaltPtrByteString :: MonadUnliftPrim s m => ByteString -> (Ptr a -> m b) -> m b-withNoHaltPtrByteString (PS (ForeignPtr addr# ptrContents) (I# o#) _) f =-  withAliveUnliftPrim ptrContents $ f (Ptr (addr# `plusAddr#` o#))+#if MIN_VERSION_bytestring(0,11,0)+withNoHaltPtrByteString (BS (ForeignPtr addr# ptrContents) _) f = do+#else+withNoHaltPtrByteString (PS (ForeignPtr addr'# ptrContents) (I# o#) _) f = do+  let addr# = addr'# `plusAddr#` o#+#endif+  withAliveUnliftPrim ptrContents $ f (Ptr addr#) {-# INLINE withNoHaltPtrByteString #-}
src/Data/Prim/Memory/Bytes.hs view
@@ -6,7 +6,6 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UnboxedTuples #-} -- | -- Module      : Data.Prim.Memory.Bytes@@ -36,6 +35,8 @@   , isPinnedMBytes   , toPinnedBytes   , toPinnedMBytes+  , toInconclusiveBytes+  , toInconclusiveMBytes   , relaxPinnedBytes   , relaxPinnedMBytes   , ensurePinnedBytes@@ -155,7 +156,6 @@ import Data.Prim import Data.Prim.Atomic import Data.Prim.Memory.Internal-import Data.Prim.Memory.Bytes.Internal import Foreign.Prim  -- | Wrap `ByteArray#` into `Bytes`@@ -176,7 +176,6 @@   - -- | Check if two mutable bytes pointers refer to the same memory isSameMBytes :: MBytes p1 s -> MBytes p2 s -> Bool isSameMBytes (MBytes mb1#) (MBytes mb2#) = isTrue# (sameMutableByteArray# mb1# mb2#)@@ -188,17 +187,9 @@  ---- Pure --- -- This works exactly the same as `compareBytes` except it is implemented with FFI--- -- call instead of a primop. It will probably prove to be useless and will be removed in--- -- the future.--- memcmpBytes :: Prim e => Bytes p1 -> Off e -> Bytes p2 -> Off e -> Count e -> Ordering--- memcmpBytes (Bytes ba1#) off1 (Bytes ba2#) off2 c =---   toOrdering# (memcmpByteArray# ba1# (fromOff# off1) ba2# (fromOff# off2) (fromCount# c))--- {-# INLINE memcmpBytes #-}- compareBytes :: Prim e => Bytes p1 -> Off e -> Bytes p2 -> Off e -> Count e -> Ordering compareBytes (Bytes b1#) off1 (Bytes b2#) off2 c =-  toOrdering# (compareByteArrays# b1# (fromOff# off1) b2# (fromOff# off2) (fromCount# c))+  toOrdering# (compareByteArrays# b1# (unOffBytes# off1) b2# (unOffBytes# off2) (unCountBytes# c)) {-# INLINE compareBytes #-}  @@ -244,14 +235,14 @@      (MonadPrim s m, Prim e) => Bytes ps -> Off e -> MBytes pd s -> Off e -> Count e -> m () copyBytesToMBytes (Bytes src#) srcOff (MBytes dst#) dstOff c =   prim_ $-  copyByteArray# src# (fromOff# srcOff) dst# (fromOff# dstOff) (fromCount# c)+  copyByteArray# src# (unOffBytes# srcOff) dst# (unOffBytes# dstOff) (unCountBytes# c) {-# INLINE copyBytesToMBytes #-}   moveMBytesToMBytes ::      (MonadPrim s m, Prim e) => MBytes ps s-> Off e -> MBytes pd s -> Off e -> Count e -> m () moveMBytesToMBytes (MBytes src#) srcOff (MBytes dst#) dstOff c =-  prim_ (copyMutableByteArray# src# (fromOff# srcOff) dst# (fromOff# dstOff) (fromCount# c))+  prim_ (copyMutableByteArray# src# (unOffBytes# srcOff) dst# (unOffBytes# dstOff) (unCountBytes# c)) {-# INLINE moveMBytesToMBytes #-}  -- | Allocated memory is not cleared, so make sure to fill it in properly, otherwise you@@ -370,36 +361,27 @@ toListSlackBytes = toListSlackMem {-# INLINE toListSlackBytes #-} --- | Returns `EQ` if the full list did fit into the supplied memory chunk exactly.--- Otherwise it will return either `LT` if the list was smaller than allocated memory or--- `GT` if the list was bigger than the available memory and did not fit into `MBytes`.-loadListMBytes :: (MonadPrim s m, Prim e) => [e] -> MBytes p s -> m Ordering-loadListMBytes ys mb = do-  (c, slack) <- getCountRemOfMBytes mb-  loadListMemN (countAsProxy ys c) slack ys mb+-- | Same as `loadListMem`+loadListMBytes :: (Prim e, Typeable p, MonadPrim s m) => [e] -> MBytes p s -> m ([e], Count e)+loadListMBytes = loadListMem {-# INLINE loadListMBytes #-} -loadListMBytes_ :: (MonadPrim s m, Prim e) => [e] -> MBytes p s -> m ()-loadListMBytes_ ys mb = do-  c <- getCountMBytes mb-  loadListMemN_ (countAsProxy ys c) ys mb+-- | Same as `loadListMem_`+loadListMBytes_ :: (Prim e, Typeable p, MonadPrim s m) => [e] -> MBytes p s -> m ()+loadListMBytes_ = loadListMem_ {-# INLINE loadListMBytes_ #-} +-- | Same as `fromListZeroMemN_` fromListBytesN_ :: (Prim e, Typeable p) => Count e -> [e] -> Bytes p-fromListBytesN_ = fromListMemN_+fromListBytesN_ = fromListZeroMemN_ {-# INLINE fromListBytesN_ #-} --- | If the list is bigger than the supplied @`Count` a@ then `GT` ordering will be--- returned, along with the `Bytes` fully filled with the prefix of the list. On the other--- hand if the list is smaller than the supplied `Count`, `LT` with partially filled--- `Bytes` will returned. In the latter case expect some garbage at the end of the--- allocated memory, since no attempt is made to zero it out. Exact match obviously--- results in an `EQ`.+-- | Exactly like `fromListMemN`, but restricted to `Bytes`. fromListBytesN ::      (Prim e, Typeable p)   => Count e   -> [e]-  -> (Ordering, Bytes p)+  -> (Either [e] (Count e), Bytes p) fromListBytesN = fromListMemN {-# INLINE fromListBytesN #-} @@ -424,14 +406,7 @@ concatBytes = concatMem {-# INLINE concatBytes #-} -relaxPinnedBytes :: Bytes p -> Bytes 'Inc-relaxPinnedBytes = castPinnedBytes -relaxPinnedMBytes :: MBytes p e -> MBytes 'Inc e-relaxPinnedMBytes = castPinnedMBytes--- ensurePinnedBytes :: Bytes p -> Bytes 'Pin ensurePinnedBytes b = fromMaybe (convertMem b) (toPinnedBytes b) {-# INLINE ensurePinnedBytes #-}@@ -906,34 +881,34 @@   prefetchBytes0 :: (MonadPrim s m, Prim e) => Bytes p -> Off e -> m ()-prefetchBytes0 (Bytes b#) off = prim_ (prefetchByteArray0# b# (fromOff# off))+prefetchBytes0 (Bytes b#) off = prim_ (prefetchByteArray0# b# (unOffBytes# off)) {-# INLINE prefetchBytes0 #-}  prefetchMBytes0 :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m ()-prefetchMBytes0 (MBytes mb#) off = prim_ (prefetchMutableByteArray0# mb# (fromOff# off))+prefetchMBytes0 (MBytes mb#) off = prim_ (prefetchMutableByteArray0# mb# (unOffBytes# off)) {-# INLINE prefetchMBytes0 #-}  prefetchBytes1 :: (MonadPrim s m, Prim e) => Bytes p -> Off e -> m ()-prefetchBytes1 (Bytes b#) off = prim_ (prefetchByteArray1# b# (fromOff# off))+prefetchBytes1 (Bytes b#) off = prim_ (prefetchByteArray1# b# (unOffBytes# off)) {-# INLINE prefetchBytes1 #-}  prefetchMBytes1 :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m ()-prefetchMBytes1 (MBytes mb#) off = prim_ (prefetchMutableByteArray1# mb# (fromOff# off))+prefetchMBytes1 (MBytes mb#) off = prim_ (prefetchMutableByteArray1# mb# (unOffBytes# off)) {-# INLINE prefetchMBytes1 #-}  prefetchBytes2 :: (MonadPrim s m, Prim e) => Bytes p -> Off e -> m ()-prefetchBytes2 (Bytes b#) off = prim_ (prefetchByteArray2# b# (fromOff# off))+prefetchBytes2 (Bytes b#) off = prim_ (prefetchByteArray2# b# (unOffBytes# off)) {-# INLINE prefetchBytes2 #-}  prefetchMBytes2 :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m ()-prefetchMBytes2 (MBytes mb#) off = prim_ (prefetchMutableByteArray2# mb# (fromOff# off))+prefetchMBytes2 (MBytes mb#) off = prim_ (prefetchMutableByteArray2# mb# (unOffBytes# off)) {-# INLINE prefetchMBytes2 #-}  prefetchBytes3 :: (MonadPrim s m, Prim e) => Bytes p -> Off e -> m ()-prefetchBytes3 (Bytes b#) off = prim_ (prefetchByteArray3# b# (fromOff# off))+prefetchBytes3 (Bytes b#) off = prim_ (prefetchByteArray3# b# (unOffBytes# off)) {-# INLINE prefetchBytes3 #-}  prefetchMBytes3 :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m ()-prefetchMBytes3 (MBytes mb#) off = prim_ (prefetchMutableByteArray3# mb# (fromOff# off))+prefetchMBytes3 (MBytes mb#) off = prim_ (prefetchMutableByteArray3# mb# (unOffBytes# off)) {-# INLINE prefetchMBytes3 #-} 
src/Data/Prim/Memory/Bytes/Internal.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RoleAnnotations #-}@@ -25,8 +25,13 @@   , isSamePinnedBytes   , isPinnedBytes   , isPinnedMBytes+  , castStateMBytes   , castPinnedBytes   , castPinnedMBytes+  , relaxPinnedBytes+  , relaxPinnedMBytes+  , toInconclusiveBytes+  , toInconclusiveMBytes   , allocMBytes   , allocPinnedMBytes   , allocAlignedMBytes@@ -59,7 +64,8 @@   , withNoHaltPtrMBytes   , toForeignPtrBytes   , toForeignPtrMBytes-  , fromForeignPtrBytes+  , castForeignPtrToBytes+  , onForeignPtrContents   , byteStringConvertError   ) where @@ -68,22 +74,26 @@ import Control.Prim.Monad.Unsafe import Data.Prim import Data.Prim.Class-import GHC.ForeignPtr import Data.Typeable import Foreign.Prim-+import GHC.ForeignPtr+import Unsafe.Coerce+#if MIN_VERSION_base(4,14,0)+import Data.IORef+#endif --- | In Haskell there is a distinction between pinned or unpinned memory.+-- | In GHC there is a distinction between pinned and unpinned memory. ----- Pinned memory is such, when allocated, it is guaranteed not to move throughout the+-- Pinned memory is such that when allocated, it is guaranteed not to move throughout the -- lifetime of a program. In other words the address pointer that refers to allocated--- bytes will not change until it gets garbage collected because it is no longer--- referenced by anything. Unpinned memory on the other hand can be moved around during--- GC, which helps to reduce memory fragmentation.+-- bytes will not change until the associated `ByteArray#` or `MutableByteArray#` is no+-- longer referenced anywhere in the program at which point it gets garbage collected. On+-- the other hand unpinned memory can be moved around during GC, which helps to reduce+-- memory fragmentation. -- -- Pinned/unpinnned choice during allocation is a bit of a lie, because when attempt is -- made to allocate memory as unpinned, but requested size is a bit more than a certain--- threashold (somewhere around 3KiB) it might still be allocated as pinned. Because of+-- threshold (somewhere around 3KiB) it might still be allocated as pinned. Because of -- that fact through out the "primal" universe there is a distinction between memory that -- is either @`Pin`ned@ or @`Inc`onclusive@. --@@ -91,15 +101,16 @@ -- `Data.Prim.Memory.Bytes.toPinnedMBytes` to get a conclusive type. -- -- @since 0.1.0-data Pinned = Pin | Inc+data Pinned+  = Pin -- ^ Pinned, which indicates that allocated memory will not move+  | Inc -- ^ Inconclusive, thus memory could be pinned or unpinned  -- | An immutable region of memory which was allocated either as pinned or unpinned. -- -- Constructor is not exported for safety. Violating type level `Pinned` kind is very -- dangerous. Type safe constructor `Data.Prim.Memory.Bytes.fromByteArray#` and unwrapper -- `Data.Prim.Memory.Bytes.toByteArray#` should be used instead. As a backdoor, of course,--- the actual constructor is available in "Data.Prim.Memory.Internal" module and specially--- unsafe function `castPinnedBytes` was crafted.+-- the actual constructor is available from @Data.Prim.Memory.Internal@ data Bytes (p :: Pinned) = Bytes ByteArray# type role Bytes nominal @@ -126,7 +137,7 @@  compareByteOffBytes :: Prim e => Bytes p1 -> Off Word8 -> Bytes p2 -> Off Word8 -> Count e -> Ordering compareByteOffBytes (Bytes b1#) (Off (I# off1#)) (Bytes b2#) (Off (I# off2#)) c =-  toOrdering# (compareByteArrays# b1# off1# b2# off2# (fromCount# c))+  toOrdering# (compareByteArrays# b1# off1# b2# off2# (unCountBytes# c)) {-# INLINE compareByteOffBytes #-}  indexOffBytes :: Prim e => Bytes p -> Off e -> e@@ -164,7 +175,7 @@ allocUnpinnedMBytes :: (MonadPrim s m, Prim e) => Count e -> m (MBytes 'Inc s) allocUnpinnedMBytes c =   prim $ \s ->-    case newByteArray# (fromCount# c) s of+    case newByteArray# (unCountBytes# c) s of       (# s', ba# #) -> (# s', MBytes ba# #) {-# INLINE allocUnpinnedMBytes #-} @@ -172,7 +183,7 @@ allocPinnedMBytes :: (MonadPrim s m, Prim e) => Count e -> m (MBytes 'Pin s) allocPinnedMBytes c =   prim $ \s ->-    case newPinnedByteArray# (fromCount# c) s of+    case newPinnedByteArray# (unCountBytes# c) s of       (# s', ba# #) -> (# s', MBytes ba# #) {-# INLINE allocPinnedMBytes #-} @@ -183,7 +194,7 @@ allocAlignedMBytes c =   prim $ \s ->     case newAlignedPinnedByteArray#-           (fromCount# c)+           (unCountBytes# c)            (alignment# (proxy# :: Proxy# e))            s of       (# s', ba# #) -> (# s', MBytes ba# #)@@ -221,13 +232,13 @@ copyByteOffBytesToMBytes ::      (MonadPrim s m, Prim e) => Bytes ps -> Off Word8 -> MBytes pd s -> Off Word8 -> Count e -> m () copyByteOffBytesToMBytes (Bytes src#) (Off (I# srcOff#)) (MBytes dst#) (Off (I# dstOff#)) c =-  prim_ $ copyByteArray# src# srcOff# dst# dstOff# (fromCount# c)+  prim_ $ copyByteArray# src# srcOff# dst# dstOff# (unCountBytes# c) {-# INLINE copyByteOffBytesToMBytes #-}  moveByteOffMBytesToMBytes ::      (MonadPrim s m, Prim e) => MBytes ps s-> Off Word8 -> MBytes pd s -> Off Word8 -> Count e -> m () moveByteOffMBytesToMBytes (MBytes src#) (Off (I# srcOff#)) (MBytes dst#) (Off (I# dstOff#)) c =-  prim_ (copyMutableByteArray# src# srcOff# dst# dstOff# (fromCount# c))+  prim_ (copyMutableByteArray# src# srcOff# dst# dstOff# (unCountBytes# c)) {-# INLINE moveByteOffMBytesToMBytes #-}  @@ -239,7 +250,7 @@ -- | Shrink mutable bytes to new specified count of elements. The new count must be less -- than or equal to the current count as reported by `getCountMBytes`. shrinkMBytes :: (MonadPrim s m, Prim e) => MBytes p s -> Count e -> m ()-shrinkMBytes (MBytes mb#) c = prim_ (shrinkMutableByteArray# mb# (fromCount# c))+shrinkMBytes (MBytes mb#) c = prim_ (shrinkMutableByteArray# mb# (unCountBytes# c)) {-# INLINE shrinkMBytes #-}  @@ -252,7 +263,7 @@      (MonadPrim s m, Prim e) => MBytes p s -> Count e -> m (MBytes 'Inc s) resizeMBytes (MBytes mb#) c =   prim $ \s ->-    case resizeMutableByteArray# mb# (fromCount# c) s of+    case resizeMutableByteArray# mb# (unCountBytes# c) s of       (# s', mb'# #) -> (# s', MBytes mb'# #) {-# INLINE resizeMBytes #-} @@ -274,12 +285,29 @@            Nothing -> castPinnedMBytes <$> resizeMBytes mb newByteCount {-# INLINABLE reallocMBytes #-} +castStateMBytes :: MBytes p s' -> MBytes p s+castStateMBytes = unsafeCoerce+ castPinnedBytes :: Bytes p' -> Bytes p castPinnedBytes (Bytes b#) = Bytes b#  castPinnedMBytes :: MBytes p' s -> MBytes p s castPinnedMBytes (MBytes b#) = MBytes b# ++relaxPinnedBytes :: Bytes 'Pin -> Bytes p+relaxPinnedBytes = castPinnedBytes++relaxPinnedMBytes :: MBytes 'Pin e -> MBytes p e+relaxPinnedMBytes = castPinnedMBytes++toInconclusiveBytes :: Bytes p -> Bytes 'Inc+toInconclusiveBytes = castPinnedBytes++toInconclusiveMBytes :: MBytes p e -> MBytes 'Inc e+toInconclusiveMBytes = castPinnedMBytes++ -- | How many elements of type @a@ fits into bytes completely. In order to get a possible -- count of leftover bytes use `countRemBytes` countBytes :: Prim e => Bytes p -> Count e@@ -373,26 +401,54 @@  toForeignPtrMBytes :: MBytes 'Pin s -> ForeignPtr e toForeignPtrMBytes (MBytes mba#) =-  ForeignPtr (byteArrayContents# (unsafeCoerce# mba#)) (PlainPtr (unsafeCoerce# mba#))+  ForeignPtr (mutableByteArrayContents# mba#) (PlainPtr (unsafeCoerce# mba#)) {-# INLINE toForeignPtrMBytes #-}  --- | Discarding the `ForeignPtr` will trigger all if there are any associated--- Haskell finalizers.-fromForeignPtrBytes :: ForeignPtr e -> Either String (Bytes 'Pin)-fromForeignPtrBytes (ForeignPtr addr# content) =-  case content of-    PlainPtr mbaRW# -> checkConvert mbaRW#-    MallocPtr mbaRW# _ -> checkConvert mbaRW#-    _ -> Left "Cannot convert a C allocated pointer"+-- | This function will only cast a pointer that was allocated on Haskell heap and it is+-- cerain that the ForeignPtr has no finalizers associated with it.+castForeignPtrToBytes :: ForeignPtr e -> Either String (Bytes 'Pin)+castForeignPtrToBytes fp =+  unsafePerformIO $+  onForeignPtrContents fp checkConvert $ \_ ->+    pure (Left "Cannot convert a C allocated pointer")   where-    checkConvert mba# =-      let !b@(Bytes ba#) = unsafePerformIO (freezeMBytes (MBytes mba#))-       in if isTrue# (byteArrayContents# ba# `eqAddr#` addr#)-            then Right b-            else Left-                   "ForeignPtr does not point to the beginning of the associated MutableByteArray#"-{-# INLINE fromForeignPtrBytes #-}+    checkConvert addr# mba# checkFinalizers = do+      ba@(Bytes ba#) <- freezeMBytes (MBytes mba#)+      if isTrue# (byteArrayContents# ba# `eqAddr#` addr#)+        then do+          hasFinilizers <- checkFinalizers+          pure $+            if hasFinilizers+              then Left "MallocPtr has associated finalizers"+              else Right ba+        else pure $+             Left+               "ForeignPtr does not point to the beginning of the associated MutableByteArray#"+{-# INLINE castForeignPtrToBytes #-}+++onForeignPtrContents ::+     MonadPrim RW m+  => ForeignPtr e+  -> (Addr# -> MutableByteArray# RW -> m Bool -> m a)+  -> (Addr# -> m a)+  -> m a+onForeignPtrContents (ForeignPtr addr# contents) onHaskellPtr onCPtr =+  case contents of+    PlainPtr mbaRW# -> onHaskellPtr addr# mbaRW# (pure False)+#if MIN_VERSION_base(4,14,0)+    MallocPtr mbaRW# fref -> onHaskellPtr addr# mbaRW# $ do+      finilizers <- liftPrimBase $ readIORef fref+      pure $! case finilizers of+        NoFinalizers         -> False+        HaskellFinalizers fs -> not $! null fs+        CFinalizers _        -> True -- impossible case, but nevertheless+#else+    MallocPtr mbaRW# _ -> onHaskellPtr addr# mbaRW# (pure True)+#endif+    PlainForeignPtr _ -> onCPtr addr#+{-# INLINE onForeignPtrContents #-}   -- | Check if two byte arrays refer to pinned memory and compare their pointers.
src/Data/Prim/Memory/ForeignPtr.hs view
@@ -2,9 +2,9 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MagicHash #-}-{-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnboxedTuples #-} -- | -- Module      : Data.Prim.Bytes.ForeignPtr -- Copyright   : (c) Alexey Kuleshevich 2020@@ -60,31 +60,19 @@   , toForeignPtrMBytes   ) where -import           Control.Prim.Monad-import           Data.Prim-import           Data.Prim.Class-import           Data.Prim.Memory.ByteString-import           Data.Prim.Memory.Bytes.Internal-  ( Bytes-  , MBytes(..)-  , Pinned(..)-  , toForeignPtrBytes-  , toForeignPtrMBytes-  , withNoHaltPtrBytes-  , withNoHaltPtrMBytes-  , withPtrBytes-  , withPtrMBytes-  )-import           Foreign.Prim-import           GHC.ForeignPtr-  ( FinalizerEnvPtr-  , FinalizerPtr-  , ForeignPtr(..)-  , ForeignPtrContents(..)-  , castForeignPtr-  , unsafeForeignPtrToPtr-  )+import Control.Prim.Monad+import Data.Prim+import Data.Prim.Class+import Data.Prim.Memory.Bytes.Internal (Bytes, MBytes(..), Pinned(..),+                                        toForeignPtrBytes, toForeignPtrMBytes,+                                        withNoHaltPtrBytes, withNoHaltPtrMBytes,+                                        withPtrBytes, withPtrMBytes)+import Data.Prim.Memory.ByteString import qualified Foreign.ForeignPtr as GHC+import Foreign.Prim+import GHC.ForeignPtr (FinalizerEnvPtr, FinalizerPtr, ForeignPtr(..),+                       ForeignPtrContents(..), castForeignPtr,+                       unsafeForeignPtrToPtr) import qualified GHC.ForeignPtr as GHC  @@ -102,19 +90,17 @@   withPtrAccess p action = toForeignPtr p >>= (`withForeignPtr` action)   {-# INLINE withPtrAccess #-} -  -- | See this GHC <https://gitlab.haskell.org/ghc/ghc/issues/18061 issue #18061> and-  -- related to get more insight why this is needed.-  withNoHaltPtrAccess :: (MonadUnliftPrim s m) => p -> (Ptr a -> m b) -> m b-  withNoHaltPtrAccess p f = do-    ForeignPtr addr# ptrContents <- toForeignPtr p-    withAliveUnliftPrim ptrContents $ f (Ptr addr#)+  -- | See this GHC <https://gitlab.haskell.org/ghc/ghc/issues/17746 issue #17746> and+  -- related to it in order to get more insight why this is needed.+  withNoHaltPtrAccess :: MonadUnliftPrim s m => p -> (Ptr a -> m b) -> m b+  withNoHaltPtrAccess p action = toForeignPtr p >>= (`withNoHaltForeignPtr` action)   {-# INLINE withNoHaltPtrAccess #-}  instance PtrAccess s (ForeignPtr a) where   toForeignPtr = pure . coerce   {-# INLINE toForeignPtr #-} --- | Read-only access, but it is not enforced.+-- | Read-only access, but immutability is not enforced. instance PtrAccess s ByteString where   toForeignPtr (PS ps s _) = pure (coerce ps `plusByteOffForeignPtr` Off s)   {-# INLINE toForeignPtr #-}@@ -131,7 +117,7 @@   withNoHaltPtrAccess mbs = withNoHaltPtrByteString (coerce mbs)   {-# INLINE withNoHaltPtrAccess #-} --- | Read-only access, but it is not enforced.+-- | Read-only access, but immutability is not enforced. instance PtrAccess s (Bytes 'Pin) where   toForeignPtr = pure . toForeignPtrBytes   {-# INLINE toForeignPtr #-}@@ -198,7 +184,7 @@ -- | Similar to `Foreign.ForeignPtr.mallocForeignPtrArray`, except instead of `Storable` we -- use `Prim`. mallocCountForeignPtr :: (MonadPrim RW m, Prim e) => Count e -> m (ForeignPtr e)-mallocCountForeignPtr = liftPrimBase . GHC.mallocForeignPtrBytes . fromCount+mallocCountForeignPtr = liftPrimBase . GHC.mallocForeignPtrBytes . unCountBytes  -- | Just like `mallocCountForeignPtr`, but memory is also aligned according to `Prim` instance mallocCountForeignPtrAligned :: (MonadPrim RW m, Prim e) => Count e -> m (ForeignPtr e)@@ -252,7 +238,7 @@ mallocCountPlainForeignPtrAligned c =   prim $ \s ->     let a# = alignment# (proxy# :: Proxy# e)-     in case newAlignedPinnedByteArray# (fromCount# c) a# s of+     in case newAlignedPinnedByteArray# (unCountBytes# c) a# s of           (# s', mba# #) ->             let addr# = mutableByteArrayContents# mba#              in (# s', ForeignPtr addr# (PlainPtr (unsafeCoerce# mba#)) #)@@ -304,7 +290,7 @@ -- @since 0.1.0 plusOffForeignPtr :: Prim e => ForeignPtr e -> Off e -> ForeignPtr e plusOffForeignPtr (ForeignPtr addr# content) off =-  ForeignPtr (addr# `plusAddr#` fromOff# off) content+  ForeignPtr (addr# `plusAddr#` unOffBytes# off) content {-# INLINE plusOffForeignPtr #-}  
src/Data/Prim/Memory/Internal.hs view
@@ -2,979 +2,2356 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RoleAnnotations #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeFamilyDependencies #-}-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--- |--- Module      : Data.Prim.Memory.Internal--- Copyright   : (c) Alexey Kuleshevich 2020--- License     : BSD3--- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>--- Stability   : experimental--- Portability : non-portable----module Data.Prim.Memory.Internal-  ( Bytes(..)-  , MBytes(..)-  , Pinned(..)-  , module Data.Prim.Memory.Internal-  ) where--import Control.Exception-import Data.List.NonEmpty (NonEmpty(..))-import Control.Monad.ST-import Control.Prim.Monad-import Control.Prim.Monad.Unsafe-import Data.Foldable as Foldable-import Data.Prim-import Data.Prim.Memory.Bytes.Internal-  ( Bytes(..)-  , MBytes(..)-  , Pinned(..)-  , allocMBytes-  , reallocMBytes-  , byteCountBytes-  , compareByteOffBytes-  , copyByteOffBytesToMBytes-  , freezeMBytes-  , getByteCountMBytes-  , indexByteOffBytes-  , indexOffBytes-  , isSameBytes-  , moveByteOffMBytesToMBytes-  , readByteOffMBytes-  , readOffMBytes-  , setMBytes-  , thawBytes-  , writeByteOffMBytes-  , writeOffMBytes-  )-import Data.List as List-import Data.Prim.Memory.ByteString-import Data.Prim.Memory.ForeignPtr-import Data.Prim.Memory.Ptr-import Foreign.Prim-import Numeric (showHex)-import qualified Data.Semigroup as Semigroup-import qualified Data.Monoid as Monoid-import Data.Kind---class MemRead r where-  byteCountMem :: r -> Count Word8--  indexOffMem :: Prim e => r -> Off e -> e--  indexByteOffMem :: Prim e => r -> Off Word8 -> e--  -- | Source and target can't refer to the same memory chunks-  copyByteOffToMBytesMem ::-    (MonadPrim s m, Prim e) => r -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m ()--  -- | Source and target can't refer to the same memory chunks-  copyByteOffToPtrMem ::-    (MonadPrim s m, Prim e) => r -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m ()--  compareByteOffToPtrMem ::-    (MonadPrim s m, Prim e) => r -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m Ordering--  compareByteOffToBytesMem ::-    (MonadPrim s m, Prim e) => r -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> m Ordering--  compareByteOffMem ::-    (MemRead r', Prim e) => r' -> Off Word8 -> r -> Off Word8 -> Count e -> Ordering---- | Generalized memory allocation and pure/mutable state conversion.-class (MemRead (FrozenMem a), MemWrite a) => MemAlloc a where-  type FrozenMem a = (fa :: Type) | fa -> a--  getByteCountMem :: MonadPrim s m => a s -> m (Count Word8)--  allocByteCountMem :: MonadPrim s m => Count Word8 -> m (a s)--  thawMem :: MonadPrim s m => FrozenMem a -> m (a s)--  freezeMem :: MonadPrim s m => a s -> m (FrozenMem a)--  resizeMem :: (MonadPrim s m, Prim e) => a s -> Count e -> m (a s)-  resizeMem = defaultResizeMem---class MemWrite w where-  readOffMem :: (MonadPrim s m, Prim e) => w s -> Off e -> m e--  readByteOffMem :: (MonadPrim s m, Prim e) => w s -> Off Word8 -> m e--  writeOffMem :: (MonadPrim s m, Prim e) => w s -> Off e -> e -> m ()--  writeByteOffMem :: (MonadPrim s m, Prim e) => w s -> Off Word8 -> e -> m ()--  -- | Source and target can be overlapping memory chunks-  moveByteOffToMBytesMem ::-    (MonadPrim s m, Prim e) => w s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m ()--  -- | Source and target can be overlapping memory chunks-  moveByteOffToPtrMem ::-    (MonadPrim s m, Prim e) => w s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m ()--  copyByteOffMem ::-    (MonadPrim s m, MemRead r, Prim e) => r -> Off Word8 -> w s -> Off Word8 -> Count e -> m ()--  moveByteOffMem ::-    (MonadPrim s m, MemWrite w', Prim e) => w' s -> Off Word8 -> w s -> Off Word8 -> Count e -> m ()--  -- TODO: Potential feature for the future implementation. Will require extra function in `Prim`.-  --setByteOffMem :: (MonadPrim s m, Prim e) => w s -> Off Word8 -> Count e -> e -> m ()--  -- | Write the same value into each cell starting at an offset.-  setMem-    :: (MonadPrim s m, Prim e)-    => w s -- ^ Writable memory. Must have enough bytes, at least: (off+count)*(sizeOf e)-    -> Off e -- ^ An offset into writable memory at which element setting should start.-    -> Count e -- ^ Numer of cells to write the elemnt into-    -> e -- ^ Element to write into all memory cells specified by offset and count. Even-         -- if the count is @0@ this element might be still fully evaluated.-    -> m ()---instance MemRead ByteString where-  byteCountMem (PS _ _ c) = Count c-  {-# INLINE byteCountMem #-}-  indexOffMem bs i = unsafeInlineIO $ withPtrAccess bs (`readOffPtr` i)-  {-# INLINE indexOffMem #-}-  indexByteOffMem bs i = unsafeInlineIO $ withPtrAccess bs (`readByteOffPtr` i)-  {-# INLINE indexByteOffMem #-}-  copyByteOffToMBytesMem bs srcOff mb dstOff c =-    withPtrAccess bs $ \srcPtr -> copyByteOffPtrToMBytes srcPtr srcOff mb dstOff c-  {-# INLINE copyByteOffToMBytesMem #-}-  copyByteOffToPtrMem bs srcOff dstPtr dstOff c =-    withPtrAccess bs $ \srcPtr -> copyByteOffPtrToPtr srcPtr srcOff dstPtr dstOff c-  {-# INLINE copyByteOffToPtrMem #-}-  compareByteOffToPtrMem bs off1 ptr2 off2 c =-    withPtrAccess bs $ \ptr1 -> pure $ compareByteOffPtrToPtr ptr1 off1 ptr2 off2 c-  {-# INLINE compareByteOffToPtrMem #-}-  compareByteOffToBytesMem bs off1 bytes off2 c =-    withPtrAccess bs $ \ptr1 -> pure $ compareByteOffPtrToBytes ptr1 off1 bytes off2 c-  {-# INLINE compareByteOffToBytesMem #-}-  compareByteOffMem mem1 off1 bs off2 c =-    unsafeInlineIO $ withPtrAccess bs $ \ptr2 -> compareByteOffToPtrMem mem1 off1 ptr2 off2 c-  {-# INLINE compareByteOffMem #-}---instance MemAlloc MByteString where-  type FrozenMem MByteString = ByteString-  getByteCountMem (MByteString (PS _ _ c)) = pure $ Count c-  {-# INLINE getByteCountMem #-}-  allocByteCountMem c = do-    fp <- mallocByteCountPlainForeignPtr c-    pure $ MByteString (PS fp 0 (coerce c))-  {-# INLINE allocByteCountMem #-}-  thawMem bs = pure $ MByteString bs-  {-# INLINE thawMem #-}-  freezeMem (MByteString bs) = pure bs-  {-# INLINE freezeMem #-}-  resizeMem bsm@(MByteString (PS fp o n)) newc-    | newn > n = defaultResizeMem bsm newc-    | otherwise = pure $ MByteString (PS fp o newn)-    where -- constant slice if we need to reduce the size-      Count newn = toByteCount newc-  {-# INLINE resizeMem #-}--instance MemWrite MByteString where-  readOffMem (MByteString mbs) i = withPtrAccess mbs (`readOffPtr` i)-  {-# INLINE readOffMem #-}-  readByteOffMem (MByteString mbs) i = withPtrAccess mbs (`readByteOffPtr` i)-  {-# INLINE readByteOffMem #-}-  writeOffMem (MByteString mbs) i a = withPtrAccess mbs $ \ptr -> writeOffPtr ptr i a-  {-# INLINE writeOffMem #-}-  writeByteOffMem (MByteString mbs) i a = withPtrAccess mbs $ \ptr -> writeByteOffPtr ptr i a-  {-# INLINE writeByteOffMem #-}-  moveByteOffToPtrMem (MByteString fsrc) srcOff dstPtr dstOff c =-    withPtrAccess fsrc $ \srcPtr -> moveByteOffPtrToPtr srcPtr srcOff dstPtr dstOff c-  {-# INLINE moveByteOffToPtrMem #-}-  moveByteOffToMBytesMem (MByteString fsrc) srcOff dst dstOff c =-    withPtrAccess fsrc $ \srcPtr -> moveByteOffPtrToMBytes srcPtr srcOff dst dstOff c-  {-# INLINE moveByteOffToMBytesMem #-}-  copyByteOffMem src srcOff (MByteString fdst) dstOff c =-    withPtrAccess fdst $ \dstPtr -> copyByteOffToPtrMem src srcOff dstPtr dstOff c-  {-# INLINE copyByteOffMem #-}-  moveByteOffMem src srcOff (MByteString fdst) dstOff c =-    withPtrAccess fdst $ \dstPtr -> moveByteOffToPtrMem src srcOff dstPtr dstOff c-  {-# INLINE moveByteOffMem #-}-  setMem (MByteString mbs) off c a = withPtrAccess mbs $ \ptr -> setOffPtr ptr off c a-  {-# INLINE setMem #-}---instance MemRead ShortByteString where-  byteCountMem = byteCountMem . fromShortByteStringBytes-  {-# INLINE byteCountMem #-}-  indexOffMem sbs = indexOffMem (fromShortByteStringBytes sbs)-  {-# INLINE indexOffMem #-}-  indexByteOffMem sbs = indexByteOffMem (fromShortByteStringBytes sbs)-  {-# INLINE indexByteOffMem #-}-  copyByteOffToMBytesMem sbs = copyByteOffToMBytesMem (fromShortByteStringBytes sbs)-  {-# INLINE copyByteOffToMBytesMem #-}-  copyByteOffToPtrMem sbs = copyByteOffToPtrMem (fromShortByteStringBytes sbs)-  {-# INLINE copyByteOffToPtrMem #-}-  compareByteOffToPtrMem sbs = compareByteOffToPtrMem (fromShortByteStringBytes sbs)-  {-# INLINE compareByteOffToPtrMem #-}-  compareByteOffToBytesMem sbs = compareByteOffToBytesMem (fromShortByteStringBytes sbs)-  {-# INLINE compareByteOffToBytesMem #-}-  compareByteOffMem mem off1 sbs = compareByteOffMem mem off1 (fromShortByteStringBytes sbs)-  {-# INLINE compareByteOffMem #-}---- | A wrapper that adds a phantom state token. It can be use with types that either--- doesn't have such state token or are designed to work in `IO` and therefore restricted--- to `RW`. Using this wrapper is very much unsafe, so make sure you know what you are--- doing.-newtype MemState a s = MemState { unMemState :: a }--instance MemWrite (MemState (ForeignPtr a)) where-  readOffMem (MemState fptr) i = withForeignPtr fptr $ \ptr -> readOffPtr (castPtr ptr) i-  {-# INLINE readOffMem #-}-  readByteOffMem (MemState fptr) i =-    withForeignPtr fptr $ \ptr -> readByteOffPtr (castPtr ptr) i-  {-# INLINE readByteOffMem #-}-  writeOffMem (MemState fptr) i a = withForeignPtr fptr $ \ptr -> writeOffPtr (castPtr ptr) i a-  {-# INLINE writeOffMem #-}-  writeByteOffMem (MemState fptr) i a =-    withForeignPtr fptr $ \ptr -> writeByteOffPtr (castPtr ptr) i a-  {-# INLINE writeByteOffMem #-}-  moveByteOffToPtrMem (MemState fsrc) srcOff dstPtr dstOff c =-    withForeignPtr fsrc $ \srcPtr -> moveByteOffPtrToPtr (castPtr srcPtr) srcOff dstPtr dstOff c-  {-# INLINE moveByteOffToPtrMem #-}-  moveByteOffToMBytesMem (MemState fsrc) srcOff dst dstOff c =-    withForeignPtr fsrc $ \srcPtr -> moveByteOffPtrToMBytes (castPtr srcPtr) srcOff dst dstOff c-  {-# INLINE moveByteOffToMBytesMem #-}-  copyByteOffMem src srcOff (MemState fdst) dstOff c =-    withForeignPtr fdst $ \dstPtr ->-       copyByteOffToPtrMem src srcOff (castPtr dstPtr) dstOff c-  {-# INLINE copyByteOffMem #-}-  moveByteOffMem src srcOff (MemState fdst) dstOff c =-    withForeignPtr fdst $ \dstPtr ->-       moveByteOffToPtrMem src srcOff (castPtr dstPtr) dstOff c-  {-# INLINE moveByteOffMem #-}-  setMem (MemState fptr) off c a = withForeignPtr fptr $ \ptr -> setOffPtr (castPtr ptr) off c a-  {-# INLINE setMem #-}--modifyFetchOldMem ::-     (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> b) -> m b-modifyFetchOldMem mem o f = modifyFetchOldMemM mem o (pure . f)-{-# INLINE modifyFetchOldMem #-}---modifyFetchNewMem ::-     (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> b) -> m b-modifyFetchNewMem mem o f = modifyFetchNewMemM mem o (pure . f)-{-# INLINE modifyFetchNewMem #-}---modifyFetchOldMemM ::-     (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> m b) -> m b-modifyFetchOldMemM mem o f = do-  a <- readOffMem mem o-  a <$ (writeOffMem mem o =<< f a)-{-# INLINE modifyFetchOldMemM #-}---modifyFetchNewMemM ::-     (MemWrite w, MonadPrim s m, Prim b) => w s -> Off b -> (b -> m b) -> m b-modifyFetchNewMemM mem o f = do-  a <- readOffMem mem o-  a' <- f a-  a' <$ writeOffMem mem o a'-{-# INLINE modifyFetchNewMemM #-}---defaultResizeMem ::-     (Prim e, MemAlloc a, MonadPrim s m) => a s -> Count e -> m (a s)-defaultResizeMem mem c = do-  let newByteCount = toByteCount c-  oldByteCount <- getByteCountMem mem-  if oldByteCount == newByteCount-    then pure mem-    else do-      newMem <- allocByteCountMem newByteCount-      newMem <$ moveMem mem 0 newMem 0 oldByteCount----- | Make @n@ copies of supplied region of memory into a contiguous chunk of memory.-cycleMemN :: (MemAlloc a, MemRead r) => Int -> r -> FrozenMem a-cycleMemN n r-  | n <= 0 = emptyMem-  | otherwise =-    runST $ do-      let bc@(Count chunk) = byteCountMem r-          c@(Count c8) = Count n * bc-      mem <- allocByteCountMem c-      let go i = when (i < c8) $ copyByteOffMem r 0 mem (Off i) bc >> go (i + chunk)-      go 0-      freezeMem mem-{-# INLINE cycleMemN #-}----- | Chunk of empty memory.-emptyMem :: MemAlloc a => FrozenMem a-emptyMem = createMemST_ (0 :: Count Word8) (\_ -> pure ())-{-# INLINE emptyMem #-}---- | A region of memory that hold a single element.-singletonMem ::-     forall e a. (MemAlloc a, Prim e)-  => e-  -> FrozenMem a-singletonMem a = createMemST_ (1 :: Count e) $ \mem -> writeOffMem mem 0 a-{-# INLINE singletonMem #-}---- | Allocate enough memory for number of elements. Memory is not initialized and may--- contain garbage. Use `allocZeroMem` if clean memory is needed.------ [Unsafe Count] Negative element count will result in unpredictable behavior------ @since 0.1.0-allocMem :: (MemAlloc a, MonadPrim s m, Prim e) => Count e -> m (a s)-allocMem n = allocByteCountMem (toByteCount n)-{-# INLINE allocMem #-}----- | Same as `allocMem`, but also use @memset@ to initialize all the new memory to zeros.------ [Unsafe Count] Negative element count will result in unpredictable behavior------ @since 0.1.0-allocZeroMem ::-     (MemAlloc a, MonadPrim s m, Prim e) => Count e -> m (a s)-allocZeroMem n = do-  m <- allocMem n-  m <$ setMem m 0 (toByteCount n) (0 :: Word8)-{-# INLINE allocZeroMem #-}---createMemST :: (MemAlloc a, Prim e) => Count e -> (forall s . a s -> ST s b) -> (b, FrozenMem a)-createMemST n f = runST $ do-  m <- allocMem n-  res <- f m-  i <- freezeMem m-  pure (res, i)-{-# INLINE createMemST #-}--createMemST_ :: (MemAlloc a, Prim e) => Count e -> (forall s . a s -> ST s b) -> FrozenMem a-createMemST_ n f = runST (allocMem n >>= \m -> f m >> freezeMem m)-{-# INLINE createMemST_ #-}--createZeroMemST :: (MemAlloc a, Prim e) => Count e -> (forall s . a s -> ST s b) -> (b, FrozenMem a)-createZeroMemST n f = runST $ do-  m <- allocZeroMem n-  res <- f m-  i <- freezeMem m-  pure (res, i)-{-# INLINE createZeroMemST #-}--createZeroMemST_ :: (MemAlloc a, Prim e) => Count e -> (forall s . a s -> ST s b) -> FrozenMem a-createZeroMemST_ n f = runST (allocZeroMem n >>= \m -> f m >> freezeMem m)-{-# INLINE createZeroMemST_ #-}---copyMem ::-     (MonadPrim s m, MemRead r, MemWrite w, Prim e)-  => r -- ^ Source memory region-  -> Off e -- ^ Offset into the source in number of elements-  -> w s -- ^ Destination memory region-  -> Off e -- ^ Offset into destination in number of elements-  -> Count e -- ^ Number of elements to copy over-  -> m ()-copyMem src srcOff dst dstOff = copyByteOffMem src (toByteOff srcOff) dst (toByteOff dstOff)-{-# INLINE copyMem #-}---moveMem ::-     (MonadPrim s m, MemWrite w1, MemWrite w2, Prim e)-  => w1 s -- ^ Source memory region-  -> Off e -- ^ Offset into the source in number of elements-  -> w2 s -- ^ Destination memory region-  -> Off e -- ^ Offset into destination in number of elements-  -> Count e -- ^ Number of elements to copy over-  -> m ()-moveMem src srcOff dst dstOff = moveByteOffMem src (toByteOff srcOff) dst (toByteOff dstOff)-{-# INLINE moveMem #-}---appendMem :: (MemRead r1, MemRead r2, MemAlloc a) => r1 -> r2 -> FrozenMem a-appendMem r1 r2 =-  createMemST_ (n1 + n2) $ \mem -> do-    copyMem r1 0 mem 0 n1-    copyMem r2 (coerce n1) mem (coerce n1) n2-  where-    n1 = byteCountMem r1-    n2 = byteCountMem r2-{-# INLINABLE appendMem #-}--concatMem :: (MemRead r, MemAlloc a) => [r] -> FrozenMem a-concatMem xs = do-  let c = Foldable.foldl' (\ !acc b -> acc + byteCountMem b) 0 xs-  createMemST_ c $ \mb -> do-    let load i b = do-          let cb@(Count n) = byteCountMem b :: Count Word8-          (i + Off n) <$ copyMem b 0 mb i cb-    foldM_ load 0 xs-{-# INLINABLE concatMem #-}---thawCopyMem ::-     (MemRead r, MemAlloc a, MonadPrim s m, Prim e) => r -> Off e -> Count e -> m (a s)-thawCopyMem a off c = do-  mem <- allocMem c-  mem <$ copyMem a off mem 0 c-{-# INLINE thawCopyMem #-}--freezeCopyMem ::-     (MemAlloc a, MonadPrim s m, Prim e)-  => a s-  -> Off e-  -> Count e-  -> m (FrozenMem a)-freezeCopyMem mem off c = freezeMem mem >>= \r -> thawCopyMem r off c >>= freezeMem-{-# INLINE freezeCopyMem #-}---thawCloneMem :: (MemRead r, MemAlloc a, MonadPrim s m) => r -> m (a s)-thawCloneMem a = thawCopyMem a 0 (byteCountMem a)-{-# INLINE thawCloneMem #-}--freezeCloneMem :: (MemAlloc a, MonadPrim s m) => a s -> m (FrozenMem a)-freezeCloneMem = freezeMem >=> thawCloneMem >=> freezeMem-{-# INLINE freezeCloneMem #-}---- | /O(n)/ - Convert a read-only memory region into a newly allocated other type of--- memory region------ >>> import Data.ByteString--- >>> bs = pack [0x10 .. 0x20]--- >>> bs--- "\DLE\DC1\DC2\DC3\DC4\NAK\SYN\ETB\CAN\EM\SUB\ESC\FS\GS\RS\US "--- >>> convertMem bs :: Bytes 'Inc--- [0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20]------ @since 0.1.0-convertMem :: (MemRead r, MemAlloc a) => r -> FrozenMem a-convertMem a = runST $ thawCloneMem a >>= freezeMem-{-# INLINE convertMem #-}---- | Figure out how many elements can fit into the region of memory. It is possible that--- there is a remainder of bytes left, see `countRemMem` for getting that too.------ ====__Examples__------ >>> b = fromListMem [0 .. 5 :: Word8] :: Bytes 'Pin--- >>> b--- [0x00,0x01,0x02,0x03,0x04,0x05]--- >>> countMem b :: Count Word16--- Count {unCount = 3}--- >>> countMem b :: Count Word32--- Count {unCount = 1}------ @since 0.1.0-countMem ::-     forall e r. (MemRead r, Prim e)-  => r -- ^ Read-only memory type-  -> Count e-countMem = fromByteCount . byteCountMem-{-# INLINE countMem #-}---- | Compute how many elements and a byte size remainder that can fit into the region of memory.------ ====__Examples__------ >>> b = fromListMem [0 .. 5 :: Word8] :: Bytes 'Pin--- >>> b--- [0x00,0x01,0x02,0x03,0x04,0x05]--- >>> countRemMem @Word16 b--- (Count {unCount = 3},0)--- >>> countRemMem @Word32 b--- (Count {unCount = 1},2)------ @since 0.1.0-countRemMem :: forall e r. (MemRead r, Prim e) => r -> (Count e, Count Word8)-countRemMem = fromByteCountRem . byteCountMem-{-# INLINE countRemMem #-}--getCountMem :: (MemAlloc r, MonadPrim s m, Prim e) => r s -> m (Count e)-getCountMem = fmap (fromByteCount . coerce) . getByteCountMem-{-# INLINE getCountMem #-}---getCountRemMem :: (MemAlloc r, MonadPrim s m, Prim e) => r s -> m (Count e, Count Word8)-getCountRemMem = fmap (fromByteCountRem . coerce) . getByteCountMem-{-# INLINE getCountRemMem #-}---clone :: (MemAlloc r, MonadPrim s m) => r s -> m (r s)-clone mb = do-  n <- getByteCountMem mb-  mb' <- allocMem n-  mb' <$ moveMem mb 0 mb' 0 n-{-# INLINE clone #-}--eqMem :: (MemRead r1, MemRead r2) => r1 -> r2 -> Bool-eqMem b1 b2 = n == byteCountMem b2 && compareByteOffMem b1 0 b2 0 n == EQ-  where-    n = byteCountMem b1-{-# INLINE eqMem #-}---- | Compare two regions of memory byte-by-byte. It will return `EQ` whenever both regions--- are exactly the same and `LT` or `GT` as soon as the first byte is reached that is less--- than or greater than respectfully in the first region when compared to the second--- one. It is safe for both regions to refer to the same part of memory, since this is a--- pure function and both regions of memory are read-only.-compareMem ::-     (MemRead r1, MemRead r2, Prim e)-  => r1 -- ^ First region of memory-  -> Off e -- ^ Offset in number of elements into the first region-  -> r2 -- ^ Second region of memory-  -> Off e -- ^ Offset in number of elements into the second region-  -> Count e -- ^ Number of elements to compare-  -> Ordering-compareMem r1 off1 r2 off2 = compareByteOffMem r1 (toByteOff off1) r2 (toByteOff off2)-{-# INLINE compareMem #-}---- | It is only guaranteed to convert the whole memory to a list whenever the size of--- allocated memory is exactly divisible by the size of the element, otherwise there will--- be some slack left unaccounted for.-toListMem :: (MemRead r, Prim e) => r -> [e]-toListMem ba = build (\ c n -> foldrCountMem (countMem ba) c n ba)-{-# INLINE toListMem #-}-{-# SPECIALIZE toListMem :: Prim e => Bytes p -> [e] #-}---- | Same as `toListMem`, except if there is some slack at the end of the memory that--- didn't fit in a list it will be returned as a list of bytes------ ====__Examples__------ >>> import Data.Word--- >>> :set -XDataKinds--- >>> a = fromListMem [0 .. 10 :: Word8] :: Bytes 'Pin--- >>> a--- [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a]--- >>> toListSlackMem a :: ([Word8], [Word8])--- ([0,1,2,3,4,5,6,7,8,9,10],[])--- >>> toListSlackMem a :: ([Word16], [Word8])--- ([256,770,1284,1798,2312],[10])--- >>> toListSlackMem a :: ([Word32], [Word8])--- ([50462976,117835012],[8,9,10])--- >>> toListSlackMem a :: ([Word64], [Word8])--- ([506097522914230528],[8,9,10])------ @since 0.1.0-toListSlackMem ::-     forall e r. (MemRead r, Prim e)-  => r-  -> ([e], [Word8])-toListSlackMem mem =-  (build (\c n -> foldrCountMem k c n mem), getSlack (k8 + r8) [])-  where-    (k, Count r8) = countRemMem mem-    Count k8 = toByteCount k-    getSlack i !acc-      | i == k8 = acc-      | otherwise =-        let i' = i - 1-         in getSlack i' (indexByteOffMem mem (Off i') : acc)-{-# INLINABLE toListSlackMem #-}---- | Right fold that is useful for converting to list while tapping into list fusion.-foldrCountMem :: (MemRead r, Prim e) => Count e -> (e -> b -> b) -> b -> r -> b-foldrCountMem (Count k) c nil bs = go 0-  where-    go i-      | i == k = nil-      | otherwise =-        let !v = indexOffMem bs (Off i)-         in v `c` go (i + 1)-{-# INLINE[0] foldrCountMem #-}---loadListMemN ::-     (MemWrite r, MonadPrim s m, Prim e)-  => Count e-  -> Count Word8-  -> [e]-  -> r s-  -> m Ordering-loadListMemN (Count n) (Count slack) ys mb = do-  let go [] !i = pure (compare i n <> compare 0 slack)-      go (x:xs) !i-        | i < n = writeOffMem mb (Off i) x >> go xs (i + 1)-        | otherwise = pure GT-  go ys 0-{-# INLINABLE loadListMemN #-}--loadListMemN_ :: (MemWrite r, MonadPrim s m, Prim e) => Count e -> [e] -> r s -> m ()-loadListMemN_ (Count n) ys mb =-  let go [] _     = pure ()-      go (x:xs) i = when (i < n) $ writeOffMem mb (Off i) x >> go xs (i + 1)-   in go ys 0-{-# INLINABLE loadListMemN_ #-}---- | Returns `EQ` if the full list did fit into the supplied memory chunk exactly.--- Otherwise it will return either `LT` if the list was smaller than allocated memory or--- `GT` if the list was bigger than the available memory and did not fit into `MBytes`.-loadListMem :: (MonadPrim s m, MemAlloc r, Prim e) => [e] -> r s -> m Ordering-loadListMem ys mb = do-  (c, slack) <- getCountRemMem mb-  loadListMemN (countAsProxy ys c) slack ys mb-{-# INLINE loadListMem #-}--loadListMem_ :: (MonadPrim s m, MemAlloc r, Prim e) => [e] -> r s -> m ()-loadListMem_ ys mb = do-  c <- getCountMem mb-  loadListMemN_ (countAsProxy ys c) ys mb-{-# INLINE loadListMem_ #-}---fromListMemN :: (MemAlloc a, Prim e) => Count e -> [e] -> (Ordering, FrozenMem a)-fromListMemN n xs = createMemST n (loadListMemN n 0 xs)-{-# INLINE fromListMemN #-}--fromListMemN_ :: (MemAlloc a, Prim e) => Count e -> [e] -> FrozenMem a-fromListMemN_ !n xs = createMemST_ n (loadListMemN_ n xs)-{-# INLINE fromListMemN_ #-}--fromListMem :: (MemAlloc a, Prim e) => [e] -> FrozenMem a-fromListMem xs = fromListMemN_ (countAsProxy xs (coerce (length xs))) xs-{-# INLINE fromListMem #-}----- | Load a list of bytes into a newly allocated memory region. Equivalent to--- `Data.ByteString.pack` for `Data.ByteString.ByteString`------ ====__Examples__------ >>> fromByteListMem [0..10] :: Bytes 'Pin--- [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a]------ @since 0.1.0-fromByteListMem :: MemAlloc a => [Word8] -> FrozenMem a-fromByteListMem = fromListMem-{-# INLINE fromByteListMem #-}---- | Convert a memory region to a list of bytes. Equivalent to `Data.ByteString.unpack`--- for `Data.ByteString.ByteString`------ >>> toByteListMem (fromByteListMem [0..10] :: Bytes 'Pin)--- [0,1,2,3,4,5,6,7,8,9,10]------ @since 0.1.0-toByteListMem :: MemAlloc a => FrozenMem a -> [Word8]-toByteListMem = toListMem-{-# INLINE toByteListMem #-}---mapByteMem :: (MemRead r, MemAlloc a, Prim e) => (Word8 -> e) -> r -> FrozenMem a-mapByteMem f = mapByteOffMem (const f)---- | Map an index aware function over memory region------ >>> a = fromListMem [1 .. 10 :: Word8] :: Bytes 'Inc--- >>> a--- [0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a]--- >>> imapMem (\i e -> (fromIntegral i :: Int8, e + 0xf0)) a :: Bytes 'Pin--- [0x00,0xf1,0x01,0xf2,0x02,0xf3,0x03,0xf4,0x04,0xf5,0x05,0xf6,0x06,0xf7,0x07,0xf8,0x08,0xf9,0x09,0xfa]------ @since 0.1.0-mapByteOffMem ::-     (MemRead r, MemAlloc a, Prim e) => (Off Word8 -> Word8 -> e) -> r -> FrozenMem a-mapByteOffMem f r = runST $ mapByteOffMemM (\i -> pure . f i) r---- @since 0.1.0-mapByteMemM ::-     (MemRead r, MemAlloc a, MonadPrim s m, Prim e)-  => (Word8 -> m e)-  -> r-  -> m (FrozenMem a)-mapByteMemM f = mapByteOffMemM (const f)----- @since 0.1.0-mapByteOffMemM ::-     (MemRead r, MemAlloc a, MonadPrim s m, Prim e)-  => (Off Word8 -> Word8 -> m e)-  -> r-  -> m (FrozenMem a)-mapByteOffMemM f r = do-  let bc@(Count n) = byteCountMem r-      c = countAsProxy (f 0 0) (Count n)-  mem <- allocMem c-  _ <- forByteOffMemM_ r 0 bc f-  -- let go i =-  --       when (i < n) $ do-  --         f i (indexByteOffMem r (Off i)) >>=-  --           writeOffMem mem (offAsProxy c (Off i))-  --         go (i + 1)-  -- go 0-  freezeMem mem----- | Iterate over a region of memory-forByteOffMemM_ ::-     (MemRead r, MonadPrim s m, Prim e)-  => r-  -> Off Word8-  -> Count e-  -> (Off Word8 -> e -> m b)-  -> m (Off Word8)-forByteOffMemM_ r (Off byteOff) c f =-  let n = coerce (toByteCount c) + byteOff-      Count k = byteCountProxy c-      go i-        | i < n = f (Off i) (indexByteOffMem r (Off i)) >> go (i + k)-        | otherwise = pure $ Off i-   in go byteOff--loopShortM :: Monad m => Int -> (Int -> a -> Bool) -> (Int -> Int) -> a -> (Int -> a -> m a) -> m a-loopShortM !startAt condition increment !initAcc f = go startAt initAcc-  where-    go !step !acc-      | condition step acc = f step acc >>= go (increment step)-      | otherwise = pure acc-{-# INLINE loopShortM #-}--loopShortM' :: Monad m => Int -> (Int -> a -> m Bool) -> (Int -> Int) -> a -> (Int -> a -> m a) -> m a-loopShortM' !startAt condition increment !initAcc f = go startAt initAcc-  where-    go !step !acc =-      condition step acc >>= \cont ->-        if cont-          then f step acc >>= go (increment step)-          else pure acc-{-# INLINE loopShortM' #-}---- -- | Iterate over a region of memory--- loopMemM_ ::---      (MemRead r, MonadPrim s m, Prim e)---   => r---   -> Off Word8---   -> Count e---   -> (Count Word8 -> a -> Bool)---   -> (Off Word8 -> e -> m b)---   -> m (Off Word8)--- foldlByteOffMemM_ r (Off byteOff) c f =---   loopShortM byteOff (\i -> f (coerce i))---   let n = coerce (toByteCount c) + byteOff---       Count k = byteCountProxy c---       go i---         | i < n = f (Off i) (indexByteOffMem r (Off i)) >> go (i + k)---         | otherwise = pure $ Off i---    in go byteOff---data MemView a = MemView-  { mvOffset :: {-# UNPACK #-} !(Off Word8)-  , mvCount :: {-# UNPACK #-} !(Count Word8)-  , mvMem :: !a-  }--data MMemView a s = MMemView-  { mmvOffset :: {-# UNPACK #-} !(Off Word8)-  , mmvCount :: {-# UNPACK #-} !(Count Word8)-  , mmvMem :: !(a s)-  }--izipWithByteOffMemM_ ::-     (MemRead r1, MemRead r2, MonadPrim s m, Prim e)-  => r1-  -> Off Word8-  -> r2-  -> Off Word8-  -> Count e-  -> (Off Word8 -> e -> Off Word8 -> e -> m b)-  -> m (Off Word8)-izipWithByteOffMemM_ r1 (Off byteOff1) r2 off2 c f =-  let n = coerce (toByteCount c) + byteOff1-      Count k = byteCountProxy c-      go i-        | i < n =-          let o1 = Off i-              o2 = Off i + off2-           in f o1 (indexByteOffMem r1 o1) o2 (indexByteOffMem r2 o2) >>-              go (i + k)-        | otherwise = pure $ Off i-   in go byteOff1---izipWithOffMemM_ ::-     (MemRead r1, MemRead r2, MonadPrim s m, Prim e1, Prim e2)-  => r1-  -> Off e1-  -> r2-  -> Off e2-  -> Int-  -> (Off e1 -> e1 -> Off e2 -> e2 -> m b)-  -> m ()-izipWithOffMemM_ r1 off1 r2 off2 nc f =-  let n = nc + coerce off1-      go o1@(Off i) o2 =-        when (i < n) $-        f o1 (indexOffMem r1 o1) o2 (indexOffMem r2 o2) >> go (o1 + 1) (o2 + 1)-   in go off1 off2----- class Mut f => MFunctor f where---   mmap :: (Elt f a, Elt f b, MonadPrim s m) => (a -> b) -> f a s -> m (f b s)---- class Mut f => MTraverse f where---   mmapM :: (Elt f a, Elt f b, MonadPrim s m) => (a -> m b) -> f a s -> m (f b s)---- class MFunctor f => MApplicative f where---   pureMut :: (Elt f a, MonadPrim s m) => a -> m (f a s)---   liftMut ::---     (Elt f a, Elt f b, Elt f c, MonadPrim s m) => (a -> b -> m c) -> f a s -> f b s -> m (f c s)---- class MApplicative f => MMonad f where---   bindMut ::---     (Elt f a, Elt f b, MonadPrim s m) => f a s -> (a -> m b) -> f b s -> m (f c s)---- instance MFunctor MAddr where---   mmap f maddr = do---     Count n <- getCountMAddr maddr---     maddr' <- allocMAddr (Count n)---     let go i =---           when (i < n) $ do---             writeOffMAddr maddr' (Off i) . f =<< readOffMAddr maddr (Off i)---             go (i + 1)---     maddr' <$ go 0---- instance MTraverse MAddr where---   mmapM f maddr = do---     Count n <- getCountMAddr maddr---     maddr' <- allocMAddr (Count n)---     let go i =---           when (i < n) $ do---             writeOffMAddr maddr' (Off i) =<< f =<< readOffMAddr maddr (Off i)---             go (i + 1)---     maddr' <$ go 0------------------------- Bytes orphans ------------------------instance MemRead (Bytes p) where-  byteCountMem = byteCountBytes-  {-# INLINE byteCountMem #-}-  indexOffMem = indexOffBytes-  {-# INLINE indexOffMem #-}-  indexByteOffMem = indexByteOffBytes-  {-# INLINE indexByteOffMem #-}-  copyByteOffToMBytesMem = copyByteOffBytesToMBytes-  {-# INLINE copyByteOffToMBytesMem #-}-  copyByteOffToPtrMem = copyByteOffBytesToPtr-  {-# INLINE copyByteOffToPtrMem #-}-  compareByteOffToPtrMem bytes1 off1 ptr2 off2 c =-    pure $ compareByteOffBytesToPtr bytes1 off1 ptr2 off2 c-  {-# INLINE compareByteOffToPtrMem #-}-  compareByteOffToBytesMem bytes1 off1 bytes2 off2 c =-    pure $ compareByteOffBytes bytes1 off1 bytes2 off2 c-  {-# INLINE compareByteOffToBytesMem #-}-  compareByteOffMem mem1 off1 bs off2 c =-    unsafeInlineIO $ compareByteOffToBytesMem mem1 off1 bs off2 c-  {-# INLINE compareByteOffMem #-}--instance Typeable p => MemAlloc (MBytes p) where-  type FrozenMem (MBytes p) = Bytes p-  getByteCountMem = getByteCountMBytes-  {-# INLINE getByteCountMem #-}-  allocByteCountMem = allocMBytes-  {-# INLINE allocByteCountMem #-}-  thawMem = thawBytes-  {-# INLINE thawMem #-}-  freezeMem = freezeMBytes-  {-# INLINE freezeMem #-}-  resizeMem = reallocMBytes-  {-# INLINE resizeMem #-}--instance MemWrite (MBytes p) where-  readOffMem = readOffMBytes-  {-# INLINE readOffMem #-}-  readByteOffMem = readByteOffMBytes-  {-# INLINE readByteOffMem #-}-  writeOffMem = writeOffMBytes-  {-# INLINE writeOffMem #-}-  writeByteOffMem = writeByteOffMBytes-  {-# INLINE writeByteOffMem #-}-  moveByteOffToPtrMem = moveByteOffMBytesToPtr-  {-# INLINE moveByteOffToPtrMem #-}-  moveByteOffToMBytesMem = moveByteOffMBytesToMBytes-  {-# INLINE moveByteOffToMBytesMem #-}-  moveByteOffMem = moveByteOffToMBytesMem-  {-# INLINE moveByteOffMem #-}-  copyByteOffMem = copyByteOffToMBytesMem-  {-# INLINE copyByteOffMem #-}-  setMem = setMBytes-  {-# INLINE setMem #-}---instance Show (Bytes p) where-  show b =-    Foldable.foldr' ($) "]" $-    ('[' :) : List.intersperse (',' :) (map (("0x" ++) .) (showsHexMem b))--instance Typeable p => IsList (Bytes p) where-  type Item (Bytes p) = Word8-  fromList = fromListMem-  fromListN n = fromListMemN_ (Count n)-  toList = toListMem--instance Eq (Bytes p) where-  b1 == b2 = isSameBytes b1 b2 || eqMem b1 b2--instance Ord (Bytes p) where-  compare b1 b2 =-    compare n (byteCountBytes b2) <> compareByteOffBytes b1 0 b2 0 n-    where-      n = byteCountBytes b1--instance Typeable p => Semigroup.Semigroup (Bytes p) where-  (<>) = appendMem-  sconcat (x :| xs) = concatMem (x:xs)-  stimes i = cycleMemN (fromIntegral i)--instance Typeable p => Monoid.Monoid (Bytes p) where-  mappend = appendMem-  mconcat = concatMem-  mempty = emptyMem----- | A list of `ShowS` that covert bytes to base16 encoded strings. Each element of the list--- is a function that will convert one byte.------ >>> mb <- newPinnedMBytes (Count 5 :: Count Int)--- >>> mapM_ (\i -> writeOffMBytes mb (pred i) i) [1 .. 5]--- >>> foldr ($) "" . showsBytesHex <$> freezeMBytes mb--- "01000000000000000200000000000000030000000000000004000000000000000500000000000000"----showsHexMem :: MemRead r => r -> [ShowS]-showsHexMem b = map toHex (toListMem b :: [Word8])-  where-    toHex b8 =-      (if b8 <= 0x0f-         then ('0' :)-         else id) .-      showHex b8---- | Ensure that memory is filled with zeros before and after it is used.-withScrubbedMem ::-     (MonadUnliftPrim RW m, Prim e, MemAlloc mem)-  => Count e-  -> (mem RW -> m a)-  -> m a-withScrubbedMem c f = do-  mem <- allocZeroMem c-  f mem `finallyPrim` setMem mem 0 (toByteCount c) 0-  where-    finallyPrim m1 m2 = withRunInPrimBase $ \run -> finally (run m1) (run m2)+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilyDependencies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# OPTIONS_HADDOCK hide, not-home #-}+-- |+-- Module      : Data.Prim.Memory.Internal+-- Copyright   : (c) Alexey Kuleshevich 2020+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>+-- Stability   : experimental+-- Portability : non-portable+--+module Data.Prim.Memory.Internal+  ( module Data.Prim.Memory.Internal+  , module Data.Prim.Memory.Bytes.Internal+  ) where++import Control.Exception+import Control.Monad.ST+import Control.Prim.Monad+import Control.Prim.Monad.Unsafe+import qualified Data.ByteString as BS+import Data.Foldable as Foldable+import Data.Kind+import Data.List as List+import Data.List.NonEmpty (NonEmpty(..))+import qualified Data.Monoid as Monoid+import Data.Prim+import Data.Prim.Memory.Bytes.Internal+import Data.Prim.Memory.ByteString+import Data.Prim.Memory.ForeignPtr+import Data.Prim.Memory.Ptr+import qualified Data.Semigroup as Semigroup+import qualified Data.Prim.Memory.Text as T+import Foreign.Prim+import Numeric (showHex)++-- | Type class that can be implemented for an immutable data type that provides+-- read-only direct access to memory+class MemRead mr where++  -- | Number of bytes allocated by the data type available for reading.+  --+  -- ====__Example__+  --+  -- >>> :set -XDataKinds+  -- >>> import Data.Prim.Memory+  -- >>> byteCountMem (fromByteListMem [1,2,3] :: Bytes 'Inc)+  -- Count {unCount = 3}+  --+  -- @since 0.1.0+  byteCountMem :: mr -> Count Word8++  -- | Read an element with an offset in number of elements, rather than bytes as is the+  -- case with `indexByteOffMem`.+  --+  -- [Unsafe] Bounds are not checked. When precondition for @off@ argument is violated the+  -- result is either unpredictable output or failure with a segfault.+  --+  -- @since 0.1.0+  indexOffMem :: Prim e+    => mr -- ^ /memRead/ - Memory to read an element from+    -> Off e+    -- ^ /off/ - Offset in number of elements from the beginning of @memRead@+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= off+    --+    -- > unOffBytes off <= unCount (byteCountMem memRead - byteCountType @e)+    --+    -> e+  indexOffMem mr off = indexByteOffMem mr (toByteOff off)+  {-# INLINE indexOffMem #-}++  -- | Read an element with an offset in number of bytes. Bounds are not checked.+  --+  -- [Unsafe] When precondition for @off@ argument is violated the result is either+  -- unpredictable output or failure with a segfault.+  --+  -- @since 0.1.0+  indexByteOffMem :: Prim e+    => mr -- ^ /memRead/ - Memory to read an element from+    -> Off Word8+    -- ^ /off/ - Offset in number of elements from the beginning of @memRead@+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= unOff off+    --+    -- > unOff off <= unCount (byteCountMem memRead - byteCountType @e)+    --+    -> e++  -- | Copy contiguous chunk of memory from the read only memory into the target mutable+  -- `MBytes`. Source and target /must not/ refer to the same memory region, otherwise+  -- that would imply that the source is not immutable which would be a violation of some+  -- other invariant elsewhere in the code.+  --+  -- [Unsafe] When a precondition for either of the offsets @memSourceOff@, @memTargetOff@+  -- or the element count @memCount@ is violated the result is either unpredictable output or+  -- failure with a segfault.+  --+  -- @since 0.1.0+  copyByteOffToMBytesMem ::+       (MonadPrim s m, Prim e)+    => mr -- ^ /memSourceRead/ - Source from where to copy+    -> Off Word8+    -- ^ /memSourceOff/ - Offset into source memory in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memSourceOff+    --+    -- > unOff memSourceOff <= unCount (byteCountMem memSourceRead - byteCountType @e)+    -> MBytes p s -- ^ /memTargetWrite/ - Target mutable memory+    -> Off Word8+    -- ^ /memTargetOff/ -  Offset into target memory in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memTargetOff+    --+    -- > unOff memTargetOff <= unCount (byteCountMem memTargetWrite - byteCountType @e)+    -> Count e+    -- ^ /memCount/ - Number of elements of type @e@ to copy+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- > unCountBytes memCount + unOff memSourceOff <= unCount (byteCountMem memSourceRead - byteCountType @e)+    --+    -- > unCountBytes memCount + unOff memTargetOff <= unCount (byteCountMem memTargetRead - byteCountType @e)+    -> m ()++  -- | Copy contiguous chunk of memory from the read only memory into the target mutable+  -- `Ptr`. Source and target /must not/ refer to the same memory region, otherwise that+  -- would imply that the source is not immutable which would be a violation of some other+  -- invariant elsewhere in the code.+  --+  -- [Unsafe] When any precondition for one of the offsets @memSourceOff@, @memTargetOff@+  -- or the element count @memCount@ is violated a call to this function can result in:+  -- copy of data that doesn't belong to @memSourceRead@, heap corruption or failure with+  -- a segfault.+  --+  --+  -- @since 0.1.0+  copyByteOffToPtrMem ::+       (MonadPrim s m, Prim e)+    => mr -- ^ /memSourceRead/ - Source from where to copy+    -> Off Word8+    -- ^ /memSourceOff/ - Offset into source memory in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memSourceOff+    --+    -- > unOff memSourceOff <= unCount (byteCountMem memSourceRead - byteCountType @e)+    -> Ptr e+    -- ^ /memTargetWrite/ - Pointer to the target mutable memory+    --+    -- /__Preconditions:__/+    --+    -- Once the pointer is advanced by @memTargetOff@ the next @unCountBytes memCount@ bytes must+    -- still belong to the same region of memory @memTargetWrite@+    -> Off Word8+    -- ^ /memTargetOff/ - Number of bytes to advance the pointer @memTargetWrite@ forward+    --+    -- /__Precondition:__/+    --+    -- Once the pointer is advanced by @memTargetOff@ it must still refer to the same+    -- memory region @memTargetWrite@+    -> Count e+    -- ^ /memCount/ - Number of elements of type @e@ to copy+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- > unCountBytes memCount + unOff memSourceOff <= unCount (byteCountMem memSourceRead - byteCountType @e)+    -> m ()++  -- | Same as `compareByteOffMem`, but compare the read-only+  -- memory region to a region addressed by a `Ptr` inside of a `MonadPrim`.+  --+  -- [Unsafe] When any precondition for either of the offsets @memOff1@, @memOff2@, the+  -- pointer @memRead2@ or the element count @memCount@ is violated the result is either+  -- unpredictable output or failure with a segfault.+  --+  -- @since 0.1.0+  compareByteOffToPtrMem ::+       (MonadPrim s m, Prim e)+    => mr -- ^ /memRead1/ - First memory region+    -> Off Word8+    -- ^ /memOff1/ - Offset for @memRead1@ in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memOff1+    --+    -- > unOff memOff1 <= unCount (byteCountMem memRead1 - byteCountType @e)+    -> Ptr e+    -- ^ /memRead2/- Second memory region that can be accessed by a pointer+    --+    -- /__Preconditions__/+    --+    -- Once the pointer is advanced by @memOff2@ the next @unCountBytes memCount@ bytes must+    -- still belong to the same region of memory @memRead2@+    -> Off Word8+    -- ^ /memOff2/ - Number of bytes to advance the pointer @memRead2@ forward+    --+    -- /__Precondition:__/+    --+    -- Once the pointer is advanced by @memOff2@ it must still refer to the same memory+    -- region @memRead2@+    -> Count e -- ^ /memCount/ - Number of elements of type @e@ to compare as binary+    -- ^ /memCount/ - Number of elements of type @e@ to compare as binary+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- > unCountBytes memCount + unOff memOff1 <= unCount (byteCountMem memRead1 - byteCountType @e)+    -> m Ordering++  -- | Same as `compareByteOffMem`, but compare the read-only memory region to `Bytes`.+  --+  -- [Unsafe] When any precondition for either of the offsets @memOff1@, @memOff2@ or the+  -- element count @memCount@ is violated the result is either unpredictable output or+  -- failure with a segfault.+  --+  -- @since 0.1.0+  compareByteOffToBytesMem ::+       Prim e+    => mr -- ^ /memRead1/ - First memory region+    -> Off Word8+    -- ^ /memOff1/ - Offset for @memRead1@ in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memOff1+    --+    -- > unOff memOff1 <= unCount (byteCountMem memRead1 - byteCountType @e)+    -> Bytes p -- ^ /memRead2/- Second memory region that is backed by `Bytes`+    -> Off Word8+    -- ^ /memOff2/ - Offset for @memRead2@ in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memOff2+    --+    -- > unOff memOff2 <= unCount (byteCountMem memRead2 - byteCountType @e)+    -> Count e+    -- ^ /memCount/ - Number of elements of type @e@ to compare as binary+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- > unCountBytes memCount + unOff memOff1 <= unCount (byteCountMem memRead1 - byteCountType @e)+    --+    -- > unCountBytes memCount + unOff memOff2 <= unCount (byteCountMem memRead2 - byteCountType @e)+    -> Ordering++  -- | Compare two read-only regions of memory byte-by-byte. The very first mismatched+  -- byte will cause this function to produce `LT` if the byte in @memRead1@ is smaller+  -- than the one in @memRead2@ and `GT` if it is bigger. It is not a requirement to+  -- short-circuit on the first mismatch, but it is a good optimization to have for+  -- non-sensitive data. Memory regions that store security critical data may choose to+  -- implement this function to work in constant time.+  --+  -- This function is usually implemented by either one of `compareByteOffToPtrMem` or+  -- `compareByteOffToBytesMem`, depending on the nature of @mr@ type. However it differs+  -- from the aforementioned functions with a fact that it is pure non-monadic+  -- computation.+  --+  -- [Unsafe] When any precondition for either of the offsets @memOff1@, @memOff2@ or the+  -- element count @memCount@ is violated the result is either unpredictable output or+  -- failure with a segfault.+  --+  -- @since 0.1.0+  compareByteOffMem ::+       (MemRead mr', Prim e)+    => mr' -- ^ /memRead1/ - First memory region+    -> Off Word8+    -- ^ /memOff1/ - Offset for @memRead1@ in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memOff1+    --+    -- > unOff memOff1 <= unCount (byteCountMem memRead1 - byteCountType @e)+    -> mr -- ^ /memRead2/ - Second memory region+    -> Off Word8+    -- ^ /memOff2/ - Offset for @memRead2@ in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memOff2+    --+    -- > unOff memOff2 <= unCount (byteCountMem memRead2 - byteCountType @e)+    -> Count e+    -- ^ /memCount/ - Number of elements of type @e@ to compare as binary+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- > unCountBytes memCount + unOff memOff1 <= unCount (byteCountMem memRead1 - byteCountType @e)+    --+    -- > unCountBytes memCount + unOff memOff2 <= unCount (byteCountMem memRead2 - byteCountType @e)+    -> Ordering++-- | Type class that can be implemented for a mutable data type that provides direct read+-- and write access to memory+class MemWrite mw where+  -- | Read an element with an offset in number of elements, rather than bytes as it is+  -- the case with `readByteOffMem`.+  --+  -- [Unsafe] Bounds are not checked. When precondition for @off@ argument is violated the+  -- result is either unpredictable output or failure with a segfault.+  --+  -- @since 0.1.0+  readOffMem :: (MonadPrim s m, Prim e)+    => mw s -- ^ /memRead/ - Memory region to read an element from+    -> Off e+    -- ^ /off/ - Offset in number of elements from the beginning of @memRead@+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= off+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > count <- getByteCountMem memRead+    -- > unOff (toByteOff off) <= unCount (count - byteCountType @e)+    --+    -> m e+  readOffMem mw off = readByteOffMem mw (toByteOff off)+  {-# INLINE readOffMem #-}++  -- | Read an element with an offset in number of bytes.+  --+  -- [Unsafe] Bounds are not checked. When precondition for @off@ argument is violated the+  -- result is either unpredictable output or failure with a segfault.+  --+  -- @since 0.1.0+  readByteOffMem :: (MonadPrim s m, Prim e)+    => mw s -- ^ /memRead/ - Memory region to read an element from+    -> Off Word8+    -- ^ /off/ - Offset in number of elements from the beginning of @memRead@+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= off+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > count <- getByteCountMem memRead+    -- > unOff (toByteOff off) <= unCount (count - byteCountType @e)+    --+    -> m e++  -- | Write an element with an offset in number of elements, rather than bytes as it is+  -- the case with `writeByteOffMem`.+  --+  -- [Unsafe] Bounds are not checked. When precondition for @off@ argument is violated the+  -- outcome is either heap corruption or failure with a segfault.+  --+  -- @since 0.1.0+  writeOffMem :: (MonadPrim s m, Prim e)+    => mw s -- ^ /memWrite/ - Memory region to write an element into+    -> Off e+    -- ^ /off/ - Offset in number of elements from the beginning of @memWrite@+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= off+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > count <- getByteCountMem memWrite+    -- > unOff (toByteOff off) <= unCount (count - byteCountType @e)+    --+    -> e -- ^ /elt/ - Element to write+    -> m ()+  writeOffMem mw off = writeByteOffMem mw (toByteOff off)+  {-# INLINE writeOffMem #-}++  -- | Write an element with an offset in number of bytes.+  --+  -- [Unsafe] Bounds are not checked. When precondition for @off@ argument is violated the+  -- outcome is either heap corruption or failure with a segfault.+  --+  -- @since 0.1.0+  writeByteOffMem :: (MonadPrim s m, Prim e)+    => mw s -- ^ /memWrite/ - Memory region to write an element into+    -> Off Word8+    -- ^ /off/ - Offset in number of elements from the beginning of @memWrite@+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= off+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > count <- getByteCountMem memWrite+    -- > unOff (toByteOff off) <= unCount (count - byteCountType @e)+    --+    -> e -> m ()++  -- | Copy contiguous chunk of memory from the source mutable memory into the target+  -- mutable `MBytes`. Source and target /may/ refer to overlapping memory regions.+  --+  -- [Unsafe] When any precondition for one of the offsets @memSourceOff@, @memTargetOff@+  -- or the element count @memCount@ is violated a call to this function can result in:+  -- copy of data that doesn't belong to @memSource@, heap corruption or failure with+  -- a segfault.+  --+  -- @since 0.1.0+  moveByteOffToMBytesMem ::+    (MonadPrim s m, Prim e)+    => mw s -- ^ /memSource/ - Source memory from where to copy+    -> Off Word8+    -- ^ /memSourceOff/ - Offset in number of bytes into source memory+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memSourceOff+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > sourceByteCount <- getByteCountMem memSource+    -- > unOff (toByteOff memSourceOff) <= unCount (sourceByteCount - byteCountType @e)+    -> MBytes p s -- ^ /memTarget/ - Target memory into where to copy+    -> Off Word8+    -- ^ /memTargetOff/ - Offset in number of bytes into target memory where writing will start+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memTargetOff+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > targetByteCount <- getByteCountMem memTarget+    -- > unOffBytes memTargetOff <= unCount (targetByteCount - byteCountType @e)+    -> Count e+    -- ^ /memCount/ - Number of elements of type @e@ to copy+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- Both source and target memory regions must have enough memory to perform a copy+    -- of @memCount@ elements starting at their respective offsets. For types that also+    -- implement `MemAlloc` this can be described as:+    --+    -- > sourceByteCount <- getByteCountMem memSource+    -- > unOff memSourceOff + unCountBytes memCount <= unCount (sourceByteCount - byteCountType @e)+    --+    -- > targetByteCount <- getByteCountMem memTarget+    -- > unOff memTargetOff + unCountBytes memCount <= unCount (targetByteCount - byteCountType @e)+    -> m ()++  -- | Copy contiguous chunk of memory from the source mutable memory into the target+  -- `Ptr`. Source and target /may/ refer to overlapping memory regions.+  --+  -- [Unsafe] When any precondition for one of the offsets @memSourceOff@ or+  -- @memTargetOff@, a target pointer @memTarget@ or the element count @memCount@ is+  -- violated a call to this function can result in: copy of data that doesn't belong to+  -- @memSource@, heap corruption or failure with a segfault.+  --+  -- @since 0.1.0+  moveByteOffToPtrMem ::+    (MonadPrim s m, Prim e)+    => mw s -- ^ /memSource/ - Source memory from where to copy+    -> Off Word8+    -- ^ /memSourceOff/ - Offset in number of bytes into source memory+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memSourceOff+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > sourceByteCount <- getByteCountMem memSource+    -- > unOff (toByteOff memSourceOff) <= unCount (sourceByteCount - byteCountType @e)+    -> Ptr e+    -- ^ /memTarget/ - Target memory into where to copy+    --+    -- /__Precondition:__/+    --+    -- Once the pointer is advanced by @memTargetOff@ the next @unCountBytes memCount@ bytes must+    -- still belong to the same region of memory @memTargetWrite@+    -> Off Word8+    -- ^ /memTargetOff/ - Offset in number of bytes into target memory where writing will start+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memTargetOff+    --+    -- Once the pointer is advanced by @memTargetOff@ it must still refer to the same+    -- memory region @memTarget@+    -> Count e+    -- ^ /memCount/ - Number of elements of type @e@ to copy+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- Both source and target memory regions must have enough memory to perform a copy+    -- of @memCount@ elements starting at their respective offsets. For /memSource/ that also+    -- implements `MemAlloc` this can be described as:+    --+    -- > sourceByteCount <- getByteCountMem memSource+    -- > unOff memSourceOff + unCountBytes memCount <= unCount (sourceByteCount - byteCountType @e)+    -> m ()++  -- | Copy contiguous chunk of memory from the read only memory region into the target+  -- mutable memory region. Source and target /must not/ refer to the same memory region,+  -- otherwise that would imply that the source is not immutable which would be a+  -- violation of some other invariant elsewhere in the code.+  --+  -- [Unsafe] When any precondition for one of the offsets @memSourceOff@, @memTargetOff@+  -- or the element count @memCount@ is violated a call to this function can result in:+  -- copy of data that doesn't belong to @memSourceRead@, heap corruption or failure with+  -- a segfault.+  --+  -- @since 0.1.0+  copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e)+    => mr -- ^ /memSourceRead/ - Read-only source memory region from where to copy+    -> Off Word8+    -- ^ /memSourceOff/ - Offset into source memory in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memSourceOff+    --+    -- > unOff memSourceOff <= unCount (byteCountMem memSourceRead - byteCountType @e)+    -> mw s -- ^ /memTargetWrite/ - Target mutable memory+    -> Off Word8+    -- ^ /memTargetOff/ -  Offset into target memory in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memTargetOff+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > targetByteCount <- getByteCountMem memTargetWrite+    -- > unOffBytes memTargetOff <= unCount (targetByteCount - byteCountType @e)+    -> Count e+    -- ^ /memCount/ - Number of elements of type @e@ to copy+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- Both source and target memory regions must have enough memory to perform a copy+    -- of @memCount@ elements starting at their respective offsets. For @memSourceRead@:+    --+    -- > unOff memSourceOff + unCountBytes memCount <= unCount (byteCountMem memSourceRead - byteCountType @e)+    --+    -- and for @memTargetWrite@ that also implements `MemAlloc` this can be described as:+    --+    -- > targetByteCount <- getByteCountMem memTargetWrite+    -- > unOff memTargetOff + unCountBytes memCount <= unCount (targetByteCount - byteCountType @e)+    -> m ()++  -- | Copy contiguous chunk of memory from a mutable memory region into the target+  -- mutable memory region. Source and target /may/ refer to the same memory region.+  --+  -- [Unsafe] When any precondition for one of the offsets @memSourceOff@, @memTargetOff@+  -- or the element count @memCount@ is violated a call to this function can result in:+  -- copy of data that doesn't belong to @memSourceRead@, heap corruption or failure with+  -- a segfault.+  --+  -- @since 0.1.0+  moveByteOffMem :: (MonadPrim s m, MemWrite mw', Prim e)+    => mw' s -- ^ /memSource/ - Source memory from where to copy+    -> Off Word8+    -- ^ /memSourceOff/ - Offset in number of bytes into source memory+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memSourceOff+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > sourceByteCount <- getByteCountMem memSource+    -- > unOffBytes memSourceOff <= unCount (sourceByteCount - byteCountType @e)+    -> mw s -- ^ /memTarget/ - Target memory into where to copy+    -> Off Word8+    -- ^ /memTargetOff/ -  Offset into target memory in number of bytes+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memTargetOff+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > targetByteCount <- getByteCountMem memTarget+    -- > unOffBytes (toByteOff memTargetOff) <= unCount (targetByteCount - byteCountType @e)+    -> Count e+    -- ^ /memCount/ - Number of elements of type @e@ to copy+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- Both source and target memory regions must have enough memory to perform a copy+    -- of @memCount@ elements starting at their respective offsets. For types that also+    -- implement `MemAlloc` this can be described as:+    --+    -- > sourceByteCount <- getByteCountMem memSource+    -- > unOff memSourceOff + unCountBytes memCount <= unCount (sourceByteCount - byteCountType @e)+    --+    -- > targetByteCount <- getByteCountMem memTarget+    -- > unOff memTargetOff + unCountBytes memCount <= unCount (targetByteCount - byteCountType @e)+    -> m ()++  -- TODO: Potential feature for the future implementation. Will require extra function in `Prim`.+  --setByteOffMem :: (MonadPrim s m, Prim e) => w s -> Off Word8 -> Count e -> e -> m ()++  -- | Write the same value @memCount@ times into each cell of @memTarget@ starting at an+  -- offset @memTargetOff@.+  --+  -- [Unsafe] Bounds are not checked. When precondition for @memTargetOff@ argument is+  -- violated the outcome is either heap corruption or failure with a segfault.+  --+  -- @since 0.1.0+  setMem+    :: (MonadPrim s m, Prim e)+    => mw s -- ^ /memTarget/ - Target memory into where to write the element+    -> Off e+    -- ^ /memTargetOff/ - Offset into target memory in number of elements at which element+    -- setting should start.+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memTargetOff+    --+    -- With offset applied it should still refer to the same memory region. For types that+    -- also implement `MemAlloc` this can be described as:+    --+    -- > targetByteCount <- getByteCountMem memTarget+    -- > unOffBytes memTargetOff <= unCount (targetByteCount - byteCountType @e)+    -> Count e+    -- ^ /memCount/ - Number of times the element @elt@ should be written+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- Target memory region should have enough memory to perform a set operation of the+    -- supplied element @memCount@ number of times starting at the supplied offset. For+    -- types that also implement `MemAlloc` this can be described as:+    --+    -- > targetByteCount <- getByteCountMem memTarget+    -- > unCountBytes memCount + unOff memTargetOff <= unCount (targetByteCount - byteCountType @e)+    -> e+    -- ^ /elt/ - Element to write into memory cells. This function is strict with+    -- respect to element, which means that the even @memCount = 0@ it might be still+    -- fully evaluated.+    -> m ()++-- | Generalized memory allocation and pure/mutable state conversion.+class (MemRead (FrozenMem ma), MemWrite ma) => MemAlloc ma where+  -- | Memory region in the immutable state. Types for frozen and thawed states of+  -- memory region are in one-to-one correspondence, therefore @ma <-> FrozeMem ma@ will+  -- always uniquely identify each other, which is an extremely useful property when it+  -- comes to type inference.+  type FrozenMem ma = (fm :: Type) | fm -> ma++  -- | Extract from the mutable memory region information about how many bytes it can hold.+  --+  -- @since 0.1.0+  getByteCountMem :: MonadPrim s m => ma s -> m (Count Word8)++  -- | Allocate a mutable memory region for specified number of elements. Memory is not+  -- reset and will likely hold some garbage data, therefore prefer to use `allocZeroMem`,+  -- unless it is guaranteed that all of allocated memory will be overwritten.+  --+  -- [Unsafe] When precondition for @memCount@ argument is violated the outcome is+  -- upredictable. One possible outcome is termination with+  -- `Control.Exception.HeapOverflow` async exception. In a pure setting, such as when+  -- executed within `runST`, if memory is not fully overwritten it can result in+  -- violation of referential transparency, because content of newly allocated+  -- region is non-determinstic.+  --+  -- @since 0.1.0+  allocMem :: (Prim e, MonadPrim s m)+    => Count e+    -- ^ /memCount/ - Number of elements to allocate.+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- Possibility of overflow:+    --+    -- > unCount memCount <= fromByteCount @e (Count maxBound)+    --+    -- When converted to bytes the value should be less then available physical memory+    -> m (ma s)++  -- | Convert the state of an immutable memory region to the mutable one. This is a no+  -- copy operation, as such it is fast, but dangerous. See `thawCopyMem` for a safe alternative.+  --+  -- [Unsafe] It makes it possible to break referential transparency, because any+  -- subsequent destructive operation to the mutable region of memory will also be+  -- reflected in the frozen immutable type as well.+  --+  -- @since 0.1.0+  thawMem :: MonadPrim s m => FrozenMem ma -> m (ma s)++  -- | Convert the state of a mutable memory region to the immutable one. This is a no+  -- copy operation, as such it is fast, but dangerous. See `freezeCopyMem` for a safe alternative.+  --+  -- [Unsafe] It makes it possible to break referential transparency, because any+  -- subsequent destructive operation to the mutable region of memory will also be+  -- reflected in the frozen immutable type as well.+  --+  -- @since 0.1.0+  freezeMem :: MonadPrim s m => ma s -> m (FrozenMem ma)++  -- | Either grow or shrink currently allocated mutable region of memory. For some+  -- implementations it might be possible to change the size of the allocated region+  -- in-place, i.e. without copy. However in all implementations there is a good chance+  -- that the memory region has to be allocated anew, in which case all of the contents+  -- up to the minimum of new and old sizes will get copied over. After the resize+  -- operation is complete the supplied @memSource@ region must not be used+  -- anymore. Moreover, no reference to the old one should be kept in order to allow+  -- garbage collection of the original in case a new one had to be allocated.+  --+  -- [Unsafe] Undefined behavior when @memSource@ is used afterwards. The same unsafety+  -- notice from `allocMem` with regards to @memCount@ is applcable here as well.+  --+  -- @since 0.1.0+  resizeMem :: (MonadPrim s m, Prim e)+    => ma s+    -- ^ /memSource/ - Source memory region to resize+    -> Count e+    -- ^ /memCount/ - Number of elements for the reallocated memory region+    --+    -- /__Preconditions:__/+    --+    -- > 0 <= memCount+    --+    -- Should be less then available physical memory+    -> m (ma s)+  resizeMem = defaultResizeMem+  {-# INLINE resizeMem #-}+++instance MemRead ByteString where+  byteCountMem = Count . BS.length+  {-# INLINE byteCountMem #-}+  indexOffMem bs i = unsafeInlineIO $ withPtrAccess bs (`readOffPtr` i)+  {-# INLINE indexOffMem #-}+  indexByteOffMem bs i = unsafeInlineIO $ withPtrAccess bs (`readByteOffPtr` i)+  {-# INLINE indexByteOffMem #-}+  copyByteOffToMBytesMem bs srcOff mb dstOff c =+    withPtrAccess bs $ \srcPtr -> copyByteOffPtrToMBytes srcPtr srcOff mb dstOff c+  {-# INLINE copyByteOffToMBytesMem #-}+  copyByteOffToPtrMem bs srcOff dstPtr dstOff c =+    withPtrAccess bs $ \srcPtr -> copyByteOffPtrToPtr srcPtr srcOff dstPtr dstOff c+  {-# INLINE copyByteOffToPtrMem #-}+  compareByteOffToPtrMem bs off1 ptr2 off2 c =+    withPtrAccess bs $ \ptr1 -> pure $! compareByteOffPtrToPtr ptr1 off1 ptr2 off2 c+  {-# INLINE compareByteOffToPtrMem #-}+  compareByteOffToBytesMem bs off1 bytes off2 c =+    unsafeInlineIO $ withPtrAccess bs $ \ptr1 ->+      pure $! compareByteOffPtrToBytes ptr1 off1 bytes off2 c+  {-# INLINE compareByteOffToBytesMem #-}+  compareByteOffMem mem1 off1 bs off2 c =+    unsafeInlineIO $ withPtrAccess bs $ \ptr2 -> compareByteOffToPtrMem mem1 off1 ptr2 off2 c+  {-# INLINE compareByteOffMem #-}+++instance MemAlloc MByteString where+  type FrozenMem MByteString = ByteString+  getByteCountMem (MByteString bs) = pure $! Count (BS.length bs)+  {-# INLINE getByteCountMem #-}+  allocMem c = do+    let cb = toByteCount c+    fp <- mallocByteCountPlainForeignPtr cb+    pure $ MByteString (PS fp 0 (coerce cb))+  {-# INLINE allocMem #-}+  thawMem bs = pure $ MByteString bs+  {-# INLINE thawMem #-}+  freezeMem (MByteString bs) = pure bs+  {-# INLINE freezeMem #-}+  resizeMem bsm@(MByteString (PS fp o n)) newc+    | newn > n = defaultResizeMem bsm newc+    | otherwise = pure $ MByteString (PS fp o newn)+    where -- constant time slice if we need to reduce the size+      Count newn = toByteCount newc+  {-# INLINE resizeMem #-}++instance MemWrite MByteString where+  readOffMem (MByteString mbs) i = withPtrAccess mbs (`readOffPtr` i)+  {-# INLINE readOffMem #-}+  readByteOffMem (MByteString mbs) i = withPtrAccess mbs (`readByteOffPtr` i)+  {-# INLINE readByteOffMem #-}+  writeOffMem (MByteString mbs) i a = withPtrAccess mbs $ \ptr -> writeOffPtr ptr i a+  {-# INLINE writeOffMem #-}+  writeByteOffMem (MByteString mbs) i a = withPtrAccess mbs $ \ptr -> writeByteOffPtr ptr i a+  {-# INLINE writeByteOffMem #-}+  moveByteOffToPtrMem (MByteString fsrc) srcOff dstPtr dstOff c =+    withPtrAccess fsrc $ \srcPtr -> moveByteOffPtrToPtr srcPtr srcOff dstPtr dstOff c+  {-# INLINE moveByteOffToPtrMem #-}+  moveByteOffToMBytesMem (MByteString fsrc) srcOff dst dstOff c =+    withPtrAccess fsrc $ \srcPtr -> moveByteOffPtrToMBytes srcPtr srcOff dst dstOff c+  {-# INLINE moveByteOffToMBytesMem #-}+  copyByteOffMem src srcOff (MByteString fdst) dstOff c =+    withPtrAccess fdst $ \dstPtr -> copyByteOffToPtrMem src srcOff dstPtr dstOff c+  {-# INLINE copyByteOffMem #-}+  moveByteOffMem src srcOff (MByteString fdst) dstOff c =+    withPtrAccess fdst $ \dstPtr -> moveByteOffToPtrMem src srcOff dstPtr dstOff c+  {-# INLINE moveByteOffMem #-}+  setMem (MByteString mbs) off c a = withPtrAccess mbs $ \ptr -> setOffPtr ptr off c a+  {-# INLINE setMem #-}++instance MemRead T.Array where+  byteCountMem = byteCountMem . T.toBytesArray+  {-# INLINE byteCountMem #-}+  indexOffMem a = indexOffMem (T.toBytesArray a)+  {-# INLINE indexOffMem #-}+  indexByteOffMem a = indexByteOffMem (T.toBytesArray a)+  {-# INLINE indexByteOffMem #-}+  copyByteOffToMBytesMem a = copyByteOffToMBytesMem (T.toBytesArray a)+  {-# INLINE copyByteOffToMBytesMem #-}+  copyByteOffToPtrMem a = copyByteOffToPtrMem (T.toBytesArray a)+  {-# INLINE copyByteOffToPtrMem #-}+  compareByteOffToPtrMem a = compareByteOffToPtrMem (T.toBytesArray a)+  {-# INLINE compareByteOffToPtrMem #-}+  compareByteOffToBytesMem a = compareByteOffToBytesMem (T.toBytesArray a)+  {-# INLINE compareByteOffToBytesMem #-}+  compareByteOffMem mem off1 a = compareByteOffMem mem off1 (T.toBytesArray a)+  {-# INLINE compareByteOffMem #-}++instance MemAlloc T.MArray where+  type FrozenMem T.MArray = T.Array+  getByteCountMem = getByteCountMBytes . T.toMBytesMArray+  {-# INLINE getByteCountMem #-}+  allocMem = fmap T.fromMBytesMArray . allocUnpinnedMBytes+  {-# INLINE allocMem #-}+  thawMem = fmap T.fromMBytesMArray . thawBytes . T.toBytesArray+  {-# INLINE thawMem #-}+  freezeMem = fmap T.fromBytesArray . freezeMBytes . T.toMBytesMArray+  {-# INLINE freezeMem #-}+  resizeMem m = fmap T.fromMBytesMArray . reallocMBytes (T.toMBytesMArray m)+  {-# INLINE resizeMem #-}++instance MemWrite T.MArray where+  readOffMem m = readOffMBytes (T.toMBytesMArray m)+  {-# INLINE readOffMem #-}+  readByteOffMem m = readByteOffMBytes (T.toMBytesMArray m)+  {-# INLINE readByteOffMem #-}+  writeOffMem m = writeOffMBytes (T.toMBytesMArray m)+  {-# INLINE writeOffMem #-}+  writeByteOffMem m = writeByteOffMBytes (T.toMBytesMArray m)+  {-# INLINE writeByteOffMem #-}+  moveByteOffToPtrMem m = moveByteOffMBytesToPtr (T.toMBytesMArray m)+  {-# INLINE moveByteOffToPtrMem #-}+  moveByteOffToMBytesMem m = moveByteOffMBytesToMBytes (T.toMBytesMArray m)+  {-# INLINE moveByteOffToMBytesMem #-}+  moveByteOffMem src srcOff m = moveByteOffToMBytesMem src srcOff (T.toMBytesMArray m)+  {-# INLINE moveByteOffMem #-}+  copyByteOffMem src srcOff m = copyByteOffToMBytesMem src srcOff (T.toMBytesMArray m)+  {-# INLINE copyByteOffMem #-}+  setMem m = setMBytes (T.toMBytesMArray m)+  {-# INLINE setMem #-}++instance MemRead T.Text where+  byteCountMem (T.Text _ _ n) = toByteCount (Count n :: Count Word16)+  {-# INLINE byteCountMem #-}+  indexByteOffMem (T.Text a o _) i = indexByteOffMem a (toByteOff (Off o :: Off Word16) + i)+  {-# INLINE indexByteOffMem #-}+  copyByteOffToMBytesMem (T.Text a o _) i =+    copyByteOffToMBytesMem a (toByteOff (Off o :: Off Word16) + i)+  {-# INLINE copyByteOffToMBytesMem #-}+  copyByteOffToPtrMem (T.Text a o _) i =+    copyByteOffToPtrMem a (toByteOff (Off o :: Off Word16) + i)+  {-# INLINE copyByteOffToPtrMem #-}+  compareByteOffToPtrMem (T.Text a o _) off =+    compareByteOffToPtrMem a (toByteOff (Off o :: Off Word16) + off)+  {-# INLINE compareByteOffToPtrMem #-}+  compareByteOffToBytesMem (T.Text a o _) off =+    compareByteOffToBytesMem a (toByteOff (Off o :: Off Word16) + off)+  {-# INLINE compareByteOffToBytesMem #-}+  compareByteOffMem mem off1 (T.Text a o _) off2 =+    compareByteOffMem mem off1 a (toByteOff (Off o :: Off Word16) + off2)+  {-# INLINE compareByteOffMem #-}+++instance MemRead ShortByteString where+  byteCountMem = byteCountMem . fromShortByteStringBytes+  {-# INLINE byteCountMem #-}+  indexOffMem sbs = indexOffMem (fromShortByteStringBytes sbs)+  {-# INLINE indexOffMem #-}+  indexByteOffMem sbs = indexByteOffMem (fromShortByteStringBytes sbs)+  {-# INLINE indexByteOffMem #-}+  copyByteOffToMBytesMem sbs = copyByteOffToMBytesMem (fromShortByteStringBytes sbs)+  {-# INLINE copyByteOffToMBytesMem #-}+  copyByteOffToPtrMem sbs = copyByteOffToPtrMem (fromShortByteStringBytes sbs)+  {-# INLINE copyByteOffToPtrMem #-}+  compareByteOffToPtrMem sbs = compareByteOffToPtrMem (fromShortByteStringBytes sbs)+  {-# INLINE compareByteOffToPtrMem #-}+  compareByteOffToBytesMem sbs = compareByteOffToBytesMem (fromShortByteStringBytes sbs)+  {-# INLINE compareByteOffToBytesMem #-}+  compareByteOffMem mem off1 sbs = compareByteOffMem mem off1 (fromShortByteStringBytes sbs)+  {-# INLINE compareByteOffMem #-}++-- | A wrapper that adds a phantom state token. It can be used with types that either+-- doesn't have such state token or are designed to work in `IO` and therefore restricted+-- to `RW`. Using this wrapper is very much unsafe, so make sure you know what you are+-- doing.+newtype MemState a s = MemState { unMemState :: a }++instance MemWrite (MemState (ForeignPtr a)) where+  readOffMem (MemState fptr) i = withForeignPtr fptr $ \ptr -> readOffPtr (castPtr ptr) i+  {-# INLINE readOffMem #-}+  readByteOffMem (MemState fptr) i =+    withForeignPtr fptr $ \ptr -> readByteOffPtr (castPtr ptr) i+  {-# INLINE readByteOffMem #-}+  writeOffMem (MemState fptr) i a = withForeignPtr fptr $ \ptr -> writeOffPtr (castPtr ptr) i a+  {-# INLINE writeOffMem #-}+  writeByteOffMem (MemState fptr) i a =+    withForeignPtr fptr $ \ptr -> writeByteOffPtr (castPtr ptr) i a+  {-# INLINE writeByteOffMem #-}+  moveByteOffToPtrMem (MemState fsrc) srcOff dstPtr dstOff c =+    withForeignPtr fsrc $ \srcPtr -> moveByteOffPtrToPtr (castPtr srcPtr) srcOff dstPtr dstOff c+  {-# INLINE moveByteOffToPtrMem #-}+  moveByteOffToMBytesMem (MemState fsrc) srcOff dst dstOff c =+    withForeignPtr fsrc $ \srcPtr -> moveByteOffPtrToMBytes (castPtr srcPtr) srcOff dst dstOff c+  {-# INLINE moveByteOffToMBytesMem #-}+  copyByteOffMem src srcOff (MemState fdst) dstOff c =+    withForeignPtr fdst $ \dstPtr ->+       copyByteOffToPtrMem src srcOff (castPtr dstPtr) dstOff c+  {-# INLINE copyByteOffMem #-}+  moveByteOffMem src srcOff (MemState fdst) dstOff c =+    withForeignPtr fdst $ \dstPtr ->+       moveByteOffToPtrMem src srcOff (castPtr dstPtr) dstOff c+  {-# INLINE moveByteOffMem #-}+  setMem (MemState fptr) off c a = withForeignPtr fptr $ \ptr -> setOffPtr (castPtr ptr) off c a+  {-# INLINE setMem #-}++modifyFetchOldMem ::+     (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> e) -> m e+modifyFetchOldMem mem o f = modifyFetchOldMemM mem o (pure . f)+{-# INLINE modifyFetchOldMem #-}+++modifyFetchNewMem ::+     (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> e) -> m e+modifyFetchNewMem mem o f = modifyFetchNewMemM mem o (pure . f)+{-# INLINE modifyFetchNewMem #-}+++modifyFetchOldMemM ::+     (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> m e) -> m e+modifyFetchOldMemM mem o f = do+  a <- readOffMem mem o+  a <$ (writeOffMem mem o =<< f a)+{-# INLINE modifyFetchOldMemM #-}+++modifyFetchNewMemM ::+     (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> m e) -> m e+modifyFetchNewMemM mem o f = do+  a <- readOffMem mem o+  a' <- f a+  a' <$ writeOffMem mem o a'+{-# INLINE modifyFetchNewMemM #-}+++defaultResizeMem ::+     (Prim e, MemAlloc ma, MonadPrim s m) => ma s -> Count e -> m (ma s)+defaultResizeMem mem c = do+  let newByteCount = toByteCount c+  oldByteCount <- getByteCountMem mem+  if oldByteCount == newByteCount+    then pure mem+    else do+      newMem <- allocMem newByteCount+      oldMem <- freezeMem mem+      newMem <$ copyMem oldMem 0 newMem 0 oldByteCount+{-# INLINE defaultResizeMem #-}+++-- | Place @n@ copies of supplied region of memory one after another in a newly allocated+-- contiguous chunk of memory. Similar to `stimes`, but the source memory @memRead@ does+-- not have to match the type of `FrozenMem` ma.+--+-- ====__Example__+--+-- >>> :set -XTypeApplications+-- >>> :set -XDataKinds+-- >>> import Data.Prim.Memory+-- >>> let b = fromListMem @Word8 @(MBytes 'Inc) [0xde, 0xad, 0xbe, 0xef]+-- >>> cycleMemN @(MBytes 'Inc) 2 b+-- [0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef]+--+-- @since 0.1.0+cycleMemN ::+     forall ma mr. (MemAlloc ma, MemRead mr)+  => Int+  -> mr+  -> FrozenMem ma+cycleMemN n r+  | n <= 0 = emptyMem+  | otherwise =+    runST $ do+      let bc@(Count chunk) = byteCountMem r+          c@(Count c8) = Count n * bc+      mem <- allocMem c+      let go i = when (i < c8) $ copyByteOffMem r 0 mem (Off i) bc >> go (i + chunk)+      go 0+      freezeMem mem+{-# INLINE cycleMemN #-}+++-- | Construct an immutable memory region that can't hold any data. Same as @`mempty` ::+-- `FrozenMem` ma@+--+-- ====__Example__+--+-- >>> :set -XTypeApplications+-- >>> :set -XDataKinds+-- >>> import Data.Prim.Memory+-- >>> toListMem (emptyMem @(MBytes 'Inc)) :: [Int]+-- []+--+-- @since 0.1.0+emptyMem ::+     forall ma. MemAlloc ma+  => FrozenMem ma+emptyMem = createMemST_ (0 :: Count Word8) (\_ -> pure ())+{-# INLINE emptyMem #-}++-- | Allocate a region of immutable memory that holds a single element.+--+-- ====__Example__+--+-- >>> :set -XTypeApplications+-- >>> :set -XDataKinds+-- >>> import Data.Prim.Memory+-- >>> toListMem (singletonMem @Word16 @(MBytes 'Inc) 0xffff) :: [Word8]+-- [255,255]+--+-- @since 0.1.0+singletonMem ::+     forall e ma. (MemAlloc ma, Prim e)+  => e -- ^ The single element that will be stored in the newly allocated region of memory+  -> FrozenMem ma+singletonMem a = createMemST_ (1 :: Count e) $ \mem -> writeOffMem mem 0 a+{-# INLINE singletonMem #-}++-- | Same as `allocMem`, but also use `setMem` to reset all of newly allocated memory to+-- zeros.+--+-- [Unsafe] When precondition for @memCount@ argument is violated the outcome is+-- upredictable. One possible outcome is termination with `Control.Exception.HeapOverflow`+-- async exception.+--+-- ====__Example__+--+-- >>> :set -XTypeApplications+-- >>> :set -XDataKinds+-- >>> import Data.Prim.Memory+-- >>> mb <- allocZeroMem @Int @(MBytes 'Inc) 10+-- >>> b <- freezeMem mb+-- >>> toListMem b :: [Int]+-- [0,0,0,0,0,0,0,0,0,0]+--+-- @since 0.1.0+allocZeroMem ::+     forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e)+  => Count e+  -- ^ /memCount/ - Number of elements to allocate.+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memCount+  --+  -- Converted to bytes should be less then available physical memory+  -> m (ma s)+allocZeroMem n = do+  m <- allocMem n+  m <$ setMem m 0 (toByteCount n) (0 :: Word8)+{-# INLINE allocZeroMem #-}+++createMemST ::+     forall e b ma. (MemAlloc ma, Prim e)+  => Count e+  -> (forall s. ma s -> ST s b)+  -> (b, FrozenMem ma)+createMemST n f = runST $ allocMem n >>= \m -> (,) <$> f m <*> freezeMem m+{-# INLINE createMemST #-}++createMemST_ :: (MemAlloc ma, Prim e)+  => Count e+  -> (forall s . ma s -> ST s b)+  -- ^ /fillAction/ -- Action that will be used to modify contents of newly allocated+  -- memory.+  --+  -- /__Required invariant:__/+  --+  -- It is important that this action overwrites all of newly allocated memory.+  -> FrozenMem ma+createMemST_ n f = runST (allocMem n >>= \m -> f m >> freezeMem m)+{-# INLINE createMemST_ #-}++createZeroMemST ::+     forall e ma b. (MemAlloc ma, Prim e)+  => Count e+  -> (forall s. ma s -> ST s b)+  -> (b, FrozenMem ma)+createZeroMemST n f = runST $ allocZeroMem n >>= \m -> (,) <$> f m <*> freezeMem m+{-# INLINE createZeroMemST #-}++-- | Same as `createMemST_`, except it ensures that the memory gets reset with zeros prior+-- to applying the @ST@ filling action @fillAction@.+--+-- [Unsafe] Same reasons as `allocZeroMem`: violation of precondition for @memCount@ may+-- result in undefined behavior or `Control.Exception.HeapOverflow` async exception.+--+-- ====__Example__+--+-- Note that this example will work correctly only on little-endian machines:+--+-- >>> :set -XTypeApplications+-- >>> import Data.Prim+-- >>> import Control.Monad+-- >>> let ibs = zip [0, 4 ..] [0x48,0x61,0x73,0x6b,0x65,0x6c,0x6c] :: [(Off Word8, Word8)]+-- >>> let c = Count (length ibs) :: Count Char+-- >>> let bc = createZeroMemST_ @_ @(MBytes 'Inc) c $ \m -> forM_ ibs $ \(i, b) -> writeByteOffMem m i b+-- >>> toListMem bc :: String+-- "Haskell"+--+-- @since 0.1.0+createZeroMemST_ ::+     forall e ma b. (MemAlloc ma, Prim e)+  => Count e+  -- ^ /memCount/ - Size of the newly allocated memory region in number of elements of+  -- type @e@+  --+  -- /__Precoditions:__/+  --+  -- Size should be non-negative, but smaller than amount of available memory. Note that the+  -- second condition simply describes overflow.+  --+  -- > 0 <= memCount+  --+  -- Possibility of overflow:+  --+  -- > unCount memCount <= fromByteCount @e (Count maxBound)+  -> (forall s. ma s -> ST s b)+  -- ^ /fillAction/ -- Action that will be used to modify contents of newly allocated+  -- memory. It is not required to overwrite the full region, since it was reset to zeros+  -- right after allocation.+  -> FrozenMem ma+createZeroMemST_ n f = runST (allocZeroMem n >>= \m -> f m >> freezeMem m)+{-# INLINE createZeroMemST_ #-}++-- | Copy all of the data from the source into a newly allocate memory region of identical+-- size.+--+-- ====__Examples__+--+-- >>> :set -XDataKinds+-- >>> import Data.Prim.Memory+-- >>> let xs = fromByteListMem @(MBytes 'Pin) [0..15] :: Bytes 'Pin+-- >>> let ys = cloneMem xs+-- >>> let report bEq pEq = print $ "Bytes equal: " ++ show bEq ++ ", their pointers equal: " ++ show pEq+-- >>> withPtrBytes xs $ \ xsPtr -> withPtrBytes ys $ \ ysPtr -> report (xs == ys) (xsPtr == ysPtr)+-- "Bytes equal: True, their pointers equal: False"+--+-- @since 0.2.0+cloneMem ::+     forall ma. MemAlloc ma+  => FrozenMem ma -- ^ /memSource/ - immutable source memory.+  -> FrozenMem ma+cloneMem fm =+  runST $ do+    let n = byteCountMem fm+    mm <- allocMem n+    copyMem fm 0 mm 0 n+    freezeMem mm+{-# INLINE cloneMem #-}++-- | Similar to `copyByteOffMem`, but supply offsets in number of elements instead of+-- bytes. Copy contiguous chunk of memory from the read only memory region into the target+-- mutable memory region. Source and target /must not/ refer to the same memory region,+-- otherwise that would imply that the source is not immutable which would be a violation+-- of some other invariant elsewhere in the code.+--+-- [Unsafe] When any precondition for one of the offsets @memSourceOff@, @memTargetOff@+-- or the element count @memCount@ is violated a call to this function can result in:+-- copy of data that doesn't belong to @memSourceRead@, heap corruption or failure with+-- a segfault.+--+-- @since 0.1.0+copyMem ::+     (MonadPrim s m, MemRead mr, MemWrite mw, Prim e)+  => mr -- ^ /memSourceRead/ - Read-only source memory region from where to copy+  -> Off e+  -- ^ /memSourceOff/ - Offset into source memory in number of elements of type @e@+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memSourceOff+  --+  -- > unOff memSourceOff < unCount (countMem memSourceRead)+  -> mw s -- ^ /memTargetWrite/ - Target mutable memory+  -> Off e+  -- ^ /memTargetOff/ -  Offset into target memory in number of elements+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memTargetOff+  --+  -- With offset applied it should still refer to the same memory region. For types that+  -- also implement `MemAlloc` this can be described as:+  --+  -- > targetCount <- getCountMem memTargetWrite+  -- > unOff memTargetOff < unCount targetCount+  -> Count e+  -- ^ /memCount/ - Number of elements of type @e@ to copy+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memCount+  --+  -- Both source and target memory regions must have enough memory to perform a copy+  -- of @memCount@ elements starting at their respective offsets. For @memSourceRead@:+  --+  -- > unOff memSourceOff + unCount memCount < unCount (countMem memSourceRead)+  --+  -- and for @memTargetWrite@ that also implements `MemAlloc` this can be described as:+  --+  -- > targetCount <- getCountMem memTargetWrite+  -- > unOff memTargetOff + unCount memCount < unCount targetCount+  -> m ()+copyMem src srcOff dst dstOff = copyByteOffMem src (toByteOff srcOff) dst (toByteOff dstOff)+{-# INLINE copyMem #-}+++moveMem ::+     (MonadPrim s m, MemWrite mw1, MemWrite mw2, Prim e)+  => mw1 s -- ^ Source memory region+  -> Off e -- ^ Offset into the source in number of elements+  -> mw2 s -- ^ Destination memory region+  -> Off e -- ^ Offset into destination in number of elements+  -> Count e -- ^ Number of elements to copy over+  -> m ()+moveMem src srcOff dst dstOff = moveByteOffMem src (toByteOff srcOff) dst (toByteOff dstOff)+{-# INLINE moveMem #-}+++appendMem ::+     forall mr1 mr2 ma. (MemRead mr1, MemRead mr2, MemAlloc ma)+  => mr1+  -> mr2+  -> FrozenMem ma+appendMem r1 r2 =+  createMemST_ (n1 + n2) $ \mem -> do+    copyMem r1 0 mem 0 n1+    copyMem r2 (coerce n1) mem (coerce n1) n2+  where+    n1 = byteCountMem r1+    n2 = byteCountMem r2+{-# INLINABLE appendMem #-}++concatMem ::+     forall mr ma. (MemRead mr, MemAlloc ma)+  => [mr]+  -> FrozenMem ma+concatMem xs = do+  let c = Foldable.foldl' (\ !acc b -> acc + byteCountMem b) 0 xs+  createMemST_ c $ \mb -> do+    let load i b = do+          let cb@(Count n) = byteCountMem b :: Count Word8+          (i + Off n) <$ copyMem b 0 mb i cb+    foldM_ load 0 xs+{-# INLINABLE concatMem #-}+++thawCopyMem ::+     forall e mr ma m s. (Prim e, MemRead mr, MemAlloc ma, MonadPrim s m)+  => mr+  -> Off e+  -> Count e+  -> m (ma s)+thawCopyMem a off c = do+  mem <- allocMem c+  mem <$ copyMem a off mem 0 c+{-# INLINE thawCopyMem #-}++freezeCopyMem ::+     forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m)+  => ma s+  -> Off e+  -> Count e+  -> m (FrozenMem ma)+freezeCopyMem mem off c = freezeMem mem >>= \r -> thawCopyMem r off c >>= freezeMem+{-# INLINE freezeCopyMem #-}+++thawCloneMem ::+     forall mr ma m s. (MemRead mr, MemAlloc ma, MonadPrim s m)+  => mr+  -> m (ma s)+thawCloneMem a = thawCopyMem a 0 (byteCountMem a)+{-# INLINE thawCloneMem #-}++freezeCloneMem ::+     forall ma m s. (MemAlloc ma, MonadPrim s m)+  => ma s+  -> m (FrozenMem ma)+freezeCloneMem = freezeMem >=> thawCloneMem >=> freezeMem+{-# INLINE freezeCloneMem #-}++-- | /O(n)/ - Convert a read-only memory region into a newly allocated other type of+-- memory region+--+-- >>> import Data.ByteString (pack)+-- >>> bs = pack [0x10 .. 0x20]+-- >>> bs+-- "\DLE\DC1\DC2\DC3\DC4\NAK\SYN\ETB\CAN\EM\SUB\ESC\FS\GS\RS\US "+-- >>> convertMem bs :: Bytes 'Inc+-- [0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20]+--+-- @since 0.1.0+convertMem :: (MemRead mr, MemAlloc ma) => mr -> FrozenMem ma+convertMem a = runST $ thawCloneMem a >>= freezeMem+{-# INLINE convertMem #-}++-- | Figure out how many elements fits into the immutable region of memory. It is+-- possible that there is a remainder of bytes left, see `countRemMem` for getting that+-- too.+--+-- ====__Examples__+--+-- >>> b = fromListMem [0 .. 5 :: Word8] :: Bytes 'Pin+-- >>> b+-- [0x00,0x01,0x02,0x03,0x04,0x05]+-- >>> countMem b :: Count Word16+-- Count {unCount = 3}+-- >>> countMem b :: Count Word32+-- Count {unCount = 1}+--+-- @since 0.1.0+countMem ::+     forall e mr. (MemRead mr, Prim e)+  => mr+  -> Count e+countMem = fromByteCount . byteCountMem+{-# INLINE countMem #-}++-- | Compute how many elements and a byte size remainder that can fit into the region of memory.+--+-- ====__Examples__+--+-- >>> b = fromListMem [0 .. 5 :: Word8] :: Bytes 'Pin+-- >>> b+-- [0x00,0x01,0x02,0x03,0x04,0x05]+-- >>> countRemMem @Word16 b+-- (Count {unCount = 3},Count {unCount = 0})+-- >>> countRemMem @Word32 b+-- (Count {unCount = 1},Count {unCount = 2})+--+-- @since 0.1.0+countRemMem :: forall e mr. (MemRead mr, Prim e) => mr -> (Count e, Count Word8)+countRemMem = fromByteCountRem . byteCountMem+{-# INLINE countRemMem #-}++getCountMem :: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) => ma s -> m (Count e)+getCountMem = fmap (fromByteCount . coerce) . getByteCountMem+{-# INLINE getCountMem #-}+++getCountRemMem ::+     forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e)+  => ma s+  -> m (Count e, Count Word8)+getCountRemMem = fmap (fromByteCountRem . coerce) . getByteCountMem+{-# INLINE getCountRemMem #-}+++clone ::+     forall ma m s. (MemAlloc ma, MonadPrim s m)+  => ma s+  -> m (ma s)+clone mb = do+  n <- getByteCountMem mb+  mb' <- allocMem n+  mb' <$ moveMem mb 0 mb' 0 n+{-# INLINE clone #-}++-- | Compare two memory regions byte-by-byte. `False` is returned immediately when sizes+-- reported by `byteCountMem` do not match. Computation may be short-circuited on the+-- first mismatch, but it is `MemRead` implementation specific.+--+-- @since 0.1.0+eqMem :: (MemRead mr1, MemRead mr2) => mr1 -> mr2 -> Bool+eqMem b1 b2 = n == byteCountMem b2 && compareByteOffMem b1 0 b2 0 n == EQ+  where+    n = byteCountMem b1+{-# INLINE eqMem #-}++-- | Compare two regions of memory byte-by-byte. It will return `EQ` whenever both regions+-- are exactly the same and `LT` or `GT` as soon as the first byte is reached that is less+-- than or greater than respectfully in the first region when compared to the second+-- one. It is safe for both regions to refer to the same part of memory, since this is a+-- pure function and both regions of memory are read-only.+compareMem ::+     forall e mr1 mr2. (MemRead mr1, MemRead mr2, Prim e)+  => mr1 -- ^ First region of memory+  -> Off e -- ^ Offset in number of elements into the first region+  -> mr2 -- ^ Second region of memory+  -> Off e -- ^ Offset in number of elements into the second region+  -> Count e -- ^ Number of elements to compare+  -> Ordering+compareMem r1 off1 r2 off2 = compareByteOffMem r1 (toByteOff off1) r2 (toByteOff off2)+{-# INLINE compareMem #-}++-- =============== --+-- List conversion --+-- =============== --++-------------+-- To List --+-------------++-- | Convert an immutable memory region to a list. Whenever memory byte count is not+-- exactly divisible by the size of the element there will be some slack left unaccounted+-- for. In order to get a hold of this slack use `toListSlackMem` instead.+--+-- ====__Examples__+--+-- >>> import Data.Prim.Memory+-- >>> import Numeric (showHex)+-- >>> let b = fromByteListMem [0x48,0x61,0x73,0x6b,0x65,0x6c,0x6c] :: Bytes 'Inc+-- >>> toListMem b :: [Int8]+-- [72,97,115,107,101,108,108]+-- >>> let xs = toListMem b :: [Word32]+-- >>> xs+-- [1802723656]+-- >>> showHex (head xs) ""+-- "6b736148"+--+-- @since 0.1.0+toListMem :: forall e mr. (MemRead mr, Prim e) => mr -> [e]+toListMem ba = build (\ c n -> foldrCountMem (countMem ba) c n ba)+{-# INLINE toListMem #-}+{-# SPECIALIZE toListMem :: Prim e => Bytes p -> [e] #-}++-- | Same as `toListMem`, except when there is some slack towards the end of the memory+-- region that didn't fit into a list it will be returned as a list of bytes.+--+-- ====__Examples__+--+-- >>> import Data.Word+-- >>> :set -XDataKinds+-- >>> a = fromListMem [0 .. 10 :: Word8] :: Bytes 'Pin+-- >>> a+-- [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a]+-- >>> toListSlackMem a :: ([Word8], [Word8])+-- ([0,1,2,3,4,5,6,7,8,9,10],[])+-- >>> toListSlackMem a :: ([Word16], [Word8])+-- ([256,770,1284,1798,2312],[10])+-- >>> toListSlackMem a :: ([Word32], [Word8])+-- ([50462976,117835012],[8,9,10])+-- >>> toListSlackMem a :: ([Word64], [Word8])+-- ([506097522914230528],[8,9,10])+--+-- @since 0.1.0+toListSlackMem ::+     forall e mr. (MemRead mr, Prim e)+  => mr+  -> ([e], [Word8])+toListSlackMem mem =+  (build (\c n -> foldrCountMem k c n mem), getSlack (k8 + r8) [])+  where+    (k, Count r8) = countRemMem mem+    Count k8 = toByteCount k+    getSlack i !acc+      | i == k8 = acc+      | otherwise =+        let i' = i - 1+         in getSlack i' (indexByteOffMem mem (Off i') : acc)+{-# INLINABLE toListSlackMem #-}++-- | Right fold that is useful for converting to a list while tapping into list fusion.+--+-- [Unsafe] Supplying Count larger than memory holds will result in reading out of bounds+-- and a potential segfault.+--+-- @since 0.1.0+foldrCountMem :: forall e b mr. (MemRead mr, Prim e) => Count e -> (e -> b -> b) -> b -> mr -> b+foldrCountMem (Count k) c nil bs = go 0+  where+    go i+      | i == k = nil+      | otherwise =+        let !v = indexOffMem bs (Off i)+         in v `c` go (i + 1)+{-# INLINE[0] foldrCountMem #-}++---------------+-- From List --+---------------++-- Pure immutable conversion --++-- | Just like `fromListMemN`, except it ensures safety by using the length of the+-- list for allocation. Because it has to figure out the length of the list first it+-- will be just a little bit slower, but that much safer.+--+-- ====__Examples__+--+-- >>> import Data.Prim.Memory+-- >>> :set -XDataKinds+-- >>> fromListMem "Hi" :: Bytes 'Inc+-- [0x48,0x00,0x00,0x00,0x69,0x00,0x00,0x00]+--+-- @since 0.1.0+fromListMem ::+     forall e ma. (Prim e, MemAlloc ma)+  => [e]+  -> FrozenMem ma+fromListMem xs =+  let count = coerce (length xs) `countForProxyTypeOf` xs+   in createMemST_ count (loadListMemN_ count xs)+{-# INLINE fromListMem #-}+++-- | Same as `fromListMem` but restricted to a list of `Word8`. Load a list of bytes into+-- a newly allocated memory region. Equivalent to `Data.ByteString.pack` for+-- `Data.ByteString.ByteString`+--+-- ====__Examples__+--+-- >>> fromByteListMem [0..10] :: Bytes 'Pin+-- [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a]+--+-- @since 0.1.0+fromByteListMem ::+     forall ma. MemAlloc ma+  => [Word8]+  -> FrozenMem ma+fromByteListMem = fromListMem+{-# INLINE fromByteListMem #-}+++-- | Similarly to `fromListMem` load a list into a newly allocated memory region, but+-- unlike the aforementioned function it also accepts a hint of how many elements is+-- expected to be in the list. Because the number of expected an actual elements might+-- not match we return not only the frozen memory region, but also:+--+-- * either a list with leftover elements from the input @list@, if it did not fully fit+--   into the allocated region. An empty list would indicate that it did fit exactly.+--+--     @+--     unCount memCount <= length list+--     @+--+-- * or an exact count of how many elements have been loaded when there was no+--   enough elements in the list+--+--+-- In the latter case a zero value would indicate that the list did fit into the newly+-- allocated memory region exactly, which is perfectly fine. But a positive value would+-- mean that the tail of the memory region is still unset and might contain garbage+-- data. Make sure to overwrite the surplus memory yourself or use the safe version+-- `fromListZeroMemN` that fills the surplus with zeros.+--+-- [Unsafe] Whenever @memCount@ precodition is violated, because on each call with the+-- same input it can produce different output therefore it will break referential+-- transparency.+--+-- ====__Examples__+--+-- >>> :set -XTypeApplications+-- >>> fromListMemN @Char @(MBytes 'Inc) 3 "Hello"+-- (Left "lo",[0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00])+-- >>> fromListMemN @Char @(MBytes 'Inc) 2 "Hi"+-- (Left "",[0x48,0x00,0x00,0x00,0x69,0x00,0x00,0x00])+-- >>> fst $ fromListMemN @Char @(MBytes 'Inc) 5 "Hi"+-- Right (Count {unCount = 2})+--+-- @since 0.2.0+fromListMemN ::+     forall e ma. (Prim e, MemAlloc ma)+  => Count e+  -- ^ /memCount/ - Expected number of elements in the list, which exactly how much+  -- memory will be allocated.+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memCount+  -- > unCount memCount <= length list+  -> [e]+  -- ^ /list/ - A list of elements to load into the newly allocated memory region.+  -> (Either [e] (Count e), FrozenMem ma)+fromListMemN count xs =+  createMemST count $ \mm -> do+    (ys, loadedCount) <- loadListOffMemN count xs mm 0+    pure $+      if loadedCount /= count && null ys+        then Right loadedCount+        else Left ys+{-# INLINE fromListMemN #-}+++-- | Just like `fromListMemN`, except it ensures safety by filling tail with zeros,+-- whenever the list is not long enough.+--+-- ====__Examples__+--+-- >>> import Data.Prim.Memory+-- >>> :set -XTypeApplications+-- >>> fromListZeroMemN @Char @(MBytes 'Inc) 3 "Hi"+-- (Right (Count {unCount = 2}),[0x48,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00])+--+-- @since 0.2.0+fromListZeroMemN ::+     forall e ma. (Prim e, MemAlloc ma)+  => Count e -- ^ /memCount/ - Number of elements to load from the list.+  -> [e]+  -> (Either [e] (Count e), FrozenMem ma)+fromListZeroMemN count xs =+  createMemST (max 0 count) $ \mm -> do+    (ys, loadedCount) <- loadListOffMemN count xs mm 0+    let loadedByteCount = toByteCount loadedCount+        surplusByteCount = toByteCount count - loadedByteCount+    when (surplusByteCount > 0) $ setMem mm (countToOff loadedByteCount) surplusByteCount 0+    pure $+      if loadedCount /= count && null ys+        then Right loadedCount+        else Left ys+{-# INLINE fromListZeroMemN #-}++-- | Same as `fromListZeroMemN`, but ignore the extra information about how the loading went.+--+-- ====__Examples__+--+-- >>> import Data.Prim.Memory+-- >>> fromListZeroMemN_ 3 "Hi" :: Bytes 'Inc+-- [0x48,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00]+--+-- @since 0.2.0+fromListZeroMemN_ ::+     forall e ma. (Prim e, MemAlloc ma)+  => Count e+  -> [e]+  -> FrozenMem ma+fromListZeroMemN_ !n = snd . fromListZeroMemN n+{-# INLINE fromListZeroMemN_ #-}++++-- Mutable loading --+++loadListByteOffHelper ::+     (MemWrite mw, MonadPrim s m, Prim e)+  => [e]+  -> mw s+  -> Off Word8 -- ^ Offset+  -> Off Word8 -- ^ Upper bound+  -> Off Word8 -- ^ Element size+  -> m ([e], Count e)+loadListByteOffHelper ys mw byteOff k step =+  let go []       i = pure ([], toLoadedCount i)+      go a@(x:xs) i+        | i < k = writeByteOffMem mw i x >> go xs (i + step)+        | otherwise = pure (a, toLoadedCount i)+      toLoadedCount i = fromByteCount (offToCount (i - byteOff))+   in go ys byteOff+{-# INLINE loadListByteOffHelper #-}+++-- | Load elements from the supplied list into a mutable memory region. Loading will+-- start at the supplied offset in number of bytes and will stop when either supplied+-- @elemCount@ number is reached or there are no more elements left in the list to+-- load. This action returns a list of elements that did not get loaded and the count of+-- how many elements did get loaded.+--+-- [Unsafe] When any precondition for either the offset @memTargetOff@ or the element+-- count @memCount@ is violated then a call to this function can result in heap corruption+-- or failure with a segfault.+--+-- ====__Examples__+--+-- For example load the @"Hell"@ somewhere in the middle of `MBytes`:+--+-- >>> ma <- allocZeroMem (6 :: Count Char) :: IO (MBytes 'Inc RW)+-- >>> loadListByteOffMemN 4 "Hello!" ma (toByteOff (1 :: Off Char))+-- ("o!",Count {unCount = 4})+-- >>> freezeMem ma+-- [0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00]+--+-- Or something more usful like loading prefixes from nested lists:+--+-- >>> import Control.Monad+-- >>> foldM_ (\o xs -> (+ o) . countToByteOff . snd <$> loadListByteOffMemN 4 xs ma o) 2 [[x..] | x <- [1..5] :: [Word8]]+-- >>> freezeMem ma+-- [0x00,0x00,0x01,0x02,0x03,0x04,0x02,0x03,0x04,0x05,0x03,0x04,0x05,0x06,0x04,0x05,0x06,0x07,0x05,0x06,0x07,0x08,0x00,0x00]+--+-- @since 0.2.0+loadListByteOffMemN ::+     (MemWrite mw, MonadPrim s m, Prim e)+  => Count e+  -- ^ /elemCount/ - Maximum number of elements to load from list into the memory region+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memCount+  --+  -- Target memory region must have enough memory to perform loading of @elemCount@+  -- elements starting at the @memTargetOff@ offset. For types that also implement+  -- `MemAlloc` this can be described as:+  --+  -- > targetByteCount <- getByteCountMem memTarget+  -- > unOff memTargetOff + unCountBytes elemCount <= unCount (targetByteCount - byteCountType @e)+  -> [e] -- ^ /listSource/ - List with elements that should be loaded+  -> mw s -- ^ /memTarget/ - Memory region where to load the elements into+  -> Off Word8+  -- ^ /memTargetOff/ - Offset in number of bytes into target memory where writing will start+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memTargetOff+  --+  -- Once the pointer is advanced by @memTargetOff@ it must still refer to the same memory+  -- region @memTarget@. For types that also implement `MemAlloc` this can be described+  -- as:+  --+  -- > targetByteCount <- getByteCountMem memTarget+  -- > unOff memTargetOff <= unCount (targetByteCount - byteCountType @e)+  -> m ([e], Count e)+  -- ^ Leftover part of the @listSource@ if any and the exact count of elements that have been loaded.+loadListByteOffMemN count ys mw byteOff = loadListByteOffHelper ys mw byteOff k step+  where+    k = byteOff + countToOff (toByteCount count)+    step = countToOff $ byteCountProxy ys+{-# INLINABLE loadListByteOffMemN #-}++-- | Same as `loadListByteOffMemN`, but infer the count from number of bytes that is+-- available in the target memory region.+--+-- [Unsafe] When a precondition for the element count @memCount@ is violated then a call+-- to this function can result in heap corruption or failure with a segfault.+--+-- ====__Examples__+--+-- >>> :set -XDataKinds+-- >>> import Data.Prim.Memory+-- >>> ma <- allocZeroMem (5 :: Count Char) :: IO (MBytes 'Inc RW)+-- >>> freezeMem ma+-- [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]+-- >>> loadListByteOffMem "Hello World" ma 0+-- (" World",Count {unCount = 5})+-- >>> freezeMem ma+-- [0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]+-- >>> loadListByteOffMem ([0xff,0xff,0xff] :: [Word8]) ma 1+-- ([],Count {unCount = 3})+-- >>> freezeMem ma+-- [0x48,0xff,0xff,0xff,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]+--+-- @since 0.2.0+loadListByteOffMem ::+     (MemAlloc ma, MonadPrim s m, Prim e)+  => [e] -- ^ /listSource/ - List with elements that should be loaded+  -> ma s -- ^ /memTarget/ - Memory region where to load the elements into+  -> Off Word8+  -- ^ /memTargetOff/ - Offset in number of bytes into target memory where writing will start+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memTargetOff+  --+  -- Once the pointer is advanced by @memTargetOff@ it must still refer to the same memory+  -- region @memTarget@. For types that also implement `MemAlloc` this can be described+  -- as:+  --+  -- > targetByteCount <- getByteCountMem memTarget+  -- > unOff memTargetOff <= unCount (targetByteCount - byteCountType @e)+  -> m ([e], Count e)+  -- ^ Leftover part of the @listSource@ if any and the exact count of elements that have been loaded.+loadListByteOffMem ys ma byteOff = do+  bCount <- getByteCountMem ma+  let k = countToOff bCount - byteOff+      step = countToOff $ byteCountProxy ys+  loadListByteOffHelper ys ma byteOff k step+{-# INLINABLE loadListByteOffMem #-}++-- | Same as `loadListByteOffMemN`, but works with offset in number of elements instead of+-- bytes.+--+-- [Unsafe] When preconditions for either the offset @memTargetOff@ or the element count+-- @memCount@ is violated then a call to this function can result in heap corruption or+-- failure with a segfault.+--+-- @since 0.2.0+loadListOffMemN ::+     (MemWrite mw, MonadPrim s m, Prim e)+  => Count e+  -- ^ /elemCount/ - Maximum number of elements to load from list into the memory region+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memCount+  --+  -- Target memory region must have enough memory to perform loading of @elemCount@+  -- elements starting at the @memTargetOff@ offset. For types that also implement+  -- `MemAlloc` this can be described as:+  --+  -- > targetCount <- getCountMem memTarget+  -- > unOff memTargetOff + unCount elemCount < unCount targetCount+  -> [e] -- ^ /listSource/ - List with elements that should be loaded+  -> mw s -- ^ /memTarget/ - Memory region where to load the elements into+  -> Off e+  -- ^ /memTargetOff/ - Offset in number of elements into target memory where writing will start+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memTargetOff+  --+  -- Once the pointer is advanced by @memTargetOff@ it must still refer to the same memory+  -- region @memTarget@. For types that also implement `MemAlloc` this can be described+  -- as:+  --+  -- > targetCount <- getByteCountMem memTarget+  -- > unOff memTargetOff < unCount targetCount+  -> m ([e], Count e)+  -- ^ Leftover part of the @listSource@ if any and the exact count of elements that have been loaded.+loadListOffMemN count ys mw off =+  let go []       i = pure ([], toLoadedCount i)+      go a@(x:xs) i+        | i < k = writeOffMem mw i x >> go xs (i + 1)+        | otherwise = pure (a, toLoadedCount i)+      k = off + countToOff count+      toLoadedCount i = offToCount (i - off)+  in go ys off+{-# INLINABLE loadListOffMemN #-}+++-- | Same as `loadListOffMemN`, but start loading at @0@ offset.+--+-- [Unsafe] When any precondition for the element count @memCount@ is violated then a call to+-- this function can result in heap corruption or failure with a segfault.+--+-- @since 0.2.0+loadListMemN ::+     forall e mw m s. (MemWrite mw, MonadPrim s m, Prim e)+  => Count e+  -- ^ /elemCount/ - Maximum number of elements to load from list into the memory region+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memCount+  --+  -- Target memory region must have enough memory to perform loading of @elemCount@+  -- elements. For types that also implement `MemAlloc` this can be described as:+  --+  -- > targetCount <- getCountMem memTarget+  -- > elemCount <= targetCount+  -> [e] -- ^ /listSource/ - List with elements that should be loaded+  -> mw s -- ^ /memTarget/ - Memory region where to load the elements into+  -> m ([e], Count e)+  -- ^ Leftover part of the @listSource@ if any and the exact count of elements that have been loaded.+loadListMemN count xs mw = loadListOffMemN count xs mw 0+{-# INLINABLE loadListMemN #-}++++-- | Same as `loadListMemN`, but ignores the result.+--+-- [Unsafe] When any precondition for the element count @memCount@ is violated then a call+-- to this function can result in heap corruption or failure with a segfault.+--+-- @since 0.2.0+loadListMemN_ ::+     forall e mw m s. (Prim e, MemWrite mw, MonadPrim s m)+  => Count e+  -- ^ /elemCount/ - Maximum number of elements to load from list into the memory region+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memCount+  --+  -- Target memory region must have enough memory to perform loading of @elemCount@+  -- elements. For types that also implement `MemAlloc` this can be described as:+  --+  -- > targetCount <- getCountMem memTarget+  -- > elemCount <= targetCount+  -> [e] -- ^ /listSource/ - List with elements that should be loaded+  -> mw s -- ^ /memTarget/ - Memory region where to load the elements into+  -> m ()+loadListMemN_ (Count n) ys mb =+  let go []     _ = pure ()+      go (x:xs) i = when (i < n) $ writeOffMem mb (Off i) x >> go xs (i + 1)+   in go ys 0+{-# INLINABLE loadListMemN_ #-}+++++-- | Same as `loadListOffMemN`, but infer the count from number of bytes that is available+-- in the target memory region.+--+-- [Unsafe] When a precondition for the element count @memCount@ is violated then a call+-- to this function can result in heap corruption or failure with a segfault.+--+-- @since 0.2.0+loadListOffMem ::+     forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m)+  => [e] -- ^ /listSource/ - List with elements that should be loaded+  -> ma s -- ^ /memTarget/ - Memory region where to load the elements into+  -> Off e+  -- ^ /memTargetOff/ - Offset in number of elements into target memory where writing will+  -- start+  --+  -- /__Preconditions:__/+  --+  -- > 0 <= memTargetOff+  --+  -- Once the pointer is advanced by @memTargetOff@ it must still refer to the same memory+  -- region @memTarget@. For types that also implement `MemAlloc` this can be described+  -- as:+  --+  -- > targetCount <- getCountMem memTarget+  -- > unOff memTargetOff < unCount targetCount+  -> m ([e], Count e)+  -- ^ Leftover part of the @listSource@ if any and the exact count of elements that have been loaded.+loadListOffMem ys ma off = getCountMem ma >>= \c -> loadListOffMemN (c - offToCount off) ys ma off+{-# INLINE loadListOffMem #-}+++-- | Same as `loadListMemN`, but tries to fit as many elements as possible into the mutable+-- memory region starting at the beginning. This operation is always safe.+--+-- ====__Examples__+--+-- >>> import Data.Prim.Memory+-- >>> ma <- allocMem (5 :: Count Char) :: IO (MBytes 'Inc RW)+-- >>> loadListMem "HelloWorld" ma+-- ("World",Count {unCount = 5})+-- >>> freezeMem ma+-- [0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]+-- >>> loadListMem (replicate 6 (0xff :: Word8)) ma+-- ([],Count {unCount = 6})+-- >>> freezeMem ma+-- [0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]+--+-- @since 0.2.0+loadListMem ::+     forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m)+  => [e] -- ^ /listSource/ - List with elements to load+  -> ma s -- ^ /memTarget/ - Mutable region where to load elements from the list+  -> m ([e], Count e)+  -- ^ Leftover part of the @listSource@ if any and the exact count of elements that have been loaded.+loadListMem ys ma = getCountMem ma >>= \c -> loadListOffMemN (c `countForProxyTypeOf` ys) ys ma 0+{-# INLINE loadListMem #-}++-- | Same as `loadListMem`, but ignores the result. Equivalence as property:+--+-- prop> let c = fromInteger (abs i) :: Count Int in (createZeroMemST_ c (loadListMem_ (xs :: [Int])) :: Bytes 'Inc) == createZeroMemST_ c (void . loadListMem xs)+--+-- @since 0.2.0+loadListMem_ ::+     forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m)+  => [e] -- ^ /listSource/ - List with elements to load+  -> ma s -- ^ /memTarget/ - Mutable region where to load elements from the list+  -> m ()+loadListMem_ ys mb = getCountMem mb >>= \c -> loadListMemN_ (c `countForProxyTypeOf` ys) ys mb+{-# INLINE loadListMem_ #-}+++-- | Convert a memory region to a list of bytes. Equivalent to `Data.ByteString.unpack`+-- for `Data.ByteString.ByteString`+--+-- ====__Example__+--+-- >>> toByteListMem (fromByteListMem [0..10] :: Bytes 'Pin)+-- [0,1,2,3,4,5,6,7,8,9,10]+--+-- @since 0.1.0+toByteListMem ::+     forall ma. MemAlloc ma+  => FrozenMem ma+  -> [Word8]+toByteListMem = toListMem+{-# INLINE toByteListMem #-}++-- mapMem ::+--      forall e e' mr ma. (MemRead mr, MemAlloc ma, Prim e, Prim e')+--   => (e -> e')+--   -> mr+--   -> (FrozenMem ma, [Word8])+-- mapMem f = undefined+++mapByteMem ::+     forall e mr ma. (MemRead mr, MemAlloc ma, Prim e)+  => (Word8 -> e)+  -> mr+  -> FrozenMem ma+mapByteMem f = imapByteOffMem (const f)++-- Map an index aware function over memory region+--+-- >>> import Data.Prim.Memory+-- >>> a = fromListMem [1 .. 10 :: Word8] :: Bytes 'Inc+-- >>> a+-- [0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a]+-- >>> imapByteOffMem (\i e -> (fromIntegral i :: Int8, e + 0xf0)) a :: Bytes 'Pin+-- [0x00,0xf1,0x01,0xf2,0x02,0xf3,0x03,0xf4,0x04,0xf5,0x05,0xf6,0x06,0xf7,0x07,0xf8,0x08,0xf9,0x09,0xfa]+--+-- @since 0.1.0+imapByteOffMem ::+     (MemRead mr, MemAlloc ma, Prim e) => (Off Word8 -> Word8 -> e) -> mr -> FrozenMem ma+imapByteOffMem f r = runST $ mapByteOffMemM (\i -> pure . f i) r++-- @since 0.1.0+mapByteMemM ::+     (MemRead mr, MemAlloc ma, MonadPrim s m, Prim e)+  => (Word8 -> m e)+  -> mr+  -> m (FrozenMem ma)+mapByteMemM f = mapByteOffMemM (const f)+++-- @since 0.1.0+mapByteOffMemM ::+     forall e mr ma m s. (MemRead mr, MemAlloc ma, MonadPrim s m, Prim e)+  => (Off Word8 -> Word8 -> m e)+  -> mr+  -> m (FrozenMem ma)+mapByteOffMemM f r = do+  let bc@(Count n) = byteCountMem r+      c = Count n `countForProxyTypeOf` f 0 0+  mem <- allocMem c+  _ <- forByteOffMemM_ r 0 bc f+  -- let go i =+  --       when (i < n) $ do+  --         f i (indexByteOffMem r (Off i)) >>=+  --           writeOffMem mem (offAsProxy c (Off i))+  --         go (i + 1)+  -- go 0+  freezeMem mem+++-- | Iterate over a region of memory+forByteOffMemM_ ::+     (MemRead mr, MonadPrim s m, Prim e)+  => mr+  -> Off Word8+  -> Count e+  -> (Off Word8 -> e -> m b)+  -> m (Off Word8)+forByteOffMemM_ r (Off byteOff) c f =+  let n = coerce (toByteCount c) + byteOff+      Count k = byteCountProxy c+      go i+        | i < n = f (Off i) (indexByteOffMem r (Off i)) >> go (i + k)+        | otherwise = pure $ Off i+   in go byteOff++loopShortM :: Monad m => Int -> (Int -> a -> Bool) -> (Int -> Int) -> a -> (Int -> a -> m a) -> m a+loopShortM !startAt condition increment !initAcc f = go startAt initAcc+  where+    go !step !acc+      | condition step acc = f step acc >>= go (increment step)+      | otherwise = pure acc+{-# INLINE loopShortM #-}++loopShortM' :: Monad m => Int -> (Int -> a -> m Bool) -> (Int -> Int) -> a -> (Int -> a -> m a) -> m a+loopShortM' !startAt condition increment !initAcc f = go startAt initAcc+  where+    go !step !acc =+      condition step acc >>= \cont ->+        if cont+          then f step acc >>= go (increment step)+          else pure acc+{-# INLINE loopShortM' #-}++-- -- | Iterate over a region of memory+-- loopMemM_ ::+--      (MemRead mr, MonadPrim s m, Prim e)+--   => r+--   -> Off Word8+--   -> Count e+--   -> (Count Word8 -> a -> Bool)+--   -> (Off Word8 -> e -> m b)+--   -> m (Off Word8)+-- foldlByteOffMemM_ r (Off byteOff) c f =+--   loopShortM byteOff (\i -> f (coerce i))+--   let n = coerce (toByteCount c) + byteOff+--       Count k = byteCountProxy c+--       go i+--         | i < n = f (Off i) (indexByteOffMem r (Off i)) >> go (i + k)+--         | otherwise = pure $ Off i+--    in go byteOff+++data MemView a = MemView+  { mvOffset :: {-# UNPACK #-} !(Off Word8)+  , mvCount  :: {-# UNPACK #-} !(Count Word8)+  , mvMem    :: !a+  }++data MMemView a s = MMemView+  { mmvOffset :: {-# UNPACK #-} !(Off Word8)+  , mmvCount  :: {-# UNPACK #-} !(Count Word8)+  , mmvMem    :: !(a s)+  }++izipWithByteOffMemM_ ::+     (MemRead mr1, MemRead mr2, MonadPrim s m, Prim e)+  => mr1+  -> Off Word8+  -> mr2+  -> Off Word8+  -> Count e+  -> (Off Word8 -> e -> Off Word8 -> e -> m b)+  -> m (Off Word8)+izipWithByteOffMemM_ r1 (Off byteOff1) r2 off2 c f =+  let n = coerce (toByteCount c) + byteOff1+      Count k = byteCountProxy c+      go i+        | i < n =+          let o1 = Off i+              o2 = Off i + off2+           in f o1 (indexByteOffMem r1 o1) o2 (indexByteOffMem r2 o2) >>+              go (i + k)+        | otherwise = pure $ Off i+   in go byteOff1+++izipWithOffMemM_ ::+     (MemRead mr1, MemRead mr2, MonadPrim s m, Prim e1, Prim e2)+  => mr1+  -> Off e1+  -> mr2+  -> Off e2+  -> Int+  -> (Off e1 -> e1 -> Off e2 -> e2 -> m b)+  -> m ()+izipWithOffMemM_ r1 off1 r2 off2 nc f =+  let n = nc + coerce off1+      go o1@(Off i) o2 =+        when (i < n) $+        f o1 (indexOffMem r1 o1) o2 (indexOffMem r2 o2) >> go (o1 + 1) (o2 + 1)+   in go off1 off2+++-- class Mut f => MFunctor f where+--   mmap :: (Elt f a, Elt f b, MonadPrim s m) => (a -> b) -> f a s -> m (f b s)++-- class Mut f => MTraverse f where+--   mmapM :: (Elt f a, Elt f b, MonadPrim s m) => (a -> m b) -> f a s -> m (f b s)++-- class MFunctor f => MApplicative f where+--   pureMut :: (Elt f a, MonadPrim s m) => a -> m (f a s)+--   liftMut ::+--     (Elt f a, Elt f b, Elt f c, MonadPrim s m) => (a -> b -> m c) -> f a s -> f b s -> m (f c s)++-- class MApplicative f => MMonad f where+--   bindMut ::+--     (Elt f a, Elt f b, MonadPrim s m) => f a s -> (a -> m b) -> f b s -> m (f c s)++-- instance MFunctor MAddr where+--   mmap f maddr = do+--     Count n <- getCountMAddr maddr+--     maddr' <- allocMAddr (Count n)+--     let go i =+--           when (i < n) $ do+--             writeOffMAddr maddr' (Off i) . f =<< readOffMAddr maddr (Off i)+--             go (i + 1)+--     maddr' <$ go 0++-- instance MTraverse MAddr where+--   mmapM f maddr = do+--     Count n <- getCountMAddr maddr+--     maddr' <- allocMAddr (Count n)+--     let go i =+--           when (i < n) $ do+--             writeOffMAddr maddr' (Off i) =<< f =<< readOffMAddr maddr (Off i)+--             go (i + 1)+--     maddr' <$ go 0+++---------------------+-- Bytes instances --+---------------------++instance MemRead (Bytes p) where+  byteCountMem = byteCountBytes+  {-# INLINE byteCountMem #-}+  indexOffMem = indexOffBytes+  {-# INLINE indexOffMem #-}+  indexByteOffMem = indexByteOffBytes+  {-# INLINE indexByteOffMem #-}+  copyByteOffToMBytesMem = copyByteOffBytesToMBytes+  {-# INLINE copyByteOffToMBytesMem #-}+  copyByteOffToPtrMem = copyByteOffBytesToPtr+  {-# INLINE copyByteOffToPtrMem #-}+  compareByteOffToPtrMem bytes1 off1 ptr2 off2 c =+    pure $! compareByteOffBytesToPtr bytes1 off1 ptr2 off2 c+  {-# INLINE compareByteOffToPtrMem #-}+  compareByteOffToBytesMem bytes1 off1 bytes2 off2 c =+    compareByteOffBytes bytes1 off1 bytes2 off2 c+  {-# INLINE compareByteOffToBytesMem #-}+  compareByteOffMem mem1 off1 bs off2 c =+    compareByteOffToBytesMem mem1 off1 bs off2 c+  {-# INLINE compareByteOffMem #-}++instance Typeable p => MemAlloc (MBytes p) where+  type FrozenMem (MBytes p) = Bytes p+  getByteCountMem = getByteCountMBytes+  {-# INLINE getByteCountMem #-}+  allocMem = allocMBytes+  {-# INLINE allocMem #-}+  thawMem = thawBytes+  {-# INLINE thawMem #-}+  freezeMem = freezeMBytes+  {-# INLINE freezeMem #-}+  resizeMem = reallocMBytes+  {-# INLINE resizeMem #-}++instance MemWrite (MBytes p) where+  readOffMem = readOffMBytes+  {-# INLINE readOffMem #-}+  readByteOffMem = readByteOffMBytes+  {-# INLINE readByteOffMem #-}+  writeOffMem = writeOffMBytes+  {-# INLINE writeOffMem #-}+  writeByteOffMem = writeByteOffMBytes+  {-# INLINE writeByteOffMem #-}+  moveByteOffToPtrMem = moveByteOffMBytesToPtr+  {-# INLINE moveByteOffToPtrMem #-}+  moveByteOffToMBytesMem = moveByteOffMBytesToMBytes+  {-# INLINE moveByteOffToMBytesMem #-}+  moveByteOffMem = moveByteOffToMBytesMem+  {-# INLINE moveByteOffMem #-}+  copyByteOffMem = copyByteOffToMBytesMem+  {-# INLINE copyByteOffMem #-}+  setMem = setMBytes+  {-# INLINE setMem #-}+++instance Show (Bytes p) where+  show b =+    Foldable.foldr' ($) "]" $+    ('[' :) : List.intersperse (',' :) (map (("0x" ++) .) (showsHexMem b))++instance Typeable p => IsList (Bytes p) where+  type Item (Bytes p) = Word8+  fromList = fromListMem+  {-# INLINE fromList #-}+  fromListN n = fromListZeroMemN_ (Count n)+  {-# INLINE fromListN #-}+  toList = toListMem+  {-# INLINE toList #-}++instance Eq (Bytes p) where+  b1 == b2 = isSameBytes b1 b2 || eqMem b1 b2+  {-# INLINE (==) #-}++instance Ord (Bytes p) where+  compare b1 b2 =+    compare n (byteCountBytes b2) <> compareByteOffBytes b1 0 b2 0 n+    where+      n = byteCountBytes b1+  {-# INLINE compare #-}++instance Typeable p => Semigroup.Semigroup (Bytes p) where+  (<>) = appendMem+  {-# INLINE (<>) #-}+  sconcat (x :| xs) = concatMem (x:xs)+  {-# INLINE sconcat #-}+  stimes i = cycleMemN (fromIntegral i)+  {-# INLINE stimes #-}++instance Typeable p => Monoid.Monoid (Bytes p) where+  mappend = appendMem+  {-# INLINE mappend #-}+  mconcat = concatMem+  {-# INLINE mconcat #-}+  mempty = emptyMem+  {-# INLINE mempty #-}+++-- | A list of `ShowS` which covert bytes to base16 encoded strings. Each element of the list+-- is a function that will convert one byte.+--+-- ====__Example__+--+-- >>> :set -XDataKinds+-- >>> import Data.Prim.Memory+-- >>> concatMap ($ " ") $ showsHexMem (fromListMem [1 :: Int16 .. 15] :: Bytes 'Inc)+-- "01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0a 00 0b 00 0c 00 0d 00 0e 00 0f 00 "+--+-- @since 0.1.0+showsHexMem :: MemRead mr => mr -> [ShowS]+showsHexMem b = map toHex (toListMem b :: [Word8])+  where+    toHex b8 =+      (if b8 <= 0x0f+         then ('0' :)+         else id) .+      showHex b8++-- | Ensure that memory is filled with zeros before and after it gets used. `PtrAccess` is+-- not used directly, but istead is used to guarantee that the memory is pinned and its+-- contents do get moved around by the garbage collector.+--+-- @since 0.2.0+withScrubbedMem ::+     forall e ma m a.+     (MonadUnliftPrim RW m, Prim e, MemAlloc ma, PtrAccess RW (ma RW))+  => Count e+  -> (ma RW -> m a)+  -> m a+withScrubbedMem c f = do+  mem <- allocZeroMem c+  let _fptr = toForeignPtr mem :: IO (ForeignPtr e) -- Force the `PtrAccess` constraint.+  f mem `finallyPrim` setMem mem 0 (toByteCount c) 0+  where+    finallyPrim m1 m2 = withRunInPrimBase $ \run -> finally (run m1) (run m2)+{-# INLINE withScrubbedMem #-}
+ src/Data/Prim/Memory/PrimArray.hs view
@@ -0,0 +1,310 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+-- |+-- Module      : Data.Prim.Memory.PrimArray+-- Copyright   : (c) Alexey Kuleshevich 2020+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>+-- Stability   : experimental+-- Portability : non-portable+--+module Data.Prim.Memory.PrimArray+  ( PrimArray(..)+  , MPrimArray(..)+  , Pinned(..)+  , fromBytesPrimArray+  , toBytesPrimArray+  , castPrimArray+  , fromMBytesMPrimArray+  , toMBytesMPrimArray+  , castMPrimArray+  , allocMPrimArray+  , allocPinnedMPrimArray+  , allocAlignedMPrimArray+  , allocUnpinnedMPrimArray+  , shrinkMPrimArray+  , resizeMPrimArray+  , reallocMPrimArray+  , isPinnedPrimArray+  , isPinnedMPrimArray++  , thawPrimArray+  , freezeMPrimArray+  , sizePrimArray+  , getSizeMPrimArray+  , readMPrimArray+  , writeMPrimArray++  , setMPrimArray+  , copyPrimArrayToMPrimArray+  , moveMPrimArrayToMPrimArray+  ) where++import Control.DeepSeq+import Control.Prim.Monad+import Foreign.Prim+import Data.Prim+import Data.Prim.Memory.Bytes+import Data.Prim.Memory.Internal+import Data.Prim.Memory.ForeignPtr+++-- | An immutable array of bytes of type @e@+newtype PrimArray (p :: Pinned) e = PrimArray (Bytes p)+  deriving (NFData, Semigroup, Monoid, MemRead)+type role PrimArray nominal nominal++-- | A mutable array of bytes of type @e@+newtype MPrimArray (p :: Pinned) e s = MPrimArray (MBytes p s)+  deriving (NFData, MemWrite)+type role MPrimArray nominal nominal nominal++-- | Read-only access, but it is not enforced.+instance PtrAccess s (PrimArray 'Pin e) where+  toForeignPtr = pure . toForeignPtrBytes . toBytesPrimArray+  {-# INLINE toForeignPtr #-}+  withPtrAccess b = withPtrBytes (toBytesPrimArray b)+  {-# INLINE withPtrAccess #-}+  withNoHaltPtrAccess b = withNoHaltPtrBytes (toBytesPrimArray b)+  {-# INLINE withNoHaltPtrAccess #-}++instance PtrAccess s (MPrimArray 'Pin e s) where+  toForeignPtr = pure . toForeignPtrMBytes . toMBytesMPrimArray+  {-# INLINE toForeignPtr #-}+  withPtrAccess mb = withPtrMBytes (toMBytesMPrimArray mb)+  {-# INLINE withPtrAccess #-}+  withNoHaltPtrAccess mb = withNoHaltPtrMBytes (toMBytesMPrimArray mb)+  {-# INLINE withNoHaltPtrAccess #-}++instance Typeable p => MemAlloc (MPrimArray p e) where+  type FrozenMem (MPrimArray p e) = PrimArray p e+  getByteCountMem = getByteCountMem . toMBytesMPrimArray+  {-# INLINE getByteCountMem #-}+  allocMem = fmap fromMBytesMPrimArray . allocMBytes+  {-# INLINE allocMem #-}+  thawMem = thawPrimArray+  {-# INLINE thawMem #-}+  freezeMem = freezeMPrimArray+  {-# INLINE freezeMem #-}+  resizeMem mba = fmap fromMBytesMPrimArray . reallocMBytes (toMBytesMPrimArray mba)+  {-# INLINE resizeMem #-}++instance (Typeable p, Prim e) => IsList (PrimArray p e) where+  type Item (PrimArray p e) = e+  fromList = fromListMem+  fromListN n = fromListZeroMemN_ (Count n)+  toList = toListMem++instance Typeable p => IsString (PrimArray p Char) where+  fromString = fromListMem++instance (Show e, Prim e) => Show (PrimArray p e) where+  show = show . toListPrimArray+++toListPrimArray :: Prim e => PrimArray p e -> [e]+toListPrimArray = toListMem++castPrimArray :: PrimArray p e' -> PrimArray p e+castPrimArray = coerce++fromBytesPrimArray :: Bytes p -> PrimArray p e+fromBytesPrimArray = coerce++toBytesPrimArray :: PrimArray p e -> Bytes p+toBytesPrimArray = coerce++castMPrimArray :: MPrimArray p e' s -> MPrimArray p e s+castMPrimArray = coerce++fromMBytesMPrimArray :: MBytes p s -> MPrimArray p e s+fromMBytesMPrimArray = coerce++toMBytesMPrimArray :: MPrimArray p e s -> MBytes p s+toMBytesMPrimArray = coerce++sizePrimArray :: forall e p. Prim e => PrimArray p e -> Size+sizePrimArray = (coerce :: Count e -> Size) . countBytes . toBytesPrimArray+{-# INLINE sizePrimArray #-}++getSizeMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> m Size+getSizeMPrimArray = fmap (coerce :: Count e -> Size) . getCountMBytes . toMBytesMPrimArray+{-# INLINE getSizeMPrimArray #-}++allocMPrimArray ::+     forall e p m s . (Typeable p, Prim e, MonadPrim s m) => Size -> m (MPrimArray p e s)+allocMPrimArray sz = fromMBytesMPrimArray <$> allocMBytes (coerce sz :: Count e)+{-# INLINE allocMPrimArray #-}++allocUnpinnedMPrimArray :: forall e m s . (MonadPrim s m, Prim e) => Size -> m (MPrimArray 'Inc e s)+allocUnpinnedMPrimArray sz = fromMBytesMPrimArray <$> allocUnpinnedMBytes (coerce sz :: Count e)+{-# INLINE allocUnpinnedMPrimArray #-}++allocPinnedMPrimArray :: forall e m s . (MonadPrim s m, Prim e) => Size -> m (MPrimArray 'Pin e s)+allocPinnedMPrimArray sz = fromMBytesMPrimArray <$> allocPinnedMBytes (coerce sz :: Count e)+{-# INLINE allocPinnedMPrimArray #-}++allocAlignedMPrimArray ::+     (MonadPrim s m, Prim e)+  => Count e -- ^ Size in number of bytes+  -> m (MPrimArray 'Pin e s)+allocAlignedMPrimArray = fmap fromMBytesMPrimArray . allocAlignedMBytes+{-# INLINE allocAlignedMPrimArray #-}++freezeMPrimArray :: MonadPrim s m => MPrimArray p e s -> m (PrimArray p e)+freezeMPrimArray = fmap fromBytesPrimArray . freezeMBytes . toMBytesMPrimArray+{-# INLINE freezeMPrimArray #-}++thawPrimArray :: MonadPrim s m => PrimArray p e -> m (MPrimArray p e s)+thawPrimArray = fmap fromMBytesMPrimArray . thawBytes . toBytesPrimArray+{-# INLINE thawPrimArray #-}++-- | Shrink mutable bytes to new specified count of elements. The new count must be less+-- than or equal to the current count as reported by `getCountMPrimArray`.+shrinkMPrimArray ::+     forall e p m s. (MonadPrim s m, Prim e)+  => MPrimArray p e s+  -> Size+  -> m ()+shrinkMPrimArray mba sz = shrinkMBytes (toMBytesMPrimArray mba) (coerce sz :: Count e)+{-# INLINE shrinkMPrimArray #-}+++-- | Attempt to resize mutable bytes in place.+--+-- * New bytes might be allocated, with the copy of an old one.+-- * Old references should not be kept around to allow GC to claim it+-- * Old references should not be used to avoid undefined behavior+resizeMPrimArray ::+     forall e p m s. (MonadPrim s m, Prim e)+  => MPrimArray p e s+  -> Size+  -> m (MPrimArray 'Inc e s)+resizeMPrimArray mba sz =+  fromMBytesMPrimArray <$>+  resizeMBytes (toMBytesMPrimArray mba) (coerce sz :: Count e)+{-# INLINE resizeMPrimArray #-}++reallocMPrimArray ::+     forall e p m s. (MonadPrim s m, Typeable p,  Prim e)+  => MPrimArray p e s+  -> Size+  -> m (MPrimArray p e s)+reallocMPrimArray mba sz =+  fromMBytesMPrimArray <$>+  reallocMBytes (toMBytesMPrimArray mba) (coerce sz :: Count e)+{-# INLINABLE reallocMPrimArray #-}+++isPinnedPrimArray :: PrimArray p e -> Bool+isPinnedPrimArray (PrimArray b) = isPinnedBytes b+{-# INLINE isPinnedPrimArray #-}++isPinnedMPrimArray :: MPrimArray p e s -> Bool+isPinnedMPrimArray (MPrimArray mb) = isPinnedMBytes mb+{-# INLINE isPinnedMPrimArray #-}++readMPrimArray :: (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> m e+readMPrimArray (MPrimArray mb) = readOffMBytes mb . coerce+{-# INLINE readMPrimArray #-}++writeMPrimArray :: (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> e -> m ()+writeMPrimArray (MPrimArray mb) o = writeOffMBytes mb (coerce o)+{-# INLINE writeMPrimArray #-}++++setMPrimArray ::+     forall e p m s. (MonadPrim s m, Prim e)+  => MPrimArray p e s -- ^ Chunk of memory to fill+  -> Int -- ^ Offset in number of elements+  -> Size -- ^ Number of cells to fill+  -> e -- ^ A value to fill the cells with+  -> m ()+setMPrimArray (MPrimArray mb) off sz = setMBytes mb (coerce off) (coerce sz)+{-# INLINE setMPrimArray #-}++copyPrimArrayToMPrimArray ::+     forall e p m s. (MonadPrim s m, Prim e)+  => PrimArray p e+  -> Int+  -> MPrimArray p e s+  -> Int+  -> Size+  -> m ()+copyPrimArrayToMPrimArray ba srcOff mba dstOff sz =+  copyMem ba (coerce srcOff) mba (coerce dstOff) (coerce sz `countForProxyTypeOf` ba)+{-# INLINE copyPrimArrayToMPrimArray #-}++moveMPrimArrayToMPrimArray ::+     forall e p m s. (MonadPrim s m, Prim e)+  => MPrimArray p e s+  -> Int+  -> MPrimArray p e s+  -> Int+  -> Size+  -> m ()+moveMPrimArrayToMPrimArray ba srcOff mba dstOff sz =+  moveMem ba (coerce srcOff) mba (coerce dstOff) (coerce sz :: Count e)+{-# INLINE moveMPrimArrayToMPrimArray #-}++++-- toPtrPrimArray :: PrimArray Pin e -> Ptr e+-- toPtrPrimArray (PrimArray ba#) = Ptr (byteArrayContents# ba#)+-- {-# INLINE toPtrPrimArray #-}++-- toPtrMPrimArray :: MPrimArray Pin e s -> Ptr e+-- toPtrMPrimArray (MPrimArray mba#) = Ptr (mutablePrimArrayContents# mba#)+-- {-# INLINE toPtrMPrimArray #-}++-- -- | Pointer access to immutable `PrimArray` should be for read only purposes, but it is+-- -- not enforced. Any mutation will break referential transparency+-- withPtrPrimArray :: MonadPrim s m => PrimArray Pin e -> (Ptr e -> m b) -> m b+-- withPtrPrimArray b f = do+--   res <- f (toPtrPrimArray b)+--   res <$ touch b+-- {-# INLINE withPtrPrimArray #-}++-- -- | Same as `withPtrPrimArray`, but is suitable for actions that don't terminate+-- withNoHaltPtrPrimArray :: MonadUnliftPrim s m => PrimArray Pin e -> (Ptr e -> m b) -> m b+-- withNoHaltPtrPrimArray b f = withAliveUnliftPrim b $ f (toPtrPrimArray b)+-- {-# INLINE withNoHaltPtrPrimArray #-}++-- withPtrMPrimArray :: MonadPrim s m => MPrimArray Pin e s -> (Ptr e -> m b) -> m b+-- withPtrMPrimArray mb f = do+--   res <- f (toPtrMPrimArray mb)+--   res <$ touch mb+-- {-# INLINE withPtrMPrimArray #-}++-- withNoHaltPtrMPrimArray :: MonadUnliftPrim s m => MPrimArray Pin e s -> (Ptr e -> m b) -> m b+-- withNoHaltPtrMPrimArray mb f = withAliveUnliftPrim mb $ f (toPtrMPrimArray mb)+-- {-# INLINE withNoHaltPtrMPrimArray #-}+++-- -- -- | Check if two byte arrays refer to pinned memory and compare their pointers.+-- -- isSamePrimArray :: PrimArray p1 e -> PrimArray p2 e -> Bool+-- -- isSamePrimArray (PrimArray b1#) (PrimArray b2#) = isTrue# (isSameByteArray# b1# b2#)+-- -- {-# INLINE[0] isSamePrimArray #-}+-- -- {-# RULES+-- -- "isSamePinnedPrimArray" isSamePrimArray = isSamePinnedPrimArray+-- --   #-}++-- -- -- | Perform pointer equality on pinned `PrimArray`.+-- -- isSamePinnedPrimArray :: PrimArray Pin e -> PrimArray Pin e -> Bool+-- -- isSamePinnedPrimArray pb e1 pb2 = toPtrPrimArray pb e1 == toPtrPrimArray pb e2+-- -- {-# INLINE isSamePinnedPrimArray #-}++++-- -- byteStringConvertError :: String -> a+-- -- byteStringConvertError msg = error $ "Cannot convert 'ByteString'. " ++ msg+-- -- {-# NOINLINE byteStringConvertError #-}+
src/Data/Prim/Memory/Ptr.hs view
@@ -55,7 +55,7 @@ copyByteOffPtrToMBytes ::      (MonadPrim s m, Prim e) => Ptr e -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () copyByteOffPtrToMBytes (Ptr srcAddr#) (Off (I# srcOff#)) (MBytes dst#) (Off (I# dstOff#)) c =-  prim_ $ copyAddrToByteArray# (srcAddr# `plusAddr#` srcOff#) dst# dstOff# (fromCount# c)+  prim_ $ copyAddrToByteArray# (srcAddr# `plusAddr#` srcOff#) dst# dstOff# (unCountBytes# c) {-# INLINE copyByteOffPtrToMBytes #-}  @@ -79,7 +79,7 @@     src#     srcOff#     (dstAddr# `plusAddr#` dstOff#)-    (fromCount# c)+    (unCountBytes# c) {-# INLINE copyByteOffBytesToPtr #-}  @@ -103,7 +103,7 @@     src#     srcOff#     (dstAddr# `plusAddr#` dstOff#)-    (fromCount# c)+    (unCountBytes# c) {-# INLINE copyByteOffMBytesToPtr #-}  @@ -122,7 +122,7 @@   -> m () moveByteOffPtrToMBytes (Ptr srcAddr#) (Off (I# srcOff#)) (MBytes dst#) (Off (I# dstOff#)) c =   unsafeIOToPrim $-  memmoveMutableByteArrayFromAddr# srcAddr# srcOff# dst# dstOff# (fromCount# c)+  memmoveMutableByteArrayFromAddr# srcAddr# srcOff# dst# dstOff# (unCountBytes# c) {-# INLINE moveByteOffPtrToMBytes #-}  moveMBytesToPtr :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> Ptr e -> Off e -> Count e -> m ()@@ -135,18 +135,18 @@   (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () moveByteOffMBytesToPtr (MBytes src#) (Off (I# srcOff#)) (Ptr dstAddr#) (Off (I# dstOff#)) c =   unsafeIOToPrim $-  memmoveMutableByteArrayToAddr# src# srcOff# dstAddr# dstOff# (fromCount# c)+  memmoveMutableByteArrayToAddr# src# srcOff# dstAddr# dstOff# (unCountBytes# c) {-# INLINE moveByteOffMBytesToPtr #-}   compareByteOffBytesToPtr ::      Prim e => Bytes p -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> Ordering compareByteOffBytesToPtr (Bytes b#) (Off (I# off1#)) (Ptr addr#) (Off (I# off2#)) c =-  toOrdering# (memcmpByteArrayAddr# b# off1# addr# off2# (fromCount# c))+  toOrdering# (memcmpByteArrayAddr# b# off1# addr# off2# (unCountBytes# c)) {-# INLINE compareByteOffBytesToPtr #-}  compareByteOffPtrToBytes ::      Prim e => Ptr e -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> Ordering compareByteOffPtrToBytes (Ptr addr#) (Off (I# off1#)) (Bytes b#) (Off (I# off2#)) c =-  toOrdering# (memcmpAddrByteArray# addr# off1# b# off2# (fromCount# c))+  toOrdering# (memcmpAddrByteArray# addr# off1# b# off2# (unCountBytes# c)) {-# INLINE compareByteOffPtrToBytes #-}
+ src/Data/Prim/Memory/Text.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE MagicHash #-}+-- |+-- Module      : Data.Prim.Memory.Text+-- Copyright   : (c) Alexey Kuleshevich 2020+-- License     : BSD3+-- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>+-- Stability   : experimental+-- Portability : non-portable+--+module Data.Prim.Memory.Text+  ( Text(..)+  , MText(..)+  , Array(..)+  , MArray(..)+  , toBytesArray+  , fromBytesArray+  , toMBytesMArray+  , fromMBytesMArray+  ) where++import Data.Text.Array+import Data.Text.Internal+import Data.Prim.Memory.Bytes.Internal+  ( Bytes(..)+  , MBytes(..)+  , Pinned(..)+  )++-- | Mutable version of a `Text`+data MText s =+  MText+    {-# UNPACK #-}!(MArray s) -- payload (Word16 elements)+    {-# UNPACK #-}!Int        -- offset (units of Word16, not Char)+    {-# UNPACK #-}!Int        -- length (units of Word16, not Char)++toBytesArray :: Array -> Bytes 'Inc+toBytesArray (Array ba#) = Bytes ba#+{-# INLINE toBytesArray #-}++fromBytesArray :: Bytes p -> Array+fromBytesArray (Bytes ba#) = Array ba#+{-# INLINE fromBytesArray #-}++toMBytesMArray :: MArray s -> MBytes 'Inc s+toMBytesMArray (MArray mba#) = MBytes mba#+{-# INLINE toMBytesMArray #-}++fromMBytesMArray :: MBytes p s -> MArray s+fromMBytesMArray (MBytes ba#) = MArray ba#+{-# INLINE fromMBytesMArray #-}++
+ tests/doctests.hs view
@@ -0,0 +1,6 @@+module Main where++import Test.DocTest (doctest)++main :: IO ()+main = doctest ["src", "-fobject-code"]