phoxal_bus/metadata.rs
1//! `BusMetadata` - the per-sample attachment (D43c/D62/D1).
2//!
3//! The wire body is the plain MessagePack payload (D62); provenance +
4//! logical time ride here, in the Zenoh attachment. Identity (which contract,
5//! which version) is no longer carried in the envelope at all - it lives in
6//! the Zenoh key itself (the version is folded into
7//! `<Body as ContractBody>::TOPIC`, D1), so a receiver's per-key subscription is
8//! the whole fast-reject. `produced_at_ns`/`epoch`/`source` give logical-time +
9//! causality.
10
11use serde::{Deserialize, Serialize};
12
13use crate::abi::CodecId;
14
15/// Per-sample metadata carried in the Zenoh attachment (MessagePack-encoded).
16///
17/// Forward-compatibility: new fields are added as `Option`/defaulted so older
18/// decoders ignore them.
19#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
20pub struct BusMetadata {
21 /// The codec used for the body payload.
22 pub codec: u8,
23 /// Logical production time in nanoseconds (the clock's `time_ns`).
24 pub produced_at_ns: u64,
25 /// The clock epoch the timestamp belongs to (reset/restart counter).
26 pub epoch: u64,
27 /// The producing participant + sequence.
28 pub source: Source,
29}
30
31/// Producer identity + monotonic sequence (D43c).
32#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
33pub struct Source {
34 /// The participant id (`ParticipantLaunch.participant_id`, never the static
35 /// participant/artifact id - repeated component drivers must not collide, D53).
36 pub participant: String,
37 /// Per-process incarnation (bumped on restart).
38 pub incarnation: u64,
39 /// Per-producer monotonically increasing sample sequence.
40 pub sequence: u64,
41}
42
43impl BusMetadata {
44 /// Encode to the MessagePack attachment bytes.
45 pub fn encode(&self) -> Vec<u8> {
46 rmp_serde::to_vec_named(self).expect("BusMetadata is always serializable")
47 }
48
49 /// Decode from the MessagePack attachment bytes.
50 pub fn decode(bytes: &[u8]) -> Result<Self, rmp_serde::decode::Error> {
51 rmp_serde::from_slice(bytes)
52 }
53
54 /// The codec id, if recognized by this wire ABI.
55 pub fn codec_id(&self) -> Option<CodecId> {
56 CodecId::from_u8(self.codec)
57 }
58}