ddn.adam

Compact Dynamic Value Type

This module provides adam, a memory-efficient dynamic value type designed to match the semantics and API of ddn.var while minimizing memory footprint. It is suitable for applications where large numbers of dynamic values must be stored or transmitted with minimal overhead.

Features:

  • Compact representation: only 16 bytes on 64-bit platforms (vs. typical 24+ bytes for variant types).
  • Tagged-length encoding: type tag and collection length share a single size_t word.
  • Full numeric tower: supports bool, all D integer types, float, double, and dchar.
  • Composite types: arrays (adam[]) and objects (adam[string]) with JSON-like semantics.
  • Type normalization: realdouble, char/wchardchar to keep the tag space small.
  • GC-safe: pointer payloads are never tagged, preserving garbage collector reachability.
  • API compatibility: mirrors ddn.var operators, conversions, and serialization methods.

Differences from ddn.var:

  • No temporal types: adam intentionally does not support DATE, TIME, DATETIME,

    SYSTIME, or DURATION types. This is a deliberate design choice to maintain compactness and simplicity. Applications requiring temporal values should use ddn.var instead, or encode temporal values as strings or numeric timestamps.

  • Type normalization: real is stored as double, and char/wchar are stored as dchar,

    reducing the number of type tags needed.

  • String ownership: adam copies string data on assignment (via .idup) to ensure

    memory safety, whereas some operations may differ from var.

Example:

import ddn.adam;

// Scalar values
adam i = 42;
adam d = 3.14;
adam s = "hello";

// Arrays
adam arr = [adam(1), adam(2), adam(3)];
assert(arr.length == 3);

// Objects
adam obj;
obj["name"] = "alice";
obj["age"] = 30;
assert(obj["name"].get!string == "alice");

// JSON serialization
string json = obj.toJSON();

Platform Notes:

  • On 64-bit systems: adam.sizeof == 16.
  • On 32-bit systems: adam.sizeof == 8, but array/string lengths are limited to 28 bits.

See Also

ddn.var for a full-featured dynamic value type with richer semantics,

ddn.data.json5 for JSON5 parsing and serialization utilities.

Types 5

structadam

ddn.adam — a compact dynamic value type.

This implementation aims to match ddn.var semantics and API shape as closely as possible, while keeping the value representation very small.

Representation:

  • A scalar-or-pointer payload word (_data).
  • A tagged length word (_lenTag) that packs the Type tag into the high bits and

(for STRING and ARRAY) the length into the low bits.

Type normalization (to keep the tag space small):

  • real values are stored as Type.DOUBLE (converted to double).
  • char and wchar values are stored as Type.DCHAR (converted to dchar).

On 64-bit platforms (size_t.sizeof == 8):

  • adam.sizeof == 16 (payload 8 bytes + tagged-length 8 bytes).

On 32-bit platforms (size_t.sizeof == 4):

  • the same tagged-length scheme is used, but the length field is smaller.
  • With the current TAG_BITS = 4, array/string lengths are limited to 28 bits

(i.e., max length 2^28 - 1).

Important design rule:

  • The pointer payload is never tagged, to preserve GC reachability.
  • The tagged length is opaque; any time a real D slice is constructed, the length

is masked before use.

