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 r::TransportRejectionReason::AccessRefused { refusal } => {
636 encoder.put_u16(t::TransportReasonTag::AccessRefused.wire_value());
637 encoder.put_string(refusal)?;
638 }
639 },
640 r::ServerValue::AttemptTokenBodyConflict(value) => match value {
641 r::AttemptTokenBodyConflict::CredentialAttach {
642 token,
643 conversation_id,
644 presented_participant_id,
645 presented_generation,
646 presented_marker_delivery_seq,
647 conflict,
648 } => {
649 encoder.put_fixed(token.as_bytes());
650 encoder.put_u16(t::AttemptOperation::CredentialAttachRequest.wire_value());
651 encoder.put_u64(*conversation_id);
652 encoder.put_u64(*presented_participant_id);
653 encoder.put_generation(*presented_generation);
654 encoder.put_option_u64(*presented_marker_delivery_seq);
655 encoder.put_u16(conflict.wire_value());
656 }
657 r::AttemptTokenBodyConflict::Leave {
658 token,
659 conversation_id,
660 presented_participant_id,
661 presented_generation,
662 } => {
663 encoder.put_fixed(token.as_bytes());
664 encoder.put_u16(t::AttemptOperation::LeaveRequest.wire_value());
665 encoder.put_u64(*conversation_id);
666 encoder.put_u64(*presented_participant_id);
667 encoder.put_generation(*presented_generation);
668 encoder.put_u16(t::AttemptConflict::Generation.wire_value());
669 }
670 r::AttemptTokenBodyConflict::RecordAdmission {
671 token,
672 conversation_id,
673 presented_participant_id,
674 presented_generation,
675 } => {
676 encoder.put_fixed(token.as_bytes());
677 encoder.put_u16(t::AttemptOperation::RecordAdmission.wire_value());
678 encoder.put_u64(*conversation_id);
679 encoder.put_u64(*presented_participant_id);
680 encoder.put_generation(*presented_generation);
681 }
682 },
683 r::ServerValue::ConnectionConversationCapacityExceeded(value) => match value {
684 r::ConnectionConversationCapacityExceeded::SemanticRequest { request, limit } => {
685 put_response_envelope(request, encoder);
686 encoder.put_u64(*limit);
687 }
688 r::ConnectionConversationCapacityExceeded::ObserverRecovery {
689 conversation_id,
690 limit,
691 } => {
692 encoder.put_u64(0);
693 encoder.put_u64(*conversation_id);
694 encoder.put_u64(*limit);
695 }
696 },
697 r::ServerValue::ConnectionConversationBindingOccupied(value) => match value {
698 r::ConnectionConversationBindingOccupied::Enrollment {
699 conversation_id,
700 enrollment_token,
701 } => {
702 encoder.put_u64(*conversation_id);
703 encoder.put_fixed(enrollment_token.as_bytes());
704 encoder.put_option_u64(None);
705 }
706 r::ConnectionConversationBindingOccupied::CredentialAttach {
707 conversation_id,
708 participant_id,
709 capability_generation,
710 attach_attempt_token,
711 accept_marker_delivery_seq,
712 } => {
713 encoder.put_u64(*conversation_id);
714 encoder.put_u64(*participant_id);
715 encoder.put_generation(*capability_generation);
716 encoder.put_fixed(attach_attempt_token.as_bytes());
717 encoder.put_option_u64(*accept_marker_delivery_seq);
718 encoder.put_option_u64(Some(*participant_id));
719 }
720 },
721 r::ServerValue::ConversationOrderExhausted(value) => {
722 put_order_allocating(value.request(), encoder);
723 encoder.put_u16(value.counter().wire_value());
724 encoder.put_u64(value.high());
725 encoder.put_option_u64(value.next_value());
726 encoder.put_u128(value.order_remaining());
727 encoder.put_u128(value.reserved_claims());
728 encoder.put_u64(r::ConversationOrderExhausted::REQUIRED_MAJORS);
729 encoder.put_u128(value.resulting_order_remaining());
730 encoder.put_u128(value.resulting_reserved_claims());
731 }
732 r::ServerValue::ParticipantUnknown(value) => {
733 put_participant_reference(&value.request, encoder);
734 }
735 r::ServerValue::NoBinding(value) => put_binding_required(&value.request, encoder),
736 r::ServerValue::StaleAuthority(value) => put_stale_authority(value, encoder),
737 r::ServerValue::Retired(value) => match value {
738 r::Retired::Enrollment {
739 request,
740 participant_id,
741 retired_generation,
742 } => {
743 put_enrollment(request, encoder);
744 encoder.put_u64(*participant_id);
745 encoder.put_generation(*retired_generation);
746 }
747 r::Retired::Participant {
748 request,
749 retired_generation,
750 } => {
751 put_participant_reference(request, encoder);
752 encoder.put_generation(*retired_generation);
753 }
754 },
755 r::ServerValue::MarkerClosureCapacityExceeded(value) => {
756 put_closure_checked(&value.request, encoder);
757 let scope = match value.reason {
758 c::ClosureRefusalReason::Capacity(_) => t::ClosureScope::Capacity,
759 c::ClosureRefusalReason::RecoveryFence => t::ClosureScope::RecoveryFence,
760 c::ClosureRefusalReason::DeliveredMarkerAwaitingAck => {
761 t::ClosureScope::DeliveredMarkerAwaitingAck
762 }
763 c::ClosureRefusalReason::EpisodeChurnLimit => t::ClosureScope::EpisodeChurnLimit,
764 };
765 encoder.put_u16(scope.wire_value());
766 put_closure_snapshot(value.snapshot, encoder);
767 if let c::ClosureRefusalReason::Capacity(reason) = value.reason {
768 encoder.put_u16(t::ResourceDimensionTag::from(reason.dimension).wire_value());
769 encoder.put_u128(reason.required);
770 encoder.put_u128(reason.limit);
771 }
772 }
773 r::ServerValue::EnrollBound(value) => put_enroll_bound(value, encoder),
774 r::ServerValue::EnrollmentKnown(value) => {
775 encoder.put_u64(value.conversation_id);
776 encoder.put_fixed(value.token.as_bytes());
777 encoder.put_u64(value.participant_id);
778 encoder.put_generation(value.current_generation);
779 }
780 r::ServerValue::ReceiptExpired(value) => put_receipt_expired(value, encoder),
781 r::ServerValue::ReceiptCapacityExceeded(value) => {
782 put_receipt_capacity(value, encoder);
783 }
784 r::ServerValue::IdentityCapacityExceeded(value) => {
785 put_enrollment(&value.request, encoder);
786 encoder.put_u16(value.scope.wire_value());
787 encoder.put_u64(value.limit);
788 encoder.put_u64(value.occupied);
789 encoder.put_u64(r::IdentityCapacityExceeded::REQUESTED);
790 }
791 r::ServerValue::ObserverBackpressure(value) => put_observer_backpressure(value, encoder),
792 r::ServerValue::ConversationSequenceExhausted(value) => {
793 put_sequence_allocating(&value.request, encoder);
794 put_sequence_budget(value.sequence_budget, encoder);
795 }
796 r::ServerValue::AttachBound(value) => put_attach_bound(value, encoder),
797 r::ServerValue::StaleOrUnknownReceipt(value) => {
798 encoder.put_u64(value.conversation_id);
799 encoder.put_fixed(value.token.as_bytes());
800 encoder.put_u64(value.participant_id);
801 encoder.put_generation(value.presented_generation);
802 encoder.put_option_u64(value.presented_marker_delivery_seq);
803 encoder.put_generation(value.current_generation);
804 }
805 r::ServerValue::MarkerNotDelivered(value) => {
806 put_marker_proof(&value.request, encoder);
807 encoder.put_u16(value.reason.wire_value());
808 encoder.put_u64(value.expected_marker_delivery_seq);
809 }
810 r::ServerValue::MarkerMismatch(value) => {
811 put_marker_proof(&value.request, encoder);
812 encoder.put_u16(value.mismatch.reason().wire_value());
813 match value.mismatch {
814 r::MarkerMismatchBody::BelowCursor { current_cursor } => {
815 encoder.put_u64(current_cursor);
816 }
817 r::MarkerMismatchBody::NoMarkerExpected => {}
818 r::MarkerMismatchBody::ExpectedDifferentMarker {
819 expected_marker_delivery_seq,
820 } => encoder.put_u64(expected_marker_delivery_seq),
821 }
822 }
823 r::ServerValue::Bound(value) | r::ServerValue::UnboundReceipt(value) => {
824 put_receipt_replay(value, encoder);
825 }
826 r::ServerValue::DetachCommitted(value) => {
827 encoder.put_u64(value.conversation_id());
828 encoder.put_u64(value.participant_id());
829 encoder.put_generation(value.capability_generation());
830 encoder.put_fixed(value.detach_attempt_token().as_bytes());
831 encoder.put_binding_epoch(value.committed_binding_epoch());
832 encoder.put_u64(value.detached_delivery_seq());
833 }
834 r::ServerValue::DetachInProgress(value) => {
835 encoder.put_u64(value.conversation_id);
836 encoder.put_u64(value.participant_id);
837 encoder.put_fixed(value.presented_token.as_bytes());
838 encoder.put_generation(value.presented_generation);
839 encoder.put_binding_epoch(value.committed_binding_epoch);
840 }
841 r::ServerValue::AckCommitted(value) => {
842 put_participant_ack(value.request(), encoder);
843 encoder.put_u64(value.current_cursor());
844 }
845 r::ServerValue::AckNoOp(value) => match value {
846 r::AckNoOp::ParticipantAck(request) => {
847 put_participant_ack(request, encoder);
848 encoder.put_u64(value.current_cursor());
849 }
850 r::AckNoOp::MarkerAck(request) => {
851 put_marker_ack(request, encoder);
852 encoder.put_u64(value.current_cursor());
853 }
854 },
855 r::ServerValue::AckGap(value) => {
856 put_participant_ack(value.request(), encoder);
857 encoder.put_u64(value.current_cursor());
858 encoder.put_u16(value.reason().wire_value());
859 }
860 r::ServerValue::AckRegression(value) => {
861 put_participant_ack(value.request(), encoder);
862 encoder.put_u64(value.current_cursor());
863 encoder.put_u16(value.reason().wire_value());
864 }
865 r::ServerValue::LeaveCommitted(value) => {
866 encoder.put_u64(value.conversation_id());
867 encoder.put_fixed(value.leave_attempt_token().as_bytes());
868 encoder.put_u64(value.participant_id());
869 encoder.put_generation(value.presented_generation());
870 encoder.put_generation(value.retired_generation());
871 encoder.put_option_binding_epoch(value.ended_binding_epoch());
872 encoder.put_option_u64(value.prior_terminal_delivery_seq());
873 encoder.put_u64(value.left_delivery_seq());
874 }
875 r::ServerValue::MarkerAckCommitted(value) => {
876 put_marker_ack(value.request(), encoder);
877 encoder.put_u64(value.current_cursor());
878 }
879 r::ServerValue::SettlementAnswer(value) => {
880 encoder.put_u64(value.conversation_id);
881 encoder.put_u64(value.participant_id);
882 encoder.put_fixed(value.record_admission_attempt_token.as_bytes());
883 match value.outcome {
884 r::SettlementOutcome::Committed { delivery_seq } => {
885 encoder.put_u8(1);
886 encoder.put_u64(delivery_seq);
887 }
888 r::SettlementOutcome::Withdrawn => encoder.put_u8(2),
889 r::SettlementOutcome::Expired => encoder.put_u8(3),
890 r::SettlementOutcome::NotCommitted => encoder.put_u8(4),
891 r::SettlementOutcome::Unknown => encoder.put_u8(5),
892 }
893 }
894 r::ServerValue::RecordCommitted(value) => {
895 put_record_admission(value.request(), encoder);
896 encoder.put_u64(value.sender_participant_id());
897 encoder.put_u64(value.delivery_seq());
898 }
899 r::ServerValue::RecordTooLarge(value) => {
900 put_record_admission(&value.request, encoder);
901 encoder.put_u16(t::ResourceDimensionTag::from(value.dimension).wire_value());
902 encoder.put_resource_vector(value.encoded_record_charge);
903 encoder.put_resource_vector(value.max_ordinary_record_charge);
904 }
905 r::ServerValue::ObserverRecoveryAccepted(value) => {
906 let count: u64 = value
907 .statuses
908 .len()
909 .try_into()
910 .map_err(|_| CodecError::LengthOverflow)?;
911 encoder.put_u64(count);
912 for status in &value.statuses {
913 encoder.put_u64(status.conversation_id);
914 encoder.put_u64(status.refused_epoch);
915 encoder.put_u64(status.current_observer_progress);
916 encoder.put_bool(status.armed);
917 encoder.put_bool(status.progressed);
918 }
919 }
920 r::ServerValue::InvalidObserverEpoch(value) => {
921 encoder.put_u64(0);
922 encoder.put_u16(value.reason().wire_value());
923 match value {
924 r::InvalidObserverEpoch::ConversationUnknown {
925 conversation_id,
926 presented_epoch,
927 } => {
928 encoder.put_u64(*conversation_id);
929 encoder.put_u64(*presented_epoch);
930 encoder.put_option_u64(None);
931 }
932 r::InvalidObserverEpoch::EpochAhead {
933 conversation_id,
934 presented_epoch,
935 current_observer_progress,
936 } => {
937 encoder.put_u64(*conversation_id);
938 encoder.put_u64(*presented_epoch);
939 encoder.put_option_u64(Some(*current_observer_progress));
940 }
941 }
942 }
943 r::ServerValue::InvalidObserverEpochList(value) => {
944 encoder.put_u64(0);
945 encoder.put_u16(value.reason().wire_value());
946 match value {
947 r::InvalidObserverEpochList::TooManyEntries {
948 presented_entries,
949 max_entries,
950 } => {
951 encoder.put_u64(*presented_entries);
952 encoder.put_u64(*max_entries);
953 }
954 r::InvalidObserverEpochList::DuplicateConversation {
955 conversation_id,
956 first_index,
957 duplicate_index,
958 } => {
959 encoder.put_u64(*conversation_id);
960 encoder.put_u64(*first_index);
961 encoder.put_u64(*duplicate_index);
962 }
963 }
964 }
965 r::ServerValue::MarkerSettlementBackpressure(value) => match value {
966 r::MarkerSettlementBackpressure::CredentialAttach {
967 conversation_id,
968 refused_epoch,
969 }
970 | r::MarkerSettlementBackpressure::Detach {
971 conversation_id,
972 refused_epoch,
973 } => {
974 encoder.put_u64(*conversation_id);
975 encoder.put_u64(*refused_epoch);
976 }
977 },
978 r::ServerValue::EnrollmentSettlementBackpressure(value) => {
979 encoder.put_u64(value.conversation_id);
980 }
981 r::ServerValue::RecordAdmissionProtocolFault(value) => {
982 put_record_admission(&value.request, encoder);
983 encoder.put_u16(value.class.tag().wire_value());
984 }
985 r::ServerValue::WriteOutcomeUnknown(value) => put_write_outcome_unknown(value, encoder),
986 }
987 Ok(())
988}
989
990fn put_write_outcome_unknown(value: &r::WriteOutcomeUnknown, encoder: &mut Encoder) {
991 match value {
992 r::WriteOutcomeUnknown::Enrollment { request } => put_enrollment(request, encoder),
993 r::WriteOutcomeUnknown::CredentialAttach { request } => put_attach(request, encoder),
994 r::WriteOutcomeUnknown::Detach { request } => put_detach(request, encoder),
995 r::WriteOutcomeUnknown::Leave { request } => put_leave(request, encoder),
996 r::WriteOutcomeUnknown::RecordAdmission { request } => {
997 put_record_admission(request, encoder);
998 }
999 }
1000}
1001
1002fn put_stale_authority(value: &r::StaleAuthority, encoder: &mut Encoder) {
1003 match value {
1004 r::StaleAuthority::Live {
1005 request,
1006 current_generation,
1007 } => {
1008 match request {
1009 r::CommonStaleAuthorityEnvelope::CredentialAttach(value) => {
1010 put_attach(value, encoder);
1011 }
1012 r::CommonStaleAuthorityEnvelope::ParticipantAck(value) => {
1013 put_participant_ack(value, encoder);
1014 }
1015 r::CommonStaleAuthorityEnvelope::MarkerAck(value) => {
1016 put_marker_ack(value, encoder);
1017 }
1018 r::CommonStaleAuthorityEnvelope::RecordAdmission(value) => {
1019 put_record_admission(value, encoder);
1020 }
1021 }
1022 encoder.put_generation(*current_generation);
1023 }
1024 r::StaleAuthority::Detach(value) => {
1025 encoder.put_u16(value.authority_state_tag().wire_value());
1026 match value {
1027 r::DetachStaleAuthority::Live {
1028 conversation_id,
1029 participant_id,
1030 capability_generation,
1031 detach_attempt_token,
1032 current_generation,
1033 } => {
1034 encoder.put_u64(*conversation_id);
1035 encoder.put_u64(*participant_id);
1036 encoder.put_generation(*capability_generation);
1037 encoder.put_fixed(detach_attempt_token.as_bytes());
1038 encoder.put_generation(*current_generation);
1039 }
1040 r::DetachStaleAuthority::TerminalizedDetachCell(value) => {
1041 encoder.put_u64(value.conversation_id());
1042 encoder.put_u64(value.participant_id());
1043 encoder.put_generation(value.capability_generation());
1044 encoder.put_fixed(value.detach_attempt_token().as_bytes());
1045 encoder.put_generation(value.current_generation());
1046 encoder.put_binding_epoch(value.committed_binding_epoch());
1047 encoder.put_u16(value.binding_state().tag().wire_value());
1048 if let r::BindingStateView::Bound {
1049 current_binding_epoch,
1050 } = value.binding_state()
1051 {
1052 encoder.put_binding_epoch(current_binding_epoch);
1053 }
1054 }
1055 }
1056 }
1057 r::StaleAuthority::Leave(value) => {
1058 encoder.put_u16(value.authority_state_tag().wire_value());
1059 match value {
1060 r::LeaveStaleAuthority::Live {
1061 conversation_id,
1062 participant_id,
1063 presented_generation,
1064 leave_attempt_token,
1065 current_generation,
1066 } => {
1067 encoder.put_u64(*conversation_id);
1068 encoder.put_u64(*participant_id);
1069 encoder.put_generation(*presented_generation);
1070 encoder.put_fixed(leave_attempt_token.as_bytes());
1071 encoder.put_generation(*current_generation);
1072 }
1073 r::LeaveStaleAuthority::CommittedLeaveTombstone {
1074 conversation_id,
1075 participant_id,
1076 presented_generation,
1077 leave_attempt_token,
1078 retired_generation,
1079 } => {
1080 encoder.put_u64(*conversation_id);
1081 encoder.put_u64(*participant_id);
1082 encoder.put_generation(*presented_generation);
1083 encoder.put_fixed(leave_attempt_token.as_bytes());
1084 encoder.put_generation(*retired_generation);
1085 }
1086 }
1087 }
1088 }
1089}
1090
1091fn put_receipt_expired(value: &r::ReceiptExpired, encoder: &mut Encoder) {
1092 match value {
1093 r::ReceiptExpired::Enrollment {
1094 conversation_id,
1095 token,
1096 participant_id,
1097 result_generation,
1098 current_generation,
1099 reason,
1100 } => {
1101 encoder.put_u64(*conversation_id);
1102 encoder.put_fixed(token.as_bytes());
1103 encoder.put_u64(*participant_id);
1104 encoder.put_option_generation(None);
1105 encoder.put_generation(*result_generation);
1106 encoder.put_generation(*current_generation);
1107 encoder.put_u16(reason.wire_value());
1108 }
1109 r::ReceiptExpired::CredentialAttach {
1110 conversation_id,
1111 token,
1112 participant_id,
1113 presented_generation,
1114 presented_marker_delivery_seq,
1115 result_generation,
1116 current_generation,
1117 reason,
1118 } => {
1119 encoder.put_u64(*conversation_id);
1120 encoder.put_fixed(token.as_bytes());
1121 encoder.put_u64(*participant_id);
1122 encoder.put_option_generation(Some(*presented_generation));
1123 encoder.put_option_u64(*presented_marker_delivery_seq);
1124 encoder.put_generation(*result_generation);
1125 encoder.put_generation(*current_generation);
1126 encoder.put_u16(reason.wire_value());
1127 }
1128 }
1129}
1130
1131fn put_receipt_capacity(value: &r::ReceiptCapacityExceeded, encoder: &mut Encoder) {
1132 match value {
1133 r::ReceiptCapacityExceeded::Enrollment {
1134 request,
1135 scope,
1136 limit,
1137 occupied,
1138 } => {
1139 put_enrollment(request, encoder);
1140 encoder.put_u16(scope.wire_scope().wire_value());
1141 encoder.put_u64(*limit);
1142 encoder.put_u64(*occupied);
1143 encoder.put_u64(r::ReceiptCapacityExceeded::REQUESTED);
1144 }
1145 r::ReceiptCapacityExceeded::CredentialAttach {
1146 request,
1147 scope,
1148 limit,
1149 occupied,
1150 } => {
1151 put_attach(request, encoder);
1152 encoder.put_u16(scope.wire_value());
1153 encoder.put_u64(*limit);
1154 encoder.put_u64(*occupied);
1155 encoder.put_u64(r::ReceiptCapacityExceeded::REQUESTED);
1156 }
1157 }
1158}
1159
1160fn put_observer_backpressure(value: &r::ObserverBackpressure, encoder: &mut Encoder) {
1161 match value {
1162 r::ObserverBackpressure::Enrollment { request, state } => {
1163 put_enrollment(request, encoder);
1164 put_backpressure_state(*state, encoder);
1165 }
1166 r::ObserverBackpressure::CredentialAttach { request, state } => {
1167 put_attach(request, encoder);
1168 put_backpressure_state(*state, encoder);
1169 }
1170 r::ObserverBackpressure::Detach {
1171 request,
1172 committed_binding_epoch,
1173 state,
1174 } => {
1175 put_detach(request, encoder);
1176 encoder.put_binding_epoch(*committed_binding_epoch);
1177 put_backpressure_state(*state, encoder);
1178 }
1179 r::ObserverBackpressure::Leave {
1180 request,
1181 state,
1182 prior_terminal_cell_exists,
1183 } => {
1184 put_leave(request, encoder);
1185 put_backpressure_state(*state, encoder);
1186 encoder.put_bool(*prior_terminal_cell_exists);
1187 }
1188 r::ObserverBackpressure::RecordAdmission { request, state } => {
1189 put_record_admission(request, encoder);
1190 put_backpressure_state(*state, encoder);
1191 }
1192 }
1193}
1194
1195fn put_backpressure_state(value: r::ObserverBackpressureState, encoder: &mut Encoder) {
1196 encoder.put_u64(value.backpressure_epoch());
1197 encoder.put_u64(value.observer_progress());
1198}
1199
1200fn put_receipt_replay(value: &r::ReceiptReplay, encoder: &mut Encoder) {
1201 match value {
1202 r::ReceiptReplay::Enrollment(value) => {
1203 encoder.put_u64(value.conversation_id());
1204 encoder.put_fixed(value.token().as_bytes());
1205 encoder.put_u64(value.participant_id());
1206 encoder.put_option_generation(None);
1207 encoder.put_generation(value.capability_generation());
1208 encoder.put_fixed(value.attach_secret().as_bytes());
1209 encoder.put_binding_epoch(value.origin_binding_epoch());
1210 encoder.put_u64(value.persisted_cursor());
1211 encoder.put_option_u64(None);
1212 encoder.put_u128(value.receipt_expires_at());
1213 encoder.put_u128(value.provenance_expires_at());
1214 }
1215 r::ReceiptReplay::CredentialAttach(value) => {
1216 encoder.put_u64(value.conversation_id());
1217 encoder.put_fixed(value.token().as_bytes());
1218 encoder.put_u64(value.participant_id());
1219 encoder.put_option_generation(Some(value.request_generation()));
1220 encoder.put_generation(value.capability_generation());
1221 encoder.put_fixed(value.attach_secret().as_bytes());
1222 encoder.put_binding_epoch(value.origin_binding_epoch());
1223 encoder.put_u64(value.persisted_cursor());
1224 encoder.put_option_u64(value.accepted_marker_delivery_seq());
1225 encoder.put_u128(value.receipt_expires_at());
1226 encoder.put_u128(value.provenance_expires_at());
1227 }
1228 }
1229}
1230
1231const fn carries_origin(discriminant: t::ServerDiscriminant) -> bool {
1239 use t::ServerDiscriminant as D;
1240
1241 !matches!(
1242 discriminant,
1243 D::ParticipantTransportRejected
1244 | D::ObserverRecoveryAccepted
1245 | D::InvalidObserverEpoch
1246 | D::InvalidObserverEpochList
1247 | D::ObserverRecoveryConnectionCapacityExceeded
1248 )
1249}
1250
1251const fn origin_is_valid(
1252 discriminant: t::ServerDiscriminant,
1253 origin: t::ClientDiscriminant,
1254) -> bool {
1255 use t::ClientDiscriminant as O;
1256 use t::ServerDiscriminant as D;
1257
1258 match discriminant {
1259 D::AttemptTokenBodyConflict => matches!(
1260 origin,
1261 O::CredentialAttachRequest | O::LeaveRequest | O::RecordAdmission
1262 ),
1263 D::ConnectionConversationCapacityExceeded => {
1264 !matches!(origin, O::ObserverRecoveryHandshake)
1265 }
1266 D::ConnectionConversationBindingOccupied => {
1267 matches!(origin, O::EnrollmentRequest | O::CredentialAttachRequest)
1268 }
1269 D::ConversationOrderExhausted => matches!(
1270 origin,
1271 O::EnrollmentRequest | O::CredentialAttachRequest | O::RecordAdmission
1272 ),
1273 D::ParticipantUnknown => {
1274 !matches!(origin, O::EnrollmentRequest | O::ObserverRecoveryHandshake)
1275 }
1276 D::NoBinding => !matches!(
1277 origin,
1278 O::EnrollmentRequest | O::CredentialAttachRequest | O::ObserverRecoveryHandshake
1279 ),
1280 D::StaleAuthority => !matches!(origin, O::EnrollmentRequest | O::ObserverRecoveryHandshake),
1281 D::Retired => !matches!(origin, O::ObserverRecoveryHandshake),
1282 D::MarkerClosureCapacityExceeded => matches!(
1283 origin,
1284 O::EnrollmentRequest
1285 | O::CredentialAttachRequest
1286 | O::LeaveRequest
1287 | O::RecordAdmission
1288 ),
1289 D::EnrollBound | D::EnrollmentKnown | D::IdentityCapacityExceeded => {
1290 matches!(origin, O::EnrollmentRequest)
1291 }
1292 D::ReceiptExpired | D::ReceiptCapacityExceeded | D::Bound | D::UnboundReceipt => {
1293 matches!(origin, O::EnrollmentRequest | O::CredentialAttachRequest)
1294 }
1295 D::ObserverBackpressure | D::WriteOutcomeUnknown => matches!(
1296 origin,
1297 O::EnrollmentRequest
1298 | O::CredentialAttachRequest
1299 | O::DetachRequest
1300 | O::LeaveRequest
1301 | O::RecordAdmission
1302 ),
1303 D::ConversationSequenceExhausted => matches!(
1304 origin,
1305 O::EnrollmentRequest | O::CredentialAttachRequest | O::RecordAdmission
1306 ),
1307 D::AttachBound | D::StaleOrUnknownReceipt => {
1308 matches!(origin, O::CredentialAttachRequest)
1309 }
1310 D::MarkerNotDelivered | D::MarkerMismatch => {
1311 matches!(origin, O::CredentialAttachRequest | O::MarkerAck)
1312 }
1313 D::DetachCommitted | D::DetachInProgress => matches!(origin, O::DetachRequest),
1314 D::AckCommitted | D::AckGap | D::AckRegression => matches!(origin, O::ParticipantAck),
1315 D::AckNoOp => matches!(origin, O::ParticipantAck | O::MarkerAck),
1316 D::LeaveCommitted => matches!(origin, O::LeaveRequest),
1317 D::MarkerAckCommitted => matches!(origin, O::MarkerAck),
1318 D::SettlementAnswer => matches!(origin, O::SettlementQuery),
1319 D::RecordCommitted | D::RecordTooLarge | D::RecordAdmissionProtocolFault => {
1320 matches!(origin, O::RecordAdmission)
1321 }
1322 D::MarkerSettlementBackpressure => {
1323 matches!(origin, O::CredentialAttachRequest | O::DetachRequest)
1324 }
1325 D::EnrollmentSettlementBackpressure => matches!(origin, O::EnrollmentRequest),
1326 D::ParticipantTransportRejected
1327 | D::ObserverRecoveryAccepted
1328 | D::InvalidObserverEpoch
1329 | D::InvalidObserverEpochList
1330 | D::ObserverRecoveryConnectionCapacityExceeded => false,
1331 }
1332}
1333
1334fn take_enrollment(decoder: &mut Decoder<'_>) -> Result<e::EnrollmentEnvelope, CodecError> {
1338 Ok(e::EnrollmentEnvelope {
1339 conversation_id: decoder.take_u64()?,
1340 enrollment_token: EnrollmentToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1341 })
1342}
1343
1344fn take_attach(decoder: &mut Decoder<'_>) -> Result<e::AttachEnvelope, CodecError> {
1345 Ok(e::AttachEnvelope {
1346 conversation_id: decoder.take_u64()?,
1347 participant_id: decoder.take_u64()?,
1348 capability_generation: decoder.take_generation()?,
1349 attach_attempt_token: AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1350 accept_marker_delivery_seq: decoder.take_option_u64()?,
1351 })
1352}
1353
1354fn take_detach(decoder: &mut Decoder<'_>) -> Result<e::DetachEnvelope, CodecError> {
1355 Ok(e::DetachEnvelope {
1356 conversation_id: decoder.take_u64()?,
1357 participant_id: decoder.take_u64()?,
1358 capability_generation: decoder.take_generation()?,
1359 detach_attempt_token: DetachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1360 })
1361}
1362
1363fn take_participant_ack(
1364 decoder: &mut Decoder<'_>,
1365) -> Result<e::ParticipantAckEnvelope, CodecError> {
1366 Ok(e::ParticipantAckEnvelope {
1367 conversation_id: decoder.take_u64()?,
1368 participant_id: decoder.take_u64()?,
1369 capability_generation: decoder.take_generation()?,
1370 through_seq: decoder.take_u64()?,
1371 })
1372}
1373
1374fn take_leave(decoder: &mut Decoder<'_>) -> Result<e::LeaveEnvelope, CodecError> {
1375 Ok(e::LeaveEnvelope {
1376 conversation_id: decoder.take_u64()?,
1377 participant_id: decoder.take_u64()?,
1378 capability_generation: decoder.take_generation()?,
1379 leave_attempt_token: LeaveAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1380 })
1381}
1382
1383fn take_marker_ack(decoder: &mut Decoder<'_>) -> Result<e::MarkerAckEnvelope, CodecError> {
1384 Ok(e::MarkerAckEnvelope {
1385 conversation_id: decoder.take_u64()?,
1386 participant_id: decoder.take_u64()?,
1387 capability_generation: decoder.take_generation()?,
1388 marker_delivery_seq: decoder.take_u64()?,
1389 })
1390}
1391
1392fn take_record_admission(
1393 decoder: &mut Decoder<'_>,
1394) -> Result<e::RecordAdmissionEnvelope, CodecError> {
1395 Ok(e::RecordAdmissionEnvelope {
1396 conversation_id: decoder.take_u64()?,
1397 participant_id: decoder.take_u64()?,
1398 capability_generation: decoder.take_generation()?,
1399 record_admission_attempt_token: RecordAdmissionAttemptToken::new(
1400 decoder.take_fixed::<TOKEN_LEN>()?,
1401 ),
1402 })
1403}
1404
1405fn take_response_envelope(
1406 origin: t::ClientDiscriminant,
1407 decoder: &mut Decoder<'_>,
1408) -> Result<e::ResponseEnvelope, CodecError> {
1409 match origin {
1410 t::ClientDiscriminant::EnrollmentRequest => {
1411 take_enrollment(decoder).map(e::ResponseEnvelope::Enrollment)
1412 }
1413 t::ClientDiscriminant::CredentialAttachRequest => {
1414 take_attach(decoder).map(e::ResponseEnvelope::CredentialAttach)
1415 }
1416 t::ClientDiscriminant::DetachRequest => {
1417 take_detach(decoder).map(e::ResponseEnvelope::Detach)
1418 }
1419 t::ClientDiscriminant::ParticipantAck => {
1420 take_participant_ack(decoder).map(e::ResponseEnvelope::ParticipantAck)
1421 }
1422 t::ClientDiscriminant::LeaveRequest => take_leave(decoder).map(e::ResponseEnvelope::Leave),
1423 t::ClientDiscriminant::MarkerAck => {
1424 take_marker_ack(decoder).map(e::ResponseEnvelope::MarkerAck)
1425 }
1426 t::ClientDiscriminant::RecordAdmission => {
1427 take_record_admission(decoder).map(e::ResponseEnvelope::RecordAdmission)
1428 }
1429 t::ClientDiscriminant::ObserverRecoveryHandshake
1430 | t::ClientDiscriminant::SettlementQuery => Err(decode_error(t::DecodeClass::InvalidField)),
1431 }
1432}
1433
1434fn take_participant_reference(
1435 origin: t::ClientDiscriminant,
1436 decoder: &mut Decoder<'_>,
1437) -> Result<r::ParticipantReferenceEnvelope, CodecError> {
1438 match origin {
1439 t::ClientDiscriminant::CredentialAttachRequest => {
1440 take_attach(decoder).map(r::ParticipantReferenceEnvelope::CredentialAttach)
1441 }
1442 t::ClientDiscriminant::DetachRequest => {
1443 take_detach(decoder).map(r::ParticipantReferenceEnvelope::Detach)
1444 }
1445 t::ClientDiscriminant::ParticipantAck => {
1446 take_participant_ack(decoder).map(r::ParticipantReferenceEnvelope::ParticipantAck)
1447 }
1448 t::ClientDiscriminant::LeaveRequest => {
1449 take_leave(decoder).map(r::ParticipantReferenceEnvelope::Leave)
1450 }
1451 t::ClientDiscriminant::MarkerAck => {
1452 take_marker_ack(decoder).map(r::ParticipantReferenceEnvelope::MarkerAck)
1453 }
1454 t::ClientDiscriminant::RecordAdmission => {
1455 take_record_admission(decoder).map(r::ParticipantReferenceEnvelope::RecordAdmission)
1456 }
1457 t::ClientDiscriminant::EnrollmentRequest
1458 | t::ClientDiscriminant::ObserverRecoveryHandshake
1459 | t::ClientDiscriminant::SettlementQuery => Err(decode_error(t::DecodeClass::InvalidField)),
1460 }
1461}
1462
1463fn take_binding_required(
1464 origin: t::ClientDiscriminant,
1465 decoder: &mut Decoder<'_>,
1466) -> Result<r::BindingRequiredEnvelope, CodecError> {
1467 match origin {
1468 t::ClientDiscriminant::DetachRequest => {
1469 take_detach(decoder).map(r::BindingRequiredEnvelope::Detach)
1470 }
1471 t::ClientDiscriminant::ParticipantAck => {
1472 take_participant_ack(decoder).map(r::BindingRequiredEnvelope::ParticipantAck)
1473 }
1474 t::ClientDiscriminant::LeaveRequest => {
1475 take_leave(decoder).map(r::BindingRequiredEnvelope::Leave)
1476 }
1477 t::ClientDiscriminant::MarkerAck => {
1478 take_marker_ack(decoder).map(r::BindingRequiredEnvelope::MarkerAck)
1479 }
1480 t::ClientDiscriminant::RecordAdmission => {
1481 take_record_admission(decoder).map(r::BindingRequiredEnvelope::RecordAdmission)
1482 }
1483 t::ClientDiscriminant::EnrollmentRequest
1484 | t::ClientDiscriminant::CredentialAttachRequest
1485 | t::ClientDiscriminant::ObserverRecoveryHandshake
1486 | t::ClientDiscriminant::SettlementQuery => Err(decode_error(t::DecodeClass::InvalidField)),
1487 }
1488}
1489
1490fn take_order_allocating(
1491 origin: t::ClientDiscriminant,
1492 decoder: &mut Decoder<'_>,
1493) -> Result<r::OrderAllocatingEnvelope, CodecError> {
1494 match origin {
1495 t::ClientDiscriminant::EnrollmentRequest => {
1496 take_enrollment(decoder).map(r::OrderAllocatingEnvelope::Enrollment)
1497 }
1498 t::ClientDiscriminant::CredentialAttachRequest => {
1499 take_attach(decoder).map(r::OrderAllocatingEnvelope::CredentialAttach)
1500 }
1501 t::ClientDiscriminant::RecordAdmission => {
1502 take_record_admission(decoder).map(r::OrderAllocatingEnvelope::RecordAdmission)
1503 }
1504 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1505 }
1506}
1507
1508fn take_closure_checked(
1509 origin: t::ClientDiscriminant,
1510 decoder: &mut Decoder<'_>,
1511) -> Result<c::ClosureCheckedEnvelope, CodecError> {
1512 match origin {
1513 t::ClientDiscriminant::EnrollmentRequest => {
1514 take_enrollment(decoder).map(c::ClosureCheckedEnvelope::Enrollment)
1515 }
1516 t::ClientDiscriminant::CredentialAttachRequest => {
1517 take_attach(decoder).map(c::ClosureCheckedEnvelope::CredentialAttach)
1518 }
1519 t::ClientDiscriminant::LeaveRequest => {
1520 take_leave(decoder).map(c::ClosureCheckedEnvelope::Leave)
1521 }
1522 t::ClientDiscriminant::RecordAdmission => {
1523 take_record_admission(decoder).map(c::ClosureCheckedEnvelope::RecordAdmission)
1524 }
1525 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1526 }
1527}
1528
1529fn take_sequence_allocating(
1530 origin: t::ClientDiscriminant,
1531 decoder: &mut Decoder<'_>,
1532) -> Result<r::SequenceAllocatingEnvelope, CodecError> {
1533 match origin {
1534 t::ClientDiscriminant::EnrollmentRequest => {
1535 take_enrollment(decoder).map(r::SequenceAllocatingEnvelope::Enrollment)
1536 }
1537 t::ClientDiscriminant::CredentialAttachRequest => {
1538 take_attach(decoder).map(r::SequenceAllocatingEnvelope::CredentialAttach)
1539 }
1540 t::ClientDiscriminant::RecordAdmission => {
1541 take_record_admission(decoder).map(r::SequenceAllocatingEnvelope::RecordAdmission)
1542 }
1543 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1544 }
1545}
1546
1547fn take_marker_proof(
1548 origin: t::ClientDiscriminant,
1549 decoder: &mut Decoder<'_>,
1550) -> Result<r::MarkerProofRequest, CodecError> {
1551 match origin {
1552 t::ClientDiscriminant::CredentialAttachRequest => Ok(
1553 r::MarkerProofRequest::CredentialAttach(r::AttachMarkerProof {
1554 conversation_id: decoder.take_u64()?,
1555 token: AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1556 participant_id: decoder.take_u64()?,
1557 capability_generation: decoder.take_generation()?,
1558 requested_marker_delivery_seq: decoder.take_u64()?,
1559 }),
1560 ),
1561 t::ClientDiscriminant::MarkerAck => {
1562 Ok(r::MarkerProofRequest::MarkerAck(r::MarkerAckProof {
1563 conversation_id: decoder.take_u64()?,
1564 participant_id: decoder.take_u64()?,
1565 capability_generation: decoder.take_generation()?,
1566 requested_marker_delivery_seq: decoder.take_u64()?,
1567 }))
1568 }
1569 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1570 }
1571}
1572
1573fn take_repayment_edge(decoder: &mut Decoder<'_>) -> Result<c::RepaymentEdge, CodecError> {
1574 let tag = t::RepaymentEdgeTag::try_from(decoder.take_u16()?)
1575 .map_err(|_| decode_error(t::DecodeClass::InvalidField))?;
1576 match tag {
1577 t::RepaymentEdgeTag::None => Ok(c::RepaymentEdge::None),
1578 t::RepaymentEdgeTag::ObserverProjection => Ok(c::RepaymentEdge::ObserverProjection {
1579 through_seq: decoder.take_u64()?,
1580 }),
1581 t::RepaymentEdgeTag::PhysicalCompaction => Ok(c::RepaymentEdge::PhysicalCompaction {
1582 from_floor: decoder.take_u64()?,
1583 through_seq: decoder.take_u64()?,
1584 }),
1585 t::RepaymentEdgeTag::MarkerDelivery => Ok(c::RepaymentEdge::MarkerDelivery {
1586 participant_id: decoder.take_u64()?,
1587 binding_epoch: decoder.take_binding_epoch()?,
1588 marker_delivery_seq: decoder.take_u64()?,
1589 }),
1590 t::RepaymentEdgeTag::ParticipantCursorProgress => Ok(
1591 c::RepaymentEdge::ParticipantCursorProgress(c::ParticipantCursorProgressEdge {
1592 participant_id: decoder.take_u64()?,
1593 binding_epoch: decoder.take_binding_epoch()?,
1594 through_seq: decoder.take_u64()?,
1595 marker_delivery_seq: decoder.take_option_u64()?,
1596 }),
1597 ),
1598 t::RepaymentEdgeTag::DetachedCredentialRecovery => {
1599 Ok(c::RepaymentEdge::DetachedCredentialRecovery {
1600 participant_id: decoder.take_u64()?,
1601 marker_delivery_seq: decoder.take_u64()?,
1602 prior_binding_epoch: decoder.take_binding_epoch()?,
1603 })
1604 }
1605 t::RepaymentEdgeTag::DetachedMarkerRelease => Ok(c::RepaymentEdge::DetachedMarkerRelease {
1606 participant_id: decoder.take_u64()?,
1607 marker_delivery_seq: decoder.take_u64()?,
1608 last_dead_binding_epoch: decoder.take_binding_epoch()?,
1609 }),
1610 t::RepaymentEdgeTag::DetachedCursorRelease => Ok(c::RepaymentEdge::DetachedCursorRelease {
1611 participant_id: decoder.take_u64()?,
1612 last_dead_binding_epoch: decoder.take_binding_epoch()?,
1613 }),
1614 }
1615}
1616
1617fn take_closure_snapshot(decoder: &mut Decoder<'_>) -> Result<c::ClosureSnapshot, CodecError> {
1618 Ok(c::ClosureSnapshot {
1619 marker_capacity_credits: decoder.take_u64()?,
1620 marker_anchors: decoder.take_u64()?,
1621 entry_debt: decoder.take_u64()?,
1622 byte_debt: decoder.take_u64()?,
1623 repayment_edge: take_repayment_edge(decoder)?,
1624 edge_sequence_claims: decoder.take_u64()?,
1625 edge_order_position_claims: decoder.take_u64()?,
1626 edge_k_remaining: decoder.take_resource_vector()?,
1627 k_headroom: decoder.take_wide_resource_vector()?,
1628 episode_churn_used: decoder.take_u64()?,
1629 delta_cycles: decoder.take_u64()?,
1630 episode_churn_limit: decoder.take_u64()?,
1631 })
1632}
1633
1634fn take_sequence_budget(decoder: &mut Decoder<'_>) -> Result<super::SequenceBudget, CodecError> {
1635 Ok(super::SequenceBudget {
1636 high_watermark: decoder.take_u64()?,
1637 remaining: decoder.take_u64()?,
1638 e: decoder.take_u64()?,
1639 t: decoder.take_u64()?,
1640 m: decoder.take_u64()?,
1641 rs: decoder.take_u64()?,
1642 rt: decoder.take_u64()?,
1643 l_times_t: decoder.take_u128()?,
1644 l_times_rt: decoder.take_u128()?,
1645 l_other_times_e: decoder.take_u128()?,
1646 })
1647}
1648
1649fn required_origin(
1650 origin: Option<t::ClientDiscriminant>,
1651) -> Result<t::ClientDiscriminant, CodecError> {
1652 origin.ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
1653}
1654
1655#[allow(clippy::too_many_lines)]
1656fn decode_server_suffix(
1657 discriminant: t::ServerDiscriminant,
1658 origin: Option<t::ClientDiscriminant>,
1659 decoder: &mut Decoder<'_>,
1660) -> Result<r::ServerValue, CodecError> {
1661 use t::ServerDiscriminant as D;
1662
1663 match discriminant {
1664 D::ParticipantTransportRejected => {
1665 let reason = match take_tag::<t::TransportReasonTag>(decoder)? {
1666 t::TransportReasonTag::FrameTooLarge => {
1667 r::TransportRejectionReason::FrameTooLarge {
1668 complete_frame_bytes: decoder.take_u64()?,
1669 max_frame_bytes: decoder.take_u64()?,
1670 }
1671 }
1672 t::TransportReasonTag::DecodeFailed => {
1673 let decode_class = take_tag::<t::DecodeClass>(decoder)?;
1674 r::TransportRejectionReason::DecodeFailed { decode_class }
1675 }
1676 t::TransportReasonTag::UnsupportedVersion => {
1677 r::TransportRejectionReason::UnsupportedVersion {
1678 presented_version: decoder.take_protocol_version()?,
1679 supported_version: decoder.take_protocol_version()?,
1680 }
1681 }
1682 t::TransportReasonTag::AuthenticationFailed => {
1683 r::TransportRejectionReason::AuthenticationFailed
1684 }
1685 t::TransportReasonTag::ParticipantCapabilityRequired => {
1686 let capability = decoder.take_string()?;
1687 if capability != r::PARTICIPANT_CAPABILITY {
1688 decoder.invalidate();
1689 }
1690 r::TransportRejectionReason::ParticipantCapabilityRequired
1691 }
1692 t::TransportReasonTag::EnrollmentNotPermitted => {
1693 r::TransportRejectionReason::EnrollmentNotPermitted
1694 }
1695 t::TransportReasonTag::EnrollmentConversationOutOfScope => {
1696 r::TransportRejectionReason::EnrollmentConversationOutOfScope
1697 }
1698 t::TransportReasonTag::CredentialAttachConversationOutOfScope => {
1699 r::TransportRejectionReason::CredentialAttachConversationOutOfScope
1700 }
1701 t::TransportReasonTag::AccessRefused => {
1702 r::TransportRejectionReason::AccessRefused {
1703 refusal: decoder.take_string()?,
1704 }
1705 }
1706 };
1707 Ok(r::ServerValue::ParticipantTransportRejected(
1708 r::ParticipantTransportRejected { reason },
1709 ))
1710 }
1711 D::AttemptTokenBodyConflict => {
1712 let origin = required_origin(origin)?;
1713 let token = decoder.take_fixed::<TOKEN_LEN>()?;
1714 let operation = take_tag::<t::AttemptOperation>(decoder)?;
1715 match origin {
1716 t::ClientDiscriminant::CredentialAttachRequest => {
1717 if operation != t::AttemptOperation::CredentialAttachRequest {
1718 return Err(decode_error(t::DecodeClass::InvalidField));
1719 }
1720 Ok(r::ServerValue::AttemptTokenBodyConflict(
1721 r::AttemptTokenBodyConflict::CredentialAttach {
1722 token: AttachAttemptToken::new(token),
1723 conversation_id: decoder.take_u64()?,
1724 presented_participant_id: decoder.take_u64()?,
1725 presented_generation: decoder.take_generation()?,
1726 presented_marker_delivery_seq: decoder.take_option_u64()?,
1727 conflict: take_tag::<t::AttemptConflict>(decoder)?,
1728 },
1729 ))
1730 }
1731 t::ClientDiscriminant::LeaveRequest => {
1732 if operation != t::AttemptOperation::LeaveRequest {
1733 return Err(decode_error(t::DecodeClass::InvalidField));
1734 }
1735 let value = r::AttemptTokenBodyConflict::Leave {
1736 token: LeaveAttemptToken::new(token),
1737 conversation_id: decoder.take_u64()?,
1738 presented_participant_id: decoder.take_u64()?,
1739 presented_generation: decoder.take_generation()?,
1740 };
1741 if take_tag::<t::AttemptConflict>(decoder)? != t::AttemptConflict::Generation {
1742 decoder.invalidate();
1743 }
1744 Ok(r::ServerValue::AttemptTokenBodyConflict(value))
1745 }
1746 t::ClientDiscriminant::RecordAdmission => {
1747 if operation != t::AttemptOperation::RecordAdmission {
1748 return Err(decode_error(t::DecodeClass::InvalidField));
1749 }
1750 Ok(r::ServerValue::AttemptTokenBodyConflict(
1751 r::AttemptTokenBodyConflict::RecordAdmission {
1752 token: RecordAdmissionAttemptToken::new(token),
1753 conversation_id: decoder.take_u64()?,
1754 presented_participant_id: decoder.take_u64()?,
1755 presented_generation: decoder.take_generation()?,
1756 },
1757 ))
1758 }
1759 _ => Err(decode_error(t::DecodeClass::InvalidField)),
1760 }
1761 }
1762 D::ConnectionConversationCapacityExceeded => {
1763 let origin = required_origin(origin)?;
1764 Ok(r::ServerValue::ConnectionConversationCapacityExceeded(
1765 r::ConnectionConversationCapacityExceeded::SemanticRequest {
1766 request: take_response_envelope(origin, decoder)?,
1767 limit: decoder.take_u64()?,
1768 },
1769 ))
1770 }
1771 D::ConnectionConversationBindingOccupied => {
1772 let origin = required_origin(origin)?;
1773 let value = match origin {
1774 t::ClientDiscriminant::EnrollmentRequest => {
1775 let conversation_id = decoder.take_u64()?;
1776 let enrollment_token = EnrollmentToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
1777 if decoder.take_option_u64()?.is_some() {
1778 decoder.invalidate();
1779 }
1780 r::ConnectionConversationBindingOccupied::Enrollment {
1781 conversation_id,
1782 enrollment_token,
1783 }
1784 }
1785 t::ClientDiscriminant::CredentialAttachRequest => {
1786 let conversation_id = decoder.take_u64()?;
1787 let participant_id = decoder.take_u64()?;
1788 let capability_generation = decoder.take_generation()?;
1789 let attach_attempt_token =
1790 AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
1791 let accept_marker_delivery_seq = decoder.take_option_u64()?;
1792 if decoder.take_option_u64()? != Some(participant_id) {
1793 decoder.invalidate();
1794 }
1795 r::ConnectionConversationBindingOccupied::CredentialAttach {
1796 conversation_id,
1797 participant_id,
1798 capability_generation,
1799 attach_attempt_token,
1800 accept_marker_delivery_seq,
1801 }
1802 }
1803 _ => return Err(decode_error(t::DecodeClass::InvalidField)),
1804 };
1805 Ok(r::ServerValue::ConnectionConversationBindingOccupied(value))
1806 }
1807 D::ConversationOrderExhausted => {
1808 let origin = required_origin(origin)?;
1809 let request = take_order_allocating(origin, decoder)?;
1810 let _counter = take_tag::<t::Counter>(decoder)?;
1811 let high = decoder.take_u64()?;
1812 let next_value = decoder.take_option_u64()?;
1813 let order_remaining = decoder.take_u128()?;
1814 let reserved_claims = decoder.take_u128()?;
1815 if decoder.take_u64()? != r::ConversationOrderExhausted::REQUIRED_MAJORS {
1816 decoder.invalidate();
1817 }
1818 let resulting_order_remaining = decoder.take_u128()?;
1819 let resulting_reserved_claims = decoder.take_u128()?;
1820 let value = r::ConversationOrderExhausted::new(
1821 request,
1822 high,
1823 order_remaining,
1824 reserved_claims,
1825 resulting_order_remaining,
1826 resulting_reserved_claims,
1827 );
1828 if next_value != value.next_value() {
1829 decoder.invalidate();
1830 }
1831 Ok(r::ServerValue::ConversationOrderExhausted(
1832 alloc::boxed::Box::new(value),
1833 ))
1834 }
1835 D::ParticipantUnknown => {
1836 let origin = required_origin(origin)?;
1837 Ok(r::ServerValue::ParticipantUnknown(r::ParticipantUnknown {
1838 request: take_participant_reference(origin, decoder)?,
1839 }))
1840 }
1841 D::NoBinding => {
1842 let origin = required_origin(origin)?;
1843 Ok(r::ServerValue::NoBinding(r::NoBinding {
1844 request: take_binding_required(origin, decoder)?,
1845 }))
1846 }
1847 D::StaleAuthority => take_stale_authority(required_origin(origin)?, decoder)
1848 .map(r::ServerValue::StaleAuthority),
1849 D::Retired => {
1850 let origin = required_origin(origin)?;
1851 let value = if origin == t::ClientDiscriminant::EnrollmentRequest {
1852 r::Retired::Enrollment {
1853 request: take_enrollment(decoder)?,
1854 participant_id: decoder.take_u64()?,
1855 retired_generation: decoder.take_generation()?,
1856 }
1857 } else {
1858 r::Retired::Participant {
1859 request: take_participant_reference(origin, decoder)?,
1860 retired_generation: decoder.take_generation()?,
1861 }
1862 };
1863 Ok(r::ServerValue::Retired(value))
1864 }
1865 D::MarkerClosureCapacityExceeded => {
1866 let origin = required_origin(origin)?;
1867 let request = take_closure_checked(origin, decoder)?;
1868 let scope = take_tag::<t::ClosureScope>(decoder)?;
1869 let snapshot = take_closure_snapshot(decoder)?;
1870 let reason = match scope {
1871 t::ClosureScope::Capacity => {
1872 let dimension =
1873 ResourceDimension::from(take_tag::<t::ResourceDimensionTag>(decoder)?);
1874 c::ClosureRefusalReason::Capacity(c::ClosureCapacityReason {
1875 dimension,
1876 required: decoder.take_u128()?,
1877 limit: decoder.take_u128()?,
1878 })
1879 }
1880 t::ClosureScope::RecoveryFence => c::ClosureRefusalReason::RecoveryFence,
1881 t::ClosureScope::DeliveredMarkerAwaitingAck => {
1882 c::ClosureRefusalReason::DeliveredMarkerAwaitingAck
1883 }
1884 t::ClosureScope::EpisodeChurnLimit => c::ClosureRefusalReason::EpisodeChurnLimit,
1885 };
1886 Ok(r::ServerValue::MarkerClosureCapacityExceeded(
1887 alloc::boxed::Box::new(c::MarkerClosureCapacityExceeded {
1888 request,
1889 snapshot,
1890 reason,
1891 }),
1892 ))
1893 }
1894 D::EnrollBound => take_enroll_bound(decoder).map(r::ServerValue::EnrollBound),
1895 D::EnrollmentKnown => Ok(r::ServerValue::EnrollmentKnown(r::EnrollmentKnown {
1896 conversation_id: decoder.take_u64()?,
1897 token: EnrollmentToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1898 participant_id: decoder.take_u64()?,
1899 current_generation: decoder.take_generation()?,
1900 })),
1901 D::ReceiptExpired => take_receipt_expired(required_origin(origin)?, decoder)
1902 .map(r::ServerValue::ReceiptExpired),
1903 D::ReceiptCapacityExceeded => take_receipt_capacity(required_origin(origin)?, decoder)
1904 .map(r::ServerValue::ReceiptCapacityExceeded),
1905 D::IdentityCapacityExceeded => {
1906 let request = take_enrollment(decoder)?;
1907 let scope = take_tag::<t::IdentityCapacityScope>(decoder)?;
1908 let limit = decoder.take_u64()?;
1909 let occupied = decoder.take_u64()?;
1910 if decoder.take_u64()? != r::IdentityCapacityExceeded::REQUESTED {
1911 decoder.invalidate();
1912 }
1913 Ok(r::ServerValue::IdentityCapacityExceeded(
1914 r::IdentityCapacityExceeded {
1915 request,
1916 scope,
1917 limit,
1918 occupied,
1919 },
1920 ))
1921 }
1922 D::ObserverBackpressure => take_observer_backpressure(required_origin(origin)?, decoder)
1923 .map(r::ServerValue::ObserverBackpressure),
1924 D::ConversationSequenceExhausted => {
1925 let request = take_sequence_allocating(required_origin(origin)?, decoder)?;
1926 Ok(r::ServerValue::ConversationSequenceExhausted(
1927 alloc::boxed::Box::new(r::ConversationSequenceExhausted {
1928 request,
1929 sequence_budget: take_sequence_budget(decoder)?,
1930 }),
1931 ))
1932 }
1933 D::AttachBound => take_attach_bound(decoder).map(r::ServerValue::AttachBound),
1934 D::StaleOrUnknownReceipt => Ok(r::ServerValue::StaleOrUnknownReceipt(
1935 r::StaleOrUnknownReceipt {
1936 conversation_id: decoder.take_u64()?,
1937 token: AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
1938 participant_id: decoder.take_u64()?,
1939 presented_generation: decoder.take_generation()?,
1940 presented_marker_delivery_seq: decoder.take_option_u64()?,
1941 current_generation: decoder.take_generation()?,
1942 },
1943 )),
1944 D::MarkerNotDelivered => {
1945 let request = take_marker_proof(required_origin(origin)?, decoder)?;
1946 let reason = take_tag::<t::MarkerNotDeliveredReason>(decoder)?;
1947 Ok(r::ServerValue::MarkerNotDelivered(r::MarkerNotDelivered {
1948 request,
1949 reason,
1950 expected_marker_delivery_seq: decoder.take_u64()?,
1951 }))
1952 }
1953 D::MarkerMismatch => {
1954 let request = take_marker_proof(required_origin(origin)?, decoder)?;
1955 let reason = take_tag::<t::MarkerMismatchReason>(decoder)?;
1956 let mismatch = match reason {
1957 t::MarkerMismatchReason::BelowCursor => r::MarkerMismatchBody::BelowCursor {
1958 current_cursor: decoder.take_u64()?,
1959 },
1960 t::MarkerMismatchReason::NoMarkerExpected => {
1961 r::MarkerMismatchBody::NoMarkerExpected
1962 }
1963 t::MarkerMismatchReason::ExpectedDifferentMarker => {
1964 r::MarkerMismatchBody::ExpectedDifferentMarker {
1965 expected_marker_delivery_seq: decoder.take_u64()?,
1966 }
1967 }
1968 };
1969 Ok(r::ServerValue::MarkerMismatch(r::MarkerMismatch {
1970 request,
1971 mismatch,
1972 }))
1973 }
1974 D::Bound => {
1975 take_receipt_replay(required_origin(origin)?, decoder).map(r::ServerValue::Bound)
1976 }
1977 D::UnboundReceipt => take_receipt_replay(required_origin(origin)?, decoder)
1978 .map(r::ServerValue::UnboundReceipt),
1979 D::DetachCommitted => {
1980 let conversation_id = decoder.take_u64()?;
1981 let participant_id = decoder.take_u64()?;
1982 let capability_generation = decoder.take_generation()?;
1983 let detach_attempt_token = DetachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
1984 let committed_binding_epoch = decoder.take_binding_epoch()?;
1985 let detached_delivery_seq = decoder.take_u64()?;
1986 if capability_generation != committed_binding_epoch.capability_generation {
1987 decoder.invalidate();
1988 }
1989 Ok(r::ServerValue::DetachCommitted(r::DetachCommitted::new(
1990 conversation_id,
1991 participant_id,
1992 detach_attempt_token,
1993 committed_binding_epoch,
1994 detached_delivery_seq,
1995 )))
1996 }
1997 D::DetachInProgress => Ok(r::ServerValue::DetachInProgress(r::DetachInProgress {
1998 conversation_id: decoder.take_u64()?,
1999 participant_id: decoder.take_u64()?,
2000 presented_token: DetachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?),
2001 presented_generation: decoder.take_generation()?,
2002 committed_binding_epoch: decoder.take_binding_epoch()?,
2003 })),
2004 D::AckCommitted => {
2005 let request = take_participant_ack(decoder)?;
2006 if decoder.take_u64()? != request.through_seq {
2007 decoder.invalidate();
2008 }
2009 Ok(r::ServerValue::AckCommitted(r::AckCommitted::new(request)))
2010 }
2011 D::AckNoOp => {
2012 take_ack_no_op(required_origin(origin)?, decoder).map(r::ServerValue::AckNoOp)
2013 }
2014 D::AckGap => {
2015 let request = take_participant_ack(decoder)?;
2016 let current_cursor = decoder.take_u64()?;
2017 let _reason = take_tag::<t::AckGapReason>(decoder)?;
2018 r::AckGap::new(request, current_cursor)
2019 .map(r::ServerValue::AckGap)
2020 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
2021 }
2022 D::AckRegression => {
2023 let request = take_participant_ack(decoder)?;
2024 let current_cursor = decoder.take_u64()?;
2025 let _reason = take_tag::<t::AckRegressionReason>(decoder)?;
2026 r::AckRegression::new(request, current_cursor)
2027 .map(r::ServerValue::AckRegression)
2028 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
2029 }
2030 D::LeaveCommitted => {
2031 let conversation_id = decoder.take_u64()?;
2032 let leave_attempt_token = LeaveAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2033 let participant_id = decoder.take_u64()?;
2034 let presented_generation = decoder.take_generation()?;
2035 let retired_generation = decoder.take_generation()?;
2036 let ended_binding_epoch = decoder.take_option_binding_epoch()?;
2037 let prior_terminal_delivery_seq = decoder.take_option_u64()?;
2038 let left_delivery_seq = decoder.take_u64()?;
2039 if presented_generation != retired_generation {
2040 return Err(decode_error(t::DecodeClass::InvalidField));
2041 }
2042 r::LeaveCommitted::new(
2043 conversation_id,
2044 leave_attempt_token,
2045 participant_id,
2046 retired_generation,
2047 ended_binding_epoch,
2048 prior_terminal_delivery_seq,
2049 left_delivery_seq,
2050 )
2051 .map(r::ServerValue::LeaveCommitted)
2052 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
2053 }
2054 D::MarkerAckCommitted => {
2055 let request = take_marker_ack(decoder)?;
2056 if decoder.take_u64()? != request.marker_delivery_seq {
2057 decoder.invalidate();
2058 }
2059 Ok(r::ServerValue::MarkerAckCommitted(
2060 r::MarkerAckCommitted::new(request),
2061 ))
2062 }
2063 D::SettlementAnswer => {
2064 let conversation_id = decoder.take_u64()?;
2065 let participant_id = decoder.take_u64()?;
2066 let record_admission_attempt_token =
2067 RecordAdmissionAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2068 let outcome = match decoder.take_u8()? {
2069 1 => r::SettlementOutcome::Committed {
2070 delivery_seq: decoder.take_u64()?,
2071 },
2072 2 => r::SettlementOutcome::Withdrawn,
2073 3 => r::SettlementOutcome::Expired,
2074 4 => r::SettlementOutcome::NotCommitted,
2075 5 => r::SettlementOutcome::Unknown,
2076 _ => return Err(decode_error(t::DecodeClass::InvalidField)),
2077 };
2078 Ok(r::ServerValue::SettlementAnswer(r::SettlementAnswer {
2079 conversation_id,
2080 participant_id,
2081 record_admission_attempt_token,
2082 outcome,
2083 }))
2084 }
2085 D::RecordCommitted => {
2086 let request = take_record_admission(decoder)?;
2087 if decoder.take_u64()? != request.participant_id {
2088 decoder.invalidate();
2089 }
2090 let delivery_seq = decoder.take_u64()?;
2091 Ok(r::ServerValue::RecordCommitted(r::RecordCommitted::new(
2092 request,
2093 delivery_seq,
2094 )))
2095 }
2096 D::RecordTooLarge => Ok(r::ServerValue::RecordTooLarge(r::RecordTooLarge {
2097 request: take_record_admission(decoder)?,
2098 dimension: ResourceDimension::from(take_tag::<t::ResourceDimensionTag>(decoder)?),
2099 encoded_record_charge: decoder.take_resource_vector()?,
2100 max_ordinary_record_charge: decoder.take_resource_vector()?,
2101 })),
2102 D::ObserverRecoveryAccepted => {
2103 take_recovery_accepted(decoder).map(r::ServerValue::ObserverRecoveryAccepted)
2104 }
2105 D::InvalidObserverEpoch => {
2106 require_zero_recovery_count(decoder)?;
2107 take_invalid_observer_epoch(decoder).map(r::ServerValue::InvalidObserverEpoch)
2108 }
2109 D::InvalidObserverEpochList => {
2110 require_zero_recovery_count(decoder)?;
2111 take_invalid_observer_epoch_list(decoder).map(r::ServerValue::InvalidObserverEpochList)
2112 }
2113 D::ObserverRecoveryConnectionCapacityExceeded => {
2114 require_zero_recovery_count(decoder)?;
2115 Ok(r::ServerValue::ConnectionConversationCapacityExceeded(
2116 r::ConnectionConversationCapacityExceeded::ObserverRecovery {
2117 conversation_id: decoder.take_u64()?,
2118 limit: decoder.take_u64()?,
2119 },
2120 ))
2121 }
2122 D::MarkerSettlementBackpressure => {
2123 let origin = required_origin(origin)?;
2124 let conversation_id = decoder.take_u64()?;
2125 let refused_epoch = decoder.take_u64()?;
2126 let value = match origin {
2127 t::ClientDiscriminant::CredentialAttachRequest => {
2128 r::MarkerSettlementBackpressure::CredentialAttach {
2129 conversation_id,
2130 refused_epoch,
2131 }
2132 }
2133 t::ClientDiscriminant::DetachRequest => r::MarkerSettlementBackpressure::Detach {
2134 conversation_id,
2135 refused_epoch,
2136 },
2137 _ => return Err(decode_error(t::DecodeClass::InvalidField)),
2138 };
2139 Ok(r::ServerValue::MarkerSettlementBackpressure(value))
2140 }
2141 D::EnrollmentSettlementBackpressure => {
2142 required_origin(origin)?;
2143 Ok(r::ServerValue::EnrollmentSettlementBackpressure(
2144 r::EnrollmentSettlementBackpressure {
2145 conversation_id: decoder.take_u64()?,
2146 },
2147 ))
2148 }
2149 D::RecordAdmissionProtocolFault => Ok(r::ServerValue::RecordAdmissionProtocolFault(
2150 r::RecordAdmissionProtocolFault {
2151 request: take_record_admission(decoder)?,
2152 class: r::RecordAdmissionFaultClass::from(take_tag::<
2153 t::RecordAdmissionFaultClassTag,
2154 >(decoder)?),
2155 },
2156 )),
2157 D::WriteOutcomeUnknown => take_write_outcome_unknown(required_origin(origin)?, decoder)
2158 .map(r::ServerValue::WriteOutcomeUnknown),
2159 }
2160}
2161
2162fn take_write_outcome_unknown(
2163 origin: t::ClientDiscriminant,
2164 decoder: &mut Decoder<'_>,
2165) -> Result<r::WriteOutcomeUnknown, CodecError> {
2166 match origin {
2167 t::ClientDiscriminant::EnrollmentRequest => Ok(r::WriteOutcomeUnknown::Enrollment {
2168 request: take_enrollment(decoder)?,
2169 }),
2170 t::ClientDiscriminant::CredentialAttachRequest => {
2171 Ok(r::WriteOutcomeUnknown::CredentialAttach {
2172 request: take_attach(decoder)?,
2173 })
2174 }
2175 t::ClientDiscriminant::DetachRequest => Ok(r::WriteOutcomeUnknown::Detach {
2176 request: take_detach(decoder)?,
2177 }),
2178 t::ClientDiscriminant::LeaveRequest => Ok(r::WriteOutcomeUnknown::Leave {
2179 request: take_leave(decoder)?,
2180 }),
2181 t::ClientDiscriminant::RecordAdmission => Ok(r::WriteOutcomeUnknown::RecordAdmission {
2182 request: take_record_admission(decoder)?,
2183 }),
2184 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2185 }
2186}
2187
2188trait WireTag: TryFrom<u16> {}
2189
2190impl WireTag for t::TransportReasonTag {}
2191impl WireTag for t::DecodeClass {}
2192impl WireTag for t::AttemptOperation {}
2193impl WireTag for t::AttemptConflict {}
2194impl WireTag for t::Counter {}
2195impl WireTag for t::ClosureScope {}
2196impl WireTag for t::ResourceDimensionTag {}
2197impl WireTag for t::IdentityCapacityScope {}
2198impl WireTag for t::MarkerNotDeliveredReason {}
2199impl WireTag for t::MarkerMismatchReason {}
2200impl WireTag for t::AckGapReason {}
2201impl WireTag for t::AckRegressionReason {}
2202impl WireTag for t::InvalidObserverEpochReason {}
2203impl WireTag for t::InvalidObserverEpochListReason {}
2204impl WireTag for t::RecordAdmissionFaultClassTag {}
2205
2206fn take_tag<T>(decoder: &mut Decoder<'_>) -> Result<T, CodecError>
2207where
2208 T: WireTag,
2209{
2210 T::try_from(decoder.take_u16()?).map_err(|_| decode_error(t::DecodeClass::InvalidField))
2211}
2212
2213fn take_stale_authority(
2214 origin: t::ClientDiscriminant,
2215 decoder: &mut Decoder<'_>,
2216) -> Result<r::StaleAuthority, CodecError> {
2217 match origin {
2218 t::ClientDiscriminant::CredentialAttachRequest => Ok(r::StaleAuthority::Live {
2219 request: r::CommonStaleAuthorityEnvelope::CredentialAttach(take_attach(decoder)?),
2220 current_generation: decoder.take_generation()?,
2221 }),
2222 t::ClientDiscriminant::ParticipantAck => Ok(r::StaleAuthority::Live {
2223 request: r::CommonStaleAuthorityEnvelope::ParticipantAck(take_participant_ack(
2224 decoder,
2225 )?),
2226 current_generation: decoder.take_generation()?,
2227 }),
2228 t::ClientDiscriminant::MarkerAck => Ok(r::StaleAuthority::Live {
2229 request: r::CommonStaleAuthorityEnvelope::MarkerAck(take_marker_ack(decoder)?),
2230 current_generation: decoder.take_generation()?,
2231 }),
2232 t::ClientDiscriminant::RecordAdmission => Ok(r::StaleAuthority::Live {
2233 request: r::CommonStaleAuthorityEnvelope::RecordAdmission(take_record_admission(
2234 decoder,
2235 )?),
2236 current_generation: decoder.take_generation()?,
2237 }),
2238 t::ClientDiscriminant::DetachRequest => {
2239 let authority = t::DetachAuthorityStateTag::try_from(decoder.take_u16()?)
2240 .map_err(|_| decode_error(t::DecodeClass::InvalidField))?;
2241 let value = match authority {
2242 t::DetachAuthorityStateTag::Live => r::DetachStaleAuthority::Live {
2243 conversation_id: decoder.take_u64()?,
2244 participant_id: decoder.take_u64()?,
2245 capability_generation: decoder.take_generation()?,
2246 detach_attempt_token: DetachAttemptToken::new(
2247 decoder.take_fixed::<TOKEN_LEN>()?,
2248 ),
2249 current_generation: decoder.take_generation()?,
2250 },
2251 t::DetachAuthorityStateTag::TerminalizedDetachCell => {
2252 let conversation_id = decoder.take_u64()?;
2253 let participant_id = decoder.take_u64()?;
2254 let capability_generation = decoder.take_generation()?;
2255 let detach_attempt_token =
2256 DetachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2257 let current_generation = decoder.take_generation()?;
2258 let committed_binding_epoch = decoder.take_binding_epoch()?;
2259 let binding_state = match t::BindingStateTag::try_from(decoder.take_u16()?)
2260 .map_err(|_| decode_error(t::DecodeClass::InvalidField))?
2261 {
2262 t::BindingStateTag::Bound => r::BindingStateView::Bound {
2263 current_binding_epoch: decoder.take_binding_epoch()?,
2264 },
2265 t::BindingStateTag::Detached => r::BindingStateView::Detached,
2266 };
2267 r::DetachStaleAuthority::TerminalizedDetachCell(
2268 r::TerminalizedDetachCell::from_wire_decode(
2269 TERMINALIZED_WIRE_DECODE_AUTHORITY,
2270 conversation_id,
2271 participant_id,
2272 capability_generation,
2273 detach_attempt_token,
2274 current_generation,
2275 committed_binding_epoch,
2276 binding_state,
2277 ),
2278 )
2279 }
2280 };
2281 Ok(r::StaleAuthority::Detach(value))
2282 }
2283 t::ClientDiscriminant::LeaveRequest => {
2284 let authority = t::LeaveAuthorityStateTag::try_from(decoder.take_u16()?)
2285 .map_err(|_| decode_error(t::DecodeClass::InvalidField))?;
2286 let conversation_id = decoder.take_u64()?;
2287 let participant_id = decoder.take_u64()?;
2288 let presented_generation = decoder.take_generation()?;
2289 let leave_attempt_token = LeaveAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2290 let value = match authority {
2291 t::LeaveAuthorityStateTag::Live => r::LeaveStaleAuthority::Live {
2292 conversation_id,
2293 participant_id,
2294 presented_generation,
2295 leave_attempt_token,
2296 current_generation: decoder.take_generation()?,
2297 },
2298 t::LeaveAuthorityStateTag::CommittedLeaveTombstone => {
2299 r::LeaveStaleAuthority::CommittedLeaveTombstone {
2300 conversation_id,
2301 participant_id,
2302 presented_generation,
2303 leave_attempt_token,
2304 retired_generation: decoder.take_generation()?,
2305 }
2306 }
2307 };
2308 Ok(r::StaleAuthority::Leave(value))
2309 }
2310 t::ClientDiscriminant::EnrollmentRequest
2311 | t::ClientDiscriminant::ObserverRecoveryHandshake
2312 | t::ClientDiscriminant::SettlementQuery => Err(decode_error(t::DecodeClass::InvalidField)),
2313 }
2314}
2315
2316pub fn encode_enrollment_committed_body(value: &r::EnrollBound) -> Vec<u8> {
2317 let mut encoder = Encoder::default();
2318 encoder.put_u16(t::ClientDiscriminant::EnrollmentRequest.wire_value());
2319 put_enroll_bound(value, &mut encoder);
2320 encoder.bytes
2321}
2322
2323pub fn encode_attach_committed_body(value: &r::AttachBound) -> Vec<u8> {
2324 let mut encoder = Encoder::default();
2325 encoder.put_u16(t::ClientDiscriminant::CredentialAttachRequest.wire_value());
2326 put_attach_bound(value, &mut encoder);
2327 encoder.bytes
2328}
2329
2330fn put_enroll_bound(value: &r::EnrollBound, encoder: &mut Encoder) {
2331 encoder.put_u64(value.conversation_id());
2332 encoder.put_fixed(value.token().as_bytes());
2333 encoder.put_u64(value.participant_id());
2334 encoder.put_option_generation(value.request_generation());
2335 encoder.put_generation(value.capability_generation());
2336 encoder.put_fixed(value.attach_secret().as_bytes());
2337 encoder.put_binding_epoch(value.origin_binding_epoch());
2338 encoder.put_u64(value.persisted_cursor());
2339 encoder.put_option_u64(value.accepted_marker_delivery_seq());
2340 encoder.put_u128(value.receipt_expires_at());
2341 encoder.put_u128(value.provenance_expires_at());
2342}
2343
2344fn put_attach_bound(value: &r::AttachBound, encoder: &mut Encoder) {
2345 encoder.put_u64(value.conversation_id());
2346 encoder.put_fixed(value.token().as_bytes());
2347 encoder.put_u64(value.participant_id());
2348 encoder.put_option_generation(Some(value.request_generation()));
2349 encoder.put_generation(value.capability_generation());
2350 encoder.put_fixed(value.attach_secret().as_bytes());
2351 encoder.put_binding_epoch(value.origin_binding_epoch());
2352 encoder.put_u64(value.persisted_cursor());
2353 encoder.put_option_u64(value.accepted_marker_delivery_seq());
2354 encoder.put_u128(value.receipt_expires_at());
2355 encoder.put_u128(value.provenance_expires_at());
2356}
2357
2358fn take_enroll_bound(decoder: &mut Decoder<'_>) -> Result<r::EnrollBound, CodecError> {
2359 let conversation_id = decoder.take_u64()?;
2360 let token = EnrollmentToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2361 let participant_id = decoder.take_u64()?;
2362 if decoder.take_option_generation()?.is_some() {
2363 decoder.invalidate();
2364 }
2365 let capability_generation = decoder.take_generation()?;
2366 if capability_generation.get() != 1 {
2367 decoder.invalidate();
2368 }
2369 let attach_secret = AttachSecret::new(decoder.take_fixed::<SECRET_LEN>()?);
2370 let origin_binding_epoch = decoder.take_binding_epoch()?;
2371 if origin_binding_epoch.capability_generation.get() != 1 {
2372 decoder.invalidate();
2373 }
2374 if decoder.take_u64()? != 0 {
2375 decoder.invalidate();
2376 }
2377 if decoder.take_option_u64()?.is_some() {
2378 decoder.invalidate();
2379 }
2380 let receipt_expires_at = decoder.take_u128()?;
2381 let provenance_expires_at = decoder.take_u128()?;
2382
2383 let valid_epoch = if origin_binding_epoch.capability_generation.get() == 1 {
2384 origin_binding_epoch
2385 } else {
2386 BindingEpoch::new(
2387 origin_binding_epoch.connection_incarnation,
2388 generation_one()?,
2389 )
2390 };
2391 r::EnrollBound::new(
2392 conversation_id,
2393 token,
2394 participant_id,
2395 attach_secret,
2396 valid_epoch,
2397 receipt_expires_at,
2398 provenance_expires_at,
2399 )
2400 .ok_or(CodecError::InvalidValue)
2401}
2402
2403fn take_receipt_expired(
2404 origin: t::ClientDiscriminant,
2405 decoder: &mut Decoder<'_>,
2406) -> Result<r::ReceiptExpired, CodecError> {
2407 let conversation_id = decoder.take_u64()?;
2408 let token = decoder.take_fixed::<TOKEN_LEN>()?;
2409 let participant_id = decoder.take_u64()?;
2410 match origin {
2411 t::ClientDiscriminant::EnrollmentRequest => {
2412 if decoder.take_option_generation()?.is_some() {
2413 decoder.invalidate();
2414 }
2415 Ok(r::ReceiptExpired::Enrollment {
2416 conversation_id,
2417 token: EnrollmentToken::new(token),
2418 participant_id,
2419 result_generation: decoder.take_generation()?,
2420 current_generation: decoder.take_generation()?,
2421 reason: take_tag::<t::ReceiptExpiryReason>(decoder)?,
2422 })
2423 }
2424 t::ClientDiscriminant::CredentialAttachRequest => {
2425 let presented_generation = required_generation_option(decoder)?;
2426 Ok(r::ReceiptExpired::CredentialAttach {
2427 conversation_id,
2428 token: AttachAttemptToken::new(token),
2429 participant_id,
2430 presented_generation,
2431 presented_marker_delivery_seq: decoder.take_option_u64()?,
2432 result_generation: decoder.take_generation()?,
2433 current_generation: decoder.take_generation()?,
2434 reason: take_tag::<t::ReceiptExpiryReason>(decoder)?,
2435 })
2436 }
2437 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2438 }
2439}
2440
2441impl WireTag for t::ReceiptExpiryReason {}
2442impl WireTag for t::ReceiptCapacityScope {}
2443
2444fn take_receipt_capacity(
2445 origin: t::ClientDiscriminant,
2446 decoder: &mut Decoder<'_>,
2447) -> Result<r::ReceiptCapacityExceeded, CodecError> {
2448 match origin {
2449 t::ClientDiscriminant::EnrollmentRequest => {
2450 let request = take_enrollment(decoder)?;
2451 let scope = match take_tag::<t::ReceiptCapacityScope>(decoder)? {
2452 t::ReceiptCapacityScope::LiveReceiptServer => {
2453 r::EnrollmentReceiptCapacityScope::LiveReceiptServer
2454 }
2455 t::ReceiptCapacityScope::ProvenanceServer => {
2456 r::EnrollmentReceiptCapacityScope::ProvenanceServer
2457 }
2458 t::ReceiptCapacityScope::ProvenanceConversation => {
2459 r::EnrollmentReceiptCapacityScope::ProvenanceConversation
2460 }
2461 t::ReceiptCapacityScope::LiveReceiptParticipant
2462 | t::ReceiptCapacityScope::ProvenanceParticipant => {
2463 return Err(decode_error(t::DecodeClass::InvalidField));
2464 }
2465 };
2466 let limit = decoder.take_u64()?;
2467 let occupied = decoder.take_u64()?;
2468 require_one(decoder, r::ReceiptCapacityExceeded::REQUESTED)?;
2469 Ok(r::ReceiptCapacityExceeded::Enrollment {
2470 request,
2471 scope,
2472 limit,
2473 occupied,
2474 })
2475 }
2476 t::ClientDiscriminant::CredentialAttachRequest => {
2477 let request = take_attach(decoder)?;
2478 let scope = take_tag::<t::ReceiptCapacityScope>(decoder)?;
2479 let limit = decoder.take_u64()?;
2480 let occupied = decoder.take_u64()?;
2481 require_one(decoder, r::ReceiptCapacityExceeded::REQUESTED)?;
2482 Ok(r::ReceiptCapacityExceeded::CredentialAttach {
2483 request,
2484 scope,
2485 limit,
2486 occupied,
2487 })
2488 }
2489 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2490 }
2491}
2492
2493fn require_one(decoder: &mut Decoder<'_>, expected: u64) -> Result<(), CodecError> {
2494 if decoder.take_u64()? != expected {
2495 decoder.invalidate();
2496 }
2497 Ok(())
2498}
2499
2500fn take_observer_backpressure(
2501 origin: t::ClientDiscriminant,
2502 decoder: &mut Decoder<'_>,
2503) -> Result<r::ObserverBackpressure, CodecError> {
2504 match origin {
2505 t::ClientDiscriminant::EnrollmentRequest => Ok(r::ObserverBackpressure::Enrollment {
2506 request: take_enrollment(decoder)?,
2507 state: take_backpressure_state(decoder)?,
2508 }),
2509 t::ClientDiscriminant::CredentialAttachRequest => {
2510 Ok(r::ObserverBackpressure::CredentialAttach {
2511 request: take_attach(decoder)?,
2512 state: take_backpressure_state(decoder)?,
2513 })
2514 }
2515 t::ClientDiscriminant::DetachRequest => Ok(r::ObserverBackpressure::Detach {
2516 request: take_detach(decoder)?,
2517 committed_binding_epoch: decoder.take_binding_epoch()?,
2518 state: take_backpressure_state(decoder)?,
2519 }),
2520 t::ClientDiscriminant::LeaveRequest => Ok(r::ObserverBackpressure::Leave {
2521 request: take_leave(decoder)?,
2522 state: take_backpressure_state(decoder)?,
2523 prior_terminal_cell_exists: decoder.take_bool()?,
2524 }),
2525 t::ClientDiscriminant::RecordAdmission => Ok(r::ObserverBackpressure::RecordAdmission {
2526 request: take_record_admission(decoder)?,
2527 state: take_backpressure_state(decoder)?,
2528 }),
2529 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2530 }
2531}
2532
2533fn take_backpressure_state(
2534 decoder: &mut Decoder<'_>,
2535) -> Result<r::ObserverBackpressureState, CodecError> {
2536 let backpressure_epoch = decoder.take_u64()?;
2537 let observer_progress = decoder.take_u64()?;
2538 r::ObserverBackpressureState::replay(backpressure_epoch, observer_progress)
2539 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))
2540}
2541
2542fn required_generation_option(decoder: &mut Decoder<'_>) -> Result<Generation, CodecError> {
2543 decoder.take_option_generation()?.map_or_else(
2544 || {
2545 decoder.invalidate();
2546 generation_one()
2547 },
2548 Ok,
2549 )
2550}
2551
2552fn take_attach_bound(decoder: &mut Decoder<'_>) -> Result<r::AttachBound, CodecError> {
2553 let conversation_id = decoder.take_u64()?;
2554 let token = AttachAttemptToken::new(decoder.take_fixed::<TOKEN_LEN>()?);
2555 let participant_id = decoder.take_u64()?;
2556 let request_generation = required_generation_option(decoder)?;
2557 let capability_generation = decoder.take_generation()?;
2558 let attach_secret = AttachSecret::new(decoder.take_fixed::<SECRET_LEN>()?);
2559 let origin_binding_epoch = decoder.take_binding_epoch()?;
2560 let persisted_cursor = decoder.take_u64()?;
2561 let accepted_marker_delivery_seq = decoder.take_option_u64()?;
2562 let receipt_expires_at = decoder.take_u128()?;
2563 let provenance_expires_at = decoder.take_u128()?;
2564
2565 let value = match accepted_marker_delivery_seq {
2566 Some(marker) if persisted_cursor == marker => r::AttachBound::fenced(
2567 conversation_id,
2568 token,
2569 participant_id,
2570 request_generation,
2571 attach_secret,
2572 origin_binding_epoch,
2573 marker,
2574 receipt_expires_at,
2575 provenance_expires_at,
2576 ),
2577 Some(_) => None,
2578 None => r::AttachBound::ordinary(
2579 conversation_id,
2580 token,
2581 participant_id,
2582 request_generation,
2583 attach_secret,
2584 origin_binding_epoch,
2585 persisted_cursor,
2586 receipt_expires_at,
2587 provenance_expires_at,
2588 ),
2589 }
2590 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))?;
2591 if value.capability_generation() == capability_generation {
2592 Ok(value)
2593 } else {
2594 Err(decode_error(t::DecodeClass::InvalidField))
2595 }
2596}
2597
2598fn take_receipt_replay(
2599 origin: t::ClientDiscriminant,
2600 decoder: &mut Decoder<'_>,
2601) -> Result<r::ReceiptReplay, CodecError> {
2602 let conversation_id = decoder.take_u64()?;
2603 let token = decoder.take_fixed::<TOKEN_LEN>()?;
2604 let participant_id = decoder.take_u64()?;
2605 match origin {
2606 t::ClientDiscriminant::EnrollmentRequest => {
2607 let request_generation = decoder.take_option_generation()?;
2608 let capability_generation = decoder.take_generation()?;
2609 let attach_secret = AttachSecret::new(decoder.take_fixed::<SECRET_LEN>()?);
2610 let origin_binding_epoch = decoder.take_binding_epoch()?;
2611 let persisted_cursor = decoder.take_u64()?;
2612 let accepted_marker_delivery_seq = decoder.take_option_u64()?;
2613 let receipt_expires_at = decoder.take_u128()?;
2614 let provenance_expires_at = decoder.take_u128()?;
2615 let value = r::EnrollBound::new(
2616 conversation_id,
2617 EnrollmentToken::new(token),
2618 participant_id,
2619 attach_secret,
2620 origin_binding_epoch,
2621 receipt_expires_at,
2622 provenance_expires_at,
2623 )
2624 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))?;
2625 if request_generation.is_none()
2626 && capability_generation == Generation::ONE
2627 && persisted_cursor == 0
2628 && accepted_marker_delivery_seq.is_none()
2629 {
2630 Ok(r::ReceiptReplay::Enrollment(value))
2631 } else {
2632 Err(decode_error(t::DecodeClass::InvalidField))
2633 }
2634 }
2635 t::ClientDiscriminant::CredentialAttachRequest => {
2636 let request_generation = required_generation_option(decoder)?;
2637 let capability_generation = decoder.take_generation()?;
2638 let attach_secret = AttachSecret::new(decoder.take_fixed::<SECRET_LEN>()?);
2639 let origin_binding_epoch = decoder.take_binding_epoch()?;
2640 let persisted_cursor = decoder.take_u64()?;
2641 let accepted_marker_delivery_seq = decoder.take_option_u64()?;
2642 let receipt_expires_at = decoder.take_u128()?;
2643 let provenance_expires_at = decoder.take_u128()?;
2644 let attach_token = AttachAttemptToken::new(token);
2645 let value = match accepted_marker_delivery_seq {
2646 Some(marker) if persisted_cursor == marker => r::AttachBound::fenced(
2647 conversation_id,
2648 attach_token,
2649 participant_id,
2650 request_generation,
2651 attach_secret,
2652 origin_binding_epoch,
2653 marker,
2654 receipt_expires_at,
2655 provenance_expires_at,
2656 ),
2657 Some(_) => None,
2658 None => r::AttachBound::ordinary(
2659 conversation_id,
2660 attach_token,
2661 participant_id,
2662 request_generation,
2663 attach_secret,
2664 origin_binding_epoch,
2665 persisted_cursor,
2666 receipt_expires_at,
2667 provenance_expires_at,
2668 ),
2669 }
2670 .ok_or_else(|| decode_error(t::DecodeClass::InvalidField))?;
2671 if value.capability_generation() == capability_generation {
2672 Ok(r::ReceiptReplay::CredentialAttach(value))
2673 } else {
2674 Err(decode_error(t::DecodeClass::InvalidField))
2675 }
2676 }
2677 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2678 }
2679}
2680
2681fn take_ack_no_op(
2682 origin: t::ClientDiscriminant,
2683 decoder: &mut Decoder<'_>,
2684) -> Result<r::AckNoOp, CodecError> {
2685 match origin {
2686 t::ClientDiscriminant::ParticipantAck => {
2687 let request = take_participant_ack(decoder)?;
2688 if decoder.take_u64()? != request.through_seq {
2689 decoder.invalidate();
2690 }
2691 Ok(r::AckNoOp::participant_ack(request))
2692 }
2693 t::ClientDiscriminant::MarkerAck => {
2694 let request = take_marker_ack(decoder)?;
2695 if decoder.take_u64()? != request.marker_delivery_seq {
2696 decoder.invalidate();
2697 }
2698 Ok(r::AckNoOp::marker_ack(request))
2699 }
2700 _ => Err(decode_error(t::DecodeClass::InvalidField)),
2701 }
2702}
2703
2704fn take_recovery_accepted(
2705 decoder: &mut Decoder<'_>,
2706) -> Result<r::ObserverRecoveryAccepted, CodecError> {
2707 let count = decoder.take_u64()?;
2708 let required = u128::from(count) * RECOVERY_STATUS_LEN;
2709 let remaining = u64::try_from(decoder.remaining())
2710 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))?;
2711 if required > u128::from(remaining) {
2712 return Err(decode_error(t::DecodeClass::MissingRequiredField));
2713 }
2714 let count_usize: usize = count
2715 .try_into()
2716 .map_err(|_| decode_error(t::DecodeClass::MissingRequiredField))?;
2717
2718 let mut statuses = Vec::new();
2719 for _ in 0..count_usize {
2720 statuses.push(r::ObserverProgressStatus {
2721 conversation_id: decoder.take_u64()?,
2722 refused_epoch: decoder.take_u64()?,
2723 current_observer_progress: decoder.take_u64()?,
2724 armed: decoder.take_bool()?,
2725 progressed: decoder.take_bool()?,
2726 });
2727 }
2728 Ok(r::ObserverRecoveryAccepted { statuses })
2729}
2730
2731fn require_zero_recovery_count(decoder: &mut Decoder<'_>) -> Result<(), CodecError> {
2732 if decoder.take_u64()? == 0 {
2733 Ok(())
2734 } else {
2735 Err(decode_error(t::DecodeClass::InvalidField))
2736 }
2737}
2738
2739fn take_invalid_observer_epoch(
2740 decoder: &mut Decoder<'_>,
2741) -> Result<r::InvalidObserverEpoch, CodecError> {
2742 let reason = take_tag::<t::InvalidObserverEpochReason>(decoder)?;
2743 let conversation_id = decoder.take_u64()?;
2744 let presented_epoch = decoder.take_u64()?;
2745 let current = decoder.take_option_u64()?;
2746 match reason {
2747 t::InvalidObserverEpochReason::ConversationUnknown => {
2748 if current.is_some() {
2749 decoder.invalidate();
2750 }
2751 Ok(r::InvalidObserverEpoch::ConversationUnknown {
2752 conversation_id,
2753 presented_epoch,
2754 })
2755 }
2756 t::InvalidObserverEpochReason::EpochAhead => {
2757 let current_observer_progress = current.unwrap_or_else(|| {
2758 decoder.invalidate();
2759 0
2760 });
2761 Ok(r::InvalidObserverEpoch::EpochAhead {
2762 conversation_id,
2763 presented_epoch,
2764 current_observer_progress,
2765 })
2766 }
2767 }
2768}
2769
2770fn take_invalid_observer_epoch_list(
2771 decoder: &mut Decoder<'_>,
2772) -> Result<r::InvalidObserverEpochList, CodecError> {
2773 match take_tag::<t::InvalidObserverEpochListReason>(decoder)? {
2774 t::InvalidObserverEpochListReason::TooManyEntries => {
2775 Ok(r::InvalidObserverEpochList::TooManyEntries {
2776 presented_entries: decoder.take_u64()?,
2777 max_entries: decoder.take_u64()?,
2778 })
2779 }
2780 t::InvalidObserverEpochListReason::DuplicateConversation => {
2781 Ok(r::InvalidObserverEpochList::DuplicateConversation {
2782 conversation_id: decoder.take_u64()?,
2783 first_index: decoder.take_u64()?,
2784 duplicate_index: decoder.take_u64()?,
2785 })
2786 }
2787 }
2788}