1use alloc::vec::Vec;
2
3use super::{
4 AttachAttemptToken, AttachSecret, BindingEpoch, ClientDiscriminant, ClientRequest,
5 CloseCauseTag, ConnectionIncarnation, CredentialAttachRequest, DecodeClass, DetachAttemptToken,
6 DetachRequest, DetachedCause, DiedCause, EnrollmentRequest, EnrollmentToken, Generation,
7 LeaveAttemptToken, LeaveRequest, MarkerAck, ObserverRecoveryHandshake, ObserverRefusal,
8 ParticipantAck, ParticipantDelivery, ParticipantRecord, ParticipantTransportRejected,
9 ProtocolVersion, PushDiscriminant, RecordAdmission, RecordAdmissionAttemptToken, RecordKind,
10 ServerDiscriminant, ServerPush, ServerValue, TransportRejectionReason,
11};
12
13pub const PARTICIPANT_FRAME_TYPE: u8 = 0x1A;
15
16pub const GENERIC_HEADER_LEN: usize = 10;
18
19pub const PARTICIPANT_PREFIX_LEN: usize = 6;
21
22pub const PARTICIPANT_FRAME_OVERHEAD: usize = GENERIC_HEADER_LEN + PARTICIPANT_PREFIX_LEN;
24
25pub const FRAME_MAX: u64 = 4_294_967_305;
27
28pub const PRECAP_PARTICIPANT_FRAME_MAX: u64 = 1_048_576;
30
31pub const MIN_PARTICIPANT_FRAME_MAX: u64 = 16;
33
34#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub enum ReceiverDirection {
37 Server,
39 Client,
41}
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
48pub struct ValidatedFrameLimit(u64);
49
50impl ValidatedFrameLimit {
51 pub const fn new(max_frame_bytes: u64) -> Result<Self, CodecError> {
58 if max_frame_bytes < MIN_PARTICIPANT_FRAME_MAX || max_frame_bytes > FRAME_MAX {
59 return Err(CodecError::InvalidFrameLimit { max_frame_bytes });
60 }
61 Ok(Self(max_frame_bytes))
62 }
63
64 #[must_use]
66 pub const fn get(self) -> u64 {
67 self.0
68 }
69}
70
71#[derive(Clone, Copy, Debug, PartialEq, Eq)]
73pub enum AuthenticationState {
74 Unauthenticated,
76 Authenticated,
78}
79
80#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85pub struct NegotiatedParticipantCapability {
86 protocol_version: ProtocolVersion,
87 max_frame_bytes: ValidatedFrameLimit,
88}
89
90impl NegotiatedParticipantCapability {
91 #[must_use]
93 pub const fn v1(max_frame_bytes: ValidatedFrameLimit) -> Self {
94 Self {
95 protocol_version: ProtocolVersion::V1,
96 max_frame_bytes,
97 }
98 }
99
100 #[must_use]
102 pub const fn protocol_version(self) -> ProtocolVersion {
103 self.protocol_version
104 }
105
106 #[must_use]
108 pub const fn max_frame_bytes(self) -> ValidatedFrameLimit {
109 self.max_frame_bytes
110 }
111}
112
113#[derive(Clone, Copy, Debug, PartialEq, Eq)]
115pub enum ParticipantCapabilityState {
116 Missing,
118 Negotiated(NegotiatedParticipantCapability),
120}
121
122#[derive(Clone, Copy, Debug, PartialEq, Eq)]
124pub struct InboundGateContext {
125 pub receiver: ReceiverDirection,
127 pub authentication: AuthenticationState,
129 pub participant_capability: ParticipantCapabilityState,
131}
132
133#[derive(Clone, Debug, PartialEq, Eq)]
135pub enum ParticipantFrame {
136 ClientRequest(ClientRequest),
138 ServerValue(ServerValue),
140 ServerPush(ServerPush),
142}
143
144#[derive(Clone, Debug, PartialEq, Eq)]
150pub enum InboundGateError {
151 NotParticipantFrame {
153 frame_type: u8,
155 },
156 ParticipantRejected(ParticipantTransportRejected),
158}
159
160#[derive(Clone, Copy, Debug, PartialEq, Eq)]
162pub enum CodecError {
163 NotParticipantFrame {
165 frame_type: u8,
167 },
168 Decode {
170 class: DecodeClass,
172 },
173 UnsupportedVersion {
175 presented: ProtocolVersion,
177 supported: ProtocolVersion,
179 },
180 OutputTooSmall {
182 required: usize,
184 available: usize,
186 },
187 LengthOverflow,
189 InvalidValue,
191 InvalidFrameLimit {
193 max_frame_bytes: u64,
195 },
196}
197
198#[must_use]
200pub fn complete_frame_bytes(payload_length: u32) -> u64 {
201 10 + u64::from(payload_length)
202}
203
204pub fn gate_inbound(
224 input: &[u8],
225 context: InboundGateContext,
226) -> Result<ParticipantFrame, InboundGateError> {
227 if let Some(frame_type) = input.first().copied() {
228 if frame_type != PARTICIPANT_FRAME_TYPE {
229 return Err(InboundGateError::NotParticipantFrame { frame_type });
230 }
231 }
232
233 let max_frame_bytes = match context.participant_capability {
234 ParticipantCapabilityState::Missing => PRECAP_PARTICIPANT_FRAME_MAX,
235 ParticipantCapabilityState::Negotiated(capability) => capability.max_frame_bytes().get(),
236 };
237
238 if let Some(complete_frame_bytes) = declared_complete_frame_bytes(input) {
239 if complete_frame_bytes > max_frame_bytes {
240 return Err(gate_rejection(TransportRejectionReason::FrameTooLarge {
241 complete_frame_bytes,
242 max_frame_bytes,
243 }));
244 }
245 }
246
247 let frame = decode(input, context.receiver).map_err(codec_gate_error)?;
248 if matches!(
249 (&frame, context.receiver),
250 (
251 ParticipantFrame::ServerValue(ServerValue::ParticipantTransportRejected(_)),
252 ReceiverDirection::Client
253 )
254 ) {
255 return Ok(frame);
256 }
257
258 if context.authentication == AuthenticationState::Unauthenticated {
259 return Err(gate_rejection(
260 TransportRejectionReason::AuthenticationFailed,
261 ));
262 }
263 if context.participant_capability == ParticipantCapabilityState::Missing {
264 return Err(gate_rejection(
265 TransportRejectionReason::ParticipantCapabilityRequired,
266 ));
267 }
268
269 Ok(frame)
270}
271
272pub fn encoded_len(frame: &ParticipantFrame) -> Result<usize, CodecError> {
279 let mut size = SizeSink::default();
280 encode_body(frame, &mut size)?;
281 let payload = PARTICIPANT_PREFIX_LEN
282 .checked_add(size.len)
283 .ok_or(CodecError::LengthOverflow)?;
284 let _: u32 = payload.try_into().map_err(|_| CodecError::LengthOverflow)?;
285 GENERIC_HEADER_LEN
286 .checked_add(payload)
287 .ok_or(CodecError::LengthOverflow)
288}
289
290pub fn encode(frame: &ParticipantFrame, output: &mut [u8]) -> Result<usize, CodecError> {
301 let required = encoded_len(frame)?;
302 if output.len() < required {
303 return Err(CodecError::OutputTooSmall {
304 required,
305 available: output.len(),
306 });
307 }
308
309 let payload_len = required
310 .checked_sub(GENERIC_HEADER_LEN)
311 .ok_or(CodecError::LengthOverflow)?;
312 let payload_len: u32 = payload_len
313 .try_into()
314 .map_err(|_| CodecError::LengthOverflow)?;
315 let discriminant = frame_discriminant(frame);
316
317 let mut writer = Writer::new(output);
318 writer.put_u8(PARTICIPANT_FRAME_TYPE)?;
319 writer.put_u8(0)?;
320 writer.put_u32(0)?;
321 writer.put_u32(payload_len)?;
322 writer.put_u16(ProtocolVersion::V1.major)?;
323 writer.put_u16(ProtocolVersion::V1.minor)?;
324 writer.put_u16(discriminant)?;
325 encode_body(frame, &mut writer)?;
326 Ok(required)
327}
328
329pub fn decode(input: &[u8], receiver: ReceiverDirection) -> Result<ParticipantFrame, CodecError> {
341 if let Some(frame_type) = input.first().copied() {
342 if frame_type != PARTICIPANT_FRAME_TYPE {
343 return Err(CodecError::NotParticipantFrame { frame_type });
344 }
345 }
346 if input.len() < GENERIC_HEADER_LEN {
347 return Err(decode_error(DecodeClass::Framing));
348 }
349
350 let mut header = Reader::new(input);
351 let _frame_type = header.take_u8()?;
352 let flags = header.take_u8()?;
353 let stream_id = header.take_u32()?;
354 let payload_len = header.take_u32()?;
355 if flags != 0 || stream_id != 0 || payload_len < 6 {
356 return Err(decode_error(DecodeClass::Framing));
357 }
358
359 let complete: usize = complete_frame_bytes(payload_len)
360 .try_into()
361 .map_err(|_| decode_error(DecodeClass::Framing))?;
362 if input.len() < complete {
363 return Err(decode_error(DecodeClass::MissingRequiredField));
364 }
365 if input.len() > complete {
366 return Err(decode_error(DecodeClass::CanonicalEncoding));
367 }
368
369 let payload = input
370 .get(GENERIC_HEADER_LEN..complete)
371 .ok_or_else(|| decode_error(DecodeClass::MissingRequiredField))?;
372 let mut prefix = Reader::new(payload);
373 let version = ProtocolVersion::new(prefix.take_u16()?, prefix.take_u16()?);
374 if version != ProtocolVersion::V1 {
375 return Err(CodecError::UnsupportedVersion {
376 presented: version,
377 supported: ProtocolVersion::V1,
378 });
379 }
380 let discriminant = prefix.take_u16()?;
381 let body = prefix.remaining_bytes();
382
383 match receiver {
384 ReceiverDirection::Server => {
385 let tag = ClientDiscriminant::try_from(discriminant)
386 .map_err(|_| decode_error(DecodeClass::UnknownDiscriminant))?;
387 decode_client_request(tag, body).map(ParticipantFrame::ClientRequest)
388 }
389 ReceiverDirection::Client => {
390 if let Ok(tag) = PushDiscriminant::try_from(discriminant) {
391 return decode_server_push(tag, body).map(ParticipantFrame::ServerPush);
392 }
393 if let Ok(tag) = ServerDiscriminant::try_from(discriminant) {
394 let (value, _) = super::server_codec::decode_server_value_body(tag, version, body)?;
395 return Ok(ParticipantFrame::ServerValue(value));
396 }
397 Err(decode_error(DecodeClass::UnknownDiscriminant))
398 }
399 }
400}
401
402fn declared_complete_frame_bytes(input: &[u8]) -> Option<u64> {
403 let payload_length = input.get(6..GENERIC_HEADER_LEN)?;
404 let payload_length = <[u8; 4]>::try_from(payload_length).ok()?;
405 Some(complete_frame_bytes(u32::from_be_bytes(payload_length)))
406}
407
408const fn transport_rejection(reason: TransportRejectionReason) -> ParticipantTransportRejected {
409 ParticipantTransportRejected { reason }
410}
411
412const fn gate_rejection(reason: TransportRejectionReason) -> InboundGateError {
413 InboundGateError::ParticipantRejected(transport_rejection(reason))
414}
415
416const fn codec_gate_error(error: CodecError) -> InboundGateError {
417 match error {
418 CodecError::NotParticipantFrame { frame_type } => {
419 InboundGateError::NotParticipantFrame { frame_type }
420 }
421 CodecError::Decode { class } => gate_rejection(TransportRejectionReason::DecodeFailed {
422 decode_class: class,
423 }),
424 CodecError::UnsupportedVersion {
425 presented,
426 supported,
427 } => gate_rejection(TransportRejectionReason::UnsupportedVersion {
428 presented_version: presented,
429 supported_version: supported,
430 }),
431 CodecError::OutputTooSmall { .. }
432 | CodecError::LengthOverflow
433 | CodecError::InvalidValue
434 | CodecError::InvalidFrameLimit { .. } => {
435 gate_rejection(TransportRejectionReason::DecodeFailed {
436 decode_class: DecodeClass::InvalidField,
437 })
438 }
439 }
440}
441
442const fn frame_discriminant(frame: &ParticipantFrame) -> u16 {
443 match frame {
444 ParticipantFrame::ClientRequest(value) => value.discriminant().wire_value(),
445 ParticipantFrame::ServerValue(value) => value.discriminant().wire_value(),
446 ParticipantFrame::ServerPush(value) => value.discriminant().wire_value(),
447 }
448}
449
450fn encode_body<S: Sink>(frame: &ParticipantFrame, sink: &mut S) -> Result<(), CodecError> {
451 match frame {
452 ParticipantFrame::ClientRequest(value) => encode_client_request(value, sink),
453 ParticipantFrame::ServerPush(value) => encode_server_push(value, sink),
454 ParticipantFrame::ServerValue(value) => {
455 let (_, body) =
456 super::server_codec::encode_server_value_body(value, ProtocolVersion::V1)?;
457 sink.put(&body)
458 }
459 }
460}
461
462fn encode_client_request<S: Sink>(value: &ClientRequest, sink: &mut S) -> Result<(), CodecError> {
463 match value {
464 ClientRequest::Enrollment(value) => {
465 sink.put_u64(value.conversation_id)?;
466 sink.put_fixed(value.enrollment_token.as_bytes())
467 }
468 ClientRequest::CredentialAttach(value) => {
469 sink.put_u64(value.conversation_id)?;
470 sink.put_u64(value.participant_id)?;
471 put_generation(sink, value.capability_generation)?;
472 sink.put_fixed(value.attach_secret.as_bytes())?;
473 sink.put_fixed(value.attach_attempt_token.as_bytes())?;
474 put_option_u64(sink, value.accept_marker_delivery_seq)
475 }
476 ClientRequest::Detach(value) => {
477 sink.put_u64(value.conversation_id)?;
478 sink.put_u64(value.participant_id)?;
479 put_generation(sink, value.capability_generation)?;
480 sink.put_fixed(value.detach_attempt_token.as_bytes())
481 }
482 ClientRequest::ParticipantAck(value) => {
483 sink.put_u64(value.conversation_id)?;
484 sink.put_u64(value.participant_id)?;
485 put_generation(sink, value.capability_generation)?;
486 sink.put_u64(value.through_seq)
487 }
488 ClientRequest::Leave(value) => {
489 sink.put_u64(value.conversation_id)?;
490 sink.put_u64(value.participant_id)?;
491 put_generation(sink, value.capability_generation)?;
492 sink.put_fixed(value.attach_secret.as_bytes())?;
493 sink.put_fixed(value.leave_attempt_token.as_bytes())
494 }
495 ClientRequest::MarkerAck(value) => {
496 sink.put_u64(value.conversation_id)?;
497 sink.put_u64(value.participant_id)?;
498 put_generation(sink, value.capability_generation)?;
499 sink.put_u64(value.marker_delivery_seq)
500 }
501 ClientRequest::RecordAdmission(value) => {
502 sink.put_u64(value.conversation_id)?;
503 sink.put_u64(value.participant_id)?;
504 put_generation(sink, value.capability_generation)?;
505 sink.put_fixed(value.record_admission_attempt_token.as_bytes())?;
506 sink.put_bytes(&value.payload)
507 }
508 ClientRequest::ObserverRecovery(value) => {
509 let count: u64 = value
510 .observer_refusals
511 .len()
512 .try_into()
513 .map_err(|_| CodecError::LengthOverflow)?;
514 sink.put_u64(count)?;
515 for refusal in &value.observer_refusals {
516 sink.put_u64(refusal.conversation_id)?;
517 sink.put_u64(refusal.refused_epoch)?;
518 }
519 Ok(())
520 }
521 }
522}
523
524fn decode_client_request(
525 tag: ClientDiscriminant,
526 body: &[u8],
527) -> Result<ClientRequest, CodecError> {
528 let mut reader = Reader::new(body);
529 let value = match tag {
530 ClientDiscriminant::EnrollmentRequest => ClientRequest::Enrollment(EnrollmentRequest {
531 conversation_id: reader.take_u64()?,
532 enrollment_token: EnrollmentToken::new(reader.take_fixed()?),
533 }),
534 ClientDiscriminant::CredentialAttachRequest => {
535 ClientRequest::CredentialAttach(CredentialAttachRequest {
536 conversation_id: reader.take_u64()?,
537 participant_id: reader.take_u64()?,
538 capability_generation: reader.take_generation()?,
539 attach_secret: AttachSecret::new(reader.take_fixed()?),
540 attach_attempt_token: AttachAttemptToken::new(reader.take_fixed()?),
541 accept_marker_delivery_seq: reader.take_option_u64()?,
542 })
543 }
544 ClientDiscriminant::DetachRequest => ClientRequest::Detach(DetachRequest {
545 conversation_id: reader.take_u64()?,
546 participant_id: reader.take_u64()?,
547 capability_generation: reader.take_generation()?,
548 detach_attempt_token: DetachAttemptToken::new(reader.take_fixed()?),
549 }),
550 ClientDiscriminant::ParticipantAck => ClientRequest::ParticipantAck(ParticipantAck {
551 conversation_id: reader.take_u64()?,
552 participant_id: reader.take_u64()?,
553 capability_generation: reader.take_generation()?,
554 through_seq: reader.take_u64()?,
555 }),
556 ClientDiscriminant::LeaveRequest => ClientRequest::Leave(LeaveRequest {
557 conversation_id: reader.take_u64()?,
558 participant_id: reader.take_u64()?,
559 capability_generation: reader.take_generation()?,
560 attach_secret: AttachSecret::new(reader.take_fixed()?),
561 leave_attempt_token: LeaveAttemptToken::new(reader.take_fixed()?),
562 }),
563 ClientDiscriminant::MarkerAck => ClientRequest::MarkerAck(MarkerAck {
564 conversation_id: reader.take_u64()?,
565 participant_id: reader.take_u64()?,
566 capability_generation: reader.take_generation()?,
567 marker_delivery_seq: reader.take_u64()?,
568 }),
569 ClientDiscriminant::RecordAdmission => ClientRequest::RecordAdmission(RecordAdmission {
570 conversation_id: reader.take_u64()?,
571 participant_id: reader.take_u64()?,
572 capability_generation: reader.take_generation()?,
573 record_admission_attempt_token: RecordAdmissionAttemptToken::new(reader.take_fixed()?),
574 payload: reader.take_bytes()?,
575 }),
576 ClientDiscriminant::ObserverRecoveryHandshake => {
577 let count = reader.take_u64()?;
578 reader.require_fixed_list(count, 16)?;
579 let mut observer_refusals = Vec::new();
580 for _ in 0..count {
581 observer_refusals.push(ObserverRefusal {
582 conversation_id: reader.take_u64()?,
583 refused_epoch: reader.take_u64()?,
584 });
585 }
586 ClientRequest::ObserverRecovery(ObserverRecoveryHandshake { observer_refusals })
587 }
588 };
589 reader.finish()?;
590 Ok(value)
591}
592
593fn encode_server_push<S: Sink>(value: &ServerPush, sink: &mut S) -> Result<(), CodecError> {
594 match value {
595 ServerPush::ObserverProgressed {
596 conversation_id,
597 refused_epoch,
598 observer_progress,
599 } => {
600 sink.put_u64(*conversation_id)?;
601 sink.put_u64(*refused_epoch)?;
602 sink.put_u64(*observer_progress)
603 }
604 ServerPush::ParticipantDelivery(value) => encode_participant_delivery(value, sink),
605 ServerPush::MarkerSettled {
606 conversation_id,
607 refused_epoch,
608 } => {
609 sink.put_u64(*conversation_id)?;
610 sink.put_u64(*refused_epoch)
611 }
612 }
613}
614
615fn encode_participant_delivery<S: Sink>(
616 value: &ParticipantDelivery,
617 sink: &mut S,
618) -> Result<(), CodecError> {
619 sink.put_u64(value.conversation_id)?;
620 sink.put_u64(value.delivery_seq)?;
621 sink.put_u16(value.record.record_kind().wire_value())?;
622 match &value.record {
623 ParticipantRecord::OrdinaryRecord {
624 sender_participant_id,
625 payload,
626 } => {
627 sink.put_u64(*sender_participant_id)?;
628 sink.put_bytes(payload)
629 }
630 ParticipantRecord::Attached {
631 affected_participant_id,
632 binding_epoch,
633 } => {
634 sink.put_u64(*affected_participant_id)?;
635 put_binding_epoch(sink, *binding_epoch)
636 }
637 ParticipantRecord::Detached {
638 affected_participant_id,
639 binding_epoch,
640 cause,
641 } => {
642 sink.put_u64(*affected_participant_id)?;
643 put_binding_epoch(sink, *binding_epoch)?;
644 sink.put_u16(cause.close_cause().tag().wire_value())
645 }
646 ParticipantRecord::Died {
647 affected_participant_id,
648 binding_epoch,
649 cause,
650 } => {
651 sink.put_u64(*affected_participant_id)?;
652 put_binding_epoch(sink, *binding_epoch)?;
653 sink.put_u16(cause.close_cause().tag().wire_value())?;
654 if let DiedCause::UncleanServerRestart {
655 prior_server_incarnation,
656 } = cause
657 {
658 sink.put_u64(*prior_server_incarnation)?;
659 }
660 Ok(())
661 }
662 ParticipantRecord::Left {
663 affected_participant_id,
664 ended_binding_epoch,
665 } => {
666 sink.put_u64(*affected_participant_id)?;
667 put_option_binding_epoch(sink, *ended_binding_epoch)
668 }
669 ParticipantRecord::HistoryCompacted {
670 affected_participant_id,
671 abandoned_after,
672 abandoned_through,
673 physical_floor_at_decision,
674 } => {
675 sink.put_u64(*affected_participant_id)?;
676 sink.put_u64(*abandoned_after)?;
677 sink.put_u64(*abandoned_through)?;
678 sink.put_u64(*physical_floor_at_decision)
679 }
680 }
681}
682
683fn decode_server_push(tag: PushDiscriminant, body: &[u8]) -> Result<ServerPush, CodecError> {
684 let mut reader = Reader::new(body);
685 let value = match tag {
686 PushDiscriminant::ObserverProgressed => ServerPush::ObserverProgressed {
687 conversation_id: reader.take_u64()?,
688 refused_epoch: reader.take_u64()?,
689 observer_progress: reader.take_u64()?,
690 },
691 PushDiscriminant::ParticipantDelivery => {
692 let conversation_id = reader.take_u64()?;
693 let delivery_seq = reader.take_u64()?;
694 let kind = RecordKind::try_from(reader.take_u16()?)
695 .map_err(|_| decode_error(DecodeClass::InvalidField))?;
696 let record = decode_participant_record(kind, &mut reader)?;
697 ServerPush::ParticipantDelivery(ParticipantDelivery {
698 conversation_id,
699 delivery_seq,
700 record,
701 })
702 }
703 PushDiscriminant::MarkerSettled => ServerPush::MarkerSettled {
704 conversation_id: reader.take_u64()?,
705 refused_epoch: reader.take_u64()?,
706 },
707 };
708 reader.finish()?;
709 Ok(value)
710}
711
712fn decode_participant_record(
713 kind: RecordKind,
714 reader: &mut Reader<'_>,
715) -> Result<ParticipantRecord, CodecError> {
716 match kind {
717 RecordKind::OrdinaryRecord => Ok(ParticipantRecord::OrdinaryRecord {
718 sender_participant_id: reader.take_u64()?,
719 payload: reader.take_bytes()?,
720 }),
721 RecordKind::Attached => Ok(ParticipantRecord::Attached {
722 affected_participant_id: reader.take_u64()?,
723 binding_epoch: reader.take_binding_epoch()?,
724 }),
725 RecordKind::Detached => {
726 let affected_participant_id = reader.take_u64()?;
727 let binding_epoch = reader.take_binding_epoch()?;
728 let tag = CloseCauseTag::try_from(reader.take_u16()?)
729 .map_err(|_| decode_error(DecodeClass::InvalidField))?;
730 let cause = match tag {
731 CloseCauseTag::CleanDeregister => DetachedCause::CleanDeregister,
732 CloseCauseTag::Superseded => DetachedCause::Superseded,
733 CloseCauseTag::ServerShutdown => DetachedCause::ServerShutdown,
734 _ => return Err(decode_error(DecodeClass::InvalidField)),
735 };
736 Ok(ParticipantRecord::Detached {
737 affected_participant_id,
738 binding_epoch,
739 cause,
740 })
741 }
742 RecordKind::Died => {
743 let affected_participant_id = reader.take_u64()?;
744 let binding_epoch = reader.take_binding_epoch()?;
745 let tag = CloseCauseTag::try_from(reader.take_u16()?)
746 .map_err(|_| decode_error(DecodeClass::InvalidField))?;
747 let cause = match tag {
748 CloseCauseTag::ConnectionLost => DiedCause::ConnectionLost,
749 CloseCauseTag::ProcessKilled => DiedCause::ProcessKilled,
750 CloseCauseTag::ProtocolError => DiedCause::ProtocolError,
751 CloseCauseTag::UncleanServerRestart => DiedCause::UncleanServerRestart {
752 prior_server_incarnation: reader.take_u64()?,
753 },
754 _ => return Err(decode_error(DecodeClass::InvalidField)),
755 };
756 Ok(ParticipantRecord::Died {
757 affected_participant_id,
758 binding_epoch,
759 cause,
760 })
761 }
762 RecordKind::Left => Ok(ParticipantRecord::Left {
763 affected_participant_id: reader.take_u64()?,
764 ended_binding_epoch: reader.take_option_binding_epoch()?,
765 }),
766 RecordKind::HistoryCompacted => Ok(ParticipantRecord::HistoryCompacted {
767 affected_participant_id: reader.take_u64()?,
768 abandoned_after: reader.take_u64()?,
769 abandoned_through: reader.take_u64()?,
770 physical_floor_at_decision: reader.take_u64()?,
771 }),
772 }
773}
774
775fn put_generation<S: Sink>(sink: &mut S, generation: Generation) -> Result<(), CodecError> {
776 sink.put_u64(generation.get())
777}
778
779fn put_connection_incarnation<S: Sink>(
780 sink: &mut S,
781 value: ConnectionIncarnation,
782) -> Result<(), CodecError> {
783 sink.put_u64(value.server_incarnation)?;
784 sink.put_u64(value.connection_ordinal)
785}
786
787fn put_binding_epoch<S: Sink>(sink: &mut S, value: BindingEpoch) -> Result<(), CodecError> {
788 put_connection_incarnation(sink, value.connection_incarnation)?;
789 put_generation(sink, value.capability_generation)
790}
791
792fn put_option_u64<S: Sink>(sink: &mut S, value: Option<u64>) -> Result<(), CodecError> {
793 match value {
794 None => sink.put_u8(0),
795 Some(value) => {
796 sink.put_u8(1)?;
797 sink.put_u64(value)
798 }
799 }
800}
801
802fn put_option_binding_epoch<S: Sink>(
803 sink: &mut S,
804 value: Option<BindingEpoch>,
805) -> Result<(), CodecError> {
806 match value {
807 None => sink.put_u8(0),
808 Some(value) => {
809 sink.put_u8(1)?;
810 put_binding_epoch(sink, value)
811 }
812 }
813}
814
815const fn decode_error(class: DecodeClass) -> CodecError {
816 CodecError::Decode { class }
817}
818
819trait Sink {
820 fn put(&mut self, bytes: &[u8]) -> Result<(), CodecError>;
821
822 fn put_u8(&mut self, value: u8) -> Result<(), CodecError> {
823 self.put(&[value])
824 }
825
826 fn put_u16(&mut self, value: u16) -> Result<(), CodecError> {
827 self.put(&value.to_be_bytes())
828 }
829
830 fn put_u32(&mut self, value: u32) -> Result<(), CodecError> {
831 self.put(&value.to_be_bytes())
832 }
833
834 fn put_u64(&mut self, value: u64) -> Result<(), CodecError> {
835 self.put(&value.to_be_bytes())
836 }
837
838 fn put_fixed<const N: usize>(&mut self, value: &[u8; N]) -> Result<(), CodecError> {
839 self.put(value)
840 }
841
842 fn put_bytes(&mut self, value: &[u8]) -> Result<(), CodecError> {
843 let length: u32 = value
844 .len()
845 .try_into()
846 .map_err(|_| CodecError::LengthOverflow)?;
847 self.put_u32(length)?;
848 self.put(value)
849 }
850}
851
852#[derive(Default)]
853struct SizeSink {
854 len: usize,
855}
856
857impl Sink for SizeSink {
858 fn put(&mut self, bytes: &[u8]) -> Result<(), CodecError> {
859 self.len = self
860 .len
861 .checked_add(bytes.len())
862 .ok_or(CodecError::LengthOverflow)?;
863 Ok(())
864 }
865}
866
867struct Writer<'a> {
868 output: &'a mut [u8],
869 position: usize,
870}
871
872impl<'a> Writer<'a> {
873 const fn new(output: &'a mut [u8]) -> Self {
874 Self {
875 output,
876 position: 0,
877 }
878 }
879}
880
881impl Sink for Writer<'_> {
882 fn put(&mut self, bytes: &[u8]) -> Result<(), CodecError> {
883 let end = self
884 .position
885 .checked_add(bytes.len())
886 .ok_or(CodecError::LengthOverflow)?;
887 let available = self.output.len();
888 let Some(destination) = self.output.get_mut(self.position..end) else {
889 return Err(CodecError::OutputTooSmall {
890 required: end,
891 available,
892 });
893 };
894 destination.copy_from_slice(bytes);
895 self.position = end;
896 Ok(())
897 }
898}
899
900struct Reader<'a> {
901 input: &'a [u8],
902 position: usize,
903 invalid_field: bool,
904}
905
906impl<'a> Reader<'a> {
907 const fn new(input: &'a [u8]) -> Self {
908 Self {
909 input,
910 position: 0,
911 invalid_field: false,
912 }
913 }
914
915 const fn remaining(&self) -> usize {
916 self.input.len().saturating_sub(self.position)
917 }
918
919 fn remaining_bytes(&self) -> &'a [u8] {
920 match self.input.get(self.position..) {
921 Some(bytes) => bytes,
922 None => &[],
923 }
924 }
925
926 fn take(&mut self, length: usize) -> Result<&'a [u8], CodecError> {
927 let end = self
928 .position
929 .checked_add(length)
930 .ok_or_else(|| decode_error(DecodeClass::MissingRequiredField))?;
931 let Some(bytes) = self.input.get(self.position..end) else {
932 return Err(decode_error(DecodeClass::MissingRequiredField));
933 };
934 self.position = end;
935 Ok(bytes)
936 }
937
938 fn take_fixed<const N: usize>(&mut self) -> Result<[u8; N], CodecError> {
939 let mut output = [0; N];
940 output.copy_from_slice(self.take(N)?);
941 Ok(output)
942 }
943
944 fn take_u8(&mut self) -> Result<u8, CodecError> {
945 Ok(u8::from_be_bytes(self.take_fixed()?))
946 }
947
948 fn take_u16(&mut self) -> Result<u16, CodecError> {
949 Ok(u16::from_be_bytes(self.take_fixed()?))
950 }
951
952 fn take_u32(&mut self) -> Result<u32, CodecError> {
953 Ok(u32::from_be_bytes(self.take_fixed()?))
954 }
955
956 fn take_u64(&mut self) -> Result<u64, CodecError> {
957 Ok(u64::from_be_bytes(self.take_fixed()?))
958 }
959
960 fn take_generation(&mut self) -> Result<Generation, CodecError> {
961 let raw = self.take_u64()?;
962 if let Some(value) = Generation::new(raw) {
963 return Ok(value);
964 }
965 self.invalid_field = true;
966 Generation::new(1).ok_or(decode_error(DecodeClass::InvalidField))
967 }
968
969 fn take_binding_epoch(&mut self) -> Result<BindingEpoch, CodecError> {
970 Ok(BindingEpoch::new(
971 ConnectionIncarnation::new(self.take_u64()?, self.take_u64()?),
972 self.take_generation()?,
973 ))
974 }
975
976 fn take_option_u64(&mut self) -> Result<Option<u64>, CodecError> {
977 match self.take_u8()? {
978 0 => Ok(None),
979 1 => self.take_u64().map(Some),
980 _ => Err(decode_error(DecodeClass::InvalidField)),
981 }
982 }
983
984 fn take_option_binding_epoch(&mut self) -> Result<Option<BindingEpoch>, CodecError> {
985 match self.take_u8()? {
986 0 => Ok(None),
987 1 => self.take_binding_epoch().map(Some),
988 _ => Err(decode_error(DecodeClass::InvalidField)),
989 }
990 }
991
992 fn take_bytes(&mut self) -> Result<Vec<u8>, CodecError> {
993 let length: usize = self
994 .take_u32()?
995 .try_into()
996 .map_err(|_| decode_error(DecodeClass::MissingRequiredField))?;
997 Ok(self.take(length)?.to_vec())
998 }
999
1000 fn require_fixed_list(&self, count: u64, width: usize) -> Result<(), CodecError> {
1001 let width =
1002 u128::try_from(width).map_err(|_| decode_error(DecodeClass::MissingRequiredField))?;
1003 let remaining = u128::try_from(self.remaining())
1004 .map_err(|_| decode_error(DecodeClass::MissingRequiredField))?;
1005 let required = u128::from(count)
1006 .checked_mul(width)
1007 .ok_or_else(|| decode_error(DecodeClass::MissingRequiredField))?;
1008 if required > remaining {
1009 return Err(decode_error(DecodeClass::MissingRequiredField));
1010 }
1011 Ok(())
1012 }
1013
1014 const fn finish(self) -> Result<(), CodecError> {
1015 if self.position != self.input.len() {
1016 return Err(decode_error(DecodeClass::CanonicalEncoding));
1017 }
1018 if self.invalid_field {
1019 return Err(decode_error(DecodeClass::InvalidField));
1020 }
1021 Ok(())
1022 }
1023}