Wire data and serialization

#[wire] marks records, enums, and machines whose schema can cross a service or remote-actor boundary. Fields and variants receive stable numeric identities. Assign explicit @N tags for a published schema, and reserve a deleted tag instead of reusing it.

#[serial(case = "camelCase")]
#[wire(version = 1, min_version = 1)]
type User {
    id: u64 @1;
    display_name: string @2;
    email: Option<string> @3 optional;
    reserved @4;
}

fn main() {
    let user = User {
        id: 7,
        display_name: "Ada",
        email: .None,
    };
    println(user.display_name);
}

Required Option<T> fields encode None as a present null. An optional Option<T> field omits its key when it is None. Changing between required and optional is incompatible. Unknown fields are discarded when decoding, so decoding and re-encoding does not preserve them.

CBOR is the binary wire and inter-node format. JSON and YAML are text interchange formats. JSON uses field names; #[serial(case = "camelCase")] sets a type-wide convention and #[serial(key = "name")] overrides one field. JSON encodes bytes as base64 text, while CBOR uses byte strings.

Run hew wire check --against path/to/published/schema in CI. It rejects reused or changed tags, incompatible field presence, and other breaking changes. Generic wire declarations are schema families: each concrete argument must itself be admissible when encoded or sent remotely.