1use alloc::{boxed::Box, string::String, vec::Vec};
2
3use crate::algebra::{ResourceDimension, ResourceVector};
4
5use super::{
6 AckGapReason, AckRegressionReason, AttachAttemptToken, AttachEnvelope, AttachSecret,
7 AttemptConflict, BindingEpoch, ClientDiscriminant, ClosureCheckedEnvelope, ConversationId,
8 Counter, DecodeClass, DeliverySeq, DetachAttemptToken, DetachEnvelope, EnrollmentEnvelope,
9 EnrollmentToken, Generation, IdentityCapacityScope, InvalidObserverEpochListReason,
10 InvalidObserverEpochReason, LeaveAttemptToken, LeaveEnvelope, MarkerAckEnvelope,
11 MarkerClosureCapacityExceeded, MarkerMismatchReason, MarkerNotDeliveredReason, ObserverEpoch,
12 ParticipantAckEnvelope, ParticipantId, ProtocolVersion, ReceiptCapacityScope,
13 ReceiptExpiryReason, RecordAdmissionAttemptToken, RecordAdmissionEnvelope, ResponseEnvelope,
14 SequenceBudget, ServerDiscriminant, SettlementEpoch,
15};
16
17pub use super::tags::{DetachAuthorityStateTag, LeaveAuthorityStateTag, ResourceDimensionTag};
18
19#[derive(Clone, Debug, PartialEq, Eq)]
21pub struct ParticipantTransportRejected {
22 pub reason: TransportRejectionReason,
24}
25
26#[derive(Clone, Debug, PartialEq, Eq)]
28pub enum TransportRejectionReason {
29 FrameTooLarge {
31 complete_frame_bytes: u64,
33 max_frame_bytes: u64,
35 },
36 DecodeFailed {
38 decode_class: DecodeClass,
40 },
41 UnsupportedVersion {
43 presented_version: ProtocolVersion,
45 supported_version: ProtocolVersion,
47 },
48 AuthenticationFailed,
50 ParticipantCapabilityRequired,
55}
56
57#[derive(Clone, Debug, PartialEq, Eq)]
62pub enum AttemptTokenBodyConflict {
63 CredentialAttach {
65 token: AttachAttemptToken,
67 conversation_id: ConversationId,
69 presented_participant_id: ParticipantId,
71 presented_generation: Generation,
73 presented_marker_delivery_seq: Option<DeliverySeq>,
75 conflict: AttemptConflict,
77 },
78 Leave {
80 token: LeaveAttemptToken,
82 conversation_id: ConversationId,
84 presented_participant_id: ParticipantId,
86 presented_generation: Generation,
88 },
89 RecordAdmission {
99 token: RecordAdmissionAttemptToken,
101 conversation_id: ConversationId,
103 presented_participant_id: ParticipantId,
105 presented_generation: Generation,
107 },
108}
109
110#[derive(Clone, Debug, PartialEq, Eq)]
117pub enum ConnectionConversationCapacityExceeded {
118 SemanticRequest {
120 request: ResponseEnvelope,
122 limit: u64,
124 },
125 ObserverRecovery {
127 conversation_id: ConversationId,
129 limit: u64,
131 },
132}
133
134#[derive(Clone, Debug, PartialEq, Eq)]
136pub enum ConnectionConversationBindingOccupied {
137 Enrollment {
139 conversation_id: ConversationId,
141 enrollment_token: EnrollmentToken,
143 },
144 CredentialAttach {
146 conversation_id: ConversationId,
148 participant_id: ParticipantId,
150 capability_generation: Generation,
152 attach_attempt_token: AttachAttemptToken,
154 accept_marker_delivery_seq: Option<DeliverySeq>,
156 },
157}
158
159#[derive(Clone, Debug, PartialEq, Eq)]
161pub enum OrderAllocatingEnvelope {
162 Enrollment(EnrollmentEnvelope),
164 CredentialAttach(AttachEnvelope),
166 RecordAdmission(RecordAdmissionEnvelope),
168}
169
170#[derive(Clone, Debug, PartialEq, Eq)]
172pub struct ConversationOrderExhausted {
173 request: OrderAllocatingEnvelope,
175 high: u64,
177 order_remaining: u128,
179 reserved_claims: u128,
181 resulting_order_remaining: u128,
183 resulting_reserved_claims: u128,
185}
186
187impl ConversationOrderExhausted {
188 pub const REQUIRED_MAJORS: u64 = 1;
190
191 #[must_use]
197 pub const fn new(
198 request: OrderAllocatingEnvelope,
199 high: u64,
200 order_remaining: u128,
201 reserved_claims: u128,
202 resulting_order_remaining: u128,
203 resulting_reserved_claims: u128,
204 ) -> Self {
205 Self {
206 request,
207 high,
208 order_remaining,
209 reserved_claims,
210 resulting_order_remaining,
211 resulting_reserved_claims,
212 }
213 }
214
215 #[must_use]
217 pub const fn request(&self) -> &OrderAllocatingEnvelope {
218 &self.request
219 }
220
221 #[must_use]
223 pub const fn counter(&self) -> Counter {
224 let _ = self;
225 Counter::TransactionOrder
226 }
227
228 #[must_use]
230 pub const fn high(&self) -> u64 {
231 self.high
232 }
233
234 #[must_use]
236 pub const fn next_value(&self) -> Option<u64> {
237 self.high.checked_add(1)
238 }
239
240 #[must_use]
242 pub const fn order_remaining(&self) -> u128 {
243 self.order_remaining
244 }
245
246 #[must_use]
248 pub const fn reserved_claims(&self) -> u128 {
249 self.reserved_claims
250 }
251
252 #[must_use]
254 pub const fn resulting_order_remaining(&self) -> u128 {
255 self.resulting_order_remaining
256 }
257
258 #[must_use]
260 pub const fn resulting_reserved_claims(&self) -> u128 {
261 self.resulting_reserved_claims
262 }
263}
264
265#[derive(Clone, Debug, PartialEq, Eq)]
267pub enum ParticipantReferenceEnvelope {
268 CredentialAttach(AttachEnvelope),
270 Detach(DetachEnvelope),
272 ParticipantAck(ParticipantAckEnvelope),
274 Leave(LeaveEnvelope),
276 MarkerAck(MarkerAckEnvelope),
278 RecordAdmission(RecordAdmissionEnvelope),
280}
281
282#[derive(Clone, Debug, PartialEq, Eq)]
284pub enum BindingRequiredEnvelope {
285 Detach(DetachEnvelope),
287 ParticipantAck(ParticipantAckEnvelope),
289 Leave(LeaveEnvelope),
291 MarkerAck(MarkerAckEnvelope),
293 RecordAdmission(RecordAdmissionEnvelope),
295}
296
297#[derive(Clone, Debug, PartialEq, Eq)]
299pub struct ParticipantUnknown {
300 pub request: ParticipantReferenceEnvelope,
302}
303
304#[derive(Clone, Debug, PartialEq, Eq)]
306pub struct NoBinding {
307 pub request: BindingRequiredEnvelope,
309}
310
311#[derive(Clone, Copy, Debug, PartialEq, Eq)]
313pub enum BindingStateView {
314 Bound {
316 current_binding_epoch: BindingEpoch,
318 },
319 Detached,
321}
322
323impl BindingStateView {
324 #[must_use]
326 pub const fn tag(self) -> super::BindingStateTag {
327 match self {
328 Self::Bound { .. } => super::BindingStateTag::Bound,
329 Self::Detached => super::BindingStateTag::Detached,
330 }
331 }
332}
333
334#[derive(Clone, Debug, PartialEq, Eq)]
339pub struct TerminalizedDetachCell {
340 conversation_id: ConversationId,
341 participant_id: ParticipantId,
342 capability_generation: Generation,
343 detach_attempt_token: DetachAttemptToken,
344 current_generation: Generation,
345 committed_binding_epoch: BindingEpoch,
346 binding_state: BindingStateView,
347}
348
349impl TerminalizedDetachCell {
350 pub(crate) const fn from_terminalized_state<V>(
358 state: &crate::lifecycle::TerminalizedDetach<V>,
359 conversation_id: ConversationId,
360 current_generation: Generation,
361 binding_state: BindingStateView,
362 ) -> Self {
363 Self {
364 conversation_id,
365 participant_id: state.participant_id(),
366 capability_generation: state.request_generation(),
367 detach_attempt_token: state.token(),
368 current_generation,
369 committed_binding_epoch: state.committed_binding_epoch(),
370 binding_state,
371 }
372 }
373
374 #[allow(clippy::too_many_arguments)]
381 pub(super) const fn from_wire_decode(
382 _authority: super::server_codec::TerminalizedWireDecodeAuthority,
383 conversation_id: ConversationId,
384 participant_id: ParticipantId,
385 capability_generation: Generation,
386 detach_attempt_token: DetachAttemptToken,
387 current_generation: Generation,
388 committed_binding_epoch: BindingEpoch,
389 binding_state: BindingStateView,
390 ) -> Self {
391 Self {
392 conversation_id,
393 participant_id,
394 capability_generation,
395 detach_attempt_token,
396 current_generation,
397 committed_binding_epoch,
398 binding_state,
399 }
400 }
401
402 #[cfg(test)]
403 pub(crate) const fn for_client_test(
404 conversation_id: ConversationId,
405 participant_id: ParticipantId,
406 capability_generation: Generation,
407 detach_attempt_token: DetachAttemptToken,
408 current_generation: Generation,
409 committed_binding_epoch: BindingEpoch,
410 binding_state: BindingStateView,
411 ) -> Self {
412 Self {
413 conversation_id,
414 participant_id,
415 capability_generation,
416 detach_attempt_token,
417 current_generation,
418 committed_binding_epoch,
419 binding_state,
420 }
421 }
422
423 #[must_use]
425 pub const fn conversation_id(&self) -> ConversationId {
426 self.conversation_id
427 }
428
429 #[must_use]
431 pub const fn participant_id(&self) -> ParticipantId {
432 self.participant_id
433 }
434
435 #[must_use]
437 pub const fn capability_generation(&self) -> Generation {
438 self.capability_generation
439 }
440
441 #[must_use]
443 pub const fn detach_attempt_token(&self) -> DetachAttemptToken {
444 self.detach_attempt_token
445 }
446
447 #[must_use]
449 pub const fn current_generation(&self) -> Generation {
450 self.current_generation
451 }
452
453 #[must_use]
455 pub const fn committed_binding_epoch(&self) -> BindingEpoch {
456 self.committed_binding_epoch
457 }
458
459 #[must_use]
461 pub const fn binding_state(&self) -> BindingStateView {
462 self.binding_state
463 }
464}
465
466#[derive(Clone, Debug, PartialEq, Eq)]
468pub enum DetachStaleAuthority {
469 Live {
471 conversation_id: ConversationId,
473 participant_id: ParticipantId,
475 capability_generation: Generation,
477 detach_attempt_token: DetachAttemptToken,
479 current_generation: Generation,
481 },
482 TerminalizedDetachCell(TerminalizedDetachCell),
484}
485
486impl DetachStaleAuthority {
487 #[must_use]
489 pub const fn authority_state_tag(&self) -> DetachAuthorityStateTag {
490 match self {
491 Self::Live { .. } => DetachAuthorityStateTag::Live,
492 Self::TerminalizedDetachCell(_) => DetachAuthorityStateTag::TerminalizedDetachCell,
493 }
494 }
495}
496
497#[derive(Clone, Debug, PartialEq, Eq)]
499pub enum LeaveStaleAuthority {
500 Live {
502 conversation_id: ConversationId,
504 participant_id: ParticipantId,
506 presented_generation: Generation,
508 leave_attempt_token: LeaveAttemptToken,
510 current_generation: Generation,
512 },
513 CommittedLeaveTombstone {
515 conversation_id: ConversationId,
517 participant_id: ParticipantId,
519 presented_generation: Generation,
521 leave_attempt_token: LeaveAttemptToken,
523 retired_generation: Generation,
525 },
526}
527
528impl LeaveStaleAuthority {
529 #[must_use]
531 pub const fn authority_state_tag(&self) -> LeaveAuthorityStateTag {
532 match self {
533 Self::Live { .. } => LeaveAuthorityStateTag::Live,
534 Self::CommittedLeaveTombstone { .. } => LeaveAuthorityStateTag::CommittedLeaveTombstone,
535 }
536 }
537}
538
539#[derive(Clone, Debug, PartialEq, Eq)]
541pub enum CommonStaleAuthorityEnvelope {
542 CredentialAttach(AttachEnvelope),
544 ParticipantAck(ParticipantAckEnvelope),
546 MarkerAck(MarkerAckEnvelope),
548 RecordAdmission(RecordAdmissionEnvelope),
550}
551
552#[derive(Clone, Debug, PartialEq, Eq)]
554pub enum StaleAuthority {
555 Live {
557 request: CommonStaleAuthorityEnvelope,
559 current_generation: Generation,
561 },
562 Detach(DetachStaleAuthority),
564 Leave(LeaveStaleAuthority),
566}
567
568#[derive(Clone, Debug, PartialEq, Eq)]
570pub enum Retired {
571 Enrollment {
573 request: EnrollmentEnvelope,
575 participant_id: ParticipantId,
577 retired_generation: Generation,
579 },
580 Participant {
582 request: ParticipantReferenceEnvelope,
584 retired_generation: Generation,
586 },
587}
588
589#[derive(Clone, Debug, PartialEq, Eq)]
591pub struct EnrollBound {
592 conversation_id: ConversationId,
593 token: EnrollmentToken,
594 participant_id: ParticipantId,
595 attach_secret: AttachSecret,
596 origin_binding_epoch: BindingEpoch,
597 receipt_expires_at: u128,
598 provenance_expires_at: u128,
599}
600
601impl EnrollBound {
602 #[must_use]
609 pub const fn new(
610 conversation_id: ConversationId,
611 token: EnrollmentToken,
612 participant_id: ParticipantId,
613 attach_secret: AttachSecret,
614 origin_binding_epoch: BindingEpoch,
615 receipt_expires_at: u128,
616 provenance_expires_at: u128,
617 ) -> Option<Self> {
618 if origin_binding_epoch.capability_generation.get() == 1 {
619 Some(Self {
620 conversation_id,
621 token,
622 participant_id,
623 attach_secret,
624 origin_binding_epoch,
625 receipt_expires_at,
626 provenance_expires_at,
627 })
628 } else {
629 None
630 }
631 }
632
633 #[must_use]
635 pub const fn conversation_id(&self) -> ConversationId {
636 self.conversation_id
637 }
638
639 #[must_use]
641 pub const fn token(&self) -> EnrollmentToken {
642 self.token
643 }
644
645 #[must_use]
647 pub const fn participant_id(&self) -> ParticipantId {
648 self.participant_id
649 }
650
651 #[must_use]
653 pub const fn request_generation(&self) -> Option<Generation> {
654 None
655 }
656
657 #[must_use]
659 pub const fn capability_generation(&self) -> Generation {
660 self.origin_binding_epoch.capability_generation
661 }
662
663 #[must_use]
665 pub const fn attach_secret(&self) -> AttachSecret {
666 self.attach_secret
667 }
668
669 #[must_use]
671 pub const fn origin_binding_epoch(&self) -> BindingEpoch {
672 self.origin_binding_epoch
673 }
674
675 #[must_use]
677 pub const fn persisted_cursor(&self) -> DeliverySeq {
678 0
679 }
680
681 #[must_use]
683 pub const fn accepted_marker_delivery_seq(&self) -> Option<DeliverySeq> {
684 None
685 }
686
687 #[must_use]
689 pub const fn receipt_expires_at(&self) -> u128 {
690 self.receipt_expires_at
691 }
692
693 #[must_use]
695 pub const fn provenance_expires_at(&self) -> u128 {
696 self.provenance_expires_at
697 }
698}
699
700#[derive(Clone, Debug, PartialEq, Eq)]
702pub struct EnrollmentKnown {
703 pub conversation_id: ConversationId,
705 pub token: EnrollmentToken,
707 pub participant_id: ParticipantId,
709 pub current_generation: Generation,
711}
712
713#[derive(Clone, Debug, PartialEq, Eq)]
715pub enum ReceiptExpired {
716 Enrollment {
718 conversation_id: ConversationId,
720 token: EnrollmentToken,
722 participant_id: ParticipantId,
724 result_generation: Generation,
726 current_generation: Generation,
728 reason: ReceiptExpiryReason,
730 },
731 CredentialAttach {
733 conversation_id: ConversationId,
735 token: AttachAttemptToken,
737 participant_id: ParticipantId,
739 presented_generation: Generation,
741 presented_marker_delivery_seq: Option<DeliverySeq>,
743 result_generation: Generation,
745 current_generation: Generation,
747 reason: ReceiptExpiryReason,
749 },
750}
751
752#[derive(Clone, Copy, Debug, PartialEq, Eq)]
757pub enum EnrollmentReceiptCapacityScope {
758 LiveReceiptServer,
760 ProvenanceServer,
762 ProvenanceConversation,
764}
765
766impl EnrollmentReceiptCapacityScope {
767 #[must_use]
769 pub const fn wire_scope(self) -> ReceiptCapacityScope {
770 match self {
771 Self::LiveReceiptServer => ReceiptCapacityScope::LiveReceiptServer,
772 Self::ProvenanceServer => ReceiptCapacityScope::ProvenanceServer,
773 Self::ProvenanceConversation => ReceiptCapacityScope::ProvenanceConversation,
774 }
775 }
776}
777
778#[derive(Clone, Debug, PartialEq, Eq)]
780pub enum ReceiptCapacityExceeded {
781 Enrollment {
783 request: EnrollmentEnvelope,
785 scope: EnrollmentReceiptCapacityScope,
787 limit: u64,
789 occupied: u64,
791 },
792 CredentialAttach {
794 request: AttachEnvelope,
796 scope: ReceiptCapacityScope,
798 limit: u64,
800 occupied: u64,
802 },
803}
804
805impl ReceiptCapacityExceeded {
806 pub const REQUESTED: u64 = 1;
808}
809
810#[derive(Clone, Debug, PartialEq, Eq)]
812pub struct IdentityCapacityExceeded {
813 pub request: EnrollmentEnvelope,
815 pub scope: IdentityCapacityScope,
817 pub limit: u64,
819 pub occupied: u64,
821}
822
823impl IdentityCapacityExceeded {
824 pub const REQUESTED: u64 = 1;
826}
827
828#[derive(Clone, Copy, Debug, PartialEq, Eq)]
830pub struct ObserverBackpressureState {
831 backpressure_epoch: ObserverEpoch,
833 observer_progress: DeliverySeq,
835}
836
837impl ObserverBackpressureState {
838 #[must_use]
843 pub const fn initial(observer_progress: DeliverySeq) -> Self {
844 Self {
845 backpressure_epoch: observer_progress,
846 observer_progress,
847 }
848 }
849
850 #[must_use]
856 pub const fn replay(
857 backpressure_epoch: ObserverEpoch,
858 observer_progress: DeliverySeq,
859 ) -> Option<Self> {
860 if backpressure_epoch == observer_progress {
861 Some(Self {
862 backpressure_epoch,
863 observer_progress,
864 })
865 } else {
866 None
867 }
868 }
869
870 #[must_use]
872 pub const fn backpressure_epoch(self) -> ObserverEpoch {
873 self.backpressure_epoch
874 }
875
876 #[must_use]
878 pub const fn observer_progress(self) -> DeliverySeq {
879 self.observer_progress
880 }
881}
882
883#[derive(Clone, Debug, PartialEq, Eq)]
885pub enum ObserverBackpressure {
886 Enrollment {
888 request: EnrollmentEnvelope,
890 state: ObserverBackpressureState,
892 },
893 CredentialAttach {
895 request: AttachEnvelope,
897 state: ObserverBackpressureState,
899 },
900 Detach {
902 request: DetachEnvelope,
904 committed_binding_epoch: BindingEpoch,
906 state: ObserverBackpressureState,
908 },
909 Leave {
911 request: LeaveEnvelope,
913 state: ObserverBackpressureState,
915 prior_terminal_cell_exists: bool,
917 },
918 RecordAdmission {
920 request: RecordAdmissionEnvelope,
922 state: ObserverBackpressureState,
924 },
925}
926
927#[derive(Clone, Copy, Debug, PartialEq, Eq)]
941pub enum MarkerSettlementBackpressure {
942 CredentialAttach {
944 conversation_id: ConversationId,
946 refused_epoch: SettlementEpoch,
948 },
949 Detach {
951 conversation_id: ConversationId,
953 refused_epoch: SettlementEpoch,
955 },
956}
957
958#[derive(Clone, Copy, Debug, PartialEq, Eq)]
969pub struct EnrollmentSettlementBackpressure {
970 pub conversation_id: ConversationId,
972}
973
974#[derive(Clone, Debug, PartialEq, Eq)]
976pub enum SequenceAllocatingEnvelope {
977 Enrollment(EnrollmentEnvelope),
979 CredentialAttach(AttachEnvelope),
981 RecordAdmission(RecordAdmissionEnvelope),
983}
984
985#[derive(Clone, Debug, PartialEq, Eq)]
987pub struct ConversationSequenceExhausted {
988 pub request: SequenceAllocatingEnvelope,
990 pub sequence_budget: SequenceBudget,
992}
993
994#[derive(Clone, Debug, PartialEq, Eq)]
996pub struct AttachBound {
997 conversation_id: ConversationId,
999 token: AttachAttemptToken,
1001 participant_id: ParticipantId,
1003 request_generation: Generation,
1005 attach_secret: AttachSecret,
1007 origin_binding_epoch: BindingEpoch,
1009 persisted_cursor: DeliverySeq,
1011 accepted_marker_delivery_seq: Option<DeliverySeq>,
1013 receipt_expires_at: u128,
1015 provenance_expires_at: u128,
1017}
1018
1019impl AttachBound {
1020 #[must_use]
1026 #[allow(clippy::too_many_arguments)]
1027 pub const fn ordinary(
1028 conversation_id: ConversationId,
1029 token: AttachAttemptToken,
1030 participant_id: ParticipantId,
1031 request_generation: Generation,
1032 attach_secret: AttachSecret,
1033 origin_binding_epoch: BindingEpoch,
1034 persisted_cursor: DeliverySeq,
1035 receipt_expires_at: u128,
1036 provenance_expires_at: u128,
1037 ) -> Option<Self> {
1038 if !is_successor_generation(
1039 request_generation,
1040 origin_binding_epoch.capability_generation,
1041 ) {
1042 return None;
1043 }
1044 Some(Self {
1045 conversation_id,
1046 token,
1047 participant_id,
1048 request_generation,
1049 attach_secret,
1050 origin_binding_epoch,
1051 persisted_cursor,
1052 accepted_marker_delivery_seq: None,
1053 receipt_expires_at,
1054 provenance_expires_at,
1055 })
1056 }
1057
1058 #[must_use]
1064 #[allow(clippy::too_many_arguments)]
1065 pub const fn fenced(
1066 conversation_id: ConversationId,
1067 token: AttachAttemptToken,
1068 participant_id: ParticipantId,
1069 request_generation: Generation,
1070 attach_secret: AttachSecret,
1071 origin_binding_epoch: BindingEpoch,
1072 accepted_marker_delivery_seq: DeliverySeq,
1073 receipt_expires_at: u128,
1074 provenance_expires_at: u128,
1075 ) -> Option<Self> {
1076 if !is_successor_generation(
1077 request_generation,
1078 origin_binding_epoch.capability_generation,
1079 ) {
1080 return None;
1081 }
1082 Some(Self {
1083 conversation_id,
1084 token,
1085 participant_id,
1086 request_generation,
1087 attach_secret,
1088 origin_binding_epoch,
1089 persisted_cursor: accepted_marker_delivery_seq,
1090 accepted_marker_delivery_seq: Some(accepted_marker_delivery_seq),
1091 receipt_expires_at,
1092 provenance_expires_at,
1093 })
1094 }
1095
1096 #[must_use]
1098 pub const fn conversation_id(&self) -> ConversationId {
1099 self.conversation_id
1100 }
1101
1102 #[must_use]
1104 pub const fn token(&self) -> AttachAttemptToken {
1105 self.token
1106 }
1107
1108 #[must_use]
1110 pub const fn participant_id(&self) -> ParticipantId {
1111 self.participant_id
1112 }
1113
1114 #[must_use]
1116 pub const fn request_generation(&self) -> Generation {
1117 self.request_generation
1118 }
1119
1120 #[must_use]
1122 pub const fn capability_generation(&self) -> Generation {
1123 self.origin_binding_epoch.capability_generation
1124 }
1125
1126 #[must_use]
1128 pub const fn attach_secret(&self) -> AttachSecret {
1129 self.attach_secret
1130 }
1131
1132 #[must_use]
1134 pub const fn origin_binding_epoch(&self) -> BindingEpoch {
1135 self.origin_binding_epoch
1136 }
1137
1138 #[must_use]
1140 pub const fn persisted_cursor(&self) -> DeliverySeq {
1141 self.persisted_cursor
1142 }
1143
1144 #[must_use]
1146 pub const fn accepted_marker_delivery_seq(&self) -> Option<DeliverySeq> {
1147 self.accepted_marker_delivery_seq
1148 }
1149
1150 #[must_use]
1152 pub const fn receipt_expires_at(&self) -> u128 {
1153 self.receipt_expires_at
1154 }
1155
1156 #[must_use]
1158 pub const fn provenance_expires_at(&self) -> u128 {
1159 self.provenance_expires_at
1160 }
1161}
1162
1163const fn is_successor_generation(previous: Generation, successor: Generation) -> bool {
1164 match previous.get().checked_add(1) {
1165 Some(expected) => successor.get() == expected,
1166 None => false,
1167 }
1168}
1169
1170#[derive(Clone, Debug, PartialEq, Eq)]
1172pub struct StaleOrUnknownReceipt {
1173 pub conversation_id: ConversationId,
1175 pub token: AttachAttemptToken,
1177 pub participant_id: ParticipantId,
1179 pub presented_generation: Generation,
1181 pub presented_marker_delivery_seq: Option<DeliverySeq>,
1183 pub current_generation: Generation,
1185}
1186
1187#[derive(Clone, Debug, PartialEq, Eq)]
1189pub struct AttachMarkerProof {
1190 pub conversation_id: ConversationId,
1192 pub token: AttachAttemptToken,
1194 pub participant_id: ParticipantId,
1196 pub capability_generation: Generation,
1198 pub requested_marker_delivery_seq: DeliverySeq,
1200}
1201
1202#[derive(Clone, Debug, PartialEq, Eq)]
1204pub struct MarkerAckProof {
1205 pub conversation_id: ConversationId,
1207 pub participant_id: ParticipantId,
1209 pub capability_generation: Generation,
1211 pub requested_marker_delivery_seq: DeliverySeq,
1213}
1214
1215#[derive(Clone, Debug, PartialEq, Eq)]
1217pub enum MarkerProofRequest {
1218 CredentialAttach(AttachMarkerProof),
1220 MarkerAck(MarkerAckProof),
1222}
1223
1224#[derive(Clone, Debug, PartialEq, Eq)]
1226pub struct MarkerNotDelivered {
1227 pub request: MarkerProofRequest,
1229 pub reason: MarkerNotDeliveredReason,
1231 pub expected_marker_delivery_seq: DeliverySeq,
1233}
1234
1235#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1237pub enum MarkerMismatchBody {
1238 BelowCursor {
1240 current_cursor: DeliverySeq,
1242 },
1243 NoMarkerExpected,
1245 ExpectedDifferentMarker {
1247 expected_marker_delivery_seq: DeliverySeq,
1249 },
1250}
1251
1252impl MarkerMismatchBody {
1253 #[must_use]
1255 pub const fn reason(self) -> MarkerMismatchReason {
1256 match self {
1257 Self::BelowCursor { .. } => MarkerMismatchReason::BelowCursor,
1258 Self::NoMarkerExpected => MarkerMismatchReason::NoMarkerExpected,
1259 Self::ExpectedDifferentMarker { .. } => MarkerMismatchReason::ExpectedDifferentMarker,
1260 }
1261 }
1262}
1263
1264#[derive(Clone, Debug, PartialEq, Eq)]
1266pub struct MarkerMismatch {
1267 pub request: MarkerProofRequest,
1269 pub mismatch: MarkerMismatchBody,
1271}
1272
1273#[derive(Clone, Debug, PartialEq, Eq)]
1275pub enum ReceiptReplay {
1276 Enrollment(EnrollBound),
1279 CredentialAttach(AttachBound),
1282}
1283
1284#[derive(Clone, Debug, PartialEq, Eq)]
1286pub struct DetachCommitted {
1287 conversation_id: ConversationId,
1289 participant_id: ParticipantId,
1291 detach_attempt_token: DetachAttemptToken,
1293 committed_binding_epoch: BindingEpoch,
1295 detached_delivery_seq: DeliverySeq,
1297}
1298
1299impl DetachCommitted {
1300 #[must_use]
1303 pub const fn new(
1304 conversation_id: ConversationId,
1305 participant_id: ParticipantId,
1306 detach_attempt_token: DetachAttemptToken,
1307 committed_binding_epoch: BindingEpoch,
1308 detached_delivery_seq: DeliverySeq,
1309 ) -> Self {
1310 Self {
1311 conversation_id,
1312 participant_id,
1313 detach_attempt_token,
1314 committed_binding_epoch,
1315 detached_delivery_seq,
1316 }
1317 }
1318
1319 #[must_use]
1321 pub const fn conversation_id(&self) -> ConversationId {
1322 self.conversation_id
1323 }
1324
1325 #[must_use]
1327 pub const fn participant_id(&self) -> ParticipantId {
1328 self.participant_id
1329 }
1330
1331 #[must_use]
1333 pub const fn capability_generation(&self) -> Generation {
1334 self.committed_binding_epoch.capability_generation
1335 }
1336
1337 #[must_use]
1339 pub const fn detach_attempt_token(&self) -> DetachAttemptToken {
1340 self.detach_attempt_token
1341 }
1342
1343 #[must_use]
1345 pub const fn committed_binding_epoch(&self) -> BindingEpoch {
1346 self.committed_binding_epoch
1347 }
1348
1349 #[must_use]
1351 pub const fn detached_delivery_seq(&self) -> DeliverySeq {
1352 self.detached_delivery_seq
1353 }
1354}
1355
1356#[derive(Clone, Debug, PartialEq, Eq)]
1358pub struct DetachInProgress {
1359 pub conversation_id: ConversationId,
1361 pub participant_id: ParticipantId,
1363 pub presented_token: DetachAttemptToken,
1365 pub presented_generation: Generation,
1367 pub committed_binding_epoch: BindingEpoch,
1369}
1370
1371#[derive(Clone, Debug, PartialEq, Eq)]
1373pub struct AckCommitted {
1374 request: ParticipantAckEnvelope,
1376}
1377
1378impl AckCommitted {
1379 #[must_use]
1382 pub const fn new(request: ParticipantAckEnvelope) -> Self {
1383 Self { request }
1384 }
1385
1386 #[must_use]
1388 pub const fn request(&self) -> &ParticipantAckEnvelope {
1389 &self.request
1390 }
1391
1392 #[must_use]
1394 pub const fn current_cursor(&self) -> DeliverySeq {
1395 self.request.through_seq
1396 }
1397}
1398
1399#[derive(Clone, Debug, PartialEq, Eq)]
1401pub enum AckNoOp {
1402 ParticipantAck(ParticipantAckEnvelope),
1404 MarkerAck(MarkerAckEnvelope),
1406}
1407
1408impl AckNoOp {
1409 #[must_use]
1412 pub const fn participant_ack(request: ParticipantAckEnvelope) -> Self {
1413 Self::ParticipantAck(request)
1414 }
1415
1416 #[must_use]
1419 pub const fn marker_ack(request: MarkerAckEnvelope) -> Self {
1420 Self::MarkerAck(request)
1421 }
1422
1423 #[must_use]
1425 pub const fn current_cursor(&self) -> DeliverySeq {
1426 match self {
1427 Self::ParticipantAck(request) => request.through_seq,
1428 Self::MarkerAck(request) => request.marker_delivery_seq,
1429 }
1430 }
1431}
1432
1433#[derive(Clone, Debug, PartialEq, Eq)]
1435pub struct AckGap {
1436 request: ParticipantAckEnvelope,
1438 current_cursor: DeliverySeq,
1440}
1441
1442impl AckGap {
1443 #[must_use]
1446 pub const fn new(request: ParticipantAckEnvelope, current_cursor: DeliverySeq) -> Option<Self> {
1447 if request.through_seq > current_cursor {
1448 Some(Self {
1449 request,
1450 current_cursor,
1451 })
1452 } else {
1453 None
1454 }
1455 }
1456
1457 #[must_use]
1459 pub const fn request(&self) -> &ParticipantAckEnvelope {
1460 &self.request
1461 }
1462
1463 #[must_use]
1465 pub const fn current_cursor(&self) -> DeliverySeq {
1466 self.current_cursor
1467 }
1468
1469 #[must_use]
1471 pub const fn reason(&self) -> AckGapReason {
1472 let _ = self;
1473 AckGapReason::NotContiguouslyAvailable
1474 }
1475}
1476
1477#[derive(Clone, Debug, PartialEq, Eq)]
1479pub struct AckRegression {
1480 request: ParticipantAckEnvelope,
1482 current_cursor: DeliverySeq,
1484}
1485
1486impl AckRegression {
1487 #[must_use]
1490 pub const fn new(request: ParticipantAckEnvelope, current_cursor: DeliverySeq) -> Option<Self> {
1491 if request.through_seq < current_cursor {
1492 Some(Self {
1493 request,
1494 current_cursor,
1495 })
1496 } else {
1497 None
1498 }
1499 }
1500
1501 #[must_use]
1503 pub const fn request(&self) -> &ParticipantAckEnvelope {
1504 &self.request
1505 }
1506
1507 #[must_use]
1509 pub const fn current_cursor(&self) -> DeliverySeq {
1510 self.current_cursor
1511 }
1512
1513 #[must_use]
1515 pub const fn reason(&self) -> AckRegressionReason {
1516 let _ = self;
1517 AckRegressionReason::BelowCursor
1518 }
1519}
1520
1521#[derive(Clone, Debug, PartialEq, Eq)]
1523pub struct LeaveCommitted {
1524 conversation_id: ConversationId,
1526 leave_attempt_token: LeaveAttemptToken,
1528 participant_id: ParticipantId,
1530 retired_generation: Generation,
1532 ended_binding_epoch: Option<BindingEpoch>,
1534 prior_terminal_delivery_seq: Option<DeliverySeq>,
1536 left_delivery_seq: DeliverySeq,
1538}
1539
1540impl LeaveCommitted {
1541 #[must_use]
1547 #[allow(clippy::too_many_arguments)]
1548 pub const fn new(
1549 conversation_id: ConversationId,
1550 leave_attempt_token: LeaveAttemptToken,
1551 participant_id: ParticipantId,
1552 retired_generation: Generation,
1553 ended_binding_epoch: Option<BindingEpoch>,
1554 prior_terminal_delivery_seq: Option<DeliverySeq>,
1555 left_delivery_seq: DeliverySeq,
1556 ) -> Option<Self> {
1557 if let Some(epoch) = ended_binding_epoch
1558 && epoch.capability_generation.get() != retired_generation.get()
1559 {
1560 return None;
1561 }
1562 if let Some(prior) = prior_terminal_delivery_seq
1563 && prior >= left_delivery_seq
1564 {
1565 return None;
1566 }
1567 Some(Self {
1568 conversation_id,
1569 leave_attempt_token,
1570 participant_id,
1571 retired_generation,
1572 ended_binding_epoch,
1573 prior_terminal_delivery_seq,
1574 left_delivery_seq,
1575 })
1576 }
1577
1578 #[must_use]
1580 pub const fn conversation_id(&self) -> ConversationId {
1581 self.conversation_id
1582 }
1583
1584 #[must_use]
1586 pub const fn leave_attempt_token(&self) -> LeaveAttemptToken {
1587 self.leave_attempt_token
1588 }
1589
1590 #[must_use]
1592 pub const fn participant_id(&self) -> ParticipantId {
1593 self.participant_id
1594 }
1595
1596 #[must_use]
1598 pub const fn presented_generation(&self) -> Generation {
1599 self.retired_generation
1600 }
1601
1602 #[must_use]
1604 pub const fn retired_generation(&self) -> Generation {
1605 self.retired_generation
1606 }
1607
1608 #[must_use]
1610 pub const fn ended_binding_epoch(&self) -> Option<BindingEpoch> {
1611 self.ended_binding_epoch
1612 }
1613
1614 #[must_use]
1616 pub const fn prior_terminal_delivery_seq(&self) -> Option<DeliverySeq> {
1617 self.prior_terminal_delivery_seq
1618 }
1619
1620 #[must_use]
1622 pub const fn left_delivery_seq(&self) -> DeliverySeq {
1623 self.left_delivery_seq
1624 }
1625}
1626
1627#[derive(Clone, Debug, PartialEq, Eq)]
1629pub struct MarkerAckCommitted {
1630 request: MarkerAckEnvelope,
1632}
1633
1634impl MarkerAckCommitted {
1635 #[must_use]
1638 pub const fn new(request: MarkerAckEnvelope) -> Self {
1639 Self { request }
1640 }
1641
1642 #[must_use]
1644 pub const fn request(&self) -> &MarkerAckEnvelope {
1645 &self.request
1646 }
1647
1648 #[must_use]
1650 pub const fn current_cursor(&self) -> DeliverySeq {
1651 self.request.marker_delivery_seq
1652 }
1653}
1654
1655#[derive(Clone, Debug, PartialEq, Eq)]
1657pub struct RecordCommitted {
1658 request: RecordAdmissionEnvelope,
1660 delivery_seq: DeliverySeq,
1662}
1663
1664impl RecordCommitted {
1665 #[must_use]
1668 pub const fn new(request: RecordAdmissionEnvelope, delivery_seq: DeliverySeq) -> Self {
1669 Self {
1670 request,
1671 delivery_seq,
1672 }
1673 }
1674
1675 #[must_use]
1677 pub const fn request(&self) -> &RecordAdmissionEnvelope {
1678 &self.request
1679 }
1680
1681 #[must_use]
1683 pub const fn sender_participant_id(&self) -> ParticipantId {
1684 self.request.participant_id
1685 }
1686
1687 #[must_use]
1689 pub const fn delivery_seq(&self) -> DeliverySeq {
1690 self.delivery_seq
1691 }
1692}
1693
1694#[derive(Clone, Debug, PartialEq, Eq)]
1696pub struct RecordTooLarge {
1697 pub request: RecordAdmissionEnvelope,
1699 pub dimension: ResourceDimension,
1701 pub encoded_record_charge: ResourceVector,
1703 pub max_ordinary_record_charge: ResourceVector,
1705}
1706
1707#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1709pub struct ObserverProgressStatus {
1710 pub conversation_id: ConversationId,
1712 pub refused_epoch: ObserverEpoch,
1714 pub current_observer_progress: DeliverySeq,
1716 pub armed: bool,
1718 pub progressed: bool,
1720}
1721
1722#[derive(Clone, Debug, PartialEq, Eq)]
1724pub struct ObserverRecoveryAccepted {
1725 pub statuses: Vec<ObserverProgressStatus>,
1727}
1728
1729#[derive(Clone, Debug, PartialEq, Eq)]
1731pub enum InvalidObserverEpoch {
1732 ConversationUnknown {
1734 conversation_id: ConversationId,
1736 presented_epoch: ObserverEpoch,
1738 },
1739 EpochAhead {
1741 conversation_id: ConversationId,
1743 presented_epoch: ObserverEpoch,
1745 current_observer_progress: DeliverySeq,
1747 },
1748}
1749
1750impl InvalidObserverEpoch {
1751 #[must_use]
1753 pub const fn reason(&self) -> InvalidObserverEpochReason {
1754 match self {
1755 Self::ConversationUnknown { .. } => InvalidObserverEpochReason::ConversationUnknown,
1756 Self::EpochAhead { .. } => InvalidObserverEpochReason::EpochAhead,
1757 }
1758 }
1759}
1760
1761#[derive(Clone, Debug, PartialEq, Eq)]
1763pub enum InvalidObserverEpochList {
1764 TooManyEntries {
1766 presented_entries: u64,
1768 max_entries: u64,
1770 },
1771 DuplicateConversation {
1773 conversation_id: ConversationId,
1775 first_index: u64,
1777 duplicate_index: u64,
1779 },
1780}
1781
1782impl InvalidObserverEpochList {
1783 #[must_use]
1785 pub const fn reason(&self) -> InvalidObserverEpochListReason {
1786 match self {
1787 Self::TooManyEntries { .. } => InvalidObserverEpochListReason::TooManyEntries,
1788 Self::DuplicateConversation { .. } => {
1789 InvalidObserverEpochListReason::DuplicateConversation
1790 }
1791 }
1792 }
1793}
1794
1795#[derive(Clone, Debug, PartialEq, Eq)]
1797pub enum ServerValue {
1798 ParticipantTransportRejected(ParticipantTransportRejected),
1800 AttemptTokenBodyConflict(AttemptTokenBodyConflict),
1802 ConnectionConversationCapacityExceeded(ConnectionConversationCapacityExceeded),
1804 ConnectionConversationBindingOccupied(ConnectionConversationBindingOccupied),
1806 ConversationOrderExhausted(Box<ConversationOrderExhausted>),
1808 ParticipantUnknown(ParticipantUnknown),
1810 NoBinding(NoBinding),
1812 StaleAuthority(StaleAuthority),
1814 Retired(Retired),
1816 MarkerClosureCapacityExceeded(Box<MarkerClosureCapacityExceeded>),
1818 EnrollBound(EnrollBound),
1820 EnrollmentKnown(EnrollmentKnown),
1822 ReceiptExpired(ReceiptExpired),
1824 ReceiptCapacityExceeded(ReceiptCapacityExceeded),
1826 IdentityCapacityExceeded(IdentityCapacityExceeded),
1828 ObserverBackpressure(ObserverBackpressure),
1830 ConversationSequenceExhausted(Box<ConversationSequenceExhausted>),
1832 AttachBound(AttachBound),
1834 StaleOrUnknownReceipt(StaleOrUnknownReceipt),
1836 MarkerNotDelivered(MarkerNotDelivered),
1838 MarkerMismatch(MarkerMismatch),
1840 Bound(ReceiptReplay),
1842 UnboundReceipt(ReceiptReplay),
1844 DetachCommitted(DetachCommitted),
1846 DetachInProgress(DetachInProgress),
1848 AckCommitted(AckCommitted),
1850 AckNoOp(AckNoOp),
1852 AckGap(AckGap),
1854 AckRegression(AckRegression),
1856 LeaveCommitted(LeaveCommitted),
1858 MarkerAckCommitted(MarkerAckCommitted),
1860 RecordCommitted(RecordCommitted),
1862 RecordTooLarge(RecordTooLarge),
1864 ObserverRecoveryAccepted(ObserverRecoveryAccepted),
1866 InvalidObserverEpoch(InvalidObserverEpoch),
1868 InvalidObserverEpochList(InvalidObserverEpochList),
1870 MarkerSettlementBackpressure(MarkerSettlementBackpressure),
1872 EnrollmentSettlementBackpressure(EnrollmentSettlementBackpressure),
1874}
1875
1876impl ServerValue {
1877 #[must_use]
1879 pub const fn discriminant(&self) -> ServerDiscriminant {
1880 match self {
1881 Self::ParticipantTransportRejected(_) => {
1882 ServerDiscriminant::ParticipantTransportRejected
1883 }
1884 Self::AttemptTokenBodyConflict(_) => ServerDiscriminant::AttemptTokenBodyConflict,
1885 Self::ConnectionConversationCapacityExceeded(value) => match value {
1886 ConnectionConversationCapacityExceeded::SemanticRequest { .. } => {
1887 ServerDiscriminant::ConnectionConversationCapacityExceeded
1888 }
1889 ConnectionConversationCapacityExceeded::ObserverRecovery { .. } => {
1890 ServerDiscriminant::ObserverRecoveryConnectionCapacityExceeded
1891 }
1892 },
1893 Self::ConnectionConversationBindingOccupied(_) => {
1894 ServerDiscriminant::ConnectionConversationBindingOccupied
1895 }
1896 Self::ConversationOrderExhausted(_) => ServerDiscriminant::ConversationOrderExhausted,
1897 Self::ParticipantUnknown(_) => ServerDiscriminant::ParticipantUnknown,
1898 Self::NoBinding(_) => ServerDiscriminant::NoBinding,
1899 Self::StaleAuthority(_) => ServerDiscriminant::StaleAuthority,
1900 Self::Retired(_) => ServerDiscriminant::Retired,
1901 Self::MarkerClosureCapacityExceeded(_) => {
1902 ServerDiscriminant::MarkerClosureCapacityExceeded
1903 }
1904 Self::EnrollBound(_) => ServerDiscriminant::EnrollBound,
1905 Self::EnrollmentKnown(_) => ServerDiscriminant::EnrollmentKnown,
1906 Self::ReceiptExpired(_) => ServerDiscriminant::ReceiptExpired,
1907 Self::ReceiptCapacityExceeded(_) => ServerDiscriminant::ReceiptCapacityExceeded,
1908 Self::IdentityCapacityExceeded(_) => ServerDiscriminant::IdentityCapacityExceeded,
1909 Self::ObserverBackpressure(_) => ServerDiscriminant::ObserverBackpressure,
1910 Self::ConversationSequenceExhausted(_) => {
1911 ServerDiscriminant::ConversationSequenceExhausted
1912 }
1913 Self::AttachBound(_) => ServerDiscriminant::AttachBound,
1914 Self::StaleOrUnknownReceipt(_) => ServerDiscriminant::StaleOrUnknownReceipt,
1915 Self::MarkerNotDelivered(_) => ServerDiscriminant::MarkerNotDelivered,
1916 Self::MarkerMismatch(_) => ServerDiscriminant::MarkerMismatch,
1917 Self::Bound(_) => ServerDiscriminant::Bound,
1918 Self::UnboundReceipt(_) => ServerDiscriminant::UnboundReceipt,
1919 Self::DetachCommitted(_) => ServerDiscriminant::DetachCommitted,
1920 Self::DetachInProgress(_) => ServerDiscriminant::DetachInProgress,
1921 Self::AckCommitted(_) => ServerDiscriminant::AckCommitted,
1922 Self::AckNoOp(_) => ServerDiscriminant::AckNoOp,
1923 Self::AckGap(_) => ServerDiscriminant::AckGap,
1924 Self::AckRegression(_) => ServerDiscriminant::AckRegression,
1925 Self::LeaveCommitted(_) => ServerDiscriminant::LeaveCommitted,
1926 Self::MarkerAckCommitted(_) => ServerDiscriminant::MarkerAckCommitted,
1927 Self::RecordCommitted(_) => ServerDiscriminant::RecordCommitted,
1928 Self::RecordTooLarge(_) => ServerDiscriminant::RecordTooLarge,
1929 Self::ObserverRecoveryAccepted(_) => ServerDiscriminant::ObserverRecoveryAccepted,
1930 Self::InvalidObserverEpoch(_) => ServerDiscriminant::InvalidObserverEpoch,
1931 Self::InvalidObserverEpochList(_) => ServerDiscriminant::InvalidObserverEpochList,
1932 Self::MarkerSettlementBackpressure(_) => {
1933 ServerDiscriminant::MarkerSettlementBackpressure
1934 }
1935 Self::EnrollmentSettlementBackpressure(_) => {
1936 ServerDiscriminant::EnrollmentSettlementBackpressure
1937 }
1938 }
1939 }
1940
1941 #[must_use]
1943 #[allow(clippy::too_many_lines)]
1944 pub const fn originating_request(&self) -> Option<ClientDiscriminant> {
1945 match self {
1946 Self::ParticipantTransportRejected(_)
1947 | Self::ObserverRecoveryAccepted(_)
1948 | Self::InvalidObserverEpoch(_)
1949 | Self::InvalidObserverEpochList(_) => None,
1950 Self::AttemptTokenBodyConflict(value) => Some(match value {
1951 AttemptTokenBodyConflict::CredentialAttach { .. } => {
1952 ClientDiscriminant::CredentialAttachRequest
1953 }
1954 AttemptTokenBodyConflict::Leave { .. } => ClientDiscriminant::LeaveRequest,
1955 AttemptTokenBodyConflict::RecordAdmission { .. } => {
1956 ClientDiscriminant::RecordAdmission
1957 }
1958 }),
1959 Self::ConnectionConversationCapacityExceeded(value) => match value {
1960 ConnectionConversationCapacityExceeded::SemanticRequest { request, .. } => {
1961 Some(request.originating_request())
1962 }
1963 ConnectionConversationCapacityExceeded::ObserverRecovery { .. } => None,
1964 },
1965 Self::ConnectionConversationBindingOccupied(value) => Some(match value {
1966 ConnectionConversationBindingOccupied::Enrollment { .. } => {
1967 ClientDiscriminant::EnrollmentRequest
1968 }
1969 ConnectionConversationBindingOccupied::CredentialAttach { .. } => {
1970 ClientDiscriminant::CredentialAttachRequest
1971 }
1972 }),
1973 Self::ConversationOrderExhausted(value) => Some(match value.request() {
1974 OrderAllocatingEnvelope::Enrollment(_) => ClientDiscriminant::EnrollmentRequest,
1975 OrderAllocatingEnvelope::CredentialAttach(_) => {
1976 ClientDiscriminant::CredentialAttachRequest
1977 }
1978 OrderAllocatingEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
1979 }),
1980 Self::ParticipantUnknown(value) => Some(participant_reference_origin(&value.request)),
1981 Self::NoBinding(value) => Some(binding_required_origin(&value.request)),
1982 Self::StaleAuthority(value) => Some(stale_authority_origin(value)),
1983 Self::Retired(value) => Some(match value {
1984 Retired::Enrollment { .. } => ClientDiscriminant::EnrollmentRequest,
1985 Retired::Participant { request, .. } => participant_reference_origin(request),
1986 }),
1987 Self::MarkerClosureCapacityExceeded(value) => Some(match &value.request {
1988 ClosureCheckedEnvelope::Enrollment(_) => ClientDiscriminant::EnrollmentRequest,
1989 ClosureCheckedEnvelope::CredentialAttach(_) => {
1990 ClientDiscriminant::CredentialAttachRequest
1991 }
1992 ClosureCheckedEnvelope::Leave(_) => ClientDiscriminant::LeaveRequest,
1993 ClosureCheckedEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
1994 }),
1995 Self::EnrollBound(_)
1996 | Self::EnrollmentKnown(_)
1997 | Self::IdentityCapacityExceeded(_)
1998 | Self::EnrollmentSettlementBackpressure(_) => {
1999 Some(ClientDiscriminant::EnrollmentRequest)
2000 }
2001 Self::ReceiptExpired(value) => Some(match value {
2002 ReceiptExpired::Enrollment { .. } => ClientDiscriminant::EnrollmentRequest,
2003 ReceiptExpired::CredentialAttach { .. } => {
2004 ClientDiscriminant::CredentialAttachRequest
2005 }
2006 }),
2007 Self::ReceiptCapacityExceeded(value) => Some(match value {
2008 ReceiptCapacityExceeded::Enrollment { .. } => ClientDiscriminant::EnrollmentRequest,
2009 ReceiptCapacityExceeded::CredentialAttach { .. } => {
2010 ClientDiscriminant::CredentialAttachRequest
2011 }
2012 }),
2013 Self::ObserverBackpressure(value) => Some(match value {
2014 ObserverBackpressure::Enrollment { .. } => ClientDiscriminant::EnrollmentRequest,
2015 ObserverBackpressure::CredentialAttach { .. } => {
2016 ClientDiscriminant::CredentialAttachRequest
2017 }
2018 ObserverBackpressure::Detach { .. } => ClientDiscriminant::DetachRequest,
2019 ObserverBackpressure::Leave { .. } => ClientDiscriminant::LeaveRequest,
2020 ObserverBackpressure::RecordAdmission { .. } => ClientDiscriminant::RecordAdmission,
2021 }),
2022 Self::ConversationSequenceExhausted(value) => Some(match &value.request {
2023 SequenceAllocatingEnvelope::Enrollment(_) => ClientDiscriminant::EnrollmentRequest,
2024 SequenceAllocatingEnvelope::CredentialAttach(_) => {
2025 ClientDiscriminant::CredentialAttachRequest
2026 }
2027 SequenceAllocatingEnvelope::RecordAdmission(_) => {
2028 ClientDiscriminant::RecordAdmission
2029 }
2030 }),
2031 Self::AttachBound(_) | Self::StaleOrUnknownReceipt(_) => {
2032 Some(ClientDiscriminant::CredentialAttachRequest)
2033 }
2034 Self::MarkerNotDelivered(value) => Some(marker_proof_origin(&value.request)),
2035 Self::MarkerMismatch(value) => Some(marker_proof_origin(&value.request)),
2036 Self::Bound(value) | Self::UnboundReceipt(value) => Some(match value {
2037 ReceiptReplay::Enrollment(_) => ClientDiscriminant::EnrollmentRequest,
2038 ReceiptReplay::CredentialAttach(_) => ClientDiscriminant::CredentialAttachRequest,
2039 }),
2040 Self::DetachCommitted(_) | Self::DetachInProgress(_) => {
2041 Some(ClientDiscriminant::DetachRequest)
2042 }
2043 Self::AckCommitted(_) | Self::AckGap(_) | Self::AckRegression(_) => {
2044 Some(ClientDiscriminant::ParticipantAck)
2045 }
2046 Self::AckNoOp(value) => Some(match value {
2047 AckNoOp::ParticipantAck(_) => ClientDiscriminant::ParticipantAck,
2048 AckNoOp::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2049 }),
2050 Self::LeaveCommitted(_) => Some(ClientDiscriminant::LeaveRequest),
2051 Self::MarkerAckCommitted(_) => Some(ClientDiscriminant::MarkerAck),
2052 Self::RecordCommitted(_) | Self::RecordTooLarge(_) => {
2053 Some(ClientDiscriminant::RecordAdmission)
2054 }
2055 Self::MarkerSettlementBackpressure(value) => Some(match value {
2056 MarkerSettlementBackpressure::CredentialAttach { .. } => {
2057 ClientDiscriminant::CredentialAttachRequest
2058 }
2059 MarkerSettlementBackpressure::Detach { .. } => ClientDiscriminant::DetachRequest,
2060 }),
2061 }
2062 }
2063}
2064
2065const fn participant_reference_origin(
2066 request: &ParticipantReferenceEnvelope,
2067) -> ClientDiscriminant {
2068 match request {
2069 ParticipantReferenceEnvelope::CredentialAttach(_) => {
2070 ClientDiscriminant::CredentialAttachRequest
2071 }
2072 ParticipantReferenceEnvelope::Detach(_) => ClientDiscriminant::DetachRequest,
2073 ParticipantReferenceEnvelope::ParticipantAck(_) => ClientDiscriminant::ParticipantAck,
2074 ParticipantReferenceEnvelope::Leave(_) => ClientDiscriminant::LeaveRequest,
2075 ParticipantReferenceEnvelope::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2076 ParticipantReferenceEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
2077 }
2078}
2079
2080const fn binding_required_origin(request: &BindingRequiredEnvelope) -> ClientDiscriminant {
2081 match request {
2082 BindingRequiredEnvelope::Detach(_) => ClientDiscriminant::DetachRequest,
2083 BindingRequiredEnvelope::ParticipantAck(_) => ClientDiscriminant::ParticipantAck,
2084 BindingRequiredEnvelope::Leave(_) => ClientDiscriminant::LeaveRequest,
2085 BindingRequiredEnvelope::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2086 BindingRequiredEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
2087 }
2088}
2089
2090const fn stale_authority_origin(value: &StaleAuthority) -> ClientDiscriminant {
2091 match value {
2092 StaleAuthority::Live { request, .. } => match request {
2093 CommonStaleAuthorityEnvelope::CredentialAttach(_) => {
2094 ClientDiscriminant::CredentialAttachRequest
2095 }
2096 CommonStaleAuthorityEnvelope::ParticipantAck(_) => ClientDiscriminant::ParticipantAck,
2097 CommonStaleAuthorityEnvelope::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2098 CommonStaleAuthorityEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
2099 },
2100 StaleAuthority::Detach(_) => ClientDiscriminant::DetachRequest,
2101 StaleAuthority::Leave(_) => ClientDiscriminant::LeaveRequest,
2102 }
2103}
2104
2105const fn marker_proof_origin(request: &MarkerProofRequest) -> ClientDiscriminant {
2106 match request {
2107 MarkerProofRequest::CredentialAttach(_) => ClientDiscriminant::CredentialAttachRequest,
2108 MarkerProofRequest::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2109 }
2110}
2111
2112pub const PARTICIPANT_CAPABILITY: &str = "participant-v1";
2114
2115#[must_use]
2117pub const fn attempt_operation(value: &AttemptTokenBodyConflict) -> super::AttemptOperation {
2118 match value {
2119 AttemptTokenBodyConflict::CredentialAttach { .. } => {
2120 super::AttemptOperation::CredentialAttachRequest
2121 }
2122 AttemptTokenBodyConflict::Leave { .. } => super::AttemptOperation::LeaveRequest,
2123 AttemptTokenBodyConflict::RecordAdmission { .. } => {
2124 super::AttemptOperation::RecordAdmission
2125 }
2126 }
2127}
2128
2129#[must_use]
2131pub fn capability_string() -> String {
2132 String::from(PARTICIPANT_CAPABILITY)
2133}