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,
14 RecordAdmissionFaultClassTag, ResponseEnvelope, SequenceBudget, ServerDiscriminant,
15 SettlementEpoch,
16};
17
18pub use super::tags::{DetachAuthorityStateTag, LeaveAuthorityStateTag, ResourceDimensionTag};
19
20#[cfg(any(test, feature = "test-support"))]
21mod client_test;
22
23#[derive(Clone, Debug, PartialEq, Eq)]
25pub struct ParticipantTransportRejected {
26 pub reason: TransportRejectionReason,
28}
29
30#[derive(Clone, Debug, PartialEq, Eq)]
32pub enum TransportRejectionReason {
33 FrameTooLarge {
35 complete_frame_bytes: u64,
37 max_frame_bytes: u64,
39 },
40 DecodeFailed {
42 decode_class: DecodeClass,
44 },
45 UnsupportedVersion {
47 presented_version: ProtocolVersion,
49 supported_version: ProtocolVersion,
51 },
52 AuthenticationFailed,
54 ParticipantCapabilityRequired,
59 EnrollmentNotPermitted,
61 EnrollmentConversationOutOfScope,
63 CredentialAttachConversationOutOfScope,
65 AccessRefused {
73 refusal: String,
75 },
76}
77
78#[derive(Clone, Debug, PartialEq, Eq)]
83pub enum AttemptTokenBodyConflict {
84 CredentialAttach {
86 token: AttachAttemptToken,
88 conversation_id: ConversationId,
90 presented_participant_id: ParticipantId,
92 presented_generation: Generation,
94 presented_marker_delivery_seq: Option<DeliverySeq>,
96 conflict: AttemptConflict,
98 },
99 Leave {
101 token: LeaveAttemptToken,
103 conversation_id: ConversationId,
105 presented_participant_id: ParticipantId,
107 presented_generation: Generation,
109 },
110 RecordAdmission {
120 token: RecordAdmissionAttemptToken,
122 conversation_id: ConversationId,
124 presented_participant_id: ParticipantId,
126 presented_generation: Generation,
128 },
129}
130
131#[derive(Clone, Debug, PartialEq, Eq)]
138pub enum ConnectionConversationCapacityExceeded {
139 SemanticRequest {
141 request: ResponseEnvelope,
143 limit: u64,
145 },
146 ObserverRecovery {
148 conversation_id: ConversationId,
150 limit: u64,
152 },
153}
154
155#[derive(Clone, Debug, PartialEq, Eq)]
157pub enum ConnectionConversationBindingOccupied {
158 Enrollment {
160 conversation_id: ConversationId,
162 enrollment_token: EnrollmentToken,
164 },
165 CredentialAttach {
167 conversation_id: ConversationId,
169 participant_id: ParticipantId,
171 capability_generation: Generation,
173 attach_attempt_token: AttachAttemptToken,
175 accept_marker_delivery_seq: Option<DeliverySeq>,
177 },
178}
179
180#[derive(Clone, Debug, PartialEq, Eq)]
182pub enum OrderAllocatingEnvelope {
183 Enrollment(EnrollmentEnvelope),
185 CredentialAttach(AttachEnvelope),
187 RecordAdmission(RecordAdmissionEnvelope),
189}
190
191#[derive(Clone, Debug, PartialEq, Eq)]
193pub struct ConversationOrderExhausted {
194 request: OrderAllocatingEnvelope,
196 high: u64,
198 order_remaining: u128,
200 reserved_claims: u128,
202 resulting_order_remaining: u128,
204 resulting_reserved_claims: u128,
206}
207
208impl ConversationOrderExhausted {
209 pub const REQUIRED_MAJORS: u64 = 1;
211
212 #[must_use]
218 pub const fn new(
219 request: OrderAllocatingEnvelope,
220 high: u64,
221 order_remaining: u128,
222 reserved_claims: u128,
223 resulting_order_remaining: u128,
224 resulting_reserved_claims: u128,
225 ) -> Self {
226 Self {
227 request,
228 high,
229 order_remaining,
230 reserved_claims,
231 resulting_order_remaining,
232 resulting_reserved_claims,
233 }
234 }
235
236 #[must_use]
238 pub const fn request(&self) -> &OrderAllocatingEnvelope {
239 &self.request
240 }
241
242 #[must_use]
244 pub const fn counter(&self) -> Counter {
245 let _ = self;
246 Counter::TransactionOrder
247 }
248
249 #[must_use]
251 pub const fn high(&self) -> u64 {
252 self.high
253 }
254
255 #[must_use]
257 pub const fn next_value(&self) -> Option<u64> {
258 self.high.checked_add(1)
259 }
260
261 #[must_use]
263 pub const fn order_remaining(&self) -> u128 {
264 self.order_remaining
265 }
266
267 #[must_use]
269 pub const fn reserved_claims(&self) -> u128 {
270 self.reserved_claims
271 }
272
273 #[must_use]
275 pub const fn resulting_order_remaining(&self) -> u128 {
276 self.resulting_order_remaining
277 }
278
279 #[must_use]
281 pub const fn resulting_reserved_claims(&self) -> u128 {
282 self.resulting_reserved_claims
283 }
284}
285
286#[derive(Clone, Debug, PartialEq, Eq)]
288pub enum ParticipantReferenceEnvelope {
289 CredentialAttach(AttachEnvelope),
291 Detach(DetachEnvelope),
293 ParticipantAck(ParticipantAckEnvelope),
295 Leave(LeaveEnvelope),
297 MarkerAck(MarkerAckEnvelope),
299 RecordAdmission(RecordAdmissionEnvelope),
301}
302
303#[derive(Clone, Debug, PartialEq, Eq)]
305pub enum BindingRequiredEnvelope {
306 Detach(DetachEnvelope),
308 ParticipantAck(ParticipantAckEnvelope),
310 Leave(LeaveEnvelope),
312 MarkerAck(MarkerAckEnvelope),
314 RecordAdmission(RecordAdmissionEnvelope),
316}
317
318#[derive(Clone, Debug, PartialEq, Eq)]
320pub struct ParticipantUnknown {
321 pub request: ParticipantReferenceEnvelope,
323}
324
325#[derive(Clone, Debug, PartialEq, Eq)]
327pub struct NoBinding {
328 pub request: BindingRequiredEnvelope,
330}
331
332#[derive(Clone, Copy, Debug, PartialEq, Eq)]
334pub enum BindingStateView {
335 Bound {
337 current_binding_epoch: BindingEpoch,
339 },
340 Detached,
342}
343
344impl BindingStateView {
345 #[must_use]
347 pub const fn tag(self) -> super::BindingStateTag {
348 match self {
349 Self::Bound { .. } => super::BindingStateTag::Bound,
350 Self::Detached => super::BindingStateTag::Detached,
351 }
352 }
353}
354
355#[derive(Clone, Debug, PartialEq, Eq)]
360pub struct TerminalizedDetachCell {
361 conversation_id: ConversationId,
362 participant_id: ParticipantId,
363 capability_generation: Generation,
364 detach_attempt_token: DetachAttemptToken,
365 current_generation: Generation,
366 committed_binding_epoch: BindingEpoch,
367 binding_state: BindingStateView,
368}
369
370impl TerminalizedDetachCell {
371 pub(crate) const fn from_terminalized_state<V>(
379 state: &crate::lifecycle::TerminalizedDetach<V>,
380 conversation_id: ConversationId,
381 current_generation: Generation,
382 binding_state: BindingStateView,
383 ) -> Self {
384 Self {
385 conversation_id,
386 participant_id: state.participant_id(),
387 capability_generation: state.request_generation(),
388 detach_attempt_token: state.token(),
389 current_generation,
390 committed_binding_epoch: state.committed_binding_epoch(),
391 binding_state,
392 }
393 }
394
395 #[allow(clippy::too_many_arguments)]
402 pub(super) const fn from_wire_decode(
403 _authority: super::server_codec::TerminalizedWireDecodeAuthority,
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, Copy, Debug, PartialEq, Eq)]
984pub enum RecordAdmissionFaultClass {
985 Projection,
987 Order,
989 Sequence,
991 RequiredCapacity,
993 RefusalInvariant,
995}
996
997impl RecordAdmissionFaultClass {
998 #[must_use]
1000 pub const fn tag(self) -> RecordAdmissionFaultClassTag {
1001 match self {
1002 Self::Projection => RecordAdmissionFaultClassTag::Projection,
1003 Self::Order => RecordAdmissionFaultClassTag::Order,
1004 Self::Sequence => RecordAdmissionFaultClassTag::Sequence,
1005 Self::RequiredCapacity => RecordAdmissionFaultClassTag::RequiredCapacity,
1006 Self::RefusalInvariant => RecordAdmissionFaultClassTag::RefusalInvariant,
1007 }
1008 }
1009}
1010
1011impl From<RecordAdmissionFaultClassTag> for RecordAdmissionFaultClass {
1012 fn from(tag: RecordAdmissionFaultClassTag) -> Self {
1013 match tag {
1014 RecordAdmissionFaultClassTag::Projection => Self::Projection,
1015 RecordAdmissionFaultClassTag::Order => Self::Order,
1016 RecordAdmissionFaultClassTag::Sequence => Self::Sequence,
1017 RecordAdmissionFaultClassTag::RequiredCapacity => Self::RequiredCapacity,
1018 RecordAdmissionFaultClassTag::RefusalInvariant => Self::RefusalInvariant,
1019 }
1020 }
1021}
1022
1023#[derive(Clone, Debug, PartialEq, Eq)]
1042pub struct RecordAdmissionProtocolFault {
1043 pub request: RecordAdmissionEnvelope,
1045 pub class: RecordAdmissionFaultClass,
1047}
1048
1049#[derive(Clone, Debug, PartialEq, Eq)]
1065pub enum WriteOutcomeUnknown {
1066 Enrollment {
1068 request: EnrollmentEnvelope,
1070 },
1071 CredentialAttach {
1073 request: AttachEnvelope,
1075 },
1076 Detach {
1078 request: DetachEnvelope,
1080 },
1081 Leave {
1083 request: LeaveEnvelope,
1085 },
1086 RecordAdmission {
1088 request: RecordAdmissionEnvelope,
1090 },
1091}
1092
1093#[derive(Clone, Debug, PartialEq, Eq)]
1095pub enum SequenceAllocatingEnvelope {
1096 Enrollment(EnrollmentEnvelope),
1098 CredentialAttach(AttachEnvelope),
1100 RecordAdmission(RecordAdmissionEnvelope),
1102}
1103
1104#[derive(Clone, Debug, PartialEq, Eq)]
1106pub struct ConversationSequenceExhausted {
1107 pub request: SequenceAllocatingEnvelope,
1109 pub sequence_budget: SequenceBudget,
1111}
1112
1113#[derive(Clone, Debug, PartialEq, Eq)]
1115pub struct AttachBound {
1116 conversation_id: ConversationId,
1118 token: AttachAttemptToken,
1120 participant_id: ParticipantId,
1122 request_generation: Generation,
1124 attach_secret: AttachSecret,
1126 origin_binding_epoch: BindingEpoch,
1128 persisted_cursor: DeliverySeq,
1130 accepted_marker_delivery_seq: Option<DeliverySeq>,
1132 receipt_expires_at: u128,
1134 provenance_expires_at: u128,
1136}
1137
1138impl AttachBound {
1139 #[must_use]
1145 #[allow(clippy::too_many_arguments)]
1146 pub const fn ordinary(
1147 conversation_id: ConversationId,
1148 token: AttachAttemptToken,
1149 participant_id: ParticipantId,
1150 request_generation: Generation,
1151 attach_secret: AttachSecret,
1152 origin_binding_epoch: BindingEpoch,
1153 persisted_cursor: DeliverySeq,
1154 receipt_expires_at: u128,
1155 provenance_expires_at: u128,
1156 ) -> Option<Self> {
1157 if !is_successor_generation(
1158 request_generation,
1159 origin_binding_epoch.capability_generation,
1160 ) {
1161 return None;
1162 }
1163 Some(Self {
1164 conversation_id,
1165 token,
1166 participant_id,
1167 request_generation,
1168 attach_secret,
1169 origin_binding_epoch,
1170 persisted_cursor,
1171 accepted_marker_delivery_seq: None,
1172 receipt_expires_at,
1173 provenance_expires_at,
1174 })
1175 }
1176
1177 #[must_use]
1183 #[allow(clippy::too_many_arguments)]
1184 pub const fn fenced(
1185 conversation_id: ConversationId,
1186 token: AttachAttemptToken,
1187 participant_id: ParticipantId,
1188 request_generation: Generation,
1189 attach_secret: AttachSecret,
1190 origin_binding_epoch: BindingEpoch,
1191 accepted_marker_delivery_seq: DeliverySeq,
1192 receipt_expires_at: u128,
1193 provenance_expires_at: u128,
1194 ) -> Option<Self> {
1195 if !is_successor_generation(
1196 request_generation,
1197 origin_binding_epoch.capability_generation,
1198 ) {
1199 return None;
1200 }
1201 Some(Self {
1202 conversation_id,
1203 token,
1204 participant_id,
1205 request_generation,
1206 attach_secret,
1207 origin_binding_epoch,
1208 persisted_cursor: accepted_marker_delivery_seq,
1209 accepted_marker_delivery_seq: Some(accepted_marker_delivery_seq),
1210 receipt_expires_at,
1211 provenance_expires_at,
1212 })
1213 }
1214
1215 #[must_use]
1217 pub const fn conversation_id(&self) -> ConversationId {
1218 self.conversation_id
1219 }
1220
1221 #[must_use]
1223 pub const fn token(&self) -> AttachAttemptToken {
1224 self.token
1225 }
1226
1227 #[must_use]
1229 pub const fn participant_id(&self) -> ParticipantId {
1230 self.participant_id
1231 }
1232
1233 #[must_use]
1235 pub const fn request_generation(&self) -> Generation {
1236 self.request_generation
1237 }
1238
1239 #[must_use]
1241 pub const fn capability_generation(&self) -> Generation {
1242 self.origin_binding_epoch.capability_generation
1243 }
1244
1245 #[must_use]
1247 pub const fn attach_secret(&self) -> AttachSecret {
1248 self.attach_secret
1249 }
1250
1251 #[must_use]
1253 pub const fn origin_binding_epoch(&self) -> BindingEpoch {
1254 self.origin_binding_epoch
1255 }
1256
1257 #[must_use]
1259 pub const fn persisted_cursor(&self) -> DeliverySeq {
1260 self.persisted_cursor
1261 }
1262
1263 #[must_use]
1265 pub const fn accepted_marker_delivery_seq(&self) -> Option<DeliverySeq> {
1266 self.accepted_marker_delivery_seq
1267 }
1268
1269 #[must_use]
1271 pub const fn receipt_expires_at(&self) -> u128 {
1272 self.receipt_expires_at
1273 }
1274
1275 #[must_use]
1277 pub const fn provenance_expires_at(&self) -> u128 {
1278 self.provenance_expires_at
1279 }
1280}
1281
1282const fn is_successor_generation(previous: Generation, successor: Generation) -> bool {
1283 match previous.get().checked_add(1) {
1284 Some(expected) => successor.get() == expected,
1285 None => false,
1286 }
1287}
1288
1289#[derive(Clone, Debug, PartialEq, Eq)]
1291pub struct StaleOrUnknownReceipt {
1292 pub conversation_id: ConversationId,
1294 pub token: AttachAttemptToken,
1296 pub participant_id: ParticipantId,
1298 pub presented_generation: Generation,
1300 pub presented_marker_delivery_seq: Option<DeliverySeq>,
1302 pub current_generation: Generation,
1304}
1305
1306#[derive(Clone, Debug, PartialEq, Eq)]
1308pub struct AttachMarkerProof {
1309 pub conversation_id: ConversationId,
1311 pub token: AttachAttemptToken,
1313 pub participant_id: ParticipantId,
1315 pub capability_generation: Generation,
1317 pub requested_marker_delivery_seq: DeliverySeq,
1319}
1320
1321#[derive(Clone, Debug, PartialEq, Eq)]
1323pub struct MarkerAckProof {
1324 pub conversation_id: ConversationId,
1326 pub participant_id: ParticipantId,
1328 pub capability_generation: Generation,
1330 pub requested_marker_delivery_seq: DeliverySeq,
1332}
1333
1334#[derive(Clone, Debug, PartialEq, Eq)]
1336pub enum MarkerProofRequest {
1337 CredentialAttach(AttachMarkerProof),
1339 MarkerAck(MarkerAckProof),
1341}
1342
1343#[derive(Clone, Debug, PartialEq, Eq)]
1345pub struct MarkerNotDelivered {
1346 pub request: MarkerProofRequest,
1348 pub reason: MarkerNotDeliveredReason,
1350 pub expected_marker_delivery_seq: DeliverySeq,
1352}
1353
1354#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1356pub enum MarkerMismatchBody {
1357 BelowCursor {
1359 current_cursor: DeliverySeq,
1361 },
1362 NoMarkerExpected,
1364 ExpectedDifferentMarker {
1366 expected_marker_delivery_seq: DeliverySeq,
1368 },
1369}
1370
1371impl MarkerMismatchBody {
1372 #[must_use]
1374 pub const fn reason(self) -> MarkerMismatchReason {
1375 match self {
1376 Self::BelowCursor { .. } => MarkerMismatchReason::BelowCursor,
1377 Self::NoMarkerExpected => MarkerMismatchReason::NoMarkerExpected,
1378 Self::ExpectedDifferentMarker { .. } => MarkerMismatchReason::ExpectedDifferentMarker,
1379 }
1380 }
1381}
1382
1383#[derive(Clone, Debug, PartialEq, Eq)]
1385pub struct MarkerMismatch {
1386 pub request: MarkerProofRequest,
1388 pub mismatch: MarkerMismatchBody,
1390}
1391
1392#[derive(Clone, Debug, PartialEq, Eq)]
1394pub enum ReceiptReplay {
1395 Enrollment(EnrollBound),
1398 CredentialAttach(AttachBound),
1401}
1402
1403#[derive(Clone, Debug, PartialEq, Eq)]
1405pub struct DetachCommitted {
1406 conversation_id: ConversationId,
1408 participant_id: ParticipantId,
1410 detach_attempt_token: DetachAttemptToken,
1412 committed_binding_epoch: BindingEpoch,
1414 detached_delivery_seq: DeliverySeq,
1416}
1417
1418impl DetachCommitted {
1419 #[must_use]
1422 pub const fn new(
1423 conversation_id: ConversationId,
1424 participant_id: ParticipantId,
1425 detach_attempt_token: DetachAttemptToken,
1426 committed_binding_epoch: BindingEpoch,
1427 detached_delivery_seq: DeliverySeq,
1428 ) -> Self {
1429 Self {
1430 conversation_id,
1431 participant_id,
1432 detach_attempt_token,
1433 committed_binding_epoch,
1434 detached_delivery_seq,
1435 }
1436 }
1437
1438 #[must_use]
1440 pub const fn conversation_id(&self) -> ConversationId {
1441 self.conversation_id
1442 }
1443
1444 #[must_use]
1446 pub const fn participant_id(&self) -> ParticipantId {
1447 self.participant_id
1448 }
1449
1450 #[must_use]
1452 pub const fn capability_generation(&self) -> Generation {
1453 self.committed_binding_epoch.capability_generation
1454 }
1455
1456 #[must_use]
1458 pub const fn detach_attempt_token(&self) -> DetachAttemptToken {
1459 self.detach_attempt_token
1460 }
1461
1462 #[must_use]
1464 pub const fn committed_binding_epoch(&self) -> BindingEpoch {
1465 self.committed_binding_epoch
1466 }
1467
1468 #[must_use]
1470 pub const fn detached_delivery_seq(&self) -> DeliverySeq {
1471 self.detached_delivery_seq
1472 }
1473}
1474
1475#[derive(Clone, Debug, PartialEq, Eq)]
1477pub struct DetachInProgress {
1478 pub conversation_id: ConversationId,
1480 pub participant_id: ParticipantId,
1482 pub presented_token: DetachAttemptToken,
1484 pub presented_generation: Generation,
1486 pub committed_binding_epoch: BindingEpoch,
1488}
1489
1490#[derive(Clone, Debug, PartialEq, Eq)]
1492pub struct AckCommitted {
1493 request: ParticipantAckEnvelope,
1495}
1496
1497impl AckCommitted {
1498 #[must_use]
1501 pub const fn new(request: ParticipantAckEnvelope) -> Self {
1502 Self { request }
1503 }
1504
1505 #[must_use]
1507 pub const fn request(&self) -> &ParticipantAckEnvelope {
1508 &self.request
1509 }
1510
1511 #[must_use]
1513 pub const fn current_cursor(&self) -> DeliverySeq {
1514 self.request.through_seq
1515 }
1516}
1517
1518#[derive(Clone, Debug, PartialEq, Eq)]
1520pub enum AckNoOp {
1521 ParticipantAck(ParticipantAckEnvelope),
1523 MarkerAck(MarkerAckEnvelope),
1525}
1526
1527impl AckNoOp {
1528 #[must_use]
1531 pub const fn participant_ack(request: ParticipantAckEnvelope) -> Self {
1532 Self::ParticipantAck(request)
1533 }
1534
1535 #[must_use]
1538 pub const fn marker_ack(request: MarkerAckEnvelope) -> Self {
1539 Self::MarkerAck(request)
1540 }
1541
1542 #[must_use]
1544 pub const fn current_cursor(&self) -> DeliverySeq {
1545 match self {
1546 Self::ParticipantAck(request) => request.through_seq,
1547 Self::MarkerAck(request) => request.marker_delivery_seq,
1548 }
1549 }
1550}
1551
1552#[derive(Clone, Debug, PartialEq, Eq)]
1554pub struct AckGap {
1555 request: ParticipantAckEnvelope,
1557 current_cursor: DeliverySeq,
1559}
1560
1561impl AckGap {
1562 #[must_use]
1565 pub const fn new(request: ParticipantAckEnvelope, current_cursor: DeliverySeq) -> Option<Self> {
1566 if request.through_seq > current_cursor {
1567 Some(Self {
1568 request,
1569 current_cursor,
1570 })
1571 } else {
1572 None
1573 }
1574 }
1575
1576 #[must_use]
1578 pub const fn request(&self) -> &ParticipantAckEnvelope {
1579 &self.request
1580 }
1581
1582 #[must_use]
1584 pub const fn current_cursor(&self) -> DeliverySeq {
1585 self.current_cursor
1586 }
1587
1588 #[must_use]
1590 pub const fn reason(&self) -> AckGapReason {
1591 let _ = self;
1592 AckGapReason::NotContiguouslyAvailable
1593 }
1594}
1595
1596#[derive(Clone, Debug, PartialEq, Eq)]
1598pub struct AckRegression {
1599 request: ParticipantAckEnvelope,
1601 current_cursor: DeliverySeq,
1603}
1604
1605impl AckRegression {
1606 #[must_use]
1609 pub const fn new(request: ParticipantAckEnvelope, current_cursor: DeliverySeq) -> Option<Self> {
1610 if request.through_seq < current_cursor {
1611 Some(Self {
1612 request,
1613 current_cursor,
1614 })
1615 } else {
1616 None
1617 }
1618 }
1619
1620 #[must_use]
1622 pub const fn request(&self) -> &ParticipantAckEnvelope {
1623 &self.request
1624 }
1625
1626 #[must_use]
1628 pub const fn current_cursor(&self) -> DeliverySeq {
1629 self.current_cursor
1630 }
1631
1632 #[must_use]
1634 pub const fn reason(&self) -> AckRegressionReason {
1635 let _ = self;
1636 AckRegressionReason::BelowCursor
1637 }
1638}
1639
1640#[derive(Clone, Debug, PartialEq, Eq)]
1642pub struct LeaveCommitted {
1643 conversation_id: ConversationId,
1645 leave_attempt_token: LeaveAttemptToken,
1647 participant_id: ParticipantId,
1649 retired_generation: Generation,
1651 ended_binding_epoch: Option<BindingEpoch>,
1653 prior_terminal_delivery_seq: Option<DeliverySeq>,
1655 left_delivery_seq: DeliverySeq,
1657}
1658
1659impl LeaveCommitted {
1660 #[must_use]
1666 #[allow(clippy::too_many_arguments)]
1667 pub const fn new(
1668 conversation_id: ConversationId,
1669 leave_attempt_token: LeaveAttemptToken,
1670 participant_id: ParticipantId,
1671 retired_generation: Generation,
1672 ended_binding_epoch: Option<BindingEpoch>,
1673 prior_terminal_delivery_seq: Option<DeliverySeq>,
1674 left_delivery_seq: DeliverySeq,
1675 ) -> Option<Self> {
1676 if let Some(epoch) = ended_binding_epoch
1677 && epoch.capability_generation.get() != retired_generation.get()
1678 {
1679 return None;
1680 }
1681 if let Some(prior) = prior_terminal_delivery_seq
1682 && prior >= left_delivery_seq
1683 {
1684 return None;
1685 }
1686 Some(Self {
1687 conversation_id,
1688 leave_attempt_token,
1689 participant_id,
1690 retired_generation,
1691 ended_binding_epoch,
1692 prior_terminal_delivery_seq,
1693 left_delivery_seq,
1694 })
1695 }
1696
1697 #[must_use]
1699 pub const fn conversation_id(&self) -> ConversationId {
1700 self.conversation_id
1701 }
1702
1703 #[must_use]
1705 pub const fn leave_attempt_token(&self) -> LeaveAttemptToken {
1706 self.leave_attempt_token
1707 }
1708
1709 #[must_use]
1711 pub const fn participant_id(&self) -> ParticipantId {
1712 self.participant_id
1713 }
1714
1715 #[must_use]
1717 pub const fn presented_generation(&self) -> Generation {
1718 self.retired_generation
1719 }
1720
1721 #[must_use]
1723 pub const fn retired_generation(&self) -> Generation {
1724 self.retired_generation
1725 }
1726
1727 #[must_use]
1729 pub const fn ended_binding_epoch(&self) -> Option<BindingEpoch> {
1730 self.ended_binding_epoch
1731 }
1732
1733 #[must_use]
1735 pub const fn prior_terminal_delivery_seq(&self) -> Option<DeliverySeq> {
1736 self.prior_terminal_delivery_seq
1737 }
1738
1739 #[must_use]
1741 pub const fn left_delivery_seq(&self) -> DeliverySeq {
1742 self.left_delivery_seq
1743 }
1744}
1745
1746#[derive(Clone, Debug, PartialEq, Eq)]
1748pub struct MarkerAckCommitted {
1749 request: MarkerAckEnvelope,
1751}
1752
1753impl MarkerAckCommitted {
1754 #[must_use]
1757 pub const fn new(request: MarkerAckEnvelope) -> Self {
1758 Self { request }
1759 }
1760
1761 #[must_use]
1763 pub const fn request(&self) -> &MarkerAckEnvelope {
1764 &self.request
1765 }
1766
1767 #[must_use]
1769 pub const fn current_cursor(&self) -> DeliverySeq {
1770 self.request.marker_delivery_seq
1771 }
1772}
1773
1774#[derive(Clone, Debug, PartialEq, Eq)]
1776pub struct RecordCommitted {
1777 request: RecordAdmissionEnvelope,
1779 delivery_seq: DeliverySeq,
1781}
1782
1783impl RecordCommitted {
1784 #[must_use]
1787 pub const fn new(request: RecordAdmissionEnvelope, delivery_seq: DeliverySeq) -> Self {
1788 Self {
1789 request,
1790 delivery_seq,
1791 }
1792 }
1793
1794 #[must_use]
1796 pub const fn request(&self) -> &RecordAdmissionEnvelope {
1797 &self.request
1798 }
1799
1800 #[must_use]
1802 pub const fn sender_participant_id(&self) -> ParticipantId {
1803 self.request.participant_id
1804 }
1805
1806 #[must_use]
1808 pub const fn delivery_seq(&self) -> DeliverySeq {
1809 self.delivery_seq
1810 }
1811}
1812
1813#[derive(Clone, Debug, PartialEq, Eq)]
1815pub struct RecordTooLarge {
1816 pub request: RecordAdmissionEnvelope,
1818 pub dimension: ResourceDimension,
1820 pub encoded_record_charge: ResourceVector,
1822 pub max_ordinary_record_charge: ResourceVector,
1824}
1825
1826#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1828pub struct ObserverProgressStatus {
1829 pub conversation_id: ConversationId,
1831 pub refused_epoch: ObserverEpoch,
1833 pub current_observer_progress: DeliverySeq,
1835 pub armed: bool,
1837 pub progressed: bool,
1839}
1840
1841#[derive(Clone, Debug, PartialEq, Eq)]
1843pub struct ObserverRecoveryAccepted {
1844 pub statuses: Vec<ObserverProgressStatus>,
1846}
1847
1848#[derive(Clone, Debug, PartialEq, Eq)]
1850pub enum InvalidObserverEpoch {
1851 ConversationUnknown {
1853 conversation_id: ConversationId,
1855 presented_epoch: ObserverEpoch,
1857 },
1858 EpochAhead {
1860 conversation_id: ConversationId,
1862 presented_epoch: ObserverEpoch,
1864 current_observer_progress: DeliverySeq,
1866 },
1867}
1868
1869impl InvalidObserverEpoch {
1870 #[must_use]
1872 pub const fn reason(&self) -> InvalidObserverEpochReason {
1873 match self {
1874 Self::ConversationUnknown { .. } => InvalidObserverEpochReason::ConversationUnknown,
1875 Self::EpochAhead { .. } => InvalidObserverEpochReason::EpochAhead,
1876 }
1877 }
1878}
1879
1880#[derive(Clone, Debug, PartialEq, Eq)]
1882pub enum InvalidObserverEpochList {
1883 TooManyEntries {
1885 presented_entries: u64,
1887 max_entries: u64,
1889 },
1890 DuplicateConversation {
1892 conversation_id: ConversationId,
1894 first_index: u64,
1896 duplicate_index: u64,
1898 },
1899}
1900
1901impl InvalidObserverEpochList {
1902 #[must_use]
1904 pub const fn reason(&self) -> InvalidObserverEpochListReason {
1905 match self {
1906 Self::TooManyEntries { .. } => InvalidObserverEpochListReason::TooManyEntries,
1907 Self::DuplicateConversation { .. } => {
1908 InvalidObserverEpochListReason::DuplicateConversation
1909 }
1910 }
1911 }
1912}
1913
1914#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1916pub enum SettlementOutcome {
1917 Committed {
1919 delivery_seq: DeliverySeq,
1921 },
1922 Withdrawn,
1924 Expired,
1926 NotCommitted,
1928 Unknown,
1930}
1931
1932#[derive(Clone, Debug, PartialEq, Eq)]
1934pub struct SettlementAnswer {
1935 pub conversation_id: ConversationId,
1937 pub participant_id: ParticipantId,
1939 pub record_admission_attempt_token: RecordAdmissionAttemptToken,
1941 pub outcome: SettlementOutcome,
1943}
1944
1945#[derive(Clone, Debug, PartialEq, Eq)]
1947pub enum ServerValue {
1948 ParticipantTransportRejected(ParticipantTransportRejected),
1950 AttemptTokenBodyConflict(AttemptTokenBodyConflict),
1952 ConnectionConversationCapacityExceeded(ConnectionConversationCapacityExceeded),
1954 ConnectionConversationBindingOccupied(ConnectionConversationBindingOccupied),
1956 ConversationOrderExhausted(Box<ConversationOrderExhausted>),
1958 ParticipantUnknown(ParticipantUnknown),
1960 NoBinding(NoBinding),
1962 StaleAuthority(StaleAuthority),
1964 Retired(Retired),
1966 MarkerClosureCapacityExceeded(Box<MarkerClosureCapacityExceeded>),
1968 EnrollBound(EnrollBound),
1970 EnrollmentKnown(EnrollmentKnown),
1972 ReceiptExpired(ReceiptExpired),
1974 ReceiptCapacityExceeded(ReceiptCapacityExceeded),
1976 IdentityCapacityExceeded(IdentityCapacityExceeded),
1978 ObserverBackpressure(ObserverBackpressure),
1980 ConversationSequenceExhausted(Box<ConversationSequenceExhausted>),
1982 AttachBound(AttachBound),
1984 StaleOrUnknownReceipt(StaleOrUnknownReceipt),
1986 MarkerNotDelivered(MarkerNotDelivered),
1988 MarkerMismatch(MarkerMismatch),
1990 Bound(ReceiptReplay),
1992 UnboundReceipt(ReceiptReplay),
1994 DetachCommitted(DetachCommitted),
1996 DetachInProgress(DetachInProgress),
1998 AckCommitted(AckCommitted),
2000 AckNoOp(AckNoOp),
2002 AckGap(AckGap),
2004 AckRegression(AckRegression),
2006 LeaveCommitted(LeaveCommitted),
2008 MarkerAckCommitted(MarkerAckCommitted),
2010 RecordCommitted(RecordCommitted),
2012 RecordTooLarge(RecordTooLarge),
2014 ObserverRecoveryAccepted(ObserverRecoveryAccepted),
2016 InvalidObserverEpoch(InvalidObserverEpoch),
2018 InvalidObserverEpochList(InvalidObserverEpochList),
2020 MarkerSettlementBackpressure(MarkerSettlementBackpressure),
2022 EnrollmentSettlementBackpressure(EnrollmentSettlementBackpressure),
2024 RecordAdmissionProtocolFault(RecordAdmissionProtocolFault),
2026 WriteOutcomeUnknown(WriteOutcomeUnknown),
2028 SettlementAnswer(SettlementAnswer),
2030}
2031
2032impl ServerValue {
2033 #[must_use]
2035 pub const fn discriminant(&self) -> ServerDiscriminant {
2036 match self {
2037 Self::ParticipantTransportRejected(_) => {
2038 ServerDiscriminant::ParticipantTransportRejected
2039 }
2040 Self::AttemptTokenBodyConflict(_) => ServerDiscriminant::AttemptTokenBodyConflict,
2041 Self::ConnectionConversationCapacityExceeded(value) => match value {
2042 ConnectionConversationCapacityExceeded::SemanticRequest { .. } => {
2043 ServerDiscriminant::ConnectionConversationCapacityExceeded
2044 }
2045 ConnectionConversationCapacityExceeded::ObserverRecovery { .. } => {
2046 ServerDiscriminant::ObserverRecoveryConnectionCapacityExceeded
2047 }
2048 },
2049 Self::ConnectionConversationBindingOccupied(_) => {
2050 ServerDiscriminant::ConnectionConversationBindingOccupied
2051 }
2052 Self::ConversationOrderExhausted(_) => ServerDiscriminant::ConversationOrderExhausted,
2053 Self::ParticipantUnknown(_) => ServerDiscriminant::ParticipantUnknown,
2054 Self::NoBinding(_) => ServerDiscriminant::NoBinding,
2055 Self::StaleAuthority(_) => ServerDiscriminant::StaleAuthority,
2056 Self::Retired(_) => ServerDiscriminant::Retired,
2057 Self::MarkerClosureCapacityExceeded(_) => {
2058 ServerDiscriminant::MarkerClosureCapacityExceeded
2059 }
2060 Self::EnrollBound(_) => ServerDiscriminant::EnrollBound,
2061 Self::EnrollmentKnown(_) => ServerDiscriminant::EnrollmentKnown,
2062 Self::ReceiptExpired(_) => ServerDiscriminant::ReceiptExpired,
2063 Self::ReceiptCapacityExceeded(_) => ServerDiscriminant::ReceiptCapacityExceeded,
2064 Self::IdentityCapacityExceeded(_) => ServerDiscriminant::IdentityCapacityExceeded,
2065 Self::ObserverBackpressure(_) => ServerDiscriminant::ObserverBackpressure,
2066 Self::ConversationSequenceExhausted(_) => {
2067 ServerDiscriminant::ConversationSequenceExhausted
2068 }
2069 Self::AttachBound(_) => ServerDiscriminant::AttachBound,
2070 Self::StaleOrUnknownReceipt(_) => ServerDiscriminant::StaleOrUnknownReceipt,
2071 Self::MarkerNotDelivered(_) => ServerDiscriminant::MarkerNotDelivered,
2072 Self::MarkerMismatch(_) => ServerDiscriminant::MarkerMismatch,
2073 Self::Bound(_) => ServerDiscriminant::Bound,
2074 Self::UnboundReceipt(_) => ServerDiscriminant::UnboundReceipt,
2075 Self::DetachCommitted(_) => ServerDiscriminant::DetachCommitted,
2076 Self::DetachInProgress(_) => ServerDiscriminant::DetachInProgress,
2077 Self::AckCommitted(_) => ServerDiscriminant::AckCommitted,
2078 Self::AckNoOp(_) => ServerDiscriminant::AckNoOp,
2079 Self::AckGap(_) => ServerDiscriminant::AckGap,
2080 Self::AckRegression(_) => ServerDiscriminant::AckRegression,
2081 Self::LeaveCommitted(_) => ServerDiscriminant::LeaveCommitted,
2082 Self::MarkerAckCommitted(_) => ServerDiscriminant::MarkerAckCommitted,
2083 Self::RecordCommitted(_) => ServerDiscriminant::RecordCommitted,
2084 Self::RecordTooLarge(_) => ServerDiscriminant::RecordTooLarge,
2085 Self::ObserverRecoveryAccepted(_) => ServerDiscriminant::ObserverRecoveryAccepted,
2086 Self::InvalidObserverEpoch(_) => ServerDiscriminant::InvalidObserverEpoch,
2087 Self::InvalidObserverEpochList(_) => ServerDiscriminant::InvalidObserverEpochList,
2088 Self::MarkerSettlementBackpressure(_) => {
2089 ServerDiscriminant::MarkerSettlementBackpressure
2090 }
2091 Self::EnrollmentSettlementBackpressure(_) => {
2092 ServerDiscriminant::EnrollmentSettlementBackpressure
2093 }
2094 Self::RecordAdmissionProtocolFault(_) => {
2095 ServerDiscriminant::RecordAdmissionProtocolFault
2096 }
2097 Self::WriteOutcomeUnknown(_) => ServerDiscriminant::WriteOutcomeUnknown,
2098 Self::SettlementAnswer(_) => ServerDiscriminant::SettlementAnswer,
2099 }
2100 }
2101
2102 #[must_use]
2104 #[allow(clippy::too_many_lines)]
2105 pub const fn originating_request(&self) -> Option<ClientDiscriminant> {
2106 match self {
2107 Self::ParticipantTransportRejected(_)
2108 | Self::ObserverRecoveryAccepted(_)
2109 | Self::InvalidObserverEpoch(_)
2110 | Self::InvalidObserverEpochList(_) => None,
2111 Self::AttemptTokenBodyConflict(value) => Some(match value {
2112 AttemptTokenBodyConflict::CredentialAttach { .. } => {
2113 ClientDiscriminant::CredentialAttachRequest
2114 }
2115 AttemptTokenBodyConflict::Leave { .. } => ClientDiscriminant::LeaveRequest,
2116 AttemptTokenBodyConflict::RecordAdmission { .. } => {
2117 ClientDiscriminant::RecordAdmission
2118 }
2119 }),
2120 Self::ConnectionConversationCapacityExceeded(value) => match value {
2121 ConnectionConversationCapacityExceeded::SemanticRequest { request, .. } => {
2122 Some(request.originating_request())
2123 }
2124 ConnectionConversationCapacityExceeded::ObserverRecovery { .. } => None,
2125 },
2126 Self::ConnectionConversationBindingOccupied(value) => Some(match value {
2127 ConnectionConversationBindingOccupied::Enrollment { .. } => {
2128 ClientDiscriminant::EnrollmentRequest
2129 }
2130 ConnectionConversationBindingOccupied::CredentialAttach { .. } => {
2131 ClientDiscriminant::CredentialAttachRequest
2132 }
2133 }),
2134 Self::ConversationOrderExhausted(value) => Some(match value.request() {
2135 OrderAllocatingEnvelope::Enrollment(_) => ClientDiscriminant::EnrollmentRequest,
2136 OrderAllocatingEnvelope::CredentialAttach(_) => {
2137 ClientDiscriminant::CredentialAttachRequest
2138 }
2139 OrderAllocatingEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
2140 }),
2141 Self::ParticipantUnknown(value) => Some(participant_reference_origin(&value.request)),
2142 Self::NoBinding(value) => Some(binding_required_origin(&value.request)),
2143 Self::StaleAuthority(value) => Some(stale_authority_origin(value)),
2144 Self::Retired(value) => Some(match value {
2145 Retired::Enrollment { .. } => ClientDiscriminant::EnrollmentRequest,
2146 Retired::Participant { request, .. } => participant_reference_origin(request),
2147 }),
2148 Self::MarkerClosureCapacityExceeded(value) => Some(match &value.request {
2149 ClosureCheckedEnvelope::Enrollment(_) => ClientDiscriminant::EnrollmentRequest,
2150 ClosureCheckedEnvelope::CredentialAttach(_) => {
2151 ClientDiscriminant::CredentialAttachRequest
2152 }
2153 ClosureCheckedEnvelope::Leave(_) => ClientDiscriminant::LeaveRequest,
2154 ClosureCheckedEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
2155 }),
2156 Self::EnrollBound(_)
2157 | Self::EnrollmentKnown(_)
2158 | Self::IdentityCapacityExceeded(_)
2159 | Self::EnrollmentSettlementBackpressure(_) => {
2160 Some(ClientDiscriminant::EnrollmentRequest)
2161 }
2162 Self::ReceiptExpired(value) => Some(match value {
2163 ReceiptExpired::Enrollment { .. } => ClientDiscriminant::EnrollmentRequest,
2164 ReceiptExpired::CredentialAttach { .. } => {
2165 ClientDiscriminant::CredentialAttachRequest
2166 }
2167 }),
2168 Self::ReceiptCapacityExceeded(value) => Some(match value {
2169 ReceiptCapacityExceeded::Enrollment { .. } => ClientDiscriminant::EnrollmentRequest,
2170 ReceiptCapacityExceeded::CredentialAttach { .. } => {
2171 ClientDiscriminant::CredentialAttachRequest
2172 }
2173 }),
2174 Self::ObserverBackpressure(value) => Some(match value {
2175 ObserverBackpressure::Enrollment { .. } => ClientDiscriminant::EnrollmentRequest,
2176 ObserverBackpressure::CredentialAttach { .. } => {
2177 ClientDiscriminant::CredentialAttachRequest
2178 }
2179 ObserverBackpressure::Detach { .. } => ClientDiscriminant::DetachRequest,
2180 ObserverBackpressure::Leave { .. } => ClientDiscriminant::LeaveRequest,
2181 ObserverBackpressure::RecordAdmission { .. } => ClientDiscriminant::RecordAdmission,
2182 }),
2183 Self::ConversationSequenceExhausted(value) => Some(match &value.request {
2184 SequenceAllocatingEnvelope::Enrollment(_) => ClientDiscriminant::EnrollmentRequest,
2185 SequenceAllocatingEnvelope::CredentialAttach(_) => {
2186 ClientDiscriminant::CredentialAttachRequest
2187 }
2188 SequenceAllocatingEnvelope::RecordAdmission(_) => {
2189 ClientDiscriminant::RecordAdmission
2190 }
2191 }),
2192 Self::AttachBound(_) | Self::StaleOrUnknownReceipt(_) => {
2193 Some(ClientDiscriminant::CredentialAttachRequest)
2194 }
2195 Self::MarkerNotDelivered(value) => Some(marker_proof_origin(&value.request)),
2196 Self::MarkerMismatch(value) => Some(marker_proof_origin(&value.request)),
2197 Self::Bound(value) | Self::UnboundReceipt(value) => Some(match value {
2198 ReceiptReplay::Enrollment(_) => ClientDiscriminant::EnrollmentRequest,
2199 ReceiptReplay::CredentialAttach(_) => ClientDiscriminant::CredentialAttachRequest,
2200 }),
2201 Self::DetachCommitted(_) | Self::DetachInProgress(_) => {
2202 Some(ClientDiscriminant::DetachRequest)
2203 }
2204 Self::AckCommitted(_) | Self::AckGap(_) | Self::AckRegression(_) => {
2205 Some(ClientDiscriminant::ParticipantAck)
2206 }
2207 Self::AckNoOp(value) => Some(match value {
2208 AckNoOp::ParticipantAck(_) => ClientDiscriminant::ParticipantAck,
2209 AckNoOp::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2210 }),
2211 Self::LeaveCommitted(_) => Some(ClientDiscriminant::LeaveRequest),
2212 Self::MarkerAckCommitted(_) => Some(ClientDiscriminant::MarkerAck),
2213 Self::RecordCommitted(_)
2214 | Self::RecordTooLarge(_)
2215 | Self::RecordAdmissionProtocolFault(_) => Some(ClientDiscriminant::RecordAdmission),
2216 Self::MarkerSettlementBackpressure(value) => Some(match value {
2217 MarkerSettlementBackpressure::CredentialAttach { .. } => {
2218 ClientDiscriminant::CredentialAttachRequest
2219 }
2220 MarkerSettlementBackpressure::Detach { .. } => ClientDiscriminant::DetachRequest,
2221 }),
2222 Self::SettlementAnswer(_) => Some(ClientDiscriminant::SettlementQuery),
2223 Self::WriteOutcomeUnknown(value) => Some(match value {
2224 WriteOutcomeUnknown::Enrollment { .. } => ClientDiscriminant::EnrollmentRequest,
2225 WriteOutcomeUnknown::CredentialAttach { .. } => {
2226 ClientDiscriminant::CredentialAttachRequest
2227 }
2228 WriteOutcomeUnknown::Detach { .. } => ClientDiscriminant::DetachRequest,
2229 WriteOutcomeUnknown::Leave { .. } => ClientDiscriminant::LeaveRequest,
2230 WriteOutcomeUnknown::RecordAdmission { .. } => ClientDiscriminant::RecordAdmission,
2231 }),
2232 }
2233 }
2234}
2235
2236const fn participant_reference_origin(
2237 request: &ParticipantReferenceEnvelope,
2238) -> ClientDiscriminant {
2239 match request {
2240 ParticipantReferenceEnvelope::CredentialAttach(_) => {
2241 ClientDiscriminant::CredentialAttachRequest
2242 }
2243 ParticipantReferenceEnvelope::Detach(_) => ClientDiscriminant::DetachRequest,
2244 ParticipantReferenceEnvelope::ParticipantAck(_) => ClientDiscriminant::ParticipantAck,
2245 ParticipantReferenceEnvelope::Leave(_) => ClientDiscriminant::LeaveRequest,
2246 ParticipantReferenceEnvelope::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2247 ParticipantReferenceEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
2248 }
2249}
2250
2251const fn binding_required_origin(request: &BindingRequiredEnvelope) -> ClientDiscriminant {
2252 match request {
2253 BindingRequiredEnvelope::Detach(_) => ClientDiscriminant::DetachRequest,
2254 BindingRequiredEnvelope::ParticipantAck(_) => ClientDiscriminant::ParticipantAck,
2255 BindingRequiredEnvelope::Leave(_) => ClientDiscriminant::LeaveRequest,
2256 BindingRequiredEnvelope::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2257 BindingRequiredEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
2258 }
2259}
2260
2261const fn stale_authority_origin(value: &StaleAuthority) -> ClientDiscriminant {
2262 match value {
2263 StaleAuthority::Live { request, .. } => match request {
2264 CommonStaleAuthorityEnvelope::CredentialAttach(_) => {
2265 ClientDiscriminant::CredentialAttachRequest
2266 }
2267 CommonStaleAuthorityEnvelope::ParticipantAck(_) => ClientDiscriminant::ParticipantAck,
2268 CommonStaleAuthorityEnvelope::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2269 CommonStaleAuthorityEnvelope::RecordAdmission(_) => ClientDiscriminant::RecordAdmission,
2270 },
2271 StaleAuthority::Detach(_) => ClientDiscriminant::DetachRequest,
2272 StaleAuthority::Leave(_) => ClientDiscriminant::LeaveRequest,
2273 }
2274}
2275
2276const fn marker_proof_origin(request: &MarkerProofRequest) -> ClientDiscriminant {
2277 match request {
2278 MarkerProofRequest::CredentialAttach(_) => ClientDiscriminant::CredentialAttachRequest,
2279 MarkerProofRequest::MarkerAck(_) => ClientDiscriminant::MarkerAck,
2280 }
2281}
2282
2283pub const PARTICIPANT_CAPABILITY: &str = "participant-v1";
2285
2286#[must_use]
2288pub const fn attempt_operation(value: &AttemptTokenBodyConflict) -> super::AttemptOperation {
2289 match value {
2290 AttemptTokenBodyConflict::CredentialAttach { .. } => {
2291 super::AttemptOperation::CredentialAttachRequest
2292 }
2293 AttemptTokenBodyConflict::Leave { .. } => super::AttemptOperation::LeaveRequest,
2294 AttemptTokenBodyConflict::RecordAdmission { .. } => {
2295 super::AttemptOperation::RecordAdmission
2296 }
2297 }
2298}
2299
2300#[must_use]
2302pub fn capability_string() -> String {
2303 String::from(PARTICIPANT_CAPABILITY)
2304}