Skip to main content

liminal_protocol/wire/
primitives.rs

1/// Stable conversation identifier.
2pub type ConversationId = u64;
3
4/// Permanent participant identifier and base identity index.
5pub type ParticipantId = u64;
6
7/// Permanent participant index used by participant-scoped progress accounting.
8pub type ParticipantIndex = u64;
9
10/// Nonzero participant capability or retired generation.
11#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct Generation(core::num::NonZeroU64);
13
14impl Generation {
15    /// Canonical first participant generation.
16    pub const ONE: Self = Self(core::num::NonZeroU64::MIN);
17
18    /// Creates a generation, returning `None` for the forbidden zero value.
19    #[must_use]
20    pub const fn new(value: u64) -> Option<Self> {
21        match core::num::NonZeroU64::new(value) {
22            Some(value) => Some(Self(value)),
23            None => None,
24        }
25    }
26
27    /// Returns the nonzero wire value.
28    #[must_use]
29    pub const fn get(self) -> u64 {
30        self.0.get()
31    }
32}
33
34/// Conversation delivery sequence.
35pub type DeliverySeq = u64;
36
37/// Serialized conversation transaction order.
38pub type TransactionOrder = u64;
39
40/// Observer refusal/progress epoch.
41pub type ObserverEpoch = u64;
42
43/// Marker-settlement refusal/clearing epoch.
44///
45/// Deliberately distinct from [`ObserverEpoch`]: the settlement family is
46/// cleared by another participant's record admission or by boot drain, never by
47/// observer progress, so the two epochs are never comparable even though both
48/// serialize as `u64` (participant contract ยง0.16 condition 2).
49pub type SettlementEpoch = u64;
50
51/// Participant protocol version carried in every inner frame prefix.
52#[derive(Clone, Copy, Debug, PartialEq, Eq)]
53pub struct ProtocolVersion {
54    /// Major version.
55    pub major: u16,
56    /// Minor version.
57    pub minor: u16,
58}
59
60impl ProtocolVersion {
61    /// Participant protocol v1.0.
62    pub const V1: Self = Self { major: 1, minor: 0 };
63
64    /// Creates a protocol version.
65    #[must_use]
66    pub const fn new(major: u16, minor: u16) -> Self {
67        Self { major, minor }
68    }
69}
70
71/// Server and connection identity for one accepted connection incarnation.
72#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
73pub struct ConnectionIncarnation {
74    /// Durable server incarnation.
75    pub server_incarnation: u64,
76    /// Connection ordinal within that server incarnation.
77    pub connection_ordinal: u64,
78}
79
80impl ConnectionIncarnation {
81    /// Creates a connection incarnation.
82    #[must_use]
83    pub const fn new(server_incarnation: u64, connection_ordinal: u64) -> Self {
84        Self {
85            server_incarnation,
86            connection_ordinal,
87        }
88    }
89}
90
91/// Immutable participant binding epoch.
92#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
93pub struct BindingEpoch {
94    /// Connection that owns the binding.
95    pub connection_incarnation: ConnectionIncarnation,
96    /// Capability generation captured by the binding commit.
97    pub capability_generation: Generation,
98}
99
100impl BindingEpoch {
101    /// Creates a binding epoch.
102    #[must_use]
103    pub const fn new(
104        connection_incarnation: ConnectionIncarnation,
105        capability_generation: Generation,
106    ) -> Self {
107        Self {
108            connection_incarnation,
109            capability_generation,
110        }
111    }
112}
113
114macro_rules! fixed_credential {
115    ($(#[$meta:meta])* $name:ident, $length:expr) => {
116        $(#[$meta])*
117        #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
118        pub struct $name([u8; $length]);
119
120        impl $name {
121            /// Creates the fixed-width value from its canonical bytes.
122            #[must_use]
123            pub const fn new(bytes: [u8; $length]) -> Self {
124                Self(bytes)
125            }
126
127            /// Returns the canonical fixed-width bytes.
128            #[must_use]
129            pub const fn into_bytes(self) -> [u8; $length] {
130                self.0
131            }
132
133            /// Borrows the canonical fixed-width bytes.
134            #[must_use]
135            pub const fn as_bytes(&self) -> &[u8; $length] {
136                &self.0
137            }
138        }
139    };
140}
141
142fixed_credential!(
143    /// Single-purpose enrollment attempt token.
144    EnrollmentToken,
145    16
146);
147fixed_credential!(
148    /// Single-purpose credential-attach attempt token.
149    AttachAttemptToken,
150    16
151);
152fixed_credential!(
153    /// Single-purpose explicit-detach attempt token.
154    DetachAttemptToken,
155    16
156);
157fixed_credential!(
158    /// Single-purpose terminal Leave attempt token.
159    LeaveAttemptToken,
160    16
161);
162fixed_credential!(
163    /// Single-purpose ordinary record-admission attempt token.
164    RecordAdmissionAttemptToken,
165    16
166);
167fixed_credential!(
168    /// Participant attach secret.
169    AttachSecret,
170    32
171);