Skip to main content

Module binding

Module binding 

Source
Expand description

Data-model binding: JSON Pointer resolution, scopes, and formatString.

A2UI keeps UI structure and application state apart. Components reference state through JSON Pointers, resolved against the surface’s data model at render time.

§Absolute and relative paths

A2UI deliberately extends RFC 6901 with relative paths to make template iteration expressible:

  • A path starting with / is absolute and always resolves from the root of the data model, wherever the component sits in the tree.
  • A path not starting with / is relative and resolves inside the current collection scope. A container whose children is a template over /employees opens one scope per element, so name inside the template resolves to /employees/0/name, /employees/1/name, and so on.

Scope models exactly this: Scope::root for the default scope and Scope::item to descend into one element of a bound collection.

§Stringification

Whenever a non-string is interpolated into text, the conversion is fixed by spec so every renderer agrees: numbers and booleans use their standard representation, null and missing paths become "", and objects and arrays are stringified as compact JSON.

use ag_ui_a2ui::binding::Scope;
use serde_json::json;

let data = json!({"company": "Acme", "employees": [{"name": "Alice"}, {"name": "Bob"}]});
let root = Scope::root(&data);
let item = root.item("/employees", 1);

// Relative inside the collection scope, absolute escapes back to the root.
assert_eq!(item.format_string("${name} @ ${/company} (#${@index(offset: 1)})").unwrap(),
           "Bob @ Acme (#2)");

§Depth

Resolution walks a serde_json::Value, and a walk over a tree is a stack frame per level unless something stops it. Two things do. Anything arriving over the wire has already passed through serde_json, which refuses to parse deeper than 127 levels, so a Value from a model or a transport is bounded before this module sees it. On top of that, Scope::resolve_dynamic and collect_bindings carry their own cap (MAX_VALUE_DEPTH) for values built in memory, which serde_json does not check. The component graph — where depth is genuinely unbounded — is walked iteratively in crate::validate instead.

Structs§

Binding
One data-model path reference found inside a component.
Scope
An evaluation scope: a data model plus the collection context bindings resolve against.

Constants§

MAX_VALUE_DEPTH
Deepest nesting these walks will descend into a value.

Traits§

FunctionResolver
Supplies renderer-side functions to formatString beyond the built-ins.

Functions§

collect_bindings
Every data-model path referenced anywhere inside a JSON value.
stringify
Renders a value as a string using A2UI’s fixed conversion rules.