Fields
Data _data
size_t _lenTag
private 4 TAG_BITS
private size_t TAG_SHIFT
private size_t LEN_MASK
private size_t TAG_MASK
private size_t LENGTH_BITS
Methods
private Type _type() @property const nothrow @nogc pure @safe
private void _setType(Type t) nothrow @nogc pure @safe
private size_t _lengthBits() @property const nothrow @nogc pure @safe
private void _validateLength(size_t n) @safeValidate that a length value fits in the tagged-length representation.
private void _setLengthBits(size_t n) nothrow @nogc pure @safeSet the length bits in the tagged-length word.
private void _clearPayload() nothrow @nogc pure @trusted
void clear() @safe nothrow @nogc pureReset this value to NULL.
Type type() @property const nothrow @nogc pure @safeGet the current type tag (property form like `var.type`).
adam opAssign(T)(T rhs) @safe
bool isNull() @property const nothrow @nogc pure @safe
bool isBool() @property const nothrow @nogc pure @safe
bool isArray() @property const nothrow @nogc pure @safe
bool isString() @property const nothrow @nogc pure @safe
bool isObject() @property const nothrow @nogc pure @safe
bool isNumeric() @property const nothrow @nogc pure @safe
private bool _getBool() const @trusted
private byte _getByte() const @trusted
private ubyte _getUbyte() const @trusted
private short _getShort() const @trusted
private ushort _getUshort() const @trusted
private int _getInt() const @trusted
private uint _getUint() const @trusted
private long _getLong() const @trusted
private ulong _getUlong() const @trusted
private float _getFloat() const @trusted
private double _getDouble() const @trusted
private double _getReal() const @trusted
private char _getChar() const @trusted
private wchar _getWchar() const @trusted
private dchar _getDchar() const @trusted
private string _getString() const @trusted
private adam[] _getArray() const @trusted
private ObjectBox * _getObjectBox() const @trusted
T as(T)() const @trustedConvert to target type `T`. Returns `T.init` on failure (matches `var.as!T` behavior).
Nullable!T tryAs(T)() const @safe`tryAs!T` returns a `Nullable!T` that is null when conversion fails.
string toString() const @trustedJSON-like representation (matches `var.toString()` style).
size_t length() @property const @safeArray length (0 for NULL). Asserts for other non-array types.
size_t opDollar() @property const @safeSupport `$` in slice expressions for arrays (0 for NULL).
private adam _arrayElemAt(size_t index) ref @trusted
private const(adam) _arrayElemAtConst(size_t index) ref const @trusted
adam opIndex(size_t index) ref @safe
const(adam) opIndex(size_t index) ref const @safe
void opIndexAssign(T)(T rhs, size_t index) @safeAssign a value to an array element at the given index.
adam opSlice(size_t start, size_t end) const @safeSlice an array and return a new ARRAY value (copies elements).
void append(T)(T rhs) @safeAppend to array (promotes NULL -> ARRAY).
void opOpAssign(string op, T)(T rhs) if (op == "~") @safe
bool insert(T)(size_t index, T rhs) @safeInsert `rhs` at position `index` (0..length). Returns false if index is out of range.
bool removeAt(size_t index) @safeRemove element at `index`. Returns false if out of range or NULL.
int opApply(scope int delegate(ref adam) dg)Foreach support over arrays.
private ObjectBox * _ensureObjectBox(string op) @trustedPromote NULL -> OBJECT and ensure a box exists.
adam opIndex(string key) ref @safe
const(adam) opIndex(string key) ref const @safe
void opIndexAssign(T)(T rhs, string key) @safe
adam opDispatch(string name)() ref @safe
bool contains(const string key) const @safe
adam get(TDefault)(const string key, TDefault defaultValue) const @safe
bool remove(string key) @safe
size_t count() @property const @safe
string[] keys() @property const @safe
adam[] values() @property const @safe
int opApply(scope int delegate(const string, ref adam) dg)Foreach support over map entries.
adam merge(const adam other, bool deepMerge = false) ref return @safeMerge another object into this one (like `var.merge`).
adam dup() const @safe
adam idup() const @safe
adam getField(T)(const string key, T defaultValue) const @safe
adam path(const string[] pathParts) const @safe
adam path(const string pathStr) const @safe
auto visit(handlers...)() const @safe
private R _unreachable(R)(string msg) @trusted
private static auto _visitDispatch(R, T, handlers...)(T value) @safe
private bool _isNumericType(Type t) nothrow @nogc pure @safe
private bool _isFloatingType(Type t) nothrow @nogc pure @safe
private double _toDouble() const @trusted
private long _toLong() const @trustedConvert the stored value to `long` for arithmetic.
private ulong _toUlong() const @trustedConvert the stored value to `ulong` for arithmetic.
private dchar _toCodePoint(const adam v) @trusted
int opCmp(const adam rhs) const @safeThree-way comparison (parity with `var.opCmp`).
bool opEquals(const adam other) const @safe
size_t toHash() const @safeReturns a hash value for this `adam`.
adam makeArray() @safe
adam makeObject() @safe
Constructors
this(T arg)Construct from another value `arg` (mirrors `var.this(T)`).
Nested Templates
Type
ObjectBox
classAdamException : Exception

Base exception type for ddn.adam runtime misuse.

Constructors
this(string msg, string file = __FILE__, size_t line = __LINE__)

Thrown when an operation requires a specific runtime adam.Type.

Constructors
this(string op, adam.Type expected, adam.Type actual, string details = null, string file = __FILE__, size_t line = __LINE__)

Thrown when an object key is missing for an operation that requires it.

Constructors
this(string op, string key, string file = __FILE__, size_t line = __LINE__)

Thrown when an array index is out of range for an operation that requires it.

Constructors
this(string op, size_t index, size_t length, string file = __FILE__, size_t line = __LINE__)