primal-memory-0.3.0.0: Unified interface for memory managemenet.
Copyright(c) Alexey Kuleshevich 2020
LicenseBSD3
MaintainerAlexey Kuleshevich <alexey@kuleshevi.ch>
Stabilityexperimental
Portabilitynon-portable
Safe HaskellNone
LanguageHaskell2010

Data.Prim.Memory

Description

 
Synopsis

Documentation

module Data.Prim

data Pinned Source #

In GHC there is a distinction between pinned and unpinned memory.

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 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 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 Pinned or Inconclusive.

It is possible to use one of toPinnedBytes or toPinnedMBytes to get a conclusive type.

Since: 0.1.0

Constructors

Pin

Pinned, which indicates that allocated memory will not move

Inc

Inconclusive, thus memory could be pinned or unpinned

Immutable

data Bytes (p :: Pinned) Source #

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 fromByteArray# and unwrapper toByteArray# should be used instead. As a backdoor, of course, the actual constructor is available from Data.Prim.Memory.Internal

Instances

Instances details
PtrAccess s (Bytes 'Pin) Source #

Read-only access, but immutability is not enforced.

Instance details

Defined in Data.Prim.Memory.ForeignPtr

Methods

toForeignPtr :: MonadPrim s m => Bytes 'Pin -> m (ForeignPtr a) Source #

withPtrAccess :: MonadPrim s m => Bytes 'Pin -> (Ptr a -> m b) -> m b Source #

withNoHaltPtrAccess :: MonadUnliftPrim s m => Bytes 'Pin -> (Ptr a -> m b) -> m b Source #

Typeable p => IsList (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Associated Types

type Item (Bytes p) #

Methods

fromList :: [Item (Bytes p)] -> Bytes p #

fromListN :: Int -> [Item (Bytes p)] -> Bytes p #

toList :: Bytes p -> [Item (Bytes p)] #

Eq (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

(==) :: Bytes p -> Bytes p -> Bool #

(/=) :: Bytes p -> Bytes p -> Bool #

Ord (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

compare :: Bytes p -> Bytes p -> Ordering #

(<) :: Bytes p -> Bytes p -> Bool #

(<=) :: Bytes p -> Bytes p -> Bool #

(>) :: Bytes p -> Bytes p -> Bool #

(>=) :: Bytes p -> Bytes p -> Bool #

max :: Bytes p -> Bytes p -> Bytes p #

min :: Bytes p -> Bytes p -> Bytes p #

Show (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

showsPrec :: Int -> Bytes p -> ShowS #

show :: Bytes p -> String #

showList :: [Bytes p] -> ShowS #

Typeable p => Semigroup (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

(<>) :: Bytes p -> Bytes p -> Bytes p #

sconcat :: NonEmpty (Bytes p) -> Bytes p #

stimes :: Integral b => b -> Bytes p -> Bytes p #

Typeable p => Monoid (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

mempty :: Bytes p #

mappend :: Bytes p -> Bytes p -> Bytes p #

mconcat :: [Bytes p] -> Bytes p #

NFData (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Bytes.Internal

Methods

rnf :: Bytes p -> () #

MemRead (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMem :: Bytes p -> Bytes p -> Bool

byteCountMem :: Bytes p -> Count Word8 Source #

indexOffMem :: Prim e => Bytes p -> Off e -> e Source #

indexByteOffMem :: Prim e => Bytes p -> Off Word8 -> e Source #

copyByteOffToMBytesMem :: forall s m e (p0 :: Pinned). (MonadPrim s m, Prim e) => Bytes p -> Off Word8 -> MBytes p0 s -> Off Word8 -> Count e -> m () Source #

copyByteOffToPtrMem :: (MonadPrim s m, Prim e) => Bytes p -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

compareByteOffToPtrMem :: (MonadPrim s m, Prim e) => Bytes p -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m Ordering Source #

compareByteOffToBytesMem :: forall e (p0 :: Pinned). Prim e => Bytes p -> Off Word8 -> Bytes p0 -> Off Word8 -> Count e -> Ordering Source #

compareByteOffMem :: (MemRead mr', Prim e) => mr' -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> Ordering Source #

type Item (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

type Item (Bytes p) = Word8

class MemRead mr Source #

Type class that can be implemented for an immutable data type that provides read-only direct access to memory

Instances

Instances details
MemRead ShortByteString Source # 
Instance details

Defined in Data.Prim.Memory.Internal

MemRead ByteString Source # 
Instance details

Defined in Data.Prim.Memory.Internal

MemRead Text Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMem :: Text -> Text -> Bool

byteCountMem :: Text -> Count Word8 Source #

indexOffMem :: Prim e => Text -> Off e -> e Source #

indexByteOffMem :: Prim e => Text -> Off Word8 -> e Source #

copyByteOffToMBytesMem :: forall s m e (p :: Pinned). (MonadPrim s m, Prim e) => Text -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

copyByteOffToPtrMem :: (MonadPrim s m, Prim e) => Text -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

compareByteOffToPtrMem :: (MonadPrim s m, Prim e) => Text -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m Ordering Source #

compareByteOffToBytesMem :: forall e (p :: Pinned). Prim e => Text -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> Ordering Source #

compareByteOffMem :: (MemRead mr', Prim e) => mr' -> Off Word8 -> Text -> Off Word8 -> Count e -> Ordering Source #

MemRead Array Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMem :: Array -> Array -> Bool

byteCountMem :: Array -> Count Word8 Source #

indexOffMem :: Prim e => Array -> Off e -> e Source #

indexByteOffMem :: Prim e => Array -> Off Word8 -> e Source #

copyByteOffToMBytesMem :: forall s m e (p :: Pinned). (MonadPrim s m, Prim e) => Array -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

copyByteOffToPtrMem :: (MonadPrim s m, Prim e) => Array -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

compareByteOffToPtrMem :: (MonadPrim s m, Prim e) => Array -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m Ordering Source #

compareByteOffToBytesMem :: forall e (p :: Pinned). Prim e => Array -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> Ordering Source #

compareByteOffMem :: (MemRead mr', Prim e) => mr' -> Off Word8 -> Array -> Off Word8 -> Count e -> Ordering Source #

MemRead (UArray e) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMem :: UArray e -> UArray e -> Bool

byteCountMem :: UArray e -> Count Word8 Source #

indexOffMem :: Prim e0 => UArray e -> Off e0 -> e0 Source #

indexByteOffMem :: Prim e0 => UArray e -> Off Word8 -> e0 Source #

copyByteOffToMBytesMem :: forall s m e0 (p :: Pinned). (MonadPrim s m, Prim e0) => UArray e -> Off Word8 -> MBytes p s -> Off Word8 -> Count e0 -> m () Source #

copyByteOffToPtrMem :: (MonadPrim s m, Prim e0) => UArray e -> Off Word8 -> Ptr e0 -> Off Word8 -> Count e0 -> m () Source #

compareByteOffToPtrMem :: (MonadPrim s m, Prim e0) => UArray e -> Off Word8 -> Ptr e0 -> Off Word8 -> Count e0 -> m Ordering Source #

compareByteOffToBytesMem :: forall e0 (p :: Pinned). Prim e0 => UArray e -> Off Word8 -> Bytes p -> Off Word8 -> Count e0 -> Ordering Source #

compareByteOffMem :: (MemRead mr', Prim e0) => mr' -> Off Word8 -> UArray e -> Off Word8 -> Count e0 -> Ordering Source #

MemRead (Bytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMem :: Bytes p -> Bytes p -> Bool

byteCountMem :: Bytes p -> Count Word8 Source #

indexOffMem :: Prim e => Bytes p -> Off e -> e Source #

indexByteOffMem :: Prim e => Bytes p -> Off Word8 -> e Source #

copyByteOffToMBytesMem :: forall s m e (p0 :: Pinned). (MonadPrim s m, Prim e) => Bytes p -> Off Word8 -> MBytes p0 s -> Off Word8 -> Count e -> m () Source #

copyByteOffToPtrMem :: (MonadPrim s m, Prim e) => Bytes p -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

compareByteOffToPtrMem :: (MonadPrim s m, Prim e) => Bytes p -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m Ordering Source #

compareByteOffToBytesMem :: forall e (p0 :: Pinned). Prim e => Bytes p -> Off Word8 -> Bytes p0 -> Off Word8 -> Count e -> Ordering Source #

compareByteOffMem :: (MemRead mr', Prim e) => mr' -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> Ordering Source #

MemRead (Addr e) Source # 
Instance details

Defined in Data.Prim.Memory.Addr

Methods

isSameMem :: Addr e -> Addr e -> Bool

byteCountMem :: Addr e -> Count Word8 Source #

indexOffMem :: Prim e0 => Addr e -> Off e0 -> e0 Source #

indexByteOffMem :: Prim e0 => Addr e -> Off Word8 -> e0 Source #

copyByteOffToMBytesMem :: forall s m e0 (p :: Pinned). (MonadPrim s m, Prim e0) => Addr e -> Off Word8 -> MBytes p s -> Off Word8 -> Count e0 -> m () Source #

copyByteOffToPtrMem :: (MonadPrim s m, Prim e0) => Addr e -> Off Word8 -> Ptr e0 -> Off Word8 -> Count e0 -> m () Source #

compareByteOffToPtrMem :: (MonadPrim s m, Prim e0) => Addr e -> Off Word8 -> Ptr e0 -> Off Word8 -> Count e0 -> m Ordering Source #

compareByteOffToBytesMem :: forall e0 (p :: Pinned). Prim e0 => Addr e -> Off Word8 -> Bytes p -> Off Word8 -> Count e0 -> Ordering Source #

compareByteOffMem :: (MemRead mr', Prim e0) => mr' -> Off Word8 -> Addr e -> Off Word8 -> Count e0 -> Ordering Source #

MemRead (PArray p e) Source # 
Instance details

Defined in Data.Prim.Memory.PArray

Methods

isSameMem :: PArray p e -> PArray p e -> Bool

byteCountMem :: PArray p e -> Count Word8 Source #

indexOffMem :: Prim e0 => PArray p e -> Off e0 -> e0 Source #

indexByteOffMem :: Prim e0 => PArray p e -> Off Word8 -> e0 Source #

copyByteOffToMBytesMem :: forall s m e0 (p0 :: Pinned). (MonadPrim s m, Prim e0) => PArray p e -> Off Word8 -> MBytes p0 s -> Off Word8 -> Count e0 -> m () Source #

copyByteOffToPtrMem :: (MonadPrim s m, Prim e0) => PArray p e -> Off Word8 -> Ptr e0 -> Off Word8 -> Count e0 -> m () Source #

compareByteOffToPtrMem :: (MonadPrim s m, Prim e0) => PArray p e -> Off Word8 -> Ptr e0 -> Off Word8 -> Count e0 -> m Ordering Source #

compareByteOffToBytesMem :: forall e0 (p0 :: Pinned). Prim e0 => PArray p e -> Off Word8 -> Bytes p0 -> Off Word8 -> Count e0 -> Ordering Source #

compareByteOffMem :: (MemRead mr', Prim e0) => mr' -> Off Word8 -> PArray p e -> Off Word8 -> Count e0 -> Ordering Source #

Size

countMem :: forall e mr. (MemRead mr, Prim e) => mr -> Count e Source #

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

Expand
>>> let 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}
>>> countMem b :: Count Word64
Count {unCount = 0}

Since: 0.1.0

countRemMem :: forall e mr. (MemRead mr, Prim e) => mr -> (Count e, Count Word8) Source #

Figure out how many elements and a byte size remainder can fit into the immutable region of memory.

Examples

Expand
>>> let 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})
>>> countRemMem @Word64 b
(Count {unCount = 0},Count {unCount = 6})

Since: 0.1.0

byteCountMem :: MemRead mr => mr -> Count Word8 Source #

Number of bytes allocated by the data type available for reading.

Example

Expand
>>> :set -XDataKinds
>>> import Data.Prim.Memory
>>> byteCountMem (fromByteListMem [1,2,3] :: Bytes 'Inc)
Count {unCount = 3}

Since: 0.1.0

Index

indexOffMem Source #

Arguments

:: (MemRead mr, 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 

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

indexByteOffMem Source #

Arguments

:: (MemRead mr, 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 

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

Construct

emptyMem :: forall ma. MemAlloc ma => FrozenMem ma Source #

Construct an immutable memory region that can't hold any data. Same as mempty :: FrozenMem ma

Example

Expand
>>> :set -XTypeApplications
>>> :set -XDataKinds
>>> import Data.Prim.Memory
>>> toListMem (emptyMem @(MBytes 'Inc)) :: [Int]
[]

Since: 0.1.0

singletonMem Source #

Arguments

:: forall e ma. (MemAlloc ma, Prim e) 
=> e

The single element that will be stored in the newly allocated region of memory

-> FrozenMem ma 

Allocate a region of immutable memory that holds a single element.

Example

Expand
>>> :set -XTypeApplications
>>> :set -XDataKinds
>>> import Data.Prim.Memory
>>> toListMem (singletonMem @Word16 @(MBytes 'Inc) 0xffff) :: [Word8]
[255,255]

Since: 0.1.0

cycleMemN :: forall ma mr. (MemAlloc ma, MemRead mr) => Int -> mr -> FrozenMem ma Source #

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

Expand
>>> :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

createMemST Source #

Arguments

:: forall e b ma. (MemAlloc ma, Prim e) 
=> Count e

memCount - Amount of memory to allocate for the region in number of elements of type e

Preconditions:

0 <= memCount

Possibility of overflow:

memCount <= fromByteCount maxBound

When converted to bytes the value should be less then available physical memory

-> (forall s. ma s -> ST s b)

memFillAction - This action will be used to modify the contents of newly allocated memory. Make sure to overwrite all of it, otherwise it might lead to breaking referential transparency.

-> (b, FrozenMem ma) 

Allocate a mutable region of memory and fill it with the supplied ST action. Besides the newly filled frozen memory this function also returns the result produced by the filling action. See createMemST_ for the version that discards it. Also see createZeroMemST for a safer alternative.

Unsafe
Same caviats as in allocMutMem

Since: 0.1.0

createMemST_ Source #

Arguments

:: (MemAlloc ma, Prim e) 
=> Count e

memCount - Amount of memory to allocate for the region in number of elements of type e

Preconditions:

0 <= memCount

Possibility of overflow:

memCount <= fromByteCount maxBound

When converted to bytes the value should be less then available physical memory

-> (forall s. ma s -> ST s b)

memFillAction - This action will be used to modify the contents of newly allocated memory. Make sure to overwrite all of it, otherwise it might lead to breaking referential transparency.

-> FrozenMem ma 

createZeroMemST Source #

Arguments

:: forall e ma b. (MemAlloc ma, Prim e) 
=> Count e

memCount - Amount of memory to allocate for the region in number of elements of type e

Preconditions:

0 <= memCount

Possibility of overflow:

memCount <= fromByteCount maxBound

When converted to bytes the value should be less then available physical memory

-> (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 the whole thing will be reset to zeros before applying this action.

-> (b, FrozenMem ma) 

Same as createMemST, except it in ensures that the memory is reset to zeros right after allocation

Unsafe
Same caviats as in allocZeroMutMem: violation of precondition for memCount may result in undefined behavior or HeapOverflow async exception.

Since: 0.1.0

createZeroMemST_ Source #

Arguments

:: forall e ma b. (MemAlloc ma, Prim e) 
=> Count e

memCount - Amount of memory to allocate for the 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:

memCount <= fromByteCount 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 the whole thing will be reset to zeros before applying this action.

-> FrozenMem ma 

Same as createMemST_, except it ensures that the memory gets reset with zeros right after allocation and prior applying the ST filling action fillAction.

Unsafe
Same reasons as allocZeroMutMem: violation of precondition for memCount may result in undefined behavior or HeapOverflow async exception.

Example

Expand

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) -> writeByteOffMutMem m i b
>>> toListMem bc :: String
"Haskell"

Since: 0.1.0

Copy

cloneMem Source #

Arguments

:: forall ma. MemAlloc ma 
=> FrozenMem ma

memSource - immutable source memory.

-> FrozenMem ma 

Copy all of the data from the source into a newly allocate memory region of identical size.

Examples

Expand
>>> :set -XDataKinds
>>> import Data.Prim.Memory
>>> import Data.Prim.Memory.Bytes
>>> 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"
>>> report (eqByteMem xs ys) (isSameBytes xs ys)
"Bytes equal: True, their pointers equal: False"

Since: 0.2.0

copyMem Source #

Arguments

:: (MonadPrim s m, MemRead mr, MemWrite mw, Prim e) 
=> mr

memSourceRead - Read-only source memory region from which the data will copied

-> 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 <- getCountMutMem 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 <- getCountMutMem memTargetWrite
unOff memTargetOff + unCount memCount < unCount targetCount
-> m () 

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

copyByteOffMem Source #

Arguments

:: (MemWrite mw, 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 <- getByteCountMutMem 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 <- getByteCountMutMem memTargetWrite
unOff memTargetOff + unCountBytes memCount <= unCount (targetByteCount - 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

copyByteOffToMBytesMem Source #

Arguments

:: (MemRead mr, 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 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

copyByteOffToPtrMem Source #

Arguments

:: (MemRead mr, 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 () 

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

Compare

eqMem :: forall e mr. (Prim e, Eq e, MemRead mr) => mr -> mr -> Bool Source #

eqOffMem Source #

Arguments

:: (Prim e, Eq e, MemRead mr1, MemRead mr2) 
=> mr1

memRead1 - First region of memory

-> Off e

memOff1 - Offset for memRead1 in number of elements

Precondition:

0 <= memOff1
-> mr2

memRead2 - Second region of memory

-> Off e

memOff2 - Offset for memRead1 in number of elements

Precondition:

0 <= memOff2
-> Count e

memCount - Number of elements of type e to compare

Preconditions:

0 <= memCount
offToCount memOff1 + memCount < countMem memRead1
offToCount memOff2 + memCount < countMem memRead2
-> Bool 

Check two regions of memory for equality using the Eq instance. It will return True whenever both regions hold exactly the same elements and False as soon as the first pair of mismatched elements is discovered in the two regions. It is safe for both regions to refer to the same part of memory.

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.3.0

eqByteMem :: (MemRead mr1, MemRead mr2) => mr1 -> mr2 -> Bool Source #

Compare two memory regions for equality byte-by-byte. False is returned immediately when sizes reported by byteCountMem do not match.

Since: 0.3.0

eqByteOffMem Source #

Arguments

:: (MemRead mr1, MemRead mr2) 
=> mr1

memRead1 - First region of memory

-> Off Word8

memOff1 - Offset for memRead1 in number of bytes

Precondition:

0 <= memOff1
-> mr2

memRead2 - Second region of memory

-> Off Word8

memOff2 - Offset for memRead1 in number of bytes

Precondition:

0 <= memOff2
-> Count Word8

memCount - Number of bytes compare

Preconditions:

0 <= memCount
offToCount memOff1 + memCount < countMem memRead1
offToCount memOff2 + memCount < countMem memRead2
-> Bool 

Compare two memory regions byte-by-byte. Computation may be short-circuited on the first mismatch, but it is MemRead implementation specific.

Since: 0.3.0

compareMem Source #

Arguments

:: forall e mr. (Prim e, Ord e, MemRead mr) 
=> mr

memRead1 - First region of memory

-> mr

memRead2 - Second region of memory

-> Ordering 

Compare two regions using the Ord instance. It will return EQ whenever both regions hold exactly the same elements and LT or GT as soon as the first discovered element 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: 0.3.0

compareOffMem Source #

Arguments

:: (Prim e, Ord e, MemRead mr1, MemRead mr2) 
=> mr1

memRead1 - First region of memory

-> Off e

memOff1 - Offset for memRead1 in number of elements

Precondition:

0 <= memOff1
-> mr2

memRead2 - Second region of memory

-> Off e

memOff2 - Offset for memRead1 in number of elements

Precondition:

0 <= memOff2
-> Count e

memCount - Number of elements of type e to compare

Preconditions:

0 <= memCount
offToCount memOff1 + memCount < countMem memRead1
offToCount memOff2 + memCount < countMem memRead2
-> Ordering 

Compare two regions using the Ord instance. It will return EQ whenever both regions hold exactly the same elements and LT or GT as soon as the first discovered element 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.

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.3.0

compareByteMem :: (MemRead mr1, MemRead mr2) => mr1 -> mr2 -> Ordering Source #

Compare two memory regions byte-by-byte.

Since: 0.3.0

compareByteOffMem Source #

Arguments

:: (MemRead mr, 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 

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

compareByteOffToPtrMem Source #

Arguments

:: (MemRead mr, 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 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

compareByteOffToBytesMem Source #

Arguments

:: (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)
-> 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 

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

Convert

convertMem :: (MemRead mr, MemAlloc ma) => mr -> FrozenMem ma Source #

O(n) - Convert a read-only memory region into a newly allocated other type of memory region

>>> import Data.ByteString (pack)
>>> let 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

To list

toListMem :: forall e mr. (MemRead mr, Prim e) => mr -> [e] Source #

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

Expand
>>> 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

toListSlackMem :: forall e mr. (MemRead mr, Prim e) => mr -> ([e], [Word8]) Source #

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

Expand
>>> import Data.Word
>>> :set -XDataKinds
>>> let 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

toByteListMem :: forall ma. MemAlloc ma => FrozenMem ma -> [Word8] Source #

Convert a memory region to a list of bytes. Equivalent to unpack for ByteString

Example

Expand
>>> toByteListMem (fromByteListMem [0..10] :: Bytes 'Pin)
[0,1,2,3,4,5,6,7,8,9,10]

Since: 0.1.0

foldrCountMem :: forall e b mr. (MemRead mr, Prim e) => Count e -> (e -> b -> b) -> b -> mr -> b Source #

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

showsHexMem :: MemRead mr => mr -> [ShowS] Source #

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

Expand
>>> :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

From list

fromListMem :: forall e ma. (Prim e, MemAlloc ma) => [e] -> FrozenMem ma Source #

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

Expand
>>> import Data.Prim.Memory
>>> :set -XDataKinds
>>> fromListMem "Hi" :: Bytes 'Inc
[0x48,0x00,0x00,0x00,0x69,0x00,0x00,0x00]

Since: 0.1.0

fromByteListMem :: forall ma. MemAlloc ma => [Word8] -> FrozenMem ma Source #

Same as fromListMem but restricted to a list of Word8. Load a list of bytes into a newly allocated memory region. Equivalent to pack for ByteString

Examples

Expand
>>> fromByteListMem [0..10] :: Bytes 'Pin
[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a]

Since: 0.1.0

fromListMemN Source #

Arguments

:: 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) 

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

Expand
>>> :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

fromListZeroMemN Source #

Arguments

:: 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) 

Just like fromListMemN, except it ensures safety by filling tail with zeros, whenever the list is not long enough.

Examples

Expand
>>> 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 -> [e] -> FrozenMem ma Source #

Same as fromListZeroMemN, but ignore the extra information about how the loading went.

Examples

Expand
>>> 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

Mutable

data MBytes (p :: Pinned) s Source #

Mutable 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 fromMutableByteArray# and unwrapper toMutableByteArray# should be used instead. As a backdoor, of course, the actual constructor is available in Data.Prim.Memory.Internal module and specially unsafe function castPinnedMBytes was crafted.

Instances

Instances details
PtrAccess s (MBytes 'Pin s) Source # 
Instance details

Defined in Data.Prim.Memory.ForeignPtr

Methods

toForeignPtr :: MonadPrim s m => MBytes 'Pin s -> m (ForeignPtr a) Source #

withPtrAccess :: MonadPrim s m => MBytes 'Pin s -> (Ptr a -> m b) -> m b Source #

withNoHaltPtrAccess :: MonadUnliftPrim s m => MBytes 'Pin s -> (Ptr a -> m b) -> m b Source #

Typeable p => MemAlloc (MBytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Associated Types

type FrozenMem (MBytes p) = (fm :: Type) Source #

Methods

getByteCountMutMem :: MonadPrim s m => MBytes p s -> m (Count Word8) Source #

allocMutMem :: (Prim e, MonadPrim s m) => Count e -> m (MBytes p s) Source #

thawMem :: MonadPrim s m => FrozenMem (MBytes p) -> m (MBytes p s) Source #

freezeMutMem :: MonadPrim s m => MBytes p s -> m (FrozenMem (MBytes p)) Source #

reallocMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Count e -> m (MBytes p s) Source #

MemWrite (MBytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMutMem :: MBytes p s -> MBytes p s -> Bool

readOffMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m e Source #

readByteOffMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> m e Source #

writeOffMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> e -> m () Source #

writeByteOffMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> e -> m () Source #

moveByteOffToMBytesMutMem :: forall s m e (p0 :: Pinned). (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> MBytes p0 s -> Off Word8 -> Count e -> m () Source #

moveByteOffToPtrMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e) => mr -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

moveByteOffMutMem :: (MonadPrim s m, MemWrite mw', Prim e) => mw' s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

setMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> Count e -> e -> m () Source #

NFData (MBytes p s) Source # 
Instance details

Defined in Data.Prim.Memory.Bytes.Internal

Methods

rnf :: MBytes p s -> () #

type FrozenMem (MBytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

type FrozenMem (MBytes p) = Bytes p

class MemWrite mw Source #

Type class that can be implemented for a mutable data type that provides direct read and write access to memory

Instances

Instances details
MemWrite MArray Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMutMem :: MArray s -> MArray s -> Bool

readOffMutMem :: (MonadPrim s m, Prim e) => MArray s -> Off e -> m e Source #

readByteOffMutMem :: (MonadPrim s m, Prim e) => MArray s -> Off Word8 -> m e Source #

writeOffMutMem :: (MonadPrim s m, Prim e) => MArray s -> Off e -> e -> m () Source #

writeByteOffMutMem :: (MonadPrim s m, Prim e) => MArray s -> Off Word8 -> e -> m () Source #

moveByteOffToMBytesMutMem :: forall s m e (p :: Pinned). (MonadPrim s m, Prim e) => MArray s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

moveByteOffToPtrMutMem :: (MonadPrim s m, Prim e) => MArray s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e) => mr -> Off Word8 -> MArray s -> Off Word8 -> Count e -> m () Source #

moveByteOffMutMem :: (MonadPrim s m, MemWrite mw', Prim e) => mw' s -> Off Word8 -> MArray s -> Off Word8 -> Count e -> m () Source #

setMutMem :: (MonadPrim s m, Prim e) => MArray s -> Off e -> Count e -> e -> m () Source #

MemWrite MByteString Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMutMem :: MByteString s -> MByteString s -> Bool

readOffMutMem :: (MonadPrim s m, Prim e) => MByteString s -> Off e -> m e Source #

readByteOffMutMem :: (MonadPrim s m, Prim e) => MByteString s -> Off Word8 -> m e Source #

writeOffMutMem :: (MonadPrim s m, Prim e) => MByteString s -> Off e -> e -> m () Source #

writeByteOffMutMem :: (MonadPrim s m, Prim e) => MByteString s -> Off Word8 -> e -> m () Source #

moveByteOffToMBytesMutMem :: forall s m e (p :: Pinned). (MonadPrim s m, Prim e) => MByteString s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

moveByteOffToPtrMutMem :: (MonadPrim s m, Prim e) => MByteString s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e) => mr -> Off Word8 -> MByteString s -> Off Word8 -> Count e -> m () Source #

moveByteOffMutMem :: (MonadPrim s m, MemWrite mw', Prim e) => mw' s -> Off Word8 -> MByteString s -> Off Word8 -> Count e -> m () Source #

setMutMem :: (MonadPrim s m, Prim e) => MByteString s -> Off e -> Count e -> e -> m () Source #

MemWrite (UMArray e) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMutMem :: UMArray e s -> UMArray e s -> Bool

readOffMutMem :: (MonadPrim s m, Prim e0) => UMArray e s -> Off e0 -> m e0 Source #

readByteOffMutMem :: (MonadPrim s m, Prim e0) => UMArray e s -> Off Word8 -> m e0 Source #

writeOffMutMem :: (MonadPrim s m, Prim e0) => UMArray e s -> Off e0 -> e0 -> m () Source #

writeByteOffMutMem :: (MonadPrim s m, Prim e0) => UMArray e s -> Off Word8 -> e0 -> m () Source #

moveByteOffToMBytesMutMem :: forall s m e0 (p :: Pinned). (MonadPrim s m, Prim e0) => UMArray e s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e0 -> m () Source #

moveByteOffToPtrMutMem :: (MonadPrim s m, Prim e0) => UMArray e s -> Off Word8 -> Ptr e0 -> Off Word8 -> Count e0 -> m () Source #

copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e0) => mr -> Off Word8 -> UMArray e s -> Off Word8 -> Count e0 -> m () Source #

moveByteOffMutMem :: (MonadPrim s m, MemWrite mw', Prim e0) => mw' s -> Off Word8 -> UMArray e s -> Off Word8 -> Count e0 -> m () Source #

setMutMem :: (MonadPrim s m, Prim e0) => UMArray e s -> Off e0 -> Count e0 -> e0 -> m () Source #

MemWrite (MBytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMutMem :: MBytes p s -> MBytes p s -> Bool

readOffMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m e Source #

readByteOffMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> m e Source #

writeOffMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> e -> m () Source #

writeByteOffMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> e -> m () Source #

moveByteOffToMBytesMutMem :: forall s m e (p0 :: Pinned). (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> MBytes p0 s -> Off Word8 -> Count e -> m () Source #

moveByteOffToPtrMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e) => mr -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

moveByteOffMutMem :: (MonadPrim s m, MemWrite mw', Prim e) => mw' s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

setMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> Count e -> e -> m () Source #

MemWrite (MemState (ForeignPtr a)) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMutMem :: MemState (ForeignPtr a) s -> MemState (ForeignPtr a) s -> Bool

readOffMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off e -> m e Source #

readByteOffMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off Word8 -> m e Source #

writeOffMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off e -> e -> m () Source #

writeByteOffMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off Word8 -> e -> m () Source #

moveByteOffToMBytesMutMem :: forall s m e (p :: Pinned). (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

moveByteOffToPtrMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e) => mr -> Off Word8 -> MemState (ForeignPtr a) s -> Off Word8 -> Count e -> m () Source #

moveByteOffMutMem :: (MonadPrim s m, MemWrite mw', Prim e) => mw' s -> Off Word8 -> MemState (ForeignPtr a) s -> Off Word8 -> Count e -> m () Source #

setMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off e -> Count e -> e -> m () Source #

MemWrite (MAddr e) Source # 
Instance details

Defined in Data.Prim.Memory.Addr

Methods

isSameMutMem :: MAddr e s -> MAddr e s -> Bool

readOffMutMem :: (MonadPrim s m, Prim e0) => MAddr e s -> Off e0 -> m e0 Source #

readByteOffMutMem :: (MonadPrim s m, Prim e0) => MAddr e s -> Off Word8 -> m e0 Source #

writeOffMutMem :: (MonadPrim s m, Prim e0) => MAddr e s -> Off e0 -> e0 -> m () Source #

writeByteOffMutMem :: (MonadPrim s m, Prim e0) => MAddr e s -> Off Word8 -> e0 -> m () Source #

moveByteOffToMBytesMutMem :: forall s m e0 (p :: Pinned). (MonadPrim s m, Prim e0) => MAddr e s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e0 -> m () Source #

moveByteOffToPtrMutMem :: (MonadPrim s m, Prim e0) => MAddr e s -> Off Word8 -> Ptr e0 -> Off Word8 -> Count e0 -> m () Source #

copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e0) => mr -> Off Word8 -> MAddr e s -> Off Word8 -> Count e0 -> m () Source #

moveByteOffMutMem :: (MonadPrim s m, MemWrite mw', Prim e0) => mw' s -> Off Word8 -> MAddr e s -> Off Word8 -> Count e0 -> m () Source #

setMutMem :: (MonadPrim s m, Prim e0) => MAddr e s -> Off e0 -> Count e0 -> e0 -> m () Source #

MemWrite (PMArray p e) Source # 
Instance details

Defined in Data.Prim.Memory.PArray

Methods

isSameMutMem :: PMArray p e s -> PMArray p e s -> Bool

readOffMutMem :: (MonadPrim s m, Prim e0) => PMArray p e s -> Off e0 -> m e0 Source #

readByteOffMutMem :: (MonadPrim s m, Prim e0) => PMArray p e s -> Off Word8 -> m e0 Source #

writeOffMutMem :: (MonadPrim s m, Prim e0) => PMArray p e s -> Off e0 -> e0 -> m () Source #

writeByteOffMutMem :: (MonadPrim s m, Prim e0) => PMArray p e s -> Off Word8 -> e0 -> m () Source #

moveByteOffToMBytesMutMem :: forall s m e0 (p0 :: Pinned). (MonadPrim s m, Prim e0) => PMArray p e s -> Off Word8 -> MBytes p0 s -> Off Word8 -> Count e0 -> m () Source #

moveByteOffToPtrMutMem :: (MonadPrim s m, Prim e0) => PMArray p e s -> Off Word8 -> Ptr e0 -> Off Word8 -> Count e0 -> m () Source #

copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e0) => mr -> Off Word8 -> PMArray p e s -> Off Word8 -> Count e0 -> m () Source #

moveByteOffMutMem :: (MonadPrim s m, MemWrite mw', Prim e0) => mw' s -> Off Word8 -> PMArray p e s -> Off Word8 -> Count e0 -> m () Source #

setMutMem :: (MonadPrim s m, Prim e0) => PMArray p e s -> Off e0 -> Count e0 -> e0 -> m () Source #

class (MemRead (FrozenMem ma), MemWrite ma) => MemAlloc ma Source #

Generalized memory allocation and pure/mutable state conversion.

Minimal complete definition

getByteCountMutMem, allocMutMem, thawMem, freezeMutMem

Associated Types

type FrozenMem ma = (fm :: Type) | fm -> ma Source #

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.

Instances

Instances details
MemAlloc MArray Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Associated Types

type FrozenMem MArray = (fm :: Type) Source #

MemAlloc MByteString Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Associated Types

type FrozenMem MByteString = (fm :: Type) Source #

MemAlloc (UMArray e) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Associated Types

type FrozenMem (UMArray e) = (fm :: Type) Source #

Methods

getByteCountMutMem :: MonadPrim s m => UMArray e s -> m (Count Word8) Source #

allocMutMem :: (Prim e0, MonadPrim s m) => Count e0 -> m (UMArray e s) Source #

thawMem :: MonadPrim s m => FrozenMem (UMArray e) -> m (UMArray e s) Source #

freezeMutMem :: MonadPrim s m => UMArray e s -> m (FrozenMem (UMArray e)) Source #

reallocMutMem :: (MonadPrim s m, Prim e0) => UMArray e s -> Count e0 -> m (UMArray e s) Source #

Typeable p => MemAlloc (MBytes p) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Associated Types

type FrozenMem (MBytes p) = (fm :: Type) Source #

Methods

getByteCountMutMem :: MonadPrim s m => MBytes p s -> m (Count Word8) Source #

allocMutMem :: (Prim e, MonadPrim s m) => Count e -> m (MBytes p s) Source #

thawMem :: MonadPrim s m => FrozenMem (MBytes p) -> m (MBytes p s) Source #

freezeMutMem :: MonadPrim s m => MBytes p s -> m (FrozenMem (MBytes p)) Source #

reallocMutMem :: (MonadPrim s m, Prim e) => MBytes p s -> Count e -> m (MBytes p s) Source #

MemAlloc (MAddr e) Source # 
Instance details

Defined in Data.Prim.Memory.Addr

Associated Types

type FrozenMem (MAddr e) = (fm :: Type) Source #

Methods

getByteCountMutMem :: MonadPrim s m => MAddr e s -> m (Count Word8) Source #

allocMutMem :: (Prim e0, MonadPrim s m) => Count e0 -> m (MAddr e s) Source #

thawMem :: MonadPrim s m => FrozenMem (MAddr e) -> m (MAddr e s) Source #

freezeMutMem :: MonadPrim s m => MAddr e s -> m (FrozenMem (MAddr e)) Source #

reallocMutMem :: (MonadPrim s m, Prim e0) => MAddr e s -> Count e0 -> m (MAddr e s) Source #

Typeable p => MemAlloc (PMArray p e) Source # 
Instance details

Defined in Data.Prim.Memory.PArray

Associated Types

type FrozenMem (PMArray p e) = (fm :: Type) Source #

Methods

getByteCountMutMem :: MonadPrim s m => PMArray p e s -> m (Count Word8) Source #

allocMutMem :: (Prim e0, MonadPrim s m) => Count e0 -> m (PMArray p e s) Source #

thawMem :: MonadPrim s m => FrozenMem (PMArray p e) -> m (PMArray p e s) Source #

freezeMutMem :: MonadPrim s m => PMArray p e s -> m (FrozenMem (PMArray p e)) Source #

reallocMutMem :: (MonadPrim s m, Prim e0) => PMArray p e s -> Count e0 -> m (PMArray p e s) Source #

newtype MemState a s Source #

A wrapper that adds a phantom state token. It can be used with types that either don't have such state token or are designed to work in IO and therefore restricted to RealWorld. Using this wrapper is very much unsafe, so make sure you know what you are doing.

Constructors

MemState 

Fields

Instances

Instances details
MemWrite (MemState (ForeignPtr a)) Source # 
Instance details

Defined in Data.Prim.Memory.Internal

Methods

isSameMutMem :: MemState (ForeignPtr a) s -> MemState (ForeignPtr a) s -> Bool

readOffMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off e -> m e Source #

readByteOffMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off Word8 -> m e Source #

writeOffMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off e -> e -> m () Source #

writeByteOffMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off Word8 -> e -> m () Source #

moveByteOffToMBytesMutMem :: forall s m e (p :: Pinned). (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () Source #

moveByteOffToPtrMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () Source #

copyByteOffMem :: (MonadPrim s m, MemRead mr, Prim e) => mr -> Off Word8 -> MemState (ForeignPtr a) s -> Off Word8 -> Count e -> m () Source #

moveByteOffMutMem :: (MonadPrim s m, MemWrite mw', Prim e) => mw' s -> Off Word8 -> MemState (ForeignPtr a) s -> Off Word8 -> Count e -> m () Source #

setMutMem :: (MonadPrim s m, Prim e) => MemState (ForeignPtr a) s -> Off e -> Count e -> e -> m () Source #

Size

getCountMutMem :: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) => ma s -> m (Count e) Source #

Figure out how many elements fits into the mutable region of memory. Similar to countMem, except that it is not a pure funciton, since the size of mutable memory can change throuhout its lifetime. It is possible that there is a remainder of bytes left, see getCountRemMem for getting that too.

Examples

Expand
>>> mb <- thawMem (fromListMem [0 .. 5 :: Word8] :: Bytes 'Pin)
>>> getCountMutMem mb :: IO (Count Word16)
Count {unCount = 3}
>>> getCountMutMem mb :: IO (Count Word32)
Count {unCount = 1}
>>> getCountMutMem mb :: IO (Count Word64)
Count {unCount = 0}
>>> mb' <- reallocMutMem mb (6 :: Count Word64)
>>> getCountMutMem mb' :: IO (Count Word32)
Count {unCount = 12}

Since: 0.3.0

getCountRemMutMem :: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) => ma s -> m (Count e, Count Word8) Source #

Figure out how many elements and a byte size remainder can fit into the mutable region of memory. Similar to countRemMem, except it is a monadic action for mutable regions instead of a pure function for immutable memory. See getCountMutMem for getting the element count only.

Examples

Expand
>>> b <- thawMem (fromListMem [0 .. 5 :: Word8] :: Bytes 'Pin)
>>> getCountRemMutMem @Word16 b
(Count {unCount = 3},Count {unCount = 0})
>>> getCountRemMutMem @Word32 b
(Count {unCount = 1},Count {unCount = 2})
>>> getCountRemMutMem @Word64 b
(Count {unCount = 0},Count {unCount = 6})

Since: 0.3.0

getByteCountMutMem :: (MemAlloc ma, MonadPrim s m) => ma s -> m (Count Word8) Source #

Extract the number of bytes a mutable memory region can hold, i.e. what is the total allocated size for this region. The size of a region can be changes and in some circuimstances even in place without copy, see reallocMutMem for more info.

Examples

Expand
>>> m <- allocMutMem (10 :: Count Int64) :: IO (MBytes 'Pin RW)
>>> getByteCountMutMem m
Count {unCount = 80}

Since: 0.3.0

Read

readOffMutMem Source #

Arguments

:: (MemWrite mw, 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 <- getByteCountMutMem memRead
unOff (toByteOff off) <= unCount (count - byteCountType @e)
-> m e 

Read an element with an offset in number of elements, rather than bytes as it is the case with readByteOffMutMem.

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.3.0

readByteOffMutMem Source #

Arguments

:: (MemWrite mw, 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 <- getByteCountMutMem memRead
unOff (toByteOff off) <= unCount (count - byteCountType @e)
-> m e 

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.3.0

Write

writeOffMutMem Source #

Arguments

:: (MemWrite mw, 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 <- getByteCountMutMem memWrite
unOff (toByteOff off) <= unCount (count - byteCountType @e)
-> e

elt - Element to write

-> m () 

Write an element with an offset in number of elements, rather than bytes as it is the case with writeByteOffMutMem.

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.3.0

writeByteOffMutMem Source #

Arguments

:: (MemWrite mw, 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 <- getByteCountMutMem memWrite
unOff (toByteOff off) <= unCount (count - byteCountType @e)
-> e 
-> m () 

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.3.0

setMutMem Source #

Arguments

:: (MemWrite mw, 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 <- getByteCountMutMem 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 <- getByteCountMutMem 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 () 

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.3.0

modifyFetchOldMutMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> e) -> m e Source #

modifyFetchOldMutMemM :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> m e) -> m e Source #

modifyFetchNewMutMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> e) -> m e Source #

modifyFetchNewMutMemM :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> m e) -> m e Source #

Allocate

allocMutMem Source #

Arguments

:: (MemAlloc ma, Prim e, MonadPrim s m) 
=> Count e

memCount - Amount of memory to allocate for the region in number of elements of type e

Preconditions:

0 <= memCount

Possibility of overflow:

memCount <= fromByteCount maxBound

When converted to bytes the value should be less then available physical memory

-> m (ma s) 

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 allocZeroMutMem, unless it is guaranteed that all of allocated memory will be overwritten.

Unsafe
When any of preconditions for memCount argument is violated the outcome is unpredictable. One possible outcome is termination with HeapOverflow async exception. In a pure setting, such as when executed within runST, if allocated memory is not fully overwritten it can lead to violation of referential transparency, because contents of newly allocated region is non-determinstic.

Since: 0.3.0

allocZeroMutMem Source #

Arguments

:: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) 
=> Count e

memCount - Amount of memory to allocate for the region in number of elements of type e

Preconditions:

0 <= memCount

Possibility of overflow:

memCount <= fromByteCount maxBound

When converted to bytes the value should be less then available physical memory

-> m (ma s) 

Same as allocMutMem, but also use setMutMem to reset all of newly allocated memory to zeros.

Unsafe
When precondition for memCount argument is violated the outcome is unpredictable. One possible outcome is termination with HeapOverflow async exception.

Example

Expand
>>> :set -XTypeApplications
>>> :set -XDataKinds
>>> import Data.Prim.Memory
>>> mb <- allocZeroMutMem @Int @(MBytes 'Inc) 10
>>> b <- freezeMutMem mb
>>> toListMem b :: [Int]
[0,0,0,0,0,0,0,0,0,0]

Since: 0.3.0

reallocMutMem Source #

Arguments

:: (MemAlloc ma, 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) 

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.

Default implementation is defaultReallocMutMem

Unsafe
Undefined behavior when memSource is used afterwards. The same unsafety notice from allocMutMem with regards to memCount is applicable here as well.

Since: 0.3.0

withScrubbedMutMem :: forall e ma m a. (MonadUnliftPrim RW m, Prim e, MemAlloc ma, PtrAccess RW (ma RW)) => Count e -> (ma RW -> m a) -> m a Source #

Allocate a new region of memory and Ensure that it is filled with zeros before and after it gets used. PtrAccess is not used directly, but instead is used to guarantee that the memory is pinned and its contents will not get moved around by the garbage collector.

Since: 0.3.0

defaultReallocMutMem :: (Prim e, MemAlloc ma, MonadPrim s m) => ma s -> Count e -> m (ma s) Source #

An action that can be used as a default implementation for reallocMutMem. Whenever current memory region byte count matches the supplied new size exactly then such memory region is simply returned back and this function is a noop. Otherwise a new memory region is allocated and all the data that can fit into the new region will be copied over.

Unsafe
Same unsafety notice as in reallocMutMem

Since: 0.3.0

Thaw/Freeze

thawCloneMem :: forall ma m s. (MemAlloc ma, MonadPrim s m) => FrozenMem ma -> m (ma s) Source #

This is a safe version of thawMem. It first makes an exact copy of the supplied memory region and only then thaws it, thus yielding a mutable region of memory. This means any mutation, will only affect the newly allocated region that was returned and not the source region.

Examples

Expand
>>> :set -XTypeApplications
>>> :set -XDataKinds
>>> import Data.Prim.Memory
>>> let fm = fromListMem @Word8 @(MBytes 'Inc) [1,2,3,4]
>>> mm <- thawCloneMem fm
>>> writeOffMutMem mm 1 (0xadde :: Word16)
>>> freezeMutMem mm
[0x01,0x02,0xde,0xad]
>>> fm
[0x01,0x02,0x03,0x04]

Since: 0.1.0

thawCopyMem Source #

Arguments

:: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) 
=> FrozenMem ma

memSource - Read-only source memory region from which the data will copied and thawed

-> Off e

memSourceOff - Offset into source memory in number of elements of type e

Preconditions:

0 <= memSourceOff
unOff memSourceOff < unCount (countMem memSource)
-> Count e

memCount - Number of elements of type e to copy

Preconditions:

0 <= memCount
unOff memSourceOff + unCount memCount < unCount (countMem memSource)
-> m (ma s) 

Similar to thawCloneMem, except it is possible to specify which portion of the frozen region will be copied over and thawed.

Unsafe
When any precondition for eihter an offset memSourceOff or the element count memCount is violated a call to this function can result in: copy of data that doesn't belong to memSource or failure with a segfault.

Examples

Expand
>>> :set -XTypeApplications
>>> :set -XDataKinds
>>> import Data.Prim.Memory
>>> let fm = fromListMem @Word8 @(MBytes 'Inc) [1,2,3,4,5]
>>> mm <- thawCopyMem fm 1 (3 :: Count Word8)
>>> writeOffMutMem mm 1 (0 :: Word8)
>>> freezeMutMem mm
[0x02,0x00,0x04]
>>> fm
[0x01,0x02,0x03,0x04,0x05]

Since: 0.1.0

thawMem :: (MemAlloc ma, MonadPrim s m) => FrozenMem ma -> m (ma s) Source #

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 thawCloneMutMem for a safe alternative.

Unsafe
This function 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

freezeCloneMutMem :: forall ma m s. (MemAlloc ma, MonadPrim s m) => ma s -> m (FrozenMem ma) Source #

Safe version of freezeMutMem. Yields an immutable copy of the supplied mutable memory region. Further mutation of the source memory region will not affect the produced copy.

freezeCopyMutMem :: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) => ma s -> Off e -> Count e -> m (FrozenMem ma) Source #

freezeMutMem :: (MemAlloc ma, MonadPrim s m) => ma s -> m (FrozenMem ma) Source #

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.3.0

Move

cloneMutMem :: forall ma m s. (MemAlloc ma, MonadPrim s m) => ma s -> m (ma s) Source #

Allocate the same amount of memory as the source memory region and copy all of its data over.

Since: 0.3.0

moveMutMem Source #

Arguments

:: (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 () 

moveByteOffMutMem Source #

Arguments

:: (MemWrite mw, 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 <- getByteCountMutMem 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 <- getByteCountMutMem 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 <- getByteCountMutMem memSource
unOff memSourceOff + unCountBytes memCount <= unCount (sourceByteCount - byteCountType @e)
targetByteCount <- getByteCountMutMem memTarget
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.3.0

moveByteOffToMBytesMutMem Source #

Arguments

:: (MemWrite mw, 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 <- getByteCountMutMem 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 <- getByteCountMutMem 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 <- getByteCountMutMem memSource
unOff memSourceOff + unCountBytes memCount <= unCount (sourceByteCount - byteCountType @e)
targetByteCount <- getByteCountMutMem memTarget
unOff memTargetOff + unCountBytes memCount <= unCount (targetByteCount - byteCountType @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.3.0

moveByteOffToPtrMutMem Source #

Arguments

:: (MemWrite mw, 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 <- getByteCountMutMem 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 <- getByteCountMutMem memSource
unOff memSourceOff + unCountBytes memCount <= unCount (sourceByteCount - 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.3.0

Load list

loadListMutMem Source #

Arguments

:: 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.

Same as loadListMutMemN, but tries to fit as many elements as possible into the mutable memory region starting at the beginning. This operation is always safe.

Examples

Expand
>>> import Data.Prim.Memory
>>> ma <- allocMutMem (5 :: Count Char) :: IO (MBytes 'Inc RW)
>>> loadListMutMem "HelloWorld" ma
("World",Count {unCount = 5})
>>> freezeMutMem ma
[0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]
>>> loadListMutMem (replicate 6 (0xff :: Word8)) ma
([],Count {unCount = 6})
>>> freezeMutMem ma
[0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]

Since: 0.3.0

loadListMutMem_ Source #

Arguments

:: 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 () 

Same as loadListMutMem, but ignores the result. Equivalence as property:

let c = fromInteger (abs i) :: Count Int in (createZeroMemST_ c (loadListMutMem_ (xs :: [Int])) :: Bytes 'Inc) == createZeroMemST_ c (void . loadListMutMem xs)

Since: 0.2.0

loadListMutMemN Source #

Arguments

:: 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 <- getCountMutMem 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.

Same as loadListOffMutMemN, 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

loadListMutMemN_ Source #

Arguments

:: 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 <- getCountMutMem memTarget
elemCount <= targetCount
-> [e]

listSource - List with elements that should be loaded

-> mw s

memTarget - Memory region where to load the elements into

-> m () 

Same as loadListMutMemN, 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

With offset

loadListOffMutMem Source #

Arguments

:: 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 <- getCountMutMem 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.

Same as loadListOffMutMemN, 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.3.0

loadListOffMutMemN Source #

Arguments

:: (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 <- getCountMutMem 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 <- getByteCountMutMem 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.

Same as loadListByteOffMutMemN, 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

loadListByteOffMutMem Source #

Arguments

:: (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 <- getByteCountMutMem 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.

Same as loadListByteOffMutMemN, 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

Expand
>>> :set -XDataKinds
>>> import Data.Prim.Memory
>>> ma <- allocZeroMutMem (5 :: Count Char) :: IO (MBytes 'Inc RW)
>>> freezeMutMem ma
[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
>>> loadListByteOffMutMem "Hello World" ma 0
(" World",Count {unCount = 5})
>>> freezeMutMem ma
[0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]
>>> loadListByteOffMutMem ([0xff,0xff,0xff] :: [Word8]) ma 1
([],Count {unCount = 3})
>>> freezeMutMem ma
[0x48,0xff,0xff,0xff,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]

Since: 0.3.0

loadListByteOffMutMemN Source #

Arguments

:: (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 <- getByteCountMutMem 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 <- getByteCountMutMem 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.

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

Expand

For example load the Hell somewhere in the middle of MBytes:

>>> ma <- allocZeroMutMem (6 :: Count Char) :: IO (MBytes 'Inc RW)
>>> loadListByteOffMutMemN 4 "Hello!" ma (toByteOff (1 :: Off Char))
("o!",Count {unCount = 4})
>>> freezeMutMem 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 useful like loading prefixes from nested lists:

>>> import Control.Monad
>>> foldM_ (\o xs -> (+ o) . countToByteOff . snd <$> loadListByteOffMutMemN 4 xs ma o) 2 [[x..] | x <- [1..5] :: [Word8]]
>>> freezeMutMem 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