1use alloc::{string::String, vec::Vec};
9
10use crate::algebra::{ResourceDimension, ResourceVector, WideResourceVector};
11
12use super::codec::CodecError;
13use super::{
14 AttachAttemptToken, AttachSecret, BindingEpoch, ConnectionIncarnation, DetachAttemptToken,
15 EnrollmentToken, Generation, LeaveAttemptToken, ProtocolVersion, RecordAdmissionAttemptToken,
16 closure as c, envelope as e, response as r, tags as t,
17};
18
19const TOKEN_LEN: usize = 16;
20const SECRET_LEN: usize = 32;
21const RECOVERY_STATUS_LEN: u128 = 26;
22
23pub(super) struct TerminalizedWireDecodeAuthority(());
26
27const TERMINALIZED_WIRE_DECODE_AUTHORITY: TerminalizedWireDecodeAuthority =
28 TerminalizedWireDecodeAuthority(());
29
30pub fn encode_server_value_body(
42 value: &r::ServerValue,
43 version: ProtocolVersion,
44) -> Result<(t::ServerDiscriminant, Vec<u8>), CodecError> {
45 require_v1(version)?;
46 let discriminant = value.discriminant();
47 let mut encoder = Encoder::default();
48
49 if carries_origin(discriminant) {
50 let originating_request = value
51 .originating_request()
52 .ok_or(CodecError::InvalidValue)?;
53 encoder.put_u16(originating_request.wire_value());
54 }
55
56 encode_server_suffix(value, &mut encoder)?;
57 Ok((discriminant, encoder.bytes))
58}
59
60pub fn decode_server_value_body(
70 discriminant: t::ServerDiscriminant,
71 version: ProtocolVersion,
72 body: &[u8],
73) -> Result<(r::ServerValue, ProtocolVersion), CodecError> {
74 require_v1(version)?;
75 let mut decoder = Decoder::new(body);
76 let originating_request = if carries_origin(discriminant) {
77 let raw = decoder.take_u16()?;
78 let request = t::ClientDiscriminant::try_from(raw)
79 .map_err(|_| decode_error(t::DecodeClass::InvalidField))?;
80 if !origin_is_valid(discriminant, request) {
81 return Err(decode_error(t::DecodeClass::InvalidField));
82 }
83 Some(request)
84 } else {
85 None
86 };
87
88 let value = decode_server_suffix(discriminant, originating_request, &mut decoder)?;
89 decoder.finish()?;
90 Ok((value, version))
91}
92
93fn require_v1(version: ProtocolVersion) -> Result<(), CodecError> {
94 if version == ProtocolVersion::V1 {
95 Ok(())
96 } else {
97 Err(CodecError::UnsupportedVersion {
98 presented: version,
99 supported: ProtocolVersion::V1,
100 })
101 }
102}
103
104const fn decode_error(class: t::DecodeClass) -> CodecError {
105 CodecError::Decode { class }
106}
107
108#[derive(Default)]
109struct Encoder {
110 bytes: Vec<u8>,
111}
112
113impl Encoder {
114 fn put_u8(&mut self, value: u8) {
115 self.bytes.push(value);
116 }
117
118 fn put_u16(&mut self, value: u16) {
119 self.bytes.extend_from_slice(&value.to_be_bytes());
120 }
121
122 fn put_u32(&mut self, value: u32) {
123 self.bytes.extend_from_slice(&value.to_be_bytes());
124 }
125
126 fn put_u64(&mut self, value: u64) {
127 self.bytes.extend_from_slice(&value.to_be_bytes());
128 }
129
130 fn put_u128(&mut self, value: u128) {
131 self.bytes.extend_from_slice(&value.to_be_bytes());
132 }
133
134 fn put_fixed(&mut self, value: &[u8]) {
135 self.bytes.extend_from_slice(value);
136 }
137
138 fn put_bool(&mut self, value: bool) {
139 self.put_u8(u8::from(value));
140 }
141
142 fn put_option_u64(&mut self, value: Option<u64>) {
143 match value {
144 Some(value) => {
145 self.put_u8(1);
146 self.put_u64(value);
147 }
148 None => self.put_u8(0),
149 }
150 }
151
152 fn put_option_generation(&mut self, value: Option<Generation>) {
153 match value {
154 Some(value) => {
155 self.put_u8(1);
156 self.put_generation(value);
157 }
158 None => self.put_u8(0),
159 }
160 }
161
162 fn put_option_binding_epoch(&mut self, value: Option<BindingEpoch>) {
163 match value {
164 Some(value) => {
165 self.put_u8(1);
166 self.put_binding_epoch(value);
167 }
168 None => self.put_u8(0),
169 }
170 }
171
172 fn put_generation(&mut self, value: Generation) {
173 self.put_u64(value.get());
174 }
175
176 fn put_protocol_version(&mut self, value: ProtocolVersion) {
177 self.put_u16(value.major);
178 self.put_u16(value.minor);
179 }
180
181 fn put_binding_epoch(&mut self, value: BindingEpoch) {
182 self.put_u64(value.connection_incarnation.server_incarnation);
183 self.put_u64(value.connection_incarnation.connection_ordinal);
184 self.put_generation(value.capability_generation);
185 }
186
187 fn put_resource_vector(&mut self, value: ResourceVector) {
188 self.put_u64(value.entries);
189 self.put_u64(value.bytes);
190 }
191
192 fn put_wide_resource_vector(&mut self, value: WideResourceVector) {
193 self.put_u128(value.entries);
194 self.put_u128(value.bytes);
195 }
196
197 fn put_string(&mut self, value: &str) -> Result<(), CodecError> {
198 let length: u32 = value
199 .len()
200 .try_into()
201 .map_err(|_| CodecError::LengthOverflow)?;
202 self.put_u32(length);
203 self.put_fixed(value.as_bytes());
204 Ok(())
205 }
206}
207
208struct Decoder<'a> {
209 input: &'a [u8],
210 position: usize,
211 invalid_field: bool,
212}
213
214impl<'a> Decoder<'a> {
215 const fn new(input: &'a [u8]) -> Self {
216 Self {
217 input,
218 position: 0,
219 invalid_field: false,
220 }
221 }
222
223 const fn remaining(&self) -> usize {
224 self.input.len().saturating_sub(self.position)
225 }
226
227 fn take(&mut self, length: usize) -> Result<&'a [u8], CodecError> {
228 let end = self
229 .position
230 .checked_add(length)
231 .ok_or_else(|| decode_error(t::DecodeClass::MissingRequiredField))?;
232 let value = self
233 .input
234 .get(self.position..end)
235 .ok_or_else(|| decode_error(t::DecodeClass::MissingRequiredField))?;
236 self.position = end;
237 Ok(value)
238 }
239
240 fn take_u8(&mut self) -> Result<u8, CodecError> {
241 let bytes = self.take(1)?;
242 bytes
243 .first()
244 .copied()
245 .ok_or_else(|| decode_error(t::DecodeClass::MissingRequiredField))
246 }
247
248 fn take_u16(&mut self) -> Result<u16, CodecError> {
249 let bytes: [u8; 2] = self
250 .take(2)?
251 .try_into()
252 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))?;
253 Ok(u16::from_be_bytes(bytes))
254 }
255
256 fn take_u32(&mut self) -> Result<u32, CodecError> {
257 let bytes: [u8; 4] = self
258 .take(4)?
259 .try_into()
260 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))?;
261 Ok(u32::from_be_bytes(bytes))
262 }
263
264 fn take_u64(&mut self) -> Result<u64, CodecError> {
265 let bytes: [u8; 8] = self
266 .take(8)?
267 .try_into()
268 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))?;
269 Ok(u64::from_be_bytes(bytes))
270 }
271
272 fn take_u128(&mut self) -> Result<u128, CodecError> {
273 let bytes: [u8; 16] = self
274 .take(16)?
275 .try_into()
276 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))?;
277 Ok(u128::from_be_bytes(bytes))
278 }
279
280 fn take_fixed<const N: usize>(&mut self) -> Result<[u8; N], CodecError> {
281 self.take(N)?
282 .try_into()
283 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))
284 }
285
286 fn take_bool(&mut self) -> Result<bool, CodecError> {
287 match self.take_u8()? {
288 0 => Ok(false),
289 1 => Ok(true),
290 _ => Err(decode_error(t::DecodeClass::InvalidField)),
291 }
292 }
293
294 fn take_option_u64(&mut self) -> Result<Option<u64>, CodecError> {
295 match self.take_u8()? {
296 0 => Ok(None),
297 1 => self.take_u64().map(Some),
298 _ => Err(decode_error(t::DecodeClass::InvalidField)),
299 }
300 }
301
302 fn take_generation(&mut self) -> Result<Generation, CodecError> {
303 let raw = self.take_u64()?;
304 if let Some(value) = Generation::new(raw) {
305 Ok(value)
306 } else {
307 self.invalid_field = true;
308 generation_one()
309 }
310 }
311
312 fn take_option_generation(&mut self) -> Result<Option<Generation>, CodecError> {
313 match self.take_u8()? {
314 0 => Ok(None),
315 1 => self.take_generation().map(Some),
316 _ => Err(decode_error(t::DecodeClass::InvalidField)),
317 }
318 }
319
320 fn take_binding_epoch(&mut self) -> Result<BindingEpoch, CodecError> {
321 Ok(BindingEpoch::new(
322 ConnectionIncarnation::new(self.take_u64()?, self.take_u64()?),
323 self.take_generation()?,
324 ))
325 }
326
327 fn take_option_binding_epoch(&mut self) -> Result<Option<BindingEpoch>, CodecError> {
328 match self.take_u8()? {
329 0 => Ok(None),
330 1 => self.take_binding_epoch().map(Some),
331 _ => Err(decode_error(t::DecodeClass::InvalidField)),
332 }
333 }
334
335 fn take_protocol_version(&mut self) -> Result<ProtocolVersion, CodecError> {
336 Ok(ProtocolVersion::new(self.take_u16()?, self.take_u16()?))
337 }
338
339 fn take_resource_vector(&mut self) -> Result<ResourceVector, CodecError> {
340 Ok(ResourceVector::new(self.take_u64()?, self.take_u64()?))
341 }
342
343 fn take_wide_resource_vector(&mut self) -> Result<WideResourceVector, CodecError> {
344 Ok(WideResourceVector::new(
345 self.take_u128()?,
346 self.take_u128()?,
347 ))
348 }
349
350 fn take_string(&mut self) -> Result<String, CodecError> {
351 let length: usize = self
352 .take_u32()?
353 .try_into()
354 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))?;
355 let bytes = self.take(length)?;
356 if let Ok(value) = core::str::from_utf8(bytes) {
357 Ok(String::from(value))
358 } else {
359 self.invalid_field = true;
360 Ok(String::new())
361 }
362 }
363
364 const fn invalidate(&mut self) {
365 self.invalid_field = true;
366 }
367
368 const fn finish(self) -> Result<(), CodecError> {
369 if self.remaining() != 0 {
370 Err(decode_error(t::DecodeClass::CanonicalEncoding))
371 } else if self.invalid_field {
372 Err(decode_error(t::DecodeClass::InvalidField))
373 } else {
374 Ok(())
375 }
376 }
377}
378
379fn generation_one() -> Result<Generation, CodecError> {
380 Generation::new(1).ok_or(CodecError::InvalidValue)
381}
382
383fn put_enrollment(value: &e::EnrollmentEnvelope, encoder: &mut Encoder) {
384 encoder.put_u64(value.conversation_id);
385 encoder.put_fixed(value.enrollment_token.as_bytes());
386}
387
388fn put_attach(value: &e::AttachEnvelope, encoder: &mut Encoder) {
389 encoder.put_u64(value.conversation_id);
390 encoder.put_u64(value.participant_id);
391 encoder.put_generation(value.capability_generation);
392 encoder.put_fixed(value.attach_attempt_token.as_bytes());
393 encoder.put_option_u64(value.accept_marker_delivery_seq);
394}
395
396fn put_detach(value: &e::DetachEnvelope, encoder: &mut Encoder) {
397 encoder.put_u64(value.conversation_id);
398 encoder.put_u64(value.participant_id);
399 encoder.put_generation(value.capability_generation);
400 encoder.put_fixed(value.detach_attempt_token.as_bytes());
401}
402
403fn put_participant_ack(value: &e::ParticipantAckEnvelope, encoder: &mut Encoder) {
404 encoder.put_u64(value.conversation_id);
405 encoder.put_u64(value.participant_id);
406 encoder.put_generation(value.capability_generation);
407 encoder.put_u64(value.through_seq);
408}
409
410fn put_leave(value: &e::LeaveEnvelope, encoder: &mut Encoder) {
411 encoder.put_u64(value.conversation_id);
412 encoder.put_u64(value.participant_id);
413 encoder.put_generation(value.capability_generation);
414 encoder.put_fixed(value.leave_attempt_token.as_bytes());
415}
416
417fn put_marker_ack(value: &e::MarkerAckEnvelope, encoder: &mut Encoder) {
418 encoder.put_u64(value.conversation_id);
419 encoder.put_u64(value.participant_id);
420 encoder.put_generation(value.capability_generation);
421 encoder.put_u64(value.marker_delivery_seq);
422}
423
424fn put_record_admission(value: &e::RecordAdmissionEnvelope, encoder: &mut Encoder) {
425 encoder.put_u64(value.conversation_id);
426 encoder.put_u64(value.participant_id);
427 encoder.put_generation(value.capability_generation);
428 encoder.put_fixed(value.record_admission_attempt_token.as_bytes());
429}
430
431fn put_response_envelope(value: &e::ResponseEnvelope, encoder: &mut Encoder) {
432 match value {
433 e::ResponseEnvelope::Enrollment(value) => put_enrollment(value, encoder),
434 e::ResponseEnvelope::CredentialAttach(value) => put_attach(value, encoder),
435 e::ResponseEnvelope::Detach(value) => put_detach(value, encoder),
436 e::ResponseEnvelope::ParticipantAck(value) => put_participant_ack(value, encoder),
437 e::ResponseEnvelope::Leave(value) => put_leave(value, encoder),
438 e::ResponseEnvelope::MarkerAck(value) => put_marker_ack(value, encoder),
439 e::ResponseEnvelope::RecordAdmission(value) => put_record_admission(value, encoder),
440 }
441}
442
443fn put_participant_reference(value: &r::ParticipantReferenceEnvelope, encoder: &mut Encoder) {
444 match value {
445 r::ParticipantReferenceEnvelope::CredentialAttach(value) => put_attach(value, encoder),
446 r::ParticipantReferenceEnvelope::Detach(value) => put_detach(value, encoder),
447 r::ParticipantReferenceEnvelope::ParticipantAck(value) => {
448 put_participant_ack(value, encoder);
449 }
450 r::ParticipantReferenceEnvelope::Leave(value) => put_leave(value, encoder),
451 r::ParticipantReferenceEnvelope::MarkerAck(value) => put_marker_ack(value, encoder),
452 r::ParticipantReferenceEnvelope::RecordAdmission(value) => {
453 put_record_admission(value, encoder);
454 }
455 }
456}
457
458fn put_binding_required(value: &r::BindingRequiredEnvelope, encoder: &mut Encoder) {
459 match value {
460 r::BindingRequiredEnvelope::Detach(value) => put_detach(value, encoder),
461 r::BindingRequiredEnvelope::ParticipantAck(value) => put_participant_ack(value, encoder),
462 r::BindingRequiredEnvelope::Leave(value) => put_leave(value, encoder),
463 r::BindingRequiredEnvelope::MarkerAck(value) => put_marker_ack(value, encoder),
464 r::BindingRequiredEnvelope::RecordAdmission(value) => put_record_admission(value, encoder),
465 }
466}
467
468fn put_order_allocating(value: &r::OrderAllocatingEnvelope, encoder: &mut Encoder) {
469 match value {
470 r::OrderAllocatingEnvelope::Enrollment(value) => put_enrollment(value, encoder),
471 r::OrderAllocatingEnvelope::CredentialAttach(value) => put_attach(value, encoder),
472 r::OrderAllocatingEnvelope::RecordAdmission(value) => put_record_admission(value, encoder),
473 }
474}
475
476fn put_closure_checked(value: &c::ClosureCheckedEnvelope, encoder: &mut Encoder) {
477 match value {
478 c::ClosureCheckedEnvelope::Enrollment(value) => put_enrollment(value, encoder),
479 c::ClosureCheckedEnvelope::CredentialAttach(value) => put_attach(value, encoder),
480 c::ClosureCheckedEnvelope::Leave(value) => put_leave(value, encoder),
481 c::ClosureCheckedEnvelope::RecordAdmission(value) => put_record_admission(value, encoder),
482 }
483}
484
485fn put_sequence_allocating(value: &r::SequenceAllocatingEnvelope, encoder: &mut Encoder) {
486 match value {
487 r::SequenceAllocatingEnvelope::Enrollment(value) => put_enrollment(value, encoder),
488 r::SequenceAllocatingEnvelope::CredentialAttach(value) => put_attach(value, encoder),
489 r::SequenceAllocatingEnvelope::RecordAdmission(value) => {
490 put_record_admission(value, encoder);
491 }
492 }
493}
494
495fn put_marker_proof(value: &r::MarkerProofRequest, encoder: &mut Encoder) {
496 match value {
497 r::MarkerProofRequest::CredentialAttach(value) => {
498 encoder.put_u64(value.conversation_id);
499 encoder.put_fixed(value.token.as_bytes());
500 encoder.put_u64(value.participant_id);
501 encoder.put_generation(value.capability_generation);
502 encoder.put_u64(value.requested_marker_delivery_seq);
503 }
504 r::MarkerProofRequest::MarkerAck(value) => {
505 encoder.put_u64(value.conversation_id);
506 encoder.put_u64(value.participant_id);
507 encoder.put_generation(value.capability_generation);
508 encoder.put_u64(value.requested_marker_delivery_seq);
509 }
510 }
511}
512
513fn put_repayment_edge(value: c::RepaymentEdge, encoder: &mut Encoder) {
514 encoder.put_u16(value.tag().wire_value());
515 match value {
516 c::RepaymentEdge::None => {}
517 c::RepaymentEdge::ObserverProjection { through_seq } => encoder.put_u64(through_seq),
518 c::RepaymentEdge::PhysicalCompaction {
519 from_floor,
520 through_seq,
521 } => {
522 encoder.put_u64(from_floor);
523 encoder.put_u64(through_seq);
524 }
525 c::RepaymentEdge::MarkerDelivery {
526 participant_id,
527 binding_epoch,
528 marker_delivery_seq,
529 } => {
530 encoder.put_u64(participant_id);
531 encoder.put_binding_epoch(binding_epoch);
532 encoder.put_u64(marker_delivery_seq);
533 }
534 c::RepaymentEdge::ParticipantCursorProgress(value) => {
535 encoder.put_u64(value.participant_id);
536 encoder.put_binding_epoch(value.binding_epoch);
537 encoder.put_u64(value.through_seq);
538 encoder.put_option_u64(value.marker_delivery_seq);
539 }
540 c::RepaymentEdge::DetachedCredentialRecovery {
541 participant_id,
542 marker_delivery_seq,
543 prior_binding_epoch,
544 } => {
545 encoder.put_u64(participant_id);
546 encoder.put_u64(marker_delivery_seq);
547 encoder.put_binding_epoch(prior_binding_epoch);
548 }
549 c::RepaymentEdge::DetachedMarkerRelease {
550 participant_id,
551 marker_delivery_seq,
552 last_dead_binding_epoch,
553 } => {
554 encoder.put_u64(participant_id);
555 encoder.put_u64(marker_delivery_seq);
556 encoder.put_binding_epoch(last_dead_binding_epoch);
557 }
558 c::RepaymentEdge::DetachedCursorRelease {
559 participant_id,
560 last_dead_binding_epoch,
561 } => {
562 encoder.put_u64(participant_id);
563 encoder.put_binding_epoch(last_dead_binding_epoch);
564 }
565 }
566}
567
568fn put_closure_snapshot(value: c::ClosureSnapshot, encoder: &mut Encoder) {
569 encoder.put_u64(value.marker_capacity_credits);
570 encoder.put_u64(value.marker_anchors);
571 encoder.put_u64(value.entry_debt);
572 encoder.put_u64(value.byte_debt);
573 put_repayment_edge(value.repayment_edge, encoder);
574 encoder.put_u64(value.edge_sequence_claims);
575 encoder.put_u64(value.edge_order_position_claims);
576 encoder.put_resource_vector(value.edge_k_remaining);
577 encoder.put_wide_resource_vector(value.k_headroom);
578 encoder.put_u64(value.episode_churn_used);
579 encoder.put_u64(value.delta_cycles);
580 encoder.put_u64(value.episode_churn_limit);
581}
582
583fn put_sequence_budget(value: super::SequenceBudget, encoder: &mut Encoder) {
584 encoder.put_u64(value.high_watermark);
585 encoder.put_u64(value.remaining);
586 encoder.put_u64(value.e);
587 encoder.put_u64(value.t);
588 encoder.put_u64(value.m);
589 encoder.put_u64(value.rs);
590 encoder.put_u64(value.rt);
591 encoder.put_u128(value.l_times_t);
592 encoder.put_u128(value.l_times_rt);
593 encoder.put_u128(value.l_other_times_e);
594}
595
596#[allow(clippy::too_many_lines)]
597fn encode_server_suffix(value: &r::ServerValue, encoder: &mut Encoder) -> Result<(), CodecError> {
598 match value {
599 r::ServerValue::ParticipantTransportRejected(value) => match &value.reason {
600 r::TransportRejectionReason::FrameTooLarge {
601 complete_frame_bytes,
602 max_frame_bytes,
603 } => {
604 encoder.put_u16(t::TransportReasonTag::FrameTooLarge.wire_value());
605 encoder.put_u64(*complete_frame_bytes);
606 encoder.put_u64(*max_frame_bytes);
607 }
608 r::TransportRejectionReason::DecodeFailed { decode_class } => {
609 encoder.put_u16(t::TransportReasonTag::DecodeFailed.wire_value());
610 encoder.put_u16(decode_class.wire_value());
611 }
612 r::TransportRejectionReason::UnsupportedVersion {
613 presented_version,
614 supported_version,
615 } => {
616 encoder.put_u16(t::TransportReasonTag::UnsupportedVersion.wire_value());
617 encoder.put_protocol_version(*presented_version);
618 encoder.put_protocol_version(*supported_version);
619 }
620 r::TransportRejectionReason::AuthenticationFailed => {
621 encoder.put_u16(t::TransportReasonTag::AuthenticationFailed.wire_value());
622 }
623 r::TransportRejectionReason::ParticipantCapabilityRequired => {
624 encoder.put_u16(t::TransportReasonTag::ParticipantCapabilityRequired.wire_value());
625 encoder.put_string(r::PARTICIPANT_CAPABILITY)?;
626 }
627 r::TransportRejectionReason::EnrollmentNotPermitted => {
628 encoder.put_u16(t::TransportReasonTag::EnrollmentNotPermitted.wire_value());
629 }
630 r::TransportRejectionReason::EnrollmentConversationOutOfScope => encoder
631 .put_u16(t::TransportReasonTag::EnrollmentConversationOutOfScope.wire_value()),
632 r::TransportRejectionReason::CredentialAttachConversationOutOfScope => encoder.put_u16(
633 t::TransportReasonTag::CredentialAttachConversationOutOfScope.wire_value(),
634 ),
635 },
636 r::ServerValue::AttemptTokenBodyConflict(value) => match value {
637 r::AttemptTokenBodyConflict::CredentialAttach {
638 token,
639 conversation_id,
640 presented_participant_id,
641 presented_generation,
642 presented_marker_delivery_seq,
643 conflict,
644 } => {
645 encoder.put_fixed(token.as_bytes());
646 encoder.put_u16(t::AttemptOperation::CredentialAttachRequest.wire_value());
647 encoder.put_u64(*conversation_id);
648 encoder.put_u64(*presented_participant_id);
649 encoder.put_generation(*presented_generation);
650 encoder.put_option_u64(*presented_marker_delivery_seq);
651 encoder.put_u16(conflict.wire_value());
652 }
653 r::AttemptTokenBodyConflict::Leave {
654 token,
655 conversation_id,
656 presented_participant_id,
657 presented_generation,
658 } => {
659 encoder.put_fixed(token.as_bytes());
660 encoder.put_u16(t::AttemptOperation::LeaveRequest.wire_value());
661 encoder.put_u64(*conversation_id);
662 encoder.put_u64(*presented_participant_id);
663 encoder.put_generation(*presented_generation);
664 encoder.put_u16(t::AttemptConflict::Generation.wire_value());
665 }
666 r::AttemptTokenBodyConflict::RecordAdmission {
667 token,
668 conversation_id,
669 presented_participant_id,
670 presented_generation,
671 } => {
672 encoder.put_fixed(token.as_bytes());
673 encoder.put_u16(t::AttemptOperation::RecordAdmission.wire_value());
674 encoder.put_u64(*conversation_id);
675 encoder.put_u64(*presented_participant_id);
676 encoder.put_generation(*presented_generation);
677 }
678 },
679 r::ServerValue::ConnectionConversationCapacityExceeded(value) => match value {
680 r::ConnectionConversationCapacityExceeded::SemanticRequest { request, limit } => {
681 put_response_envelope(request, encoder);
682 encoder.put_u64(*limit);
683 }
684 r::ConnectionConversationCapacityExceeded::ObserverRecovery {
685 conversation_id,
686 limit,
687 } => {
688 encoder.put_u64(0);
689 encoder.put_u64(*conversation_id);
690 encoder.put_u64(*limit);
691 }
692 },
693 r::ServerValue::ConnectionConversationBindingOccupied(value) => match value {
694 r::ConnectionConversationBindingOccupied::Enrollment {
695 conversation_id,
696 enrollment_token,
697 } => {
698 encoder.put_u64(*conversation_id);
699 encoder.put_fixed(enrollment_token.as_bytes());
700 encoder.put_option_u64(None);
701 }
702 r::ConnectionConversationBindingOccupied::CredentialAttach {
703 conversation_id,
704 participant_id,
705 capability_generation,
706 attach_attempt_token,
707 accept_marker_delivery_seq,
708 } => {
709 encoder.put_u64(*conversation_id);
710 encoder.put_u64(*participant_id);
711 encoder.put_generation(*capability_generation);
712 encoder.put_fixed(attach_attempt_token.as_bytes());
713 encoder.put_option_u64(*accept_marker_delivery_seq);
714 encoder.put_option_u64(Some(*participant_id));
715 }
716 },
717 r::ServerValue::ConversationOrderExhausted(value) => {
718 put_order_allocating(value.request(), encoder);
719 encoder.put_u16(value.counter().wire_value());
720 encoder.put_u64(value.high());
721 encoder.put_option_u64(value.next_value());
722 encoder.put_u128(value.order_remaining());
723 encoder.put_u128(value.reserved_claims());
724 encoder.put_u64(r::ConversationOrderExhausted::REQUIRED_MAJORS);
725 encoder.put_u128(value.resulting_order_remaining());
726 encoder.put_u128(value.resulting_reserved_claims());
727 }
728 r::ServerValue::ParticipantUnknown(value) => {
729 put_participant_reference(&value.request, encoder);
730 }
731 r::ServerValue::NoBinding(value) => put_binding_required(&value.request, encoder),
732 r::ServerValue::StaleAuthority(value) => put_stale_authority(value, encoder),
733 r::ServerValue::Retired(value) => match value {
734 r::Retired::Enrollment {
735 request,
736 participant_id,
737 retired_generation,
738 } => {
739 put_enrollment(request, encoder);
740 encoder.put_u64(*participant_id);
741 encoder.put_generation(*retired_generation);
742 }
743 r::Retired::Participant {
744 request,
745 retired_generation,
746 } => {
747 put_participant_reference(request, encoder);
748 encoder.put_generation(*retired_generation);
749 }
750 },
751 r::ServerValue::MarkerClosureCapacityExceeded(value) => {
752 put_closure_checked(&value.request, encoder);
753 let scope = match value.reason {
754 c::ClosureRefusalReason::Capacity(_) => t::ClosureScope::Capacity,
755 c::ClosureRefusalReason::RecoveryFence => t::ClosureScope::RecoveryFence,
756 c::ClosureRefusalReason::DeliveredMarkerAwaitingAck => {
757 t::ClosureScope::DeliveredMarkerAwaitingAck
758 }
759 c::ClosureRefusalReason::EpisodeChurnLimit => t::ClosureScope::EpisodeChurnLimit,
760 };
761 encoder.put_u16(scope.wire_value());
762 put_closure_snapshot(value.snapshot, encoder);
763 if let c::ClosureRefusalReason::Capacity(reason) = value.reason {
764 encoder.put_u16(t::ResourceDimensionTag::from(reason.dimension).wire_value());
765 encoder.put_u128(reason.required);
766 encoder.put_u128(reason.limit);
767 }
768 }
769 r::ServerValue::EnrollBound(value) => {
770 encoder.put_u64(value.conversation_id());
771 encoder.put_fixed(value.token().as_bytes());
772 encoder.put_u64(value.participant_id());
773 encoder.put_option_generation(value.request_generation());
774 encoder.put_generation(value.capability_generation());
775 encoder.put_fixed(value.attach_secret().as_bytes());
776 encoder.put_binding_epoch(value.origin_binding_epoch());
777 encoder.put_u64(value.persisted_cursor());
778 encoder.put_option_u64(value.accepted_marker_delivery_seq());
779 encoder.put_u128(value.receipt_expires_at());
780 encoder.put_u128(value.provenance_expires_at());
781 }
782 r::ServerValue::EnrollmentKnown(value) => {
783 encoder.put_u64(value.conversation_id);
784 encoder.put_fixed(value.token.as_bytes());
785 encoder.put_u64(value.participant_id);
786 encoder.put_generation(value.current_generation);
787 }
788 r::ServerValue::ReceiptExpired(value) => put_receipt_expired(value, encoder),
789 r::ServerValue::ReceiptCapacityExceeded(value) => {
790 put_receipt_capacity(value, encoder);
791 }
792 r::ServerValue::IdentityCapacityExceeded(value) => {
793 put_enrollment(&value.request, encoder);
794 encoder.put_u16(value.scope.wire_value());
795 encoder.put_u64(value.limit);
796 encoder.put_u64(value.occupied);
797 encoder.put_u64(r::IdentityCapacityExceeded::REQUESTED);
798 }
799 r::ServerValue::ObserverBackpressure(value) => put_observer_backpressure(value, encoder),
800 r::ServerValue::ConversationSequenceExhausted(value) => {
801 put_sequence_allocating(&value.request, encoder);
802 put_sequence_budget(value.sequence_budget, encoder);
803 }
804 r::ServerValue::AttachBound(value) => {
805 encoder.put_u64(value.conversation_id());
806 encoder.put_fixed(value.token().as_bytes());
807 encoder.put_u64(value.participant_id());
808 encoder.put_option_generation(Some(value.request_generation()));
809 encoder.put_generation(value.capability_generation());
810 encoder.put_fixed(value.attach_secret().as_bytes());
811 encoder.put_binding_epoch(value.origin_binding_epoch());
812 encoder.put_u64(value.persisted_cursor());
813 encoder.put_option_u64(value.accepted_marker_delivery_seq());
814 encoder.put_u128(value.receipt_expires_at());
815 encoder.put_u128(value.provenance_expires_at());
816 }
817 r::ServerValue::StaleOrUnknownReceipt(value) => {
818 encoder.put_u64(value.conversation_id);
819 encoder.put_fixed(value.token.as_bytes());
820 encoder.put_u64(value.participant_id);
821 encoder.put_generation(value.presented_generation);
822 encoder.put_option_u64(value.presented_marker_delivery_seq);
823 encoder.put_generation(value.current_generation);
824 }
825 r::ServerValue::MarkerNotDelivered(value) => {
826 put_marker_proof(&value.request, encoder);
827 encoder.put_u16(value.reason.wire_value());
828 encoder.put_u64(value.expected_marker_delivery_seq);
829 }
830 r::ServerValue::MarkerMismatch(value) => {
831 put_marker_proof(&value.request, encoder);
832 encoder.put_u16(value.mismatch.reason().wire_value());
833 match value.mismatch {
834 r::MarkerMismatchBody::BelowCursor { current_cursor } => {
835 encoder.put_u64(current_cursor);
836 }
837 r::MarkerMismatchBody::NoMarkerExpected => {}
838 r::MarkerMismatchBody::ExpectedDifferentMarker {
839 expected_marker_delivery_seq,
840 } => encoder.put_u64(expected_marker_delivery_seq),
841 }
842 }
843 r::ServerValue::Bound(value) | r::ServerValue::UnboundReceipt(value) => {
844 put_receipt_replay(value, encoder);
845 }
846 r::ServerValue::DetachCommitted(value) => {
847 encoder.put_u64(value.conversation_id());
848 encoder.put_u64(value.participant_id());
849 encoder.put_generation(value.capability_generation());
850 encoder.put_fixed(value.detach_attempt_token().as_bytes());
851 encoder.put_binding_epoch(value.committed_binding_epoch());
852 encoder.put_u64(value.detached_delivery_seq());
853 }
854 r::ServerValue::DetachInProgress(value) => {
855 encoder.put_u64(value.conversation_id);
856 encoder.put_u64(value.participant_id);
857 encoder.put_fixed(value.presented_token.as_bytes());
858 encoder.put_generation(value.presented_generation);
859 encoder.put_binding_epoch(value.committed_binding_epoch);
860 }
861 r::ServerValue::AckCommitted(value) => {
862 put_participant_ack(value.request(), encoder);
863 encoder.put_u64(value.current_cursor());
864 }
865 r::ServerValue::AckNoOp(value) => match value {
866 r::AckNoOp::ParticipantAck(request) => {
867 put_participant_ack(request, encoder);
868 encoder.put_u64(value.current_cursor());
869 }
870 r::AckNoOp::MarkerAck(request) => {
871 put_marker_ack(request, encoder);
872 encoder.put_u64(value.current_cursor());
873 }
874 },
875 r::ServerValue::AckGap(value) => {
876 put_participant_ack(value.request(), encoder);
877 encoder.put_u64(value.current_cursor());
878 encoder.put_u16(value.reason().wire_value());
879 }
880 r::ServerValue::AckRegression(value) => {
881 put_participant_ack(value.request(), encoder);
882 encoder.put_u64(value.current_cursor());
883 encoder.put_u16(value.reason().wire_value());
884 }
885 r::ServerValue::LeaveCommitted(value) => {
886 encoder.put_u64(value.conversation_id());
887 encoder.put_fixed(value.leave_attempt_token().as_bytes());
888 encoder.put_u64(value.participant_id());
889 encoder.put_generation(value.presented_generation());
890 encoder.put_generation(value.retired_generation());
891 encoder.put_option_binding_epoch(value.ended_binding_epoch());
892 encoder.put_option_u64(value.prior_terminal_delivery_seq());
893 encoder.put_u64(value.left_delivery_seq());
894 }
895 r::ServerValue::MarkerAckCommitted(value) => {
896 put_marker_ack(value.request(), encoder);
897 encoder.put_u64(value.current_cursor());
898 }
899 r::ServerValue::SettlementAnswer(value) => {
900 encoder.put_u64(value.conversation_id);
901 encoder.put_u64(value.participant_id);
902 encoder.put_fixed(value.record_admission_attempt_token.as_bytes());
903 match value.outcome {
904 r::SettlementOutcome::Committed { delivery_seq } => {
905 encoder.put_u8(1);
906 encoder.put_u64(delivery_seq);
907 }
908 r::SettlementOutcome::Withdrawn => encoder.put_u8(2),
909 r::SettlementOutcome::Expired => encoder.put_u8(3),
910 r::SettlementOutcome::NotCommitted => encoder.put_u8(4),
911 r::SettlementOutcome::Unknown => encoder.put_u8(5),
912 }
913 }
914 r::ServerValue::RecordCommitted(value) => {
915 put_record_admission(value.request(), encoder);
916 encoder.put_u64(value.sender_participant_id());
917 encoder.put_u64(value.delivery_seq());
918 }
919 r::ServerValue::RecordTooLarge(value) => {
920 put_record_admission(&value.request, encoder);
921 encoder.put_u16(t::ResourceDimensionTag::from(value.dimension).wire_value());
922 encoder.put_resource_vector(value.encoded_record_charge);
923 encoder.put_resource_vector(value.max_ordinary_record_charge);
924 }
925 r::ServerValue::ObserverRecoveryAccepted(value) => {
926 let count: u64 = value
927 .statuses
928 .len()
929 .try_into()
930 .map_err(|_| CodecError::LengthOverflow)?;
931 encoder.put_u64(count);
932 for status in &value.statuses {
933 encoder.put_u64(status.conversation_id);
934 encoder.put_u64(status.refused_epoch);
935 encoder.put_u64(status.current_observer_progress);
936 encoder.put_bool(status.armed);
937 encoder.put_bool(status.progressed);
938 }
939 }
940 r::ServerValue::InvalidObserverEpoch(value) => {
941 encoder.put_u64(0);
942 encoder.put_u16(value.reason().wire_value());
943 match value {
944 r::InvalidObserverEpoch::ConversationUnknown {
945 conversation_id,
946 presented_epoch,
947 } => {
948 encoder.put_u64(*conversation_id);
949 encoder.put_u64(*presented_epoch);
950 encoder.put_option_u64(None);
951 }
952 r::InvalidObserverEpoch::EpochAhead {
953 conversation_id,
954 presented_epoch,
955 current_observer_progress,
956 } => {
957 encoder.put_u64(*conversation_id);
958 encoder.put_u64(*presented_epoch);
959 encoder.put_option_u64(Some(*current_observer_progress));
960 }
961 }
962 }
963 r::ServerValue::InvalidObserverEpochList(value) => {
964 encoder.put_u64(0);
965 encoder.put_u16(value.reason().wire_value());
966 match value {
967 r::InvalidObserverEpochList::TooManyEntries {
968 presented_entries,
969 max_entries,
970 } => {
971 encoder.put_u64(*presented_entries);
972 encoder.put_u64(*max_entries);
973 }
974 r::InvalidObserverEpochList::DuplicateConversation {
975 conversation_id,
976 first_index,
977 duplicate_index,
978 } => {
979 encoder.put_u64(*conversation_id);
980 encoder.put_u64(*first_index);
981 encoder.put_u64(*duplicate_index);
982 }
983 }
984 }
985 r::ServerValue::MarkerSettlementBackpressure(value) => match value {
986 r::MarkerSettlementBackpressure::CredentialAttach {
987 conversation_id,
988 refused_epoch,
989 }
990 | r::MarkerSettlementBackpressure::Detach {
991 conversation_id,
992 refused_epoch,
993 } => {
994 encoder.put_u64(*conversation_id);
995 encoder.put_u64(*refused_epoch);
996 }
997 },
998 r::ServerValue::EnrollmentSettlementBackpressure(value) => {
999 encoder.put_u64(value.conversation_id);
1000 }
1001 r::ServerValue::RecordAdmissionProtocolFault(value) => {
1002 put_record_admission(&value.request, encoder);
1003 encoder.put_u16(value.class.tag().wire_value());
1004 }
1005 r::ServerValue::WriteOutcomeUnknown(value) => put_write_outcome_unknown(value, encoder),
1006 }
1007 Ok(())
1008}
1009
1010fn put_write_outcome_unknown(value: &r::WriteOutcomeUnknown, encoder: &mut Encoder) {
1011 match value {
1012 r::WriteOutcomeUnknown::Enrollment { request } => put_enrollment(request, encoder),
1013 r::WriteOutcomeUnknown::CredentialAttach { request } => put_attach(request, encoder),
1014 r::WriteOutcomeUnknown::Detach { request } => put_detach(request, encoder),
1015 r::WriteOutcomeUnknown::Leave { request } => put_leave(request, encoder),
1016 r::WriteOutcomeUnknown::RecordAdmission { request } => {
1017 put_record_admission(request, encoder);
1018 }
1019 }
1020}
1021
1022fn put_stale_authority(value: &r::StaleAuthority, encoder: &mut Encoder) {
1023 match value {
1024 r::StaleAuthority::Live {
1025 request,
1026 current_generation,
1027 } => {
1028 match request {
1029 r::CommonStaleAuthorityEnvelope::CredentialAttach(value) => {
1030 put_attach(value, encoder);
1031 }
1032 r::CommonStaleAuthorityEnvelope::ParticipantAck(value) => {
1033 put_participant_ack(value, encoder);
1034 }
1035 r::CommonStaleAuthorityEnvelope::MarkerAck(value) => {
1036 put_marker_ack(value, encoder);
1037 }
1038 r::CommonStaleAuthorityEnvelope::RecordAdmission(value) => {
1039 put_record_admission(value, encoder);
1040 }
1041 }
1042 encoder.put_generation(*current_generation);
1043 }
1044 r::StaleAuthority::Detach(value) => {
1045 encoder.put_u16(value.authority_state_tag().wire_value());
1046 match value {
1047 r::DetachStaleAuthority::Live {
1048 conversation_id,
1049 participant_id,
1050 capability_generation,
1051 detach_attempt_token,
1052 current_generation,
1053 } => {
1054 encoder.put_u64(*conversation_id);
1055 encoder.put_u64(*participant_id);
1056 encoder.put_generation(*capability_generation);
1057 encoder.put_fixed(detach_attempt_token.as_bytes());
1058 encoder.put_generation(*current_generation);
1059 }
1060 r::DetachStaleAuthority::TerminalizedDetachCell(value) => {
1061 encoder.put_u64(value.conversation_id());
1062 encoder.put_u64(value.participant_id());
1063 encoder.put_generation(value.capability_generation());
1064 encoder.put_fixed(value.detach_attempt_token().as_bytes());
1065 encoder.put_generation(value.current_generation());
1066 encoder.put_binding_epoch(value.committed_binding_epoch());
1067 encoder.put_u16(value.binding_state().tag().wire_value());
1068 if let r::BindingStateView::Bound {
1069 current_binding_epoch,
1070 } = value.binding_state()
1071 {
1072 encoder.put_binding_epoch(current_binding_epoch);
1073 }
1074 }
1075 }
1076 }
1077 r::StaleAuthority::Leave(value) => {
1078 encoder.put_u16(value.authority_state_tag().wire_value());
1079 match value {
1080 r::LeaveStaleAuthority::Live {
1081 conversation_id,
1082 participant_id,
1083 presented_generation,
1084 leave_attempt_token,
1085 current_generation,
1086 } => {
1087 encoder.put_u64(*conversation_id);
1088 encoder.put_u64(*participant_id);
1089 encoder.put_generation(*presented_generation);
1090 encoder.put_fixed(leave_attempt_token.as_bytes());
1091 encoder.put_generation(*current_generation);
1092 }
1093 r::LeaveStaleAuthority::CommittedLeaveTombstone {
1094 conversation_id,
1095 participant_id,
1096 presented_generation,
1097 leave_attempt_token,
1098 retired_generation,
1099 } => {
1100 encoder.put_u64(*conversation_id);
1101 encoder.put_u64(*participant_id);
1102 encoder.put_generation(*presented_generation);
1103 encoder.put_fixed(leave_attempt_token.as_bytes());
1104 encoder.put_generation(*retired_generation);
1105 }
1106 }
1107 }
1108 }
1109}
1110
1111fn put_receipt_expired(value: &r::ReceiptExpired, encoder: &mut Encoder) {
1112 match value {
1113 r::ReceiptExpired::Enrollment {
1114 conversation_id,
1115 token,
1116 participant_id,
1117 result_generation,
1118 current_generation,
1119 reason,
1120 } => {
1121 encoder.put_u64(*conversation_id);
1122 encoder.put_fixed(token.as_bytes());
1123 encoder.put_u64(*participant_id);
1124 encoder.put_option_generation(None);
1125 encoder.put_generation(*result_generation);
1126 encoder.put_generation(*current_generation);
1127 encoder.put_u16(reason.wire_value());
1128 }
1129 r::ReceiptExpired::CredentialAttach {
1130 conversation_id,
1131 token,
1132 participant_id,
1133 presented_generation,
1134 presented_marker_delivery_seq,
1135 result_generation,
1136 current_generation,
1137 reason,
1138 } => {
1139 encoder.put_u64(*conversation_id);
1140 encoder.put_fixed(token.as_bytes());
1141 encoder.put_u64(*participant_id);
1142 encoder.put_option_generation(Some(*presented_generation));
1143 encoder.put_option_u64(*presented_marker_delivery_seq);
1144 encoder.put_generation(*result_generation);
1145 encoder.put_generation(*current_generation);
1146 encoder.put_u16(reason.wire_value());
1147 }
1148 }
1149}
1150
1151fn put_receipt_capacity(value: &r::ReceiptCapacityExceeded, encoder: &mut Encoder) {
1152 match value {
1153 r::ReceiptCapacityExceeded::Enrollment {
1154 request,
1155 scope,
1156 limit,
1157 occupied,
1158 } => {
1159 put_enrollment(request, encoder);
1160 encoder.put_u16(scope.wire_scope().wire_value());
1161 encoder.put_u64(*limit);
1162 encoder.put_u64(*occupied);
1163 encoder.put_u64(r::ReceiptCapacityExceeded::REQUESTED);
1164 }
1165 r::ReceiptCapacityExceeded::CredentialAttach {
1166 request,
1167 scope,
1168 limit,
1169 occupied,
1170 } => {
1171 put_attach(request, encoder);
1172 encoder.put_u16(scope.wire_value());
1173 encoder.put_u64(*limit);
1174 encoder.put_u64(*occupied);
1175 encoder.put_u64(r::ReceiptCapacityExceeded::REQUESTED);
1176 }
1177 }
1178}
1179
1180fn put_observer_backpressure(value: &r::ObserverBackpressure, encoder: &mut Encoder) {
1181 match value {
1182 r::ObserverBackpressure::Enrollment { request, state } => {
1183 put_enrollment(request, encoder);
1184 put_backpressure_state(*state, encoder);
1185 }
1186 r::ObserverBackpressure::CredentialAttach { request, state } => {
1187 put_attach(request, encoder);
1188 put_backpressure_state(*state, encoder);
1189 }
1190 r::ObserverBackpressure::Detach {
1191 request,
1192 committed_binding_epoch,
1193 state,
1194 } => {
1195 put_detach(request, encoder);
1196 encoder.put_binding_epoch(*committed_binding_epoch);
1197 put_backpressure_state(*state, encoder);
1198 }
1199 r::ObserverBackpressure::Leave {
1200 request,
1201 state,
1202 prior_terminal_cell_exists,
1203 } => {
1204 put_leave(request, encoder);
1205 put_backpressure_state(*state, encoder);
1206 encoder.put_bool(*prior_terminal_cell_exists);
1207 }
1208 r::ObserverBackpressure::RecordAdmission { request, state } => {
1209 put_record_admission(request, encoder);
1210 put_backpressure_state(*state, encoder);
1211 }
1212 }
1213}
1214
1215fn put_backpressure_state(value: r::ObserverBackpressureState, encoder: &mut Encoder) {
1216 encoder.put_u64(value.backpressure_epoch());
1217 encoder.put_u64(value.observer_progress());
1218}
1219
1220fn put_receipt_replay(value: &r::ReceiptReplay, encoder: &mut Encoder) {
1221 match value {
1222 r::ReceiptReplay::Enrollment(value) => {
1223 encoder.put_u64(value.conversation_id());
1224 encoder.put_fixed(value.token().as_bytes());
1225 encoder.put_u64(value.participant_id());
1226 encoder.put_option_generation(None);
1227 encoder.put_generation(value.capability_generation());
1228 encoder.put_fixed(value.attach_secret().as_bytes());
1229 encoder.put_binding_epoch(value.origin_binding_epoch());
1230 encoder.put_u64(value.persisted_cursor());
1231 encoder.put_option_u64(None);
1232 encoder.put_u128(value.receipt_expires_at());
1233 encoder.put_u128(value.provenance_expires_at());
1234 }
1235 r::ReceiptReplay::CredentialAttach(value) => {
1236 encoder.put_u64(value.conversation_id());
1237 encoder.put_fixed(value.token().as_bytes());
1238 encoder.put_u64(value.participant_id());
1239 encoder.put_option_generation(Some(value.request_generation()));
1240 encoder.put_generation(value.capability_generation());
1241 encoder.put_fixed(value.attach_secret().as_bytes());
1242 encoder.put_binding_epoch(value.origin_binding_epoch());
1243 encoder.put_u64(value.persisted_cursor());
1244 encoder.put_option_u64(value.accepted_marker_delivery_seq());
1245 encoder.put_u128(value.receipt_expires_at());
1246 encoder.put_u128(value.provenance_expires_at());
1247 }
1248 }
1249}
1250
1251const fn carries_origin(discriminant: t::ServerDiscriminant) -> bool {
1259 use t::ServerDiscriminant as D;
1260
1261 !matches!(
1262 discriminant,
1263 D::ParticipantTransportRejected
1264 | D::ObserverRecoveryAccepted
1265 | D::InvalidObserverEpoch
1266 | D::InvalidObserverEpochList
1267 | D::ObserverRecoveryConnectionCapacityExceeded
1268 )
1269}
1270
1271const fn origin_is_valid(
1272 discriminant: t::ServerDiscriminant,
1273 origin: t::ClientDiscriminant,
1274) -> bool {
1275 use t::ClientDiscriminant as O;
1276 use t::ServerDiscriminant as D;
1277
1278 match discriminant {
1279 D::AttemptTokenBodyConflict => matches!(
1280 origin,
1281 O::CredentialAttachRequest | O::LeaveRequest | O::RecordAdmission
1282 ),
1283 D::ConnectionConversationCapacityExceeded => {
1284 !matches!(origin, O::ObserverRecoveryHandshake)
1285 }
1286 D::ConnectionConversationBindingOccupied => {
1287 matches!(origin, O::EnrollmentRequest | O::CredentialAttachRequest)
1288 }
1289 D::ConversationOrderExhausted => matches!(
1290 origin,
1291 O::EnrollmentRequest | O::CredentialAttachRequest | O::RecordAdmission
1292 ),
1293 D::ParticipantUnknown => {
1294 !matches!(origin, O::EnrollmentRequest | O::ObserverRecoveryHandshake)
1295 }
1296 D::NoBinding => !matches!(
1297 origin,
1298 O::EnrollmentRequest | O::CredentialAttachRequest | O::ObserverRecoveryHandshake
1299 ),
1300 D::StaleAuthority => !matches!(origin, O::EnrollmentRequest | O::ObserverRecoveryHandshake),
1301 D::Retired => !matches!(origin, O::ObserverRecoveryHandshake),
1302 D::MarkerClosureCapacityExceeded => matches!(
1303 origin,
1304 O::EnrollmentRequest
1305 | O::CredentialAttachRequest
1306 | O::LeaveRequest
1307 | O::RecordAdmission
1308 ),
1309 D::EnrollBound | D::EnrollmentKnown | D::IdentityCapacityExceeded => {
1310 matches!(origin, O::EnrollmentRequest)
1311 }
1312 D::ReceiptExpired | D::ReceiptCapacityExceeded | D::Bound | D::UnboundReceipt => {
1313 matches!(origin, O::EnrollmentRequest | O::CredentialAttachRequest)
1314 }
1315 D::ObserverBackpressure | D::WriteOutcomeUnknown => matches!(
1316 origin,
1317 O::EnrollmentRequest
1318 | O::CredentialAttachRequest
1319 | O::DetachRequest
1320 | O::LeaveRequest
1321 | O::RecordAdmission
1322 ),
1323 D::ConversationSequenceExhausted => matches!(
1324 origin,
1325 O::EnrollmentRequest | O::CredentialAttachRequest | O::RecordAdmission
1326 ),
1327 D::AttachBound | D::StaleOrUnknownReceipt => {
1328 matches!(origin, O::CredentialAttachRequest)
1329 }
1330 D::MarkerNotDelivered | D::MarkerMismatch => {
1331 matches!(origin, O::CredentialAttachRequest | O::MarkerAck)
1332 }
1333 D::DetachCommitted | D::DetachInProgress => matches!(origin, O::DetachRequest),
1334 D::AckCommitted | D::AckGap | D::AckRegression => matches!(origin, O::ParticipantAck),
1335 D::AckNoOp => matches!(origin, O::ParticipantAck | O::MarkerAck),
1336 D::LeaveCommitted => matches!(origin, O::LeaveRequest),
1337 D::MarkerAckCommitted => matches!(origin, O::MarkerAck),
1338 D::SettlementAnswer => matches!(origin, O::SettlementQuery),
1339 D::RecordCommitted | D::RecordTooLarge | D::RecordAdmissionProtocolFault => {
1340 matches!(origin, O::RecordAdmission)
1341 }
1342 D::MarkerSettlementBackpressure => {
1343 matches!(origin, O::CredentialAttachRequest | O::DetachRequest)
1344 }
1345 D::EnrollmentSettlementBackpressure => matches!(origin, O::EnrollmentRequest),
1346 D::ParticipantTransportRejected
1347 | D::ObserverRecoveryAccepted
1348 | D::InvalidObserverEpoch
1349 | D::InvalidObserverEpochList
1350 | D::ObserverRecoveryConnectionCapacityExceeded => false,
1351 }
1352}
1353
1354fn take_enrollment(decoder: &mut Decoder<'_>) -> Result<e::EnrollmentEnvelope, CodecError> {
1358 Ok(e::EnrollmentEnvelope {
1359 conversation_id: decoder.take_u64()?,
1360 enrollment_token: EnrollmentToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1361 })
1362}
1363
1364fn take_attach(decoder: &mut Decoder<'_>) -> Result<e::AttachEnvelope, CodecError> {
1365 Ok(e::AttachEnvelope {
1366 conversation_id: decoder.take_u64()?,
1367 participant_id: decoder.take_u64()?,
1368 capability_generation: decoder.take_generation()?,
1369 attach_attempt_token: AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1370 accept_marker_delivery_seq: decoder.take_option_u64()?,
1371 })
1372}
1373
1374fn take_detach(decoder: &mut Decoder<'_>) -> Result<e::DetachEnvelope, CodecError> {
1375 Ok(e::DetachEnvelope {
1376 conversation_id: decoder.take_u64()?,
1377 participant_id: decoder.take_u64()?,
1378 capability_generation: decoder.take_generation()?,
1379 detach_attempt_token: DetachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1380 })
1381}
1382
1383fn take_participant_ack(
1384 decoder: &mut Decoder<'_>,
1385) -> Result<e::ParticipantAckEnvelope, CodecError> {
1386 Ok(e::ParticipantAckEnvelope {
1387 conversation_id: decoder.take_u64()?,
1388 participant_id: decoder.take_u64()?,
1389 capability_generation: decoder.take_generation()?,
1390 through_seq: decoder.take_u64()?,
1391 })
1392}
1393
1394fn take_leave(decoder: &mut Decoder<'_>) -> Result<e::LeaveEnvelope, CodecError> {
1395 Ok(e::LeaveEnvelope {
1396 conversation_id: decoder.take_u64()?,
1397 participant_id: decoder.take_u64()?,
1398 capability_generation: decoder.take_generation()?,
1399 leave_attempt_token: LeaveAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1400 })
1401}
1402
1403fn take_marker_ack(decoder: &mut Decoder<'_>) -> Result<e::MarkerAckEnvelope, CodecError> {
1404 Ok(e::MarkerAckEnvelope {
1405 conversation_id: decoder.take_u64()?,
1406 participant_id: decoder.take_u64()?,
1407 capability_generation: decoder.take_generation()?,
1408 marker_delivery_seq: decoder.take_u64()?,
1409 })
1410}
1411
1412fn take_record_admission(
1413 decoder: &mut Decoder<'_>,
1414) -> Result<e::RecordAdmissionEnvelope, CodecError> {
1415 Ok(e::RecordAdmissionEnvelope {
1416 conversation_id: decoder.take_u64()?,
1417 participant_id: decoder.take_u64()?,
1418 capability_generation: decoder.take_generation()?,
1419 record_admission_attempt_token: RecordAdmissionAttemptToken::new(
1420 decoder.take_fixed::<TOKEN_LEN>()?,
1421 ),
1422 })
1423}
1424
1425fn take_response_envelope(
1426 origin: t::ClientDiscriminant,
1427 decoder: &mut Decoder<'_>,
1428) -> Result<e::ResponseEnvelope, CodecError> {
1429 match origin {
1430 t::ClientDiscriminant::EnrollmentRequest => {
1431 take_enrollment(decoder).map(e::ResponseEnvelope::Enrollment)
1432 }
1433 t::ClientDiscriminant::CredentialAttachRequest => {
1434 take_attach(decoder).map(e::ResponseEnvelope::CredentialAttach)
1435 }
1436 t::ClientDiscriminant::DetachRequest => {
1437 take_detach(decoder).map(e::ResponseEnvelope::Detach)
1438 }
1439 t::ClientDiscriminant::ParticipantAck => {
1440 take_participant_ack(decoder).map(e::ResponseEnvelope::ParticipantAck)
1441 }
1442 t::ClientDiscriminant::LeaveRequest => take_leave(decoder).map(e::ResponseEnvelope::Leave),
1443 t::ClientDiscriminant::MarkerAck => {
1444 take_marker_ack(decoder).map(e::ResponseEnvelope::MarkerAck)
1445 }
1446 t::ClientDiscriminant::RecordAdmission => {
1447 take_record_admission(decoder).map(e::ResponseEnvelope::RecordAdmission)
1448 }
1449 t::ClientDiscriminant::ObserverRecoveryHandshake
1450 | t::ClientDiscriminant::SettlementQuery => Err(decode_error(t::DecodeClass::InvalidField)),
1451 }
1452}
1453
1454fn take_participant_reference(
1455 origin: t::ClientDiscriminant,
1456 decoder: &mut Decoder<'_>,
1457) -> Result<r::ParticipantReferenceEnvelope, CodecError> {
1458 match origin {
1459 t::ClientDiscriminant::CredentialAttachRequest => {
1460 take_attach(decoder).map(r::ParticipantReferenceEnvelope::CredentialAttach)
1461 }
1462 t::ClientDiscriminant::DetachRequest => {
1463 take_detach(decoder).map(r::ParticipantReferenceEnvelope::Detach)
1464 }
1465 t::ClientDiscriminant::ParticipantAck => {
1466 take_participant_ack(decoder).map(r::ParticipantReferenceEnvelope::ParticipantAck)
1467 }
1468 t::ClientDiscriminant::LeaveRequest => {
1469 take_leave(decoder).map(r::ParticipantReferenceEnvelope::Leave)
1470 }
1471 t::ClientDiscriminant::MarkerAck => {
1472 take_marker_ack(decoder).map(r::ParticipantReferenceEnvelope::MarkerAck)
1473 }
1474 t::ClientDiscriminant::RecordAdmission => {
1475 take_record_admission(decoder).map(r::ParticipantReferenceEnvelope::RecordAdmission)
1476 }
1477 t::ClientDiscriminant::EnrollmentRequest
1478 | t::ClientDiscriminant::ObserverRecoveryHandshake
1479 | t::ClientDiscriminant::SettlementQuery => Err(decode_error(t::DecodeClass::InvalidField)),
1480 }
1481}
1482
1483fn take_binding_required(
1484 origin: t::ClientDiscriminant,
1485 decoder: &mut Decoder<'_>,
1486) -> Result<r::BindingRequiredEnvelope, CodecError> {
1487 match origin {
1488 t::ClientDiscriminant::DetachRequest => {
1489 take_detach(decoder).map(r::BindingRequiredEnvelope::Detach)
1490 }
1491 t::ClientDiscriminant::ParticipantAck => {
1492 take_participant_ack(decoder).map(r::BindingRequiredEnvelope::ParticipantAck)
1493 }
1494 t::ClientDiscriminant::LeaveRequest => {
1495 take_leave(decoder).map(r::BindingRequiredEnvelope::Leave)
1496 }
1497 t::ClientDiscriminant::MarkerAck => {
1498 take_marker_ack(decoder).map(r::BindingRequiredEnvelope::MarkerAck)
1499 }
1500 t::ClientDiscriminant::RecordAdmission => {
1501 take_record_admission(decoder).map(r::BindingRequiredEnvelope::RecordAdmission)
1502 }
1503 t::ClientDiscriminant::EnrollmentRequest
1504 | t::ClientDiscriminant::CredentialAttachRequest
1505 | t::ClientDiscriminant::ObserverRecoveryHandshake
1506 | t::ClientDiscriminant::SettlementQuery => Err(decode_error(t::DecodeClass::InvalidField)),
1507 }
1508}
1509
1510fn take_order_allocating(
1511 origin: t::ClientDiscriminant,
1512 decoder: &mut Decoder<'_>,
1513) -> Result<r::OrderAllocatingEnvelope, CodecError> {
1514 match origin {
1515 t::ClientDiscriminant::EnrollmentRequest => {
1516 take_enrollment(decoder).map(r::OrderAllocatingEnvelope::Enrollment)
1517 }
1518 t::ClientDiscriminant::CredentialAttachRequest => {
1519 take_attach(decoder).map(r::OrderAllocatingEnvelope::CredentialAttach)
1520 }
1521 t::ClientDiscriminant::RecordAdmission => {
1522 take_record_admission(decoder).map(r::OrderAllocatingEnvelope::RecordAdmission)
1523 }
1524 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1525 }
1526}
1527
1528fn take_closure_checked(
1529 origin: t::ClientDiscriminant,
1530 decoder: &mut Decoder<'_>,
1531) -> Result<c::ClosureCheckedEnvelope, CodecError> {
1532 match origin {
1533 t::ClientDiscriminant::EnrollmentRequest => {
1534 take_enrollment(decoder).map(c::ClosureCheckedEnvelope::Enrollment)
1535 }
1536 t::ClientDiscriminant::CredentialAttachRequest => {
1537 take_attach(decoder).map(c::ClosureCheckedEnvelope::CredentialAttach)
1538 }
1539 t::ClientDiscriminant::LeaveRequest => {
1540 take_leave(decoder).map(c::ClosureCheckedEnvelope::Leave)
1541 }
1542 t::ClientDiscriminant::RecordAdmission => {
1543 take_record_admission(decoder).map(c::ClosureCheckedEnvelope::RecordAdmission)
1544 }
1545 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1546 }
1547}
1548
1549fn take_sequence_allocating(
1550 origin: t::ClientDiscriminant,
1551 decoder: &mut Decoder<'_>,
1552) -> Result<r::SequenceAllocatingEnvelope, CodecError> {
1553 match origin {
1554 t::ClientDiscriminant::EnrollmentRequest => {
1555 take_enrollment(decoder).map(r::SequenceAllocatingEnvelope::Enrollment)
1556 }
1557 t::ClientDiscriminant::CredentialAttachRequest => {
1558 take_attach(decoder).map(r::SequenceAllocatingEnvelope::CredentialAttach)
1559 }
1560 t::ClientDiscriminant::RecordAdmission => {
1561 take_record_admission(decoder).map(r::SequenceAllocatingEnvelope::RecordAdmission)
1562 }
1563 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1564 }
1565}
1566
1567fn take_marker_proof(
1568 origin: t::ClientDiscriminant,
1569 decoder: &mut Decoder<'_>,
1570) -> Result<r::MarkerProofRequest, CodecError> {
1571 match origin {
1572 t::ClientDiscriminant::CredentialAttachRequest => Ok(
1573 r::MarkerProofRequest::CredentialAttach(r::AttachMarkerProof {
1574 conversation_id: decoder.take_u64()?,
1575 token: AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1576 participant_id: decoder.take_u64()?,
1577 capability_generation: decoder.take_generation()?,
1578 requested_marker_delivery_seq: decoder.take_u64()?,
1579 }),
1580 ),
1581 t::ClientDiscriminant::MarkerAck => {
1582 Ok(r::MarkerProofRequest::MarkerAck(r::MarkerAckProof {
1583 conversation_id: decoder.take_u64()?,
1584 participant_id: decoder.take_u64()?,
1585 capability_generation: decoder.take_generation()?,
1586 requested_marker_delivery_seq: decoder.take_u64()?,
1587 }))
1588 }
1589 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1590 }
1591}
1592
1593fn take_repayment_edge(decoder: &mut Decoder<'_>) -> Result<c::RepaymentEdge, CodecError> {
1594 let tag = t::RepaymentEdgeTag::try_from(decoder.take_u16()?)
1595 .map_err(|_| decode_error(t::DecodeClass::InvalidField))?;
1596 match tag {
1597 t::RepaymentEdgeTag::None => Ok(c::RepaymentEdge::None),
1598 t::RepaymentEdgeTag::ObserverProjection => Ok(c::RepaymentEdge::ObserverProjection {
1599 through_seq: decoder.take_u64()?,
1600 }),
1601 t::RepaymentEdgeTag::PhysicalCompaction => Ok(c::RepaymentEdge::PhysicalCompaction {
1602 from_floor: decoder.take_u64()?,
1603 through_seq: decoder.take_u64()?,
1604 }),
1605 t::RepaymentEdgeTag::MarkerDelivery => Ok(c::RepaymentEdge::MarkerDelivery {
1606 participant_id: decoder.take_u64()?,
1607 binding_epoch: decoder.take_binding_epoch()?,
1608 marker_delivery_seq: decoder.take_u64()?,
1609 }),
1610 t::RepaymentEdgeTag::ParticipantCursorProgress => Ok(
1611 c::RepaymentEdge::ParticipantCursorProgress(c::ParticipantCursorProgressEdge {
1612 participant_id: decoder.take_u64()?,
1613 binding_epoch: decoder.take_binding_epoch()?,
1614 through_seq: decoder.take_u64()?,
1615 marker_delivery_seq: decoder.take_option_u64()?,
1616 }),
1617 ),
1618 t::RepaymentEdgeTag::DetachedCredentialRecovery => {
1619 Ok(c::RepaymentEdge::DetachedCredentialRecovery {
1620 participant_id: decoder.take_u64()?,
1621 marker_delivery_seq: decoder.take_u64()?,
1622 prior_binding_epoch: decoder.take_binding_epoch()?,
1623 })
1624 }
1625 t::RepaymentEdgeTag::DetachedMarkerRelease => Ok(c::RepaymentEdge::DetachedMarkerRelease {
1626 participant_id: decoder.take_u64()?,
1627 marker_delivery_seq: decoder.take_u64()?,
1628 last_dead_binding_epoch: decoder.take_binding_epoch()?,
1629 }),
1630 t::RepaymentEdgeTag::DetachedCursorRelease => Ok(c::RepaymentEdge::DetachedCursorRelease {
1631 participant_id: decoder.take_u64()?,
1632 last_dead_binding_epoch: decoder.take_binding_epoch()?,
1633 }),
1634 }
1635}
1636
1637fn take_closure_snapshot(decoder: &mut Decoder<'_>) -> Result<c::ClosureSnapshot, CodecError> {
1638 Ok(c::ClosureSnapshot {
1639 marker_capacity_credits: decoder.take_u64()?,
1640 marker_anchors: decoder.take_u64()?,
1641 entry_debt: decoder.take_u64()?,
1642 byte_debt: decoder.take_u64()?,
1643 repayment_edge: take_repayment_edge(decoder)?,
1644 edge_sequence_claims: decoder.take_u64()?,
1645 edge_order_position_claims: decoder.take_u64()?,
1646 edge_k_remaining: decoder.take_resource_vector()?,
1647 k_headroom: decoder.take_wide_resource_vector()?,
1648 episode_churn_used: decoder.take_u64()?,
1649 delta_cycles: decoder.take_u64()?,
1650 episode_churn_limit: decoder.take_u64()?,
1651 })
1652}
1653
1654fn take_sequence_budget(decoder: &mut Decoder<'_>) -> Result<super::SequenceBudget, CodecError> {
1655 Ok(super::SequenceBudget {
1656 high_watermark: decoder.take_u64()?,
1657 remaining: decoder.take_u64()?,
1658 e: decoder.take_u64()?,
1659 t: decoder.take_u64()?,
1660 m: decoder.take_u64()?,
1661 rs: decoder.take_u64()?,
1662 rt: decoder.take_u64()?,
1663 l_times_t: decoder.take_u128()?,
1664 l_times_rt: decoder.take_u128()?,
1665 l_other_times_e: decoder.take_u128()?,
1666 })
1667}
1668
1669fn required_origin(
1670 origin: Option<t::ClientDiscriminant>,
1671) -> Result<t::ClientDiscriminant, CodecError> {
1672 origin.ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
1673}
1674
1675#[allow(clippy::too_many_lines)]
1676fn decode_server_suffix(
1677 discriminant: t::ServerDiscriminant,
1678 origin: Option<t::ClientDiscriminant>,
1679 decoder: &mut Decoder<'_>,
1680) -> Result<r::ServerValue, CodecError> {
1681 use t::ServerDiscriminant as D;
1682
1683 match discriminant {
1684 D::ParticipantTransportRejected => {
1685 let reason = match take_tag::<t::TransportReasonTag>(decoder)? {
1686 t::TransportReasonTag::FrameTooLarge => {
1687 r::TransportRejectionReason::FrameTooLarge {
1688 complete_frame_bytes: decoder.take_u64()?,
1689 max_frame_bytes: decoder.take_u64()?,
1690 }
1691 }
1692 t::TransportReasonTag::DecodeFailed => {
1693 let decode_class = take_tag::<t::DecodeClass>(decoder)?;
1694 r::TransportRejectionReason::DecodeFailed { decode_class }
1695 }
1696 t::TransportReasonTag::UnsupportedVersion => {
1697 r::TransportRejectionReason::UnsupportedVersion {
1698 presented_version: decoder.take_protocol_version()?,
1699 supported_version: decoder.take_protocol_version()?,
1700 }
1701 }
1702 t::TransportReasonTag::AuthenticationFailed => {
1703 r::TransportRejectionReason::AuthenticationFailed
1704 }
1705 t::TransportReasonTag::ParticipantCapabilityRequired => {
1706 let capability = decoder.take_string()?;
1707 if capability != r::PARTICIPANT_CAPABILITY {
1708 decoder.invalidate();
1709 }
1710 r::TransportRejectionReason::ParticipantCapabilityRequired
1711 }
1712 t::TransportReasonTag::EnrollmentNotPermitted => {
1713 r::TransportRejectionReason::EnrollmentNotPermitted
1714 }
1715 t::TransportReasonTag::EnrollmentConversationOutOfScope => {
1716 r::TransportRejectionReason::EnrollmentConversationOutOfScope
1717 }
1718 t::TransportReasonTag::CredentialAttachConversationOutOfScope => {
1719 r::TransportRejectionReason::CredentialAttachConversationOutOfScope
1720 }
1721 };
1722 Ok(r::ServerValue::ParticipantTransportRejected(
1723 r::ParticipantTransportRejected { reason },
1724 ))
1725 }
1726 D::AttemptTokenBodyConflict => {
1727 let origin = required_origin(origin)?;
1728 let token = decoder.take_fixed::<TOKEN_LEN>()?;
1729 let operation = take_tag::<t::AttemptOperation>(decoder)?;
1730 match origin {
1731 t::ClientDiscriminant::CredentialAttachRequest => {
1732 if operation != t::AttemptOperation::CredentialAttachRequest {
1733 return Err(decode_error(t::DecodeClass::InvalidField));
1734 }
1735 Ok(r::ServerValue::AttemptTokenBodyConflict(
1736 r::AttemptTokenBodyConflict::CredentialAttach {
1737 token: AttachAttemptToken::new(token),
1738 conversation_id: decoder.take_u64()?,
1739 presented_participant_id: decoder.take_u64()?,
1740 presented_generation: decoder.take_generation()?,
1741 presented_marker_delivery_seq: decoder.take_option_u64()?,
1742 conflict: take_tag::<t::AttemptConflict>(decoder)?,
1743 },
1744 ))
1745 }
1746 t::ClientDiscriminant::LeaveRequest => {
1747 if operation != t::AttemptOperation::LeaveRequest {
1748 return Err(decode_error(t::DecodeClass::InvalidField));
1749 }
1750 let value = r::AttemptTokenBodyConflict::Leave {
1751 token: LeaveAttemptToken::new(token),
1752 conversation_id: decoder.take_u64()?,
1753 presented_participant_id: decoder.take_u64()?,
1754 presented_generation: decoder.take_generation()?,
1755 };
1756 if take_tag::<t::AttemptConflict>(decoder)? != t::AttemptConflict::Generation {
1757 decoder.invalidate();
1758 }
1759 Ok(r::ServerValue::AttemptTokenBodyConflict(value))
1760 }
1761 t::ClientDiscriminant::RecordAdmission => {
1762 if operation != t::AttemptOperation::RecordAdmission {
1763 return Err(decode_error(t::DecodeClass::InvalidField));
1764 }
1765 Ok(r::ServerValue::AttemptTokenBodyConflict(
1766 r::AttemptTokenBodyConflict::RecordAdmission {
1767 token: RecordAdmissionAttemptToken::new(token),
1768 conversation_id: decoder.take_u64()?,
1769 presented_participant_id: decoder.take_u64()?,
1770 presented_generation: decoder.take_generation()?,
1771 },
1772 ))
1773 }
1774 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1775 }
1776 }
1777 D::ConnectionConversationCapacityExceeded => {
1778 let origin = required_origin(origin)?;
1779 Ok(r::ServerValue::ConnectionConversationCapacityExceeded(
1780 r::ConnectionConversationCapacityExceeded::SemanticRequest {
1781 request: take_response_envelope(origin, decoder)?,
1782 limit: decoder.take_u64()?,
1783 },
1784 ))
1785 }
1786 D::ConnectionConversationBindingOccupied => {
1787 let origin = required_origin(origin)?;
1788 let value = match origin {
1789 t::ClientDiscriminant::EnrollmentRequest => {
1790 let conversation_id = decoder.take_u64()?;
1791 let enrollment_token = EnrollmentToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
1792 if decoder.take_option_u64()?.is_some() {
1793 decoder.invalidate();
1794 }
1795 r::ConnectionConversationBindingOccupied::Enrollment {
1796 conversation_id,
1797 enrollment_token,
1798 }
1799 }
1800 t::ClientDiscriminant::CredentialAttachRequest => {
1801 let conversation_id = decoder.take_u64()?;
1802 let participant_id = decoder.take_u64()?;
1803 let capability_generation = decoder.take_generation()?;
1804 let attach_attempt_token =
1805 AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
1806 let accept_marker_delivery_seq = decoder.take_option_u64()?;
1807 if decoder.take_option_u64()? != Some(participant_id) {
1808 decoder.invalidate();
1809 }
1810 r::ConnectionConversationBindingOccupied::CredentialAttach {
1811 conversation_id,
1812 participant_id,
1813 capability_generation,
1814 attach_attempt_token,
1815 accept_marker_delivery_seq,
1816 }
1817 }
1818 _ => return Err(decode_error(t::DecodeClass::InvalidField)),
1819 };
1820 Ok(r::ServerValue::ConnectionConversationBindingOccupied(value))
1821 }
1822 D::ConversationOrderExhausted => {
1823 let origin = required_origin(origin)?;
1824 let request = take_order_allocating(origin, decoder)?;
1825 let _counter = take_tag::<t::Counter>(decoder)?;
1826 let high = decoder.take_u64()?;
1827 let next_value = decoder.take_option_u64()?;
1828 let order_remaining = decoder.take_u128()?;
1829 let reserved_claims = decoder.take_u128()?;
1830 if decoder.take_u64()? != r::ConversationOrderExhausted::REQUIRED_MAJORS {
1831 decoder.invalidate();
1832 }
1833 let resulting_order_remaining = decoder.take_u128()?;
1834 let resulting_reserved_claims = decoder.take_u128()?;
1835 let value = r::ConversationOrderExhausted::new(
1836 request,
1837 high,
1838 order_remaining,
1839 reserved_claims,
1840 resulting_order_remaining,
1841 resulting_reserved_claims,
1842 );
1843 if next_value != value.next_value() {
1844 decoder.invalidate();
1845 }
1846 Ok(r::ServerValue::ConversationOrderExhausted(
1847 alloc::boxed::Box::new(value),
1848 ))
1849 }
1850 D::ParticipantUnknown => {
1851 let origin = required_origin(origin)?;
1852 Ok(r::ServerValue::ParticipantUnknown(r::ParticipantUnknown {
1853 request: take_participant_reference(origin, decoder)?,
1854 }))
1855 }
1856 D::NoBinding => {
1857 let origin = required_origin(origin)?;
1858 Ok(r::ServerValue::NoBinding(r::NoBinding {
1859 request: take_binding_required(origin, decoder)?,
1860 }))
1861 }
1862 D::StaleAuthority => take_stale_authority(required_origin(origin)?, decoder)
1863 .map(r::ServerValue::StaleAuthority),
1864 D::Retired => {
1865 let origin = required_origin(origin)?;
1866 let value = if origin == t::ClientDiscriminant::EnrollmentRequest {
1867 r::Retired::Enrollment {
1868 request: take_enrollment(decoder)?,
1869 participant_id: decoder.take_u64()?,
1870 retired_generation: decoder.take_generation()?,
1871 }
1872 } else {
1873 r::Retired::Participant {
1874 request: take_participant_reference(origin, decoder)?,
1875 retired_generation: decoder.take_generation()?,
1876 }
1877 };
1878 Ok(r::ServerValue::Retired(value))
1879 }
1880 D::MarkerClosureCapacityExceeded => {
1881 let origin = required_origin(origin)?;
1882 let request = take_closure_checked(origin, decoder)?;
1883 let scope = take_tag::<t::ClosureScope>(decoder)?;
1884 let snapshot = take_closure_snapshot(decoder)?;
1885 let reason = match scope {
1886 t::ClosureScope::Capacity => {
1887 let dimension =
1888 ResourceDimension::from(take_tag::<t::ResourceDimensionTag>(decoder)?);
1889 c::ClosureRefusalReason::Capacity(c::ClosureCapacityReason {
1890 dimension,
1891 required: decoder.take_u128()?,
1892 limit: decoder.take_u128()?,
1893 })
1894 }
1895 t::ClosureScope::RecoveryFence => c::ClosureRefusalReason::RecoveryFence,
1896 t::ClosureScope::DeliveredMarkerAwaitingAck => {
1897 c::ClosureRefusalReason::DeliveredMarkerAwaitingAck
1898 }
1899 t::ClosureScope::EpisodeChurnLimit => c::ClosureRefusalReason::EpisodeChurnLimit,
1900 };
1901 Ok(r::ServerValue::MarkerClosureCapacityExceeded(
1902 alloc::boxed::Box::new(c::MarkerClosureCapacityExceeded {
1903 request,
1904 snapshot,
1905 reason,
1906 }),
1907 ))
1908 }
1909 D::EnrollBound => take_enroll_bound(decoder).map(r::ServerValue::EnrollBound),
1910 D::EnrollmentKnown => Ok(r::ServerValue::EnrollmentKnown(r::EnrollmentKnown {
1911 conversation_id: decoder.take_u64()?,
1912 token: EnrollmentToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1913 participant_id: decoder.take_u64()?,
1914 current_generation: decoder.take_generation()?,
1915 })),
1916 D::ReceiptExpired => take_receipt_expired(required_origin(origin)?, decoder)
1917 .map(r::ServerValue::ReceiptExpired),
1918 D::ReceiptCapacityExceeded => take_receipt_capacity(required_origin(origin)?, decoder)
1919 .map(r::ServerValue::ReceiptCapacityExceeded),
1920 D::IdentityCapacityExceeded => {
1921 let request = take_enrollment(decoder)?;
1922 let scope = take_tag::<t::IdentityCapacityScope>(decoder)?;
1923 let limit = decoder.take_u64()?;
1924 let occupied = decoder.take_u64()?;
1925 if decoder.take_u64()? != r::IdentityCapacityExceeded::REQUESTED {
1926 decoder.invalidate();
1927 }
1928 Ok(r::ServerValue::IdentityCapacityExceeded(
1929 r::IdentityCapacityExceeded {
1930 request,
1931 scope,
1932 limit,
1933 occupied,
1934 },
1935 ))
1936 }
1937 D::ObserverBackpressure => take_observer_backpressure(required_origin(origin)?, decoder)
1938 .map(r::ServerValue::ObserverBackpressure),
1939 D::ConversationSequenceExhausted => {
1940 let request = take_sequence_allocating(required_origin(origin)?, decoder)?;
1941 Ok(r::ServerValue::ConversationSequenceExhausted(
1942 alloc::boxed::Box::new(r::ConversationSequenceExhausted {
1943 request,
1944 sequence_budget: take_sequence_budget(decoder)?,
1945 }),
1946 ))
1947 }
1948 D::AttachBound => take_attach_bound(decoder).map(r::ServerValue::AttachBound),
1949 D::StaleOrUnknownReceipt => Ok(r::ServerValue::StaleOrUnknownReceipt(
1950 r::StaleOrUnknownReceipt {
1951 conversation_id: decoder.take_u64()?,
1952 token: AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1953 participant_id: decoder.take_u64()?,
1954 presented_generation: decoder.take_generation()?,
1955 presented_marker_delivery_seq: decoder.take_option_u64()?,
1956 current_generation: decoder.take_generation()?,
1957 },
1958 )),
1959 D::MarkerNotDelivered => {
1960 let request = take_marker_proof(required_origin(origin)?, decoder)?;
1961 let reason = take_tag::<t::MarkerNotDeliveredReason>(decoder)?;
1962 Ok(r::ServerValue::MarkerNotDelivered(r::MarkerNotDelivered {
1963 request,
1964 reason,
1965 expected_marker_delivery_seq: decoder.take_u64()?,
1966 }))
1967 }
1968 D::MarkerMismatch => {
1969 let request = take_marker_proof(required_origin(origin)?, decoder)?;
1970 let reason = take_tag::<t::MarkerMismatchReason>(decoder)?;
1971 let mismatch = match reason {
1972 t::MarkerMismatchReason::BelowCursor => r::MarkerMismatchBody::BelowCursor {
1973 current_cursor: decoder.take_u64()?,
1974 },
1975 t::MarkerMismatchReason::NoMarkerExpected => {
1976 r::MarkerMismatchBody::NoMarkerExpected
1977 }
1978 t::MarkerMismatchReason::ExpectedDifferentMarker => {
1979 r::MarkerMismatchBody::ExpectedDifferentMarker {
1980 expected_marker_delivery_seq: decoder.take_u64()?,
1981 }
1982 }
1983 };
1984 Ok(r::ServerValue::MarkerMismatch(r::MarkerMismatch {
1985 request,
1986 mismatch,
1987 }))
1988 }
1989 D::Bound => {
1990 take_receipt_replay(required_origin(origin)?, decoder).map(r::ServerValue::Bound)
1991 }
1992 D::UnboundReceipt => take_receipt_replay(required_origin(origin)?, decoder)
1993 .map(r::ServerValue::UnboundReceipt),
1994 D::DetachCommitted => {
1995 let conversation_id = decoder.take_u64()?;
1996 let participant_id = decoder.take_u64()?;
1997 let capability_generation = decoder.take_generation()?;
1998 let detach_attempt_token = DetachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
1999 let committed_binding_epoch = decoder.take_binding_epoch()?;
2000 let detached_delivery_seq = decoder.take_u64()?;
2001 if capability_generation != committed_binding_epoch.capability_generation {
2002 decoder.invalidate();
2003 }
2004 Ok(r::ServerValue::DetachCommitted(r::DetachCommitted::new(
2005 conversation_id,
2006 participant_id,
2007 detach_attempt_token,
2008 committed_binding_epoch,
2009 detached_delivery_seq,
2010 )))
2011 }
2012 D::DetachInProgress => Ok(r::ServerValue::DetachInProgress(r::DetachInProgress {
2013 conversation_id: decoder.take_u64()?,
2014 participant_id: decoder.take_u64()?,
2015 presented_token: DetachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
2016 presented_generation: decoder.take_generation()?,
2017 committed_binding_epoch: decoder.take_binding_epoch()?,
2018 })),
2019 D::AckCommitted => {
2020 let request = take_participant_ack(decoder)?;
2021 if decoder.take_u64()? != request.through_seq {
2022 decoder.invalidate();
2023 }
2024 Ok(r::ServerValue::AckCommitted(r::AckCommitted::new(request)))
2025 }
2026 D::AckNoOp => {
2027 take_ack_no_op(required_origin(origin)?, decoder).map(r::ServerValue::AckNoOp)
2028 }
2029 D::AckGap => {
2030 let request = take_participant_ack(decoder)?;
2031 let current_cursor = decoder.take_u64()?;
2032 let _reason = take_tag::<t::AckGapReason>(decoder)?;
2033 r::AckGap::new(request, current_cursor)
2034 .map(r::ServerValue::AckGap)
2035 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
2036 }
2037 D::AckRegression => {
2038 let request = take_participant_ack(decoder)?;
2039 let current_cursor = decoder.take_u64()?;
2040 let _reason = take_tag::<t::AckRegressionReason>(decoder)?;
2041 r::AckRegression::new(request, current_cursor)
2042 .map(r::ServerValue::AckRegression)
2043 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
2044 }
2045 D::LeaveCommitted => {
2046 let conversation_id = decoder.take_u64()?;
2047 let leave_attempt_token = LeaveAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2048 let participant_id = decoder.take_u64()?;
2049 let presented_generation = decoder.take_generation()?;
2050 let retired_generation = decoder.take_generation()?;
2051 let ended_binding_epoch = decoder.take_option_binding_epoch()?;
2052 let prior_terminal_delivery_seq = decoder.take_option_u64()?;
2053 let left_delivery_seq = decoder.take_u64()?;
2054 if presented_generation != retired_generation {
2055 return Err(decode_error(t::DecodeClass::InvalidField));
2056 }
2057 r::LeaveCommitted::new(
2058 conversation_id,
2059 leave_attempt_token,
2060 participant_id,
2061 retired_generation,
2062 ended_binding_epoch,
2063 prior_terminal_delivery_seq,
2064 left_delivery_seq,
2065 )
2066 .map(r::ServerValue::LeaveCommitted)
2067 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
2068 }
2069 D::MarkerAckCommitted => {
2070 let request = take_marker_ack(decoder)?;
2071 if decoder.take_u64()? != request.marker_delivery_seq {
2072 decoder.invalidate();
2073 }
2074 Ok(r::ServerValue::MarkerAckCommitted(
2075 r::MarkerAckCommitted::new(request),
2076 ))
2077 }
2078 D::SettlementAnswer => {
2079 let conversation_id = decoder.take_u64()?;
2080 let participant_id = decoder.take_u64()?;
2081 let record_admission_attempt_token =
2082 RecordAdmissionAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2083 let outcome = match decoder.take_u8()? {
2084 1 => r::SettlementOutcome::Committed {
2085 delivery_seq: decoder.take_u64()?,
2086 },
2087 2 => r::SettlementOutcome::Withdrawn,
2088 3 => r::SettlementOutcome::Expired,
2089 4 => r::SettlementOutcome::NotCommitted,
2090 5 => r::SettlementOutcome::Unknown,
2091 _ => return Err(decode_error(t::DecodeClass::InvalidField)),
2092 };
2093 Ok(r::ServerValue::SettlementAnswer(r::SettlementAnswer {
2094 conversation_id,
2095 participant_id,
2096 record_admission_attempt_token,
2097 outcome,
2098 }))
2099 }
2100 D::RecordCommitted => {
2101 let request = take_record_admission(decoder)?;
2102 if decoder.take_u64()? != request.participant_id {
2103 decoder.invalidate();
2104 }
2105 let delivery_seq = decoder.take_u64()?;
2106 Ok(r::ServerValue::RecordCommitted(r::RecordCommitted::new(
2107 request,
2108 delivery_seq,
2109 )))
2110 }
2111 D::RecordTooLarge => Ok(r::ServerValue::RecordTooLarge(r::RecordTooLarge {
2112 request: take_record_admission(decoder)?,
2113 dimension: ResourceDimension::from(take_tag::<t::ResourceDimensionTag>(decoder)?),
2114 encoded_record_charge: decoder.take_resource_vector()?,
2115 max_ordinary_record_charge: decoder.take_resource_vector()?,
2116 })),
2117 D::ObserverRecoveryAccepted => {
2118 take_recovery_accepted(decoder).map(r::ServerValue::ObserverRecoveryAccepted)
2119 }
2120 D::InvalidObserverEpoch => {
2121 require_zero_recovery_count(decoder)?;
2122 take_invalid_observer_epoch(decoder).map(r::ServerValue::InvalidObserverEpoch)
2123 }
2124 D::InvalidObserverEpochList => {
2125 require_zero_recovery_count(decoder)?;
2126 take_invalid_observer_epoch_list(decoder).map(r::ServerValue::InvalidObserverEpochList)
2127 }
2128 D::ObserverRecoveryConnectionCapacityExceeded => {
2129 require_zero_recovery_count(decoder)?;
2130 Ok(r::ServerValue::ConnectionConversationCapacityExceeded(
2131 r::ConnectionConversationCapacityExceeded::ObserverRecovery {
2132 conversation_id: decoder.take_u64()?,
2133 limit: decoder.take_u64()?,
2134 },
2135 ))
2136 }
2137 D::MarkerSettlementBackpressure => {
2138 let origin = required_origin(origin)?;
2139 let conversation_id = decoder.take_u64()?;
2140 let refused_epoch = decoder.take_u64()?;
2141 let value = match origin {
2142 t::ClientDiscriminant::CredentialAttachRequest => {
2143 r::MarkerSettlementBackpressure::CredentialAttach {
2144 conversation_id,
2145 refused_epoch,
2146 }
2147 }
2148 t::ClientDiscriminant::DetachRequest => r::MarkerSettlementBackpressure::Detach {
2149 conversation_id,
2150 refused_epoch,
2151 },
2152 _ => return Err(decode_error(t::DecodeClass::InvalidField)),
2153 };
2154 Ok(r::ServerValue::MarkerSettlementBackpressure(value))
2155 }
2156 D::EnrollmentSettlementBackpressure => {
2157 required_origin(origin)?;
2158 Ok(r::ServerValue::EnrollmentSettlementBackpressure(
2159 r::EnrollmentSettlementBackpressure {
2160 conversation_id: decoder.take_u64()?,
2161 },
2162 ))
2163 }
2164 D::RecordAdmissionProtocolFault => Ok(r::ServerValue::RecordAdmissionProtocolFault(
2165 r::RecordAdmissionProtocolFault {
2166 request: take_record_admission(decoder)?,
2167 class: r::RecordAdmissionFaultClass::from(take_tag::<
2168 t::RecordAdmissionFaultClassTag,
2169 >(decoder)?),
2170 },
2171 )),
2172 D::WriteOutcomeUnknown => take_write_outcome_unknown(required_origin(origin)?, decoder)
2173 .map(r::ServerValue::WriteOutcomeUnknown),
2174 }
2175}
2176
2177fn take_write_outcome_unknown(
2178 origin: t::ClientDiscriminant,
2179 decoder: &mut Decoder<'_>,
2180) -> Result<r::WriteOutcomeUnknown, CodecError> {
2181 match origin {
2182 t::ClientDiscriminant::EnrollmentRequest => Ok(r::WriteOutcomeUnknown::Enrollment {
2183 request: take_enrollment(decoder)?,
2184 }),
2185 t::ClientDiscriminant::CredentialAttachRequest => {
2186 Ok(r::WriteOutcomeUnknown::CredentialAttach {
2187 request: take_attach(decoder)?,
2188 })
2189 }
2190 t::ClientDiscriminant::DetachRequest => Ok(r::WriteOutcomeUnknown::Detach {
2191 request: take_detach(decoder)?,
2192 }),
2193 t::ClientDiscriminant::LeaveRequest => Ok(r::WriteOutcomeUnknown::Leave {
2194 request: take_leave(decoder)?,
2195 }),
2196 t::ClientDiscriminant::RecordAdmission => Ok(r::WriteOutcomeUnknown::RecordAdmission {
2197 request: take_record_admission(decoder)?,
2198 }),
2199 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2200 }
2201}
2202
2203trait WireTag: TryFrom<u16> {}
2204
2205impl WireTag for t::TransportReasonTag {}
2206impl WireTag for t::DecodeClass {}
2207impl WireTag for t::AttemptOperation {}
2208impl WireTag for t::AttemptConflict {}
2209impl WireTag for t::Counter {}
2210impl WireTag for t::ClosureScope {}
2211impl WireTag for t::ResourceDimensionTag {}
2212impl WireTag for t::IdentityCapacityScope {}
2213impl WireTag for t::MarkerNotDeliveredReason {}
2214impl WireTag for t::MarkerMismatchReason {}
2215impl WireTag for t::AckGapReason {}
2216impl WireTag for t::AckRegressionReason {}
2217impl WireTag for t::InvalidObserverEpochReason {}
2218impl WireTag for t::InvalidObserverEpochListReason {}
2219impl WireTag for t::RecordAdmissionFaultClassTag {}
2220
2221fn take_tag<T>(decoder: &mut Decoder<'_>) -> Result<T, CodecError>
2222where
2223 T: WireTag,
2224{
2225 T::try_from(decoder.take_u16()?).map_err(|_| decode_error(t::DecodeClass::InvalidField))
2226}
2227
2228fn take_stale_authority(
2229 origin: t::ClientDiscriminant,
2230 decoder: &mut Decoder<'_>,
2231) -> Result<r::StaleAuthority, CodecError> {
2232 match origin {
2233 t::ClientDiscriminant::CredentialAttachRequest => Ok(r::StaleAuthority::Live {
2234 request: r::CommonStaleAuthorityEnvelope::CredentialAttach(take_attach(decoder)?),
2235 current_generation: decoder.take_generation()?,
2236 }),
2237 t::ClientDiscriminant::ParticipantAck => Ok(r::StaleAuthority::Live {
2238 request: r::CommonStaleAuthorityEnvelope::ParticipantAck(take_participant_ack(
2239 decoder,
2240 )?),
2241 current_generation: decoder.take_generation()?,
2242 }),
2243 t::ClientDiscriminant::MarkerAck => Ok(r::StaleAuthority::Live {
2244 request: r::CommonStaleAuthorityEnvelope::MarkerAck(take_marker_ack(decoder)?),
2245 current_generation: decoder.take_generation()?,
2246 }),
2247 t::ClientDiscriminant::RecordAdmission => Ok(r::StaleAuthority::Live {
2248 request: r::CommonStaleAuthorityEnvelope::RecordAdmission(take_record_admission(
2249 decoder,
2250 )?),
2251 current_generation: decoder.take_generation()?,
2252 }),
2253 t::ClientDiscriminant::DetachRequest => {
2254 let authority = t::DetachAuthorityStateTag::try_from(decoder.take_u16()?)
2255 .map_err(|_| decode_error(t::DecodeClass::InvalidField))?;
2256 let value = match authority {
2257 t::DetachAuthorityStateTag::Live => r::DetachStaleAuthority::Live {
2258 conversation_id: decoder.take_u64()?,
2259 participant_id: decoder.take_u64()?,
2260 capability_generation: decoder.take_generation()?,
2261 detach_attempt_token: DetachAttemptToken::new(
2262 decoder.take_fixed::<TOKEN_LEN>()?,
2263 ),
2264 current_generation: decoder.take_generation()?,
2265 },
2266 t::DetachAuthorityStateTag::TerminalizedDetachCell => {
2267 let conversation_id = decoder.take_u64()?;
2268 let participant_id = decoder.take_u64()?;
2269 let capability_generation = decoder.take_generation()?;
2270 let detach_attempt_token =
2271 DetachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2272 let current_generation = decoder.take_generation()?;
2273 let committed_binding_epoch = decoder.take_binding_epoch()?;
2274 let binding_state = match t::BindingStateTag::try_from(decoder.take_u16()?)
2275 .map_err(|_| decode_error(t::DecodeClass::InvalidField))?
2276 {
2277 t::BindingStateTag::Bound => r::BindingStateView::Bound {
2278 current_binding_epoch: decoder.take_binding_epoch()?,
2279 },
2280 t::BindingStateTag::Detached => r::BindingStateView::Detached,
2281 };
2282 r::DetachStaleAuthority::TerminalizedDetachCell(
2283 r::TerminalizedDetachCell::from_wire_decode(
2284 TERMINALIZED_WIRE_DECODE_AUTHORITY,
2285 conversation_id,
2286 participant_id,
2287 capability_generation,
2288 detach_attempt_token,
2289 current_generation,
2290 committed_binding_epoch,
2291 binding_state,
2292 ),
2293 )
2294 }
2295 };
2296 Ok(r::StaleAuthority::Detach(value))
2297 }
2298 t::ClientDiscriminant::LeaveRequest => {
2299 let authority = t::LeaveAuthorityStateTag::try_from(decoder.take_u16()?)
2300 .map_err(|_| decode_error(t::DecodeClass::InvalidField))?;
2301 let conversation_id = decoder.take_u64()?;
2302 let participant_id = decoder.take_u64()?;
2303 let presented_generation = decoder.take_generation()?;
2304 let leave_attempt_token = LeaveAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2305 let value = match authority {
2306 t::LeaveAuthorityStateTag::Live => r::LeaveStaleAuthority::Live {
2307 conversation_id,
2308 participant_id,
2309 presented_generation,
2310 leave_attempt_token,
2311 current_generation: decoder.take_generation()?,
2312 },
2313 t::LeaveAuthorityStateTag::CommittedLeaveTombstone => {
2314 r::LeaveStaleAuthority::CommittedLeaveTombstone {
2315 conversation_id,
2316 participant_id,
2317 presented_generation,
2318 leave_attempt_token,
2319 retired_generation: decoder.take_generation()?,
2320 }
2321 }
2322 };
2323 Ok(r::StaleAuthority::Leave(value))
2324 }
2325 t::ClientDiscriminant::EnrollmentRequest
2326 | t::ClientDiscriminant::ObserverRecoveryHandshake
2327 | t::ClientDiscriminant::SettlementQuery => Err(decode_error(t::DecodeClass::InvalidField)),
2328 }
2329}
2330
2331fn take_enroll_bound(decoder: &mut Decoder<'_>) -> Result<r::EnrollBound, CodecError> {
2332 let conversation_id = decoder.take_u64()?;
2333 let token = EnrollmentToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2334 let participant_id = decoder.take_u64()?;
2335 if decoder.take_option_generation()?.is_some() {
2336 decoder.invalidate();
2337 }
2338 let capability_generation = decoder.take_generation()?;
2339 if capability_generation.get() != 1 {
2340 decoder.invalidate();
2341 }
2342 let attach_secret = AttachSecret::new(decoder.take_fixed::<SECRET_LEN>()?);
2343 let origin_binding_epoch = decoder.take_binding_epoch()?;
2344 if origin_binding_epoch.capability_generation.get() != 1 {
2345 decoder.invalidate();
2346 }
2347 if decoder.take_u64()? != 0 {
2348 decoder.invalidate();
2349 }
2350 if decoder.take_option_u64()?.is_some() {
2351 decoder.invalidate();
2352 }
2353 let receipt_expires_at = decoder.take_u128()?;
2354 let provenance_expires_at = decoder.take_u128()?;
2355
2356 let valid_epoch = if origin_binding_epoch.capability_generation.get() == 1 {
2357 origin_binding_epoch
2358 } else {
2359 BindingEpoch::new(
2360 origin_binding_epoch.connection_incarnation,
2361 generation_one()?,
2362 )
2363 };
2364 r::EnrollBound::new(
2365 conversation_id,
2366 token,
2367 participant_id,
2368 attach_secret,
2369 valid_epoch,
2370 receipt_expires_at,
2371 provenance_expires_at,
2372 )
2373 .ok_or(CodecError::InvalidValue)
2374}
2375
2376fn take_receipt_expired(
2377 origin: t::ClientDiscriminant,
2378 decoder: &mut Decoder<'_>,
2379) -> Result<r::ReceiptExpired, CodecError> {
2380 let conversation_id = decoder.take_u64()?;
2381 let token = decoder.take_fixed::<TOKEN_LEN>()?;
2382 let participant_id = decoder.take_u64()?;
2383 match origin {
2384 t::ClientDiscriminant::EnrollmentRequest => {
2385 if decoder.take_option_generation()?.is_some() {
2386 decoder.invalidate();
2387 }
2388 Ok(r::ReceiptExpired::Enrollment {
2389 conversation_id,
2390 token: EnrollmentToken::new(token),
2391 participant_id,
2392 result_generation: decoder.take_generation()?,
2393 current_generation: decoder.take_generation()?,
2394 reason: take_tag::<t::ReceiptExpiryReason>(decoder)?,
2395 })
2396 }
2397 t::ClientDiscriminant::CredentialAttachRequest => {
2398 let presented_generation = required_generation_option(decoder)?;
2399 Ok(r::ReceiptExpired::CredentialAttach {
2400 conversation_id,
2401 token: AttachAttemptToken::new(token),
2402 participant_id,
2403 presented_generation,
2404 presented_marker_delivery_seq: decoder.take_option_u64()?,
2405 result_generation: decoder.take_generation()?,
2406 current_generation: decoder.take_generation()?,
2407 reason: take_tag::<t::ReceiptExpiryReason>(decoder)?,
2408 })
2409 }
2410 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2411 }
2412}
2413
2414impl WireTag for t::ReceiptExpiryReason {}
2415impl WireTag for t::ReceiptCapacityScope {}
2416
2417fn take_receipt_capacity(
2418 origin: t::ClientDiscriminant,
2419 decoder: &mut Decoder<'_>,
2420) -> Result<r::ReceiptCapacityExceeded, CodecError> {
2421 match origin {
2422 t::ClientDiscriminant::EnrollmentRequest => {
2423 let request = take_enrollment(decoder)?;
2424 let scope = match take_tag::<t::ReceiptCapacityScope>(decoder)? {
2425 t::ReceiptCapacityScope::LiveReceiptServer => {
2426 r::EnrollmentReceiptCapacityScope::LiveReceiptServer
2427 }
2428 t::ReceiptCapacityScope::ProvenanceServer => {
2429 r::EnrollmentReceiptCapacityScope::ProvenanceServer
2430 }
2431 t::ReceiptCapacityScope::ProvenanceConversation => {
2432 r::EnrollmentReceiptCapacityScope::ProvenanceConversation
2433 }
2434 t::ReceiptCapacityScope::LiveReceiptParticipant
2435 | t::ReceiptCapacityScope::ProvenanceParticipant => {
2436 return Err(decode_error(t::DecodeClass::InvalidField));
2437 }
2438 };
2439 let limit = decoder.take_u64()?;
2440 let occupied = decoder.take_u64()?;
2441 require_one(decoder, r::ReceiptCapacityExceeded::REQUESTED)?;
2442 Ok(r::ReceiptCapacityExceeded::Enrollment {
2443 request,
2444 scope,
2445 limit,
2446 occupied,
2447 })
2448 }
2449 t::ClientDiscriminant::CredentialAttachRequest => {
2450 let request = take_attach(decoder)?;
2451 let scope = take_tag::<t::ReceiptCapacityScope>(decoder)?;
2452 let limit = decoder.take_u64()?;
2453 let occupied = decoder.take_u64()?;
2454 require_one(decoder, r::ReceiptCapacityExceeded::REQUESTED)?;
2455 Ok(r::ReceiptCapacityExceeded::CredentialAttach {
2456 request,
2457 scope,
2458 limit,
2459 occupied,
2460 })
2461 }
2462 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2463 }
2464}
2465
2466fn require_one(decoder: &mut Decoder<'_>, expected: u64) -> Result<(), CodecError> {
2467 if decoder.take_u64()? != expected {
2468 decoder.invalidate();
2469 }
2470 Ok(())
2471}
2472
2473fn take_observer_backpressure(
2474 origin: t::ClientDiscriminant,
2475 decoder: &mut Decoder<'_>,
2476) -> Result<r::ObserverBackpressure, CodecError> {
2477 match origin {
2478 t::ClientDiscriminant::EnrollmentRequest => Ok(r::ObserverBackpressure::Enrollment {
2479 request: take_enrollment(decoder)?,
2480 state: take_backpressure_state(decoder)?,
2481 }),
2482 t::ClientDiscriminant::CredentialAttachRequest => {
2483 Ok(r::ObserverBackpressure::CredentialAttach {
2484 request: take_attach(decoder)?,
2485 state: take_backpressure_state(decoder)?,
2486 })
2487 }
2488 t::ClientDiscriminant::DetachRequest => Ok(r::ObserverBackpressure::Detach {
2489 request: take_detach(decoder)?,
2490 committed_binding_epoch: decoder.take_binding_epoch()?,
2491 state: take_backpressure_state(decoder)?,
2492 }),
2493 t::ClientDiscriminant::LeaveRequest => Ok(r::ObserverBackpressure::Leave {
2494 request: take_leave(decoder)?,
2495 state: take_backpressure_state(decoder)?,
2496 prior_terminal_cell_exists: decoder.take_bool()?,
2497 }),
2498 t::ClientDiscriminant::RecordAdmission => Ok(r::ObserverBackpressure::RecordAdmission {
2499 request: take_record_admission(decoder)?,
2500 state: take_backpressure_state(decoder)?,
2501 }),
2502 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2503 }
2504}
2505
2506fn take_backpressure_state(
2507 decoder: &mut Decoder<'_>,
2508) -> Result<r::ObserverBackpressureState, CodecError> {
2509 let backpressure_epoch = decoder.take_u64()?;
2510 let observer_progress = decoder.take_u64()?;
2511 r::ObserverBackpressureState::replay(backpressure_epoch, observer_progress)
2512 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
2513}
2514
2515fn required_generation_option(decoder: &mut Decoder<'_>) -> Result<Generation, CodecError> {
2516 decoder.take_option_generation()?.map_or_else(
2517 || {
2518 decoder.invalidate();
2519 generation_one()
2520 },
2521 Ok,
2522 )
2523}
2524
2525fn take_attach_bound(decoder: &mut Decoder<'_>) -> Result<r::AttachBound, CodecError> {
2526 let conversation_id = decoder.take_u64()?;
2527 let token = AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2528 let participant_id = decoder.take_u64()?;
2529 let request_generation = required_generation_option(decoder)?;
2530 let capability_generation = decoder.take_generation()?;
2531 let attach_secret = AttachSecret::new(decoder.take_fixed::<SECRET_LEN>()?);
2532 let origin_binding_epoch = decoder.take_binding_epoch()?;
2533 let persisted_cursor = decoder.take_u64()?;
2534 let accepted_marker_delivery_seq = decoder.take_option_u64()?;
2535 let receipt_expires_at = decoder.take_u128()?;
2536 let provenance_expires_at = decoder.take_u128()?;
2537
2538 let value = match accepted_marker_delivery_seq {
2539 Some(marker) if persisted_cursor == marker => r::AttachBound::fenced(
2540 conversation_id,
2541 token,
2542 participant_id,
2543 request_generation,
2544 attach_secret,
2545 origin_binding_epoch,
2546 marker,
2547 receipt_expires_at,
2548 provenance_expires_at,
2549 ),
2550 Some(_) => None,
2551 None => r::AttachBound::ordinary(
2552 conversation_id,
2553 token,
2554 participant_id,
2555 request_generation,
2556 attach_secret,
2557 origin_binding_epoch,
2558 persisted_cursor,
2559 receipt_expires_at,
2560 provenance_expires_at,
2561 ),
2562 }
2563 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))?;
2564 if value.capability_generation() == capability_generation {
2565 Ok(value)
2566 } else {
2567 Err(decode_error(t::DecodeClass::InvalidField))
2568 }
2569}
2570
2571fn take_receipt_replay(
2572 origin: t::ClientDiscriminant,
2573 decoder: &mut Decoder<'_>,
2574) -> Result<r::ReceiptReplay, CodecError> {
2575 let conversation_id = decoder.take_u64()?;
2576 let token = decoder.take_fixed::<TOKEN_LEN>()?;
2577 let participant_id = decoder.take_u64()?;
2578 match origin {
2579 t::ClientDiscriminant::EnrollmentRequest => {
2580 let request_generation = decoder.take_option_generation()?;
2581 let capability_generation = decoder.take_generation()?;
2582 let attach_secret = AttachSecret::new(decoder.take_fixed::<SECRET_LEN>()?);
2583 let origin_binding_epoch = decoder.take_binding_epoch()?;
2584 let persisted_cursor = decoder.take_u64()?;
2585 let accepted_marker_delivery_seq = decoder.take_option_u64()?;
2586 let receipt_expires_at = decoder.take_u128()?;
2587 let provenance_expires_at = decoder.take_u128()?;
2588 let value = r::EnrollBound::new(
2589 conversation_id,
2590 EnrollmentToken::new(token),
2591 participant_id,
2592 attach_secret,
2593 origin_binding_epoch,
2594 receipt_expires_at,
2595 provenance_expires_at,
2596 )
2597 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))?;
2598 if request_generation.is_none()
2599 && capability_generation == Generation::ONE
2600 && persisted_cursor == 0
2601 && accepted_marker_delivery_seq.is_none()
2602 {
2603 Ok(r::ReceiptReplay::Enrollment(value))
2604 } else {
2605 Err(decode_error(t::DecodeClass::InvalidField))
2606 }
2607 }
2608 t::ClientDiscriminant::CredentialAttachRequest => {
2609 let request_generation = required_generation_option(decoder)?;
2610 let capability_generation = decoder.take_generation()?;
2611 let attach_secret = AttachSecret::new(decoder.take_fixed::<SECRET_LEN>()?);
2612 let origin_binding_epoch = decoder.take_binding_epoch()?;
2613 let persisted_cursor = decoder.take_u64()?;
2614 let accepted_marker_delivery_seq = decoder.take_option_u64()?;
2615 let receipt_expires_at = decoder.take_u128()?;
2616 let provenance_expires_at = decoder.take_u128()?;
2617 let attach_token = AttachAttemptToken::new(token);
2618 let value = match accepted_marker_delivery_seq {
2619 Some(marker) if persisted_cursor == marker => r::AttachBound::fenced(
2620 conversation_id,
2621 attach_token,
2622 participant_id,
2623 request_generation,
2624 attach_secret,
2625 origin_binding_epoch,
2626 marker,
2627 receipt_expires_at,
2628 provenance_expires_at,
2629 ),
2630 Some(_) => None,
2631 None => r::AttachBound::ordinary(
2632 conversation_id,
2633 attach_token,
2634 participant_id,
2635 request_generation,
2636 attach_secret,
2637 origin_binding_epoch,
2638 persisted_cursor,
2639 receipt_expires_at,
2640 provenance_expires_at,
2641 ),
2642 }
2643 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))?;
2644 if value.capability_generation() == capability_generation {
2645 Ok(r::ReceiptReplay::CredentialAttach(value))
2646 } else {
2647 Err(decode_error(t::DecodeClass::InvalidField))
2648 }
2649 }
2650 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2651 }
2652}
2653
2654fn take_ack_no_op(
2655 origin: t::ClientDiscriminant,
2656 decoder: &mut Decoder<'_>,
2657) -> Result<r::AckNoOp, CodecError> {
2658 match origin {
2659 t::ClientDiscriminant::ParticipantAck => {
2660 let request = take_participant_ack(decoder)?;
2661 if decoder.take_u64()? != request.through_seq {
2662 decoder.invalidate();
2663 }
2664 Ok(r::AckNoOp::participant_ack(request))
2665 }
2666 t::ClientDiscriminant::MarkerAck => {
2667 let request = take_marker_ack(decoder)?;
2668 if decoder.take_u64()? != request.marker_delivery_seq {
2669 decoder.invalidate();
2670 }
2671 Ok(r::AckNoOp::marker_ack(request))
2672 }
2673 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2674 }
2675}
2676
2677fn take_recovery_accepted(
2678 decoder: &mut Decoder<'_>,
2679) -> Result<r::ObserverRecoveryAccepted, CodecError> {
2680 let count = decoder.take_u64()?;
2681 let required = u128::from(count) * RECOVERY_STATUS_LEN;
2682 let remaining = u64::try_from(decoder.remaining())
2683 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))?;
2684 if required > u128::from(remaining) {
2685 return Err(decode_error(t::DecodeClass::MissingRequiredField));
2686 }
2687 let count_usize: usize = count
2688 .try_into()
2689 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))?;
2690
2691 let mut statuses = Vec::new();
2692 for _ in 0..count_usize {
2693 statuses.push(r::ObserverProgressStatus {
2694 conversation_id: decoder.take_u64()?,
2695 refused_epoch: decoder.take_u64()?,
2696 current_observer_progress: decoder.take_u64()?,
2697 armed: decoder.take_bool()?,
2698 progressed: decoder.take_bool()?,
2699 });
2700 }
2701 Ok(r::ObserverRecoveryAccepted { statuses })
2702}
2703
2704fn require_zero_recovery_count(decoder: &mut Decoder<'_>) -> Result<(), CodecError> {
2705 if decoder.take_u64()? == 0 {
2706 Ok(())
2707 } else {
2708 Err(decode_error(t::DecodeClass::InvalidField))
2709 }
2710}
2711
2712fn take_invalid_observer_epoch(
2713 decoder: &mut Decoder<'_>,
2714) -> Result<r::InvalidObserverEpoch, CodecError> {
2715 let reason = take_tag::<t::InvalidObserverEpochReason>(decoder)?;
2716 let conversation_id = decoder.take_u64()?;
2717 let presented_epoch = decoder.take_u64()?;
2718 let current = decoder.take_option_u64()?;
2719 match reason {
2720 t::InvalidObserverEpochReason::ConversationUnknown => {
2721 if current.is_some() {
2722 decoder.invalidate();
2723 }
2724 Ok(r::InvalidObserverEpoch::ConversationUnknown {
2725 conversation_id,
2726 presented_epoch,
2727 })
2728 }
2729 t::InvalidObserverEpochReason::EpochAhead => {
2730 let current_observer_progress = current.unwrap_or_else(|| {
2731 decoder.invalidate();
2732 0
2733 });
2734 Ok(r::InvalidObserverEpoch::EpochAhead {
2735 conversation_id,
2736 presented_epoch,
2737 current_observer_progress,
2738 })
2739 }
2740 }
2741}
2742
2743fn take_invalid_observer_epoch_list(
2744 decoder: &mut Decoder<'_>,
2745) -> Result<r::InvalidObserverEpochList, CodecError> {
2746 match take_tag::<t::InvalidObserverEpochListReason>(decoder)? {
2747 t::InvalidObserverEpochListReason::TooManyEntries => {
2748 Ok(r::InvalidObserverEpochList::TooManyEntries {
2749 presented_entries: decoder.take_u64()?,
2750 max_entries: decoder.take_u64()?,
2751 })
2752 }
2753 t::InvalidObserverEpochListReason::DuplicateConversation => {
2754 Ok(r::InvalidObserverEpochList::DuplicateConversation {
2755 conversation_id: decoder.take_u64()?,
2756 first_index: decoder.take_u64()?,
2757 duplicate_index: decoder.take_u64()?,
2758 })
2759 }
2760 }
2761}