# WASM Phase 1: DValue C ABI and UCEB1 Phase 1 freezes the native DValue ABI that the future WASM core and units use as their shared structured-value contract. The implementation is in `src/lib/dvalue.{h,cpp}` and is available in the native runtime before any WASM backend is enabled. ## Opaque handle ```c typedef struct DValue uce_dvalue; ``` `uce_dvalue*` is a borrowed pointer owned by the active request/workspace. It must not be freed by ABI callers and it must not be retained beyond that workspace lifetime. ## Accessors ```c uce_dvalue* uce_dv_root(void); uce_dvalue* uce_dv_get(uce_dvalue* value, const char* key, size_t key_len); uce_dvalue* uce_dv_find(uce_dvalue* value, const char* key, size_t key_len); const char* uce_dv_value(uce_dvalue* value, size_t* len_out); void uce_dv_set_value(uce_dvalue* value, const char* bytes, size_t len); size_t uce_dv_count(uce_dvalue* value); int uce_dv_is_list(uce_dvalue* value); ``` - `uce_dv_root()` returns the current native request's `context.call` root. The WASM core will later map this to the decoded request context root. - `uce_dv_get()` creates the child if absent. `uce_dv_find()` returns `NULL` if absent. - String inputs and outputs are length-delimited and binary-safe. - `uce_dv_value()` returns a borrowed pointer valid until the next ABI value call on the same thread. - Bad `NULL` inputs return `NULL`, zero, or no-op rather than trapping. ## Iteration ```c typedef struct uce_dv_iter { size_t position; size_t reserved[3]; } uce_dv_iter; uce_dv_iter uce_dv_iter_begin(uce_dvalue* value); int uce_dv_iter_next(uce_dvalue* value, uce_dv_iter* iter, const char** key_out, size_t* key_len_out, uce_dvalue** child_out); ``` Map iteration follows DValue's native order. List-shaped maps iterate in numeric index order (`0`, `1`, ...), matching `DValue::each()`, `dv_values()`, and the serializers. The reserved iterator fields are caller-opaque and must be zero-preserved by callers that copy the iterator; they provide ABI headroom for future non-linear keyed-map iteration without changing the struct size. ## UCEB1 wire format UCEB1 is the membrane/cross-instance binary DValue encoding. ``` document := "UCEB" version node version := 0x01 node := flags scalar children flags := u8 bitset; bit0 = list-shaped map scalar := varuint length, bytes children := varuint count, count * (key, node) key := varuint length, bytes ``` Varuint is unsigned LEB128. Strings are byte sequences; the codec does not assume NUL termination and preserves embedded NUL bytes. The Phase 1 layout stores scalar values as their native string representation plus child nodes and the list-shape flag. Floating-point values use `max_digits10` precision so numeric scalars can round-trip through the string form. Pointer/reference identity is intentionally not part of the wire contract; pointer nodes encode as an empty scalar rather than leaking process addresses. An empty non-list map has no wire distinction from an empty scalar in UCEB1 v1. Documents that contain both scalar bytes and child nodes are reserved for future use; the v1 decoder accepts the children and ignores the scalar. ## Codec APIs C++/UCE-visible helpers: ```cpp String ucb_encode(const DValue& value); DValue ucb_decode(const String& encoded); bool ucb_decode(const String& encoded, DValue& out, String* error_out = 0); ``` C ABI helpers: ```c size_t uce_dv_encode(uce_dvalue* value, char* buf, size_t cap); uce_dvalue* uce_dv_decode(const char* buf, size_t len); const char* uce_dv_last_error(void); ``` `uce_dv_encode()` returns the required byte length even when `buf` is `NULL` or `cap` is zero. `uce_dv_decode()` returns a thread-local decoded root, or `NULL` with `uce_dv_last_error()` populated. The returned decoded root is valid until the next `uce_dv_decode()` call on the same thread. Decoding rejects documents deeper than 1024 nested nodes so malformed input cannot recurse without bound. ## Test coverage `site/tests/core.uce` covers: - UCEB1 round-trip for maps, nested values, lists, empty lists, and embedded NUL scalar bytes. - C ABI get/find/value/count/list/iteration/encode/decode behavior.