pub trait ContractBody:
Serialize
+ DeserializeOwned
+ Clone
+ Send
+ Sync
+ 'static {
type Api: ApiVersion;
const FAMILY: &'static str;
const SCHEMA_ID: &'static str;
const TOPIC: &'static str;
}Expand description
The contract primitive traits, re-exported from the phoxal-bus crate (the
ABI floor) so they stay addressable at phoxal_api::ApiVersion /
phoxal_api::ContractBody.
ApiVersionis the marker trait identifying one dated API version (D60), implemented only by the zero-variantenum Api {}thatphoxal_api_tree!generates inside each version module; itsIDis the dated module name ("y2026_1") and is carried in bus metadata as informational provenance.ContractBodyis a version-local wire body (D61): a plain serde type bound to exactly oneApiVersionand one contract family/topic. Every body declared inside aphoxal_api_tree!node gets a generated impl; handles,SetupContextbuilders, and theService/Driverderive assertions key off itsApi/FAMILY/SCHEMA_ID/TOPIC. Runtime decode compatibility keys offSCHEMA_ID; its serde encoding is the wire payload, with no version envelope (D62). A version-local wire body: a plain serde type bound to exactly oneApiVersionand one contract family/topic (D61).
Every body declared inside a phoxal_api_tree! node gets a generated impl.
Handles, SetupContext builders, and the Service/Driver derive assertions
all key off Api/FAMILY/TOPIC,
which is how a body from the wrong API version is rejected at compile time.
The serde encoding of an implementor is the wire payload; there is no version
envelope (D62). Version and family travel as bus metadata, derived from
Api and FAMILY.
Runtime decode compatibility keys off SCHEMA_ID,
not the graph API version. SCHEMA_ID is a normalized hash of the body’s
transitive wire shape. The canonical hash input is phoxal.schema/v0\n
followed by this grammar:
body = unit | newtype | tuple | struct | enum
struct = "struct{" field* "}"
field = "f" byte_len ":" utf8_name "=" ty ";"
enum = "enum(" repr "){" variant* "}"
repr = "external" | "internal(tag=" name ")"
| "adjacent(tag=" name ",content=" name ")" | "untagged"
variant = "v" byte_len ":" utf8_name "=" payload ";"
payload = unit | "newtype(" ty ")" | tuple | struct
newtype = "newtype(" ty ")"
tuple = "tuple(" (ty ";")* ")"
ty = nil | bool | string | bytes | integer | float | option | seq | array
| map | tuple | body
integer = "u8" | "u16" | "u32" | "u64" | "u128"
| "i8" | "i16" | "i32" | "i64" | "i128"
float = "f32" | "f64"
option = "option(" ty ")"
seq = "seq(" ty ")"
array = "array[" decimal_len "](" ty ")"
map = "map(" ty "," ty ")"
name = byte_len ":" utf8_nameFields stay in declared order and use their serde wire names, including
rename and rename_all. Enums include serde representation mode, variant
wire names, and payload shapes. Nested API-tree structs and enums are expanded
transitively, with generic type parameters substituted by concrete type
arguments before expansion. Only understood serde attributes and known
wire-neutral attributes such as doc comments and simple derives are accepted.
Non-wire details such as Rust type identifiers when the wire shape has already
been expanded are excluded. The displayed id is lower-hex
sha256(canonical_string), truncated to the first 16 hex characters.
Required Associated Constants§
Sourceconst FAMILY: &'static str
const FAMILY: &'static str
Canonical contract family id: the ::-joined node path plus the body type
name, with dynamic variables excluded, e.g. "drive::State" or
"component::motor::Command".
Sourceconst SCHEMA_ID: &'static str
const SCHEMA_ID: &'static str
Per-contract compatibility id: lower-hex SHA-256 of the canonical transitive wire-shape string, truncated to 16 hex characters.
Sourceconst TOPIC: &'static str
const TOPIC: &'static str
Versionless topic key: the /-joined node path plus the topic leaf, with
each dynamic node contributing a {var} placeholder, e.g. "drive/state"
or "component/{instance}/motor/{capability}/command". The concrete key is
produced by the api-local topic builder, which fills the placeholders.
Required Associated Types§
Sourcetype Api: ApiVersion
type Api: ApiVersion
The single API version this body belongs to. Two bodies from different
versions have different Api, so the type system keeps them apart.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".