Class MemorySession
- Namespace
- CStructSharp.Memory
- Assembly
- CStructSharp.dll
Caller-owned arrays and explicitly bounded transport operations.
public sealed class MemorySession
- Inheritance
-
MemorySession
- Inherited Members
Remarks
A session joins two independent descriptions. The schema says how a type's bytes are arranged; a region says where some bytes live. Neither knows about the other, so one session can read the same record type from a file, from a mapped process image, and from a test fixture. The session itself keeps no bytes and no per-region state, which is why it can be reused freely and why every operation takes its own MemoryAccessContext.
The main operations build on one another. Resolve(MemoryRegion, string, string, MemoryAccessContext?) turns a path such as
"items[2].next.value.pid" into a MemorySelection: the region, type, and field the path
names. Read(MemoryRegion, string, string, MemoryAccessContext?) resolves and then decodes the selected bytes. Inspect(MemoryRegion, string, string, MemoryAccessContext?) additionally
flattens mapping layers to report where the bytes physically came from. PlanUpdate(MemoryRegion, string, string, object?, MemoryAccessContext?) resolves,
reads the current bytes, encodes the new value over them, and returns a MemoryPatch that a caller
commits separately. Serialize(string, object?, MemoryAccessContext?) stands apart: it needs no region because it creates new bytes.
Pointers are the one place where the session must read data to know where to go next. Reading a pointer field
yields a StoredPointer and stops. Only the explicit .value path step calls the resolver
supplied at construction, which may apply a relative base, strip a tag, or switch to another address space.
The default resolver treats a nonzero stored value as an absolute address in the same source. Primitive decoding and
encoding always go through the core compiled codecs; composite traversal applies the schema's explicit offsets.
Failures use the core CStructException hierarchy. A path that cannot be parsed or resolved against
the schema throws CStructPathException; a value that does not have the declared shape throws
CStructWriteException; memory that cannot be read throws MemoryAccessException, a
CStructReadException. When one of these crosses a session operation, the session records the
requested typeId.path as Path and, for a memory access failure, the root
region as LogicalRegion. Null arguments and cancellation keep their .NET
exception types.
Constructors
MemorySession(MemorySchema, Func<PointerRequest, MemoryAccessContext, MemoryRegion>?)
Creates a session over a compiled schema, optionally with a custom pointer resolver.
public MemorySession(MemorySchema schema, Func<PointerRequest, MemoryAccessContext, MemoryRegion>? resolver = null)
Parameters
schemaMemorySchemaValidated type graph that describes the records this session reads.
resolverFunc<PointerRequest, MemoryAccessContext, MemoryRegion>Turns stored pointer bits into a target region using the active operation context; null selects absolute addressing in the pointer's own source. The callback must forward this context to translation reads and must not retain it.
Properties
Schema
Gets the immutable compiled schema this session applies.
public MemorySchema Schema { get; }
Property Value
Methods
Inspect(MemoryRegion, string, string, MemoryAccessContext?)
Reads one selection and reports both its logical location and the physical backing ranges that supplied its bytes.
public MemoryInspection Inspect(MemoryRegion region, string typeId, string path = "", MemoryAccessContext? context = null)
Parameters
regionMemoryRegionFinite caller-owned region holding the root record.
typeIdstringID of the root record's type in the schema.
pathstringMember/index path from the root; pointer targets need an explicit
.valuestep.contextMemoryAccessContextShared operation budget and cancellation, or null to create a default budget.
Returns
- MemoryInspection
The value, its selection metadata, and the ordered backing ranges.
Remarks
Use this for an inspector that must show where a value came from. Flattening mapping tables costs extra requests beyond the value read, so prefer Read(MemoryRegion, string, string, MemoryAccessContext?) when provenance is unnecessary. Backing ranges follow every MappedMemorySource layer; a custom source is reported as-is because the library cannot see inside it. The result describes this read; it does not lock the bytes against later change.
Exceptions
- ArgumentNullException
regionorpathis null.- CStructPathException
typeIdis unknown, or the path is malformed or names no member, element, or pointer that can be followed.- MemoryAccessException
The bytes needed to resolve or read the value are unavailable, a followed pointer is null, or the budget is exhausted.
- OperationCanceledException
The context's token was cancelled.
PlanUpdate(MemoryRegion, string, string, object?, MemoryAccessContext?)
Stages a replacement of the selected storage, preserving every byte and bit the new value does not cover. Nothing is written.
public MemoryPatch PlanUpdate(MemoryRegion region, string typeId, string path, object? value, MemoryAccessContext? context = null)
Parameters
regionMemoryRegionFinite caller-owned region holding the root record.
typeIdstringID of the root record's type in the schema.
pathstringMember/index path from the root; pointer targets need an explicit
.valuestep.valueobjectNew value in the declared shape of the selected type.
contextMemoryAccessContextShared operation budget and cancellation, or null to create a default budget.
Returns
- MemoryPatch
An immutable preview of the physical writes; no backing bytes are changed.
Remarks
The selected bytes are read first and the new value is encoded over a copy of them, so padding and neighboring bit slices survive. Replacing a whole union with a UnionValue that selects a member is the exception: the union is cleared before the chosen member is encoded. The returned patch has already flattened mapping layers and captured expected bytes, which means planning reads the storage more than once and needs a budget larger than the replacement length. Call Commit(MemoryAccessContext?) to perform the writes.
Exceptions
- ArgumentNullException
regionorpathis null.- CStructPathException
typeIdis unknown, or the path is malformed or names nothing writable.- CStructWriteException
valuedoes not have the declared shape, or a bit-slice value is out of range.- MemoryAccessException
The current bytes are unavailable, the selection exceeds the byte budget, or planning found a stale source.
- OperationCanceledException
The context's token was cancelled.
Read(MemoryRegion, string, string, MemoryAccessContext?)
Resolves a path and decodes the selected value. Pointers stay StoredPointer unless the path consumes .value.
public object? Read(MemoryRegion region, string typeId, string path = "", MemoryAccessContext? context = null)
Parameters
regionMemoryRegionFinite caller-owned region holding the root record.
typeIdstringID of the root record's type in the schema.
pathstringMember/index path from the root; pointer targets need an explicit
.valuestep.contextMemoryAccessContextShared operation budget and cancellation, or null to create a default budget.
Returns
- object
The decoded scalar, stored pointer, structure, or fixed array.
Remarks
An empty path reads the root. Values have the shapes the core reader returns: a struct is a StructValue, a union a UnionValue with its raw storage and every member's interpretation of it, an array of a numeric or bool scalar a PrimitiveArray<T> and any other array a List<T> of object, a scalar its codec's managed type, and a signed bit slice a long. A selected path decodes only the storage it needs, so an unavailable unrelated member does not prevent reading a known field. Reading a whole union does not decide which member the application's tag selects.
Exceptions
- ArgumentNullException
regionorpathis null.- CStructPathException
typeIdis unknown, or the path is malformed or names no member, element, or pointer that can be followed.- MemoryAccessException
The bytes needed to resolve or read the value are unavailable, a followed pointer is null, or the budget is exhausted.
- OperationCanceledException
The context's token was cancelled.
ReadArray<T>(MemoryRegion, string, Span<T>, MemoryAccessContext?, MemoryArrayReadMode, int)
Decodes a caller-counted numeric or stored-pointer array within an explicit permitted storage extent.
public void ReadArray<T>(MemoryRegion storage, string elementTypeId, Span<T> destination, MemoryAccessContext? context = null, MemoryArrayReadMode mode = MemoryArrayReadMode.Elementwise, int chunkBytes = 4096) where T : unmanaged
Parameters
storageMemoryRegionExplicitly permitted array extent, independent of a fixed-size root header. No read may exceed it.
elementTypeIdstringSchema identity of one scalar or pointer element.
destinationSpan<T>Caller-owned destination; its element count determines the read count.
contextMemoryAccessContextShared budget and cancellation.
modeMemoryArrayReadModeElementwise by default; Bulk explicitly changes requests and failure boundaries.
chunkBytesintMaximum bulk request bytes, 1 to 65536 and at least one complete element.
Type Parameters
TExact numeric codec type; use ulong for pointers of any supported width, preserving all stored bits.
Remarks
On an unavailable-memory outcome every complete element of the confirmed copied prefix is committed, even within the final partial chunk. Unread elements remain untouched; an incomplete element's staged bytes are discarded. Custom codecs and enums use the ordinary API. Counts and total extent are validated before transport or staging allocation.
ReadBytes(MemoryRegion, string, string, MemoryAccessContext?)
Reads a declared one-byte integer array into its final owned raw-byte result without an intermediate numeric array.
public byte[] ReadBytes(MemoryRegion region, string typeId, string path = "", MemoryAccessContext? context = null)
Parameters
regionMemoryRegionFinite root record.
typeIdstringRoot schema identity.
pathstringRelative byte-array path.
contextMemoryAccessContextShared operation context; the full byte count is checked before allocation.
Returns
- byte[]
A complete owned array; missing bytes never become zero padding.
Exceptions
- ArgumentException
The path does not select a one-byte integer array.
- MemoryAccessException
The source is unavailable or the operation budget is exhausted.
ReadBytes(MemoryRegion, string, string, Span<byte>, MemoryAccessContext?)
Copies a declared byte or signed-byte array directly to caller-owned raw storage.
public void ReadBytes(MemoryRegion region, string typeId, string path, Span<byte> destination, MemoryAccessContext? context = null)
Parameters
regionMemoryRegionFinite root record.
typeIdstringRoot type identity.
pathstringPath to a fixed one-byte integer array.
destinationSpan<byte>Destination with exactly the declared element count.
contextMemoryAccessContextShared context, or null to create one.
Remarks
The destination must hold exactly the declared count. Each byte is read individually. Use ReadArray with Bulk for explicit chunked transport. A failure can leave a written prefix; no unread byte is manufactured.
Exceptions
- ArgumentException
The path does not select a byte array or its count differs from the destination.
Resolve(MemoryRegion, string, string, MemoryAccessContext?)
Walks a path step by step to the region, type, and field it names, without decoding the final value.
public MemorySelection Resolve(MemoryRegion region, string typeId, string path = "", MemoryAccessContext? context = null)
Parameters
regionMemoryRegionFinite caller-owned region holding the root record.
typeIdstringID of the root record's type in the schema.
pathstringMember/index path from the root; pointer targets need an explicit
.valuestep.contextMemoryAccessContextShared operation budget and cancellation, or null to create a default budget.
Returns
- MemorySelection
The selected storage location and its metadata; the value is not decoded.
Remarks
The walk starts with the root type over the root region and applies one token at a time. A member name
slices the current region by the field's offset; an index slices an array by element size; both are pure
arithmetic on schema data. A .value step on a pointer is different: the session must read the pointer
bytes, refuse null and incomplete targets, and ask the resolver for the target region, which may lie outside
the root region or in another source. A .address step keeps the pointer's stored-bit semantics and
must end the path, so an update through it can never encode a resolved target by mistake.
Member and index steps count against the context's MaxNestingDepth, which
restarts at each pointer target; every .value step counts against
MaxPointerDepth. Together they bound pathological paths and pointer chains.
Exceptions
- ArgumentNullException
regionorpathis null.- CStructPathException
typeIdis unknown, or the path is malformed or names no member, element, or pointer that can be followed.- MemoryAccessException
The bytes needed to resolve or read the value are unavailable, a followed pointer is null, or the budget is exhausted.
- OperationCanceledException
The context's token was cancelled.
Serialize(string, object?, MemoryAccessContext?)
Creates the bytes of one new record from zero-filled storage. Gaps and unselected union bytes stay zero.
public byte[] Serialize(string typeId, object? value, MemoryAccessContext? context = null)
Parameters
typeIdstringID of the type to encode.
valueobjectValue in the declared shape for that type.
contextMemoryAccessContextShared operation budget and cancellation, or null to create a default budget.
Returns
- byte[]
A new owned byte array of the type's size containing the encoded value.
Remarks
Struct input is a dictionary of member values, an array is an IList of the declared count, a pointer is a StoredPointer of the declared width, and a union is a UnionValue, as for the core writer: FromRaw(string, ReadOnlySpan<byte>) for its exact bytes or FromMember(string, string, object?) for one member. The method creates storage for this one value only; it does not allocate pointer targets or choose addresses. Write the result into a source yourself or pass it to Create(MemoryRegion, ReadOnlySpan<byte>, MemoryAccessContext?, byte[]?). Unlike PlanUpdate(MemoryRegion, string, string, object?, MemoryAccessContext?), this starts from zeroes, so padding recorded by the metadata is initialized to zero rather than preserved.
Exceptions
- CStructPathException
typeIdis unknown or names an incomplete type.- CStructWriteException
valuedoes not have the declared shape, or a scalar codec rejects it.- MemoryAccessException
The output or the nesting exceeds the budget; the failure has no source coordinates.
- OperationCanceledException
The context's token was cancelled.
TryReadArray<T>(MemoryRegion, string, Span<T>, out int, out MemoryReadFailure?, MemoryAccessContext?, MemoryArrayReadMode, int)
Decodes a bounded caller-counted array, reporting completed elements and expected memory failure as data.
public bool TryReadArray<T>(MemoryRegion storage, string elementTypeId, Span<T> destination, out int elementsWritten, out MemoryReadFailure? failure, MemoryAccessContext? context = null, MemoryArrayReadMode mode = MemoryArrayReadMode.Elementwise, int chunkBytes = 4096) where T : unmanaged
Parameters
storageMemoryRegionFinite permitted byte extent; a flexible-array count never extends this region.
elementTypeIdstringScalar or pointer element identity.
destinationSpan<T>Caller-owned values; unread elements are untouched.
elementsWrittenintComplete elements committed, including the confirmed prefix of a failed chunk.
failureMemoryReadFailureMemory failure on false, null on success.
contextMemoryAccessContextOperation budget; exhaustion and cancellation propagate.
modeMemoryArrayReadModeExplicit transport shape.
chunkBytesintBulk staging/request bound in bytes, at most 65536.
Returns
- bool
Whether every element was decoded.
Type Parameters
TExact primitive result type, or ulong for stored pointers.
Exceptions
- ArgumentException
Element type, destination extent or mode is invalid.
- MemoryAccessException
The remaining operation budget is insufficient.
- OperationCanceledException
Cancellation was requested.
TryResolve(MemoryRegion, string, string, out MemorySelection?, out MemoryReadFailure?, MemoryAccessContext?)
Resolves a path while returning expected schema and memory failures as structured data.
public bool TryResolve(MemoryRegion region, string typeId, string path, out MemorySelection? selection, out MemoryReadFailure? failure, MemoryAccessContext? context = null)
Parameters
regionMemoryRegionFinite root storage.
typeIdstringRoot schema identity.
pathstringRelative member/index/pointer path.
selectionMemorySelectionSelected storage when true.
failureMemoryReadFailureStructured outcome when false.
contextMemoryAccessContextShared operation context; budget exhaustion and cancellation propagate.
Returns
- bool
Whether the complete path resolved.