Table of Contents

Class VBUserDefinedTypeLayout

Namespace
RDCore.SDK.Model.Types
Assembly
RDCore.SDK.dll

Where each field of a VBUserDefinedType sits in memory, and how much memory the whole type occupies — MS-VBAL §2.1's "linear concatenation of the aggregated data values possibly with implementation defined padding between data values".

public sealed class VBUserDefinedTypeLayout
Inheritance
VBUserDefinedTypeLayout
Inherited Members

Remarks

A UDT has two sizes, and MS-VBAL §6.1.2.11 says so where it defines Len and LenB: "with user-defined types, Len returns the size as it will be written to the file", while "LenB returns the in-memory size, including any implementation-specific padding between elements". This is the second one. The first belongs to whatever writes the record — a Put statement concatenates the fields with no padding at all, so a file is never laid out like memory is.

🎯 The padding is "implementation-specific" by the specification's own word, so RDCore is free to choose it — and chooses MS-VBA's, because a UDT is exactly the kind of thing whose in-memory size a program measures with LenB and then relies on. Each field is aligned to its own natural boundary, and the type as a whole is padded up to the strictest boundary any of its fields asked for.

👉 Widths here are memory widths, which are not always the widths the same value takes in a file: a variable-length String field is a pointer in memory and its characters in a record, and a fixed-length String field is Unicode in memory and ANSI in a record. That is the whole reason Len and LenB disagree about a UDT.

Fields

DefaultPointerWidth

The pointer width a layout assumes when the caller does not say — 32-bit, which is the width every MS-VBA UDT is laid out for, and therefore the one a file or a LenB from MS-VBA agrees with.

public const int DefaultPointerWidth = 4

Field Value

int

Remarks

🚧 A 64-bit host lays the same declaration out differently (a pointer field, and LongPtr, both widen). TODO thread the environment's own pointer width through to here, the way CLngPtr's declared type already is, once a UDT can be declared in a 64-bit host session.

MaxAlignment

The strictest boundary any field is aligned to, whatever its natural alignment would be.

public const int MaxAlignment = 8

Field Value

int

Remarks

An 8-byte boundary, which is what a Double, a Currency and a Date each ask for. Nothing in a UDT asks for more: a Variant is sixteen bytes of data but is itself aligned to eight, and a fixed-length String or a Byte to one.

Properties

Alignment

The boundary the type as a whole is aligned to: the strictest any of its fields asked for.

public int Alignment { get; }

Property Value

int

Fields

Each field, in declaration order, with the offset it sits at.

public IReadOnlyList<VBUserDefinedTypeField> Fields { get; }

Property Value

IReadOnlyList<VBUserDefinedTypeField>

Size

The in-memory size of the whole type, padding included — what LenB reports.

public int Size { get; }

Property Value

int

Methods

Of(VBUserDefinedType, int)

Lays type out.

public static VBUserDefinedTypeLayout Of(VBUserDefinedType type, int pointerWidth = 4)

Parameters

type VBUserDefinedType

The type to lay out.

pointerWidth int

The host's pointer width in bytes; DefaultPointerWidth unless the caller knows better.

Returns

VBUserDefinedTypeLayout

OffsetOf(string)

The offset of the field named name, or null when the type has no such field.

public int? OffsetOf(string name)

Parameters

name string

The field name, compared the way VBA compares identifiers.

Returns

int?