pub trait Component:
Send
+ Sync
+ 'static {
type Value;
type Mutation;
const ID: ComponentId;
const COMPONENT_TYPE: ComponentType;
// Required methods
fn decode_value(bytes: &[u8]) -> Result<Self::Value, ComponentTypedError>;
fn encode_value(value: &Self::Value) -> Result<Vec<u8>, ComponentTypedError>;
fn encode_mutation(
mutation: &Self::Mutation,
) -> Result<Vec<u8>, ComponentTypedError>;
fn apply_update_payload(
payload: &[u8],
prior: Option<&[u8]>,
) -> Result<Vec<u8>, ComponentTypedError>;
fn expand_to_changes(
op: &AppDataUpdateOperation,
prior: Option<&[u8]>,
) -> Result<Vec<ExpandedComponentChange>, ComponentTypedError>;
// Provided method
fn validate_invariant(
_change: &ComponentChange<'_>,
_registry: &ComponentRegistry,
) -> Result<(), ComponentInvariantError> { ... }
}Expand description
A typed view of a well-known AppData component.
One impl per ComponentId — pairs the wire identifier with the
component’s logical type, decode/encode round-trip, mutation
serialization, in-place apply behavior for incoming Update payloads,
and (optionally) component-local invariant checks.
The registry’s permission check (validate_component_write in
app_data::validation) is cross-cutting and runs outside this
trait. Component::validate_invariant is for component-LOCAL
invariants (e.g. “GROUP_NAME ≤ 1 KiB”, “ADMIN_LIST always has at
least one super-admin mirror”) that the policy evaluator can’t
express.
Required Associated Constants§
Sourceconst ID: ComponentId
const ID: ComponentId
Stable wire identifier. Const-known so registries can build static lookup tables.
Sourceconst COMPONENT_TYPE: ComponentType
const COMPONENT_TYPE: ComponentType
Logical wire type, written into the registry’s
ComponentMetadata.component_type slot at bootstrap.
Required Associated Types§
Sourcetype Mutation
type Mutation
Decoded payload that goes inside an
AppDataUpdateOperation::Update.
For Bytes/String components this is the same as Value (a
full-value replacement). For collection components this is
the wire-level delta (TlsSetDelta<K> /
TlsMapDelta<K, V>) carrying one or more mutations — every
mutation in the delta lands as one atomic change at the
receiver. Single-mutation callers build a one-element delta
via the fluent builder (TlsSetDelta::new().insert(x)).
Batching matters for components like GROUP_MEMBERSHIP where
all installation changes for an inbox (additions, removals,
new installations) must travel in a single proposal so the
receiver applies them atomically.
Required Methods§
Sourcefn decode_value(bytes: &[u8]) -> Result<Self::Value, ComponentTypedError>
fn decode_value(bytes: &[u8]) -> Result<Self::Value, ComponentTypedError>
Decode the component’s stored bytes (as found in the AppData dictionary) into the typed value.
Sourcefn encode_value(value: &Self::Value) -> Result<Vec<u8>, ComponentTypedError>
fn encode_value(value: &Self::Value) -> Result<Vec<u8>, ComponentTypedError>
Encode a typed value back to the bytes that go in the AppData
dictionary slot. The inverse of Component::decode_value.
Sourcefn encode_mutation(
mutation: &Self::Mutation,
) -> Result<Vec<u8>, ComponentTypedError>
fn encode_mutation( mutation: &Self::Mutation, ) -> Result<Vec<u8>, ComponentTypedError>
Encode a Self::Mutation as the bytes that go inside an
AppDataUpdateOperation::Update payload.
Bytes/String components pass through; collection components
serialize the delta (which may carry multiple mutations — see
the Self::Mutation doc on batching).
Sourcefn apply_update_payload(
payload: &[u8],
prior: Option<&[u8]>,
) -> Result<Vec<u8>, ComponentTypedError>
fn apply_update_payload( payload: &[u8], prior: Option<&[u8]>, ) -> Result<Vec<u8>, ComponentTypedError>
Apply an AppDataUpdateOperation::Update payload against the
component’s prior bytes (or None if first write) and return
the new full bytes.
Bytes/String components ignore prior and pass through;
collection components decode payload as a delta and apply it
to the decoded prior set/map.
Sourcefn expand_to_changes(
op: &AppDataUpdateOperation,
prior: Option<&[u8]>,
) -> Result<Vec<ExpandedComponentChange>, ComponentTypedError>
fn expand_to_changes( op: &AppDataUpdateOperation, prior: Option<&[u8]>, ) -> Result<Vec<ExpandedComponentChange>, ComponentTypedError>
Expand an AppDataUpdate proposal (Update or Remove) into the
per-element changes the validator’s policy loop iterates over.
Bytes components produce exactly one entry; collection components produce one entry per delta mutation.
Provided Methods§
Sourcefn validate_invariant(
_change: &ComponentChange<'_>,
_registry: &ComponentRegistry,
) -> Result<(), ComponentInvariantError>
fn validate_invariant( _change: &ComponentChange<'_>, _registry: &ComponentRegistry, ) -> Result<(), ComponentInvariantError>
Optional component-local invariant check that runs after
validate_component_write’s policy verdict. Default is no-op
— components with no extra invariants don’t override.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.