use crate::wire::{
BindingEpoch, ConversationId, DeliverySeq, DetachAttemptToken, DetachedCause, Generation,
LeaveCommitted, ParticipantId, TransactionOrder,
};
use super::{
AttachCommit, CommittedDetachTransition, EnrollmentCommit, NonzeroParticipantAckCommit,
OrdinaryBindingFate, RecoveredBindingFate, RetiredIdentity,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct EnrolledOperation {
conversation_id: ConversationId,
participant_id: ParticipantId,
binding_epoch: BindingEpoch,
attached_transaction_order: TransactionOrder,
attached_delivery_seq: DeliverySeq,
}
impl EnrolledOperation {
#[must_use]
pub const fn new<F>(commit: &EnrollmentCommit<F>) -> Self {
let attached = commit.attached;
Self {
conversation_id: attached.conversation_id(),
participant_id: attached.participant_id(),
binding_epoch: attached.binding_epoch(),
attached_transaction_order: attached.admission_order().transaction_order(),
attached_delivery_seq: attached.delivery_seq(),
}
}
pub(super) fn from_decoded(
conversation_id: ConversationId,
participant_id: ParticipantId,
binding_epoch: BindingEpoch,
attached_transaction_order: TransactionOrder,
attached_delivery_seq: DeliverySeq,
) -> Option<Self> {
if binding_epoch.capability_generation != Generation::ONE {
return None;
}
Some(Self {
conversation_id,
participant_id,
binding_epoch,
attached_transaction_order,
attached_delivery_seq,
})
}
#[must_use]
pub const fn conversation_id(self) -> ConversationId {
self.conversation_id
}
#[must_use]
pub const fn participant_id(self) -> ParticipantId {
self.participant_id
}
#[must_use]
pub const fn binding_epoch(self) -> BindingEpoch {
self.binding_epoch
}
#[must_use]
pub const fn attached_transaction_order(self) -> TransactionOrder {
self.attached_transaction_order
}
#[must_use]
pub const fn attached_delivery_seq(self) -> DeliverySeq {
self.attached_delivery_seq
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct AttachedOperation {
conversation_id: ConversationId,
participant_id: ParticipantId,
binding_epoch: BindingEpoch,
attached_transaction_order: TransactionOrder,
attached_delivery_seq: DeliverySeq,
}
impl AttachedOperation {
#[must_use]
pub const fn new<F, V>(commit: &AttachCommit<F, V>) -> Self {
let attached = commit.attached;
Self {
conversation_id: attached.conversation_id(),
participant_id: attached.participant_id(),
binding_epoch: attached.binding_epoch(),
attached_transaction_order: attached.admission_order().transaction_order(),
attached_delivery_seq: attached.delivery_seq(),
}
}
pub(super) fn from_decoded(
conversation_id: ConversationId,
participant_id: ParticipantId,
binding_epoch: BindingEpoch,
attached_transaction_order: TransactionOrder,
attached_delivery_seq: DeliverySeq,
) -> Option<Self> {
if binding_epoch.capability_generation == Generation::ONE {
return None;
}
Some(Self {
conversation_id,
participant_id,
binding_epoch,
attached_transaction_order,
attached_delivery_seq,
})
}
#[must_use]
pub const fn conversation_id(self) -> ConversationId {
self.conversation_id
}
#[must_use]
pub const fn participant_id(self) -> ParticipantId {
self.participant_id
}
#[must_use]
pub const fn binding_epoch(self) -> BindingEpoch {
self.binding_epoch
}
#[must_use]
pub const fn attached_transaction_order(self) -> TransactionOrder {
self.attached_transaction_order
}
#[must_use]
pub const fn attached_delivery_seq(self) -> DeliverySeq {
self.attached_delivery_seq
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DetachedOperation {
detach_attempt_token: DetachAttemptToken,
conversation_id: ConversationId,
participant_id: ParticipantId,
committed_binding_epoch: BindingEpoch,
detached_transaction_order: TransactionOrder,
detached_delivery_seq: DeliverySeq,
}
impl DetachedOperation {
#[must_use]
pub fn new<EF, V>(transition: &CommittedDetachTransition<EF, V>) -> Option<Self> {
let terminal = transition.terminal();
let cell = transition.cell();
if terminal.cause() != DetachedCause::CleanDeregister {
return None;
}
let participant_matches = cell.participant_id() == terminal.participant_id();
let epoch_matches = cell.committed_binding_epoch() == terminal.binding_epoch();
let delivery_matches = cell.detached_delivery_seq() == terminal.delivery_seq();
if !(participant_matches && epoch_matches && delivery_matches) {
return None;
}
Some(Self {
detach_attempt_token: cell.token(),
conversation_id: terminal.conversation_id(),
participant_id: terminal.participant_id(),
committed_binding_epoch: terminal.binding_epoch(),
detached_transaction_order: terminal.admission_order().transaction_order(),
detached_delivery_seq: terminal.delivery_seq(),
})
}
pub(super) const fn from_decoded(
detach_attempt_token: DetachAttemptToken,
conversation_id: ConversationId,
participant_id: ParticipantId,
committed_binding_epoch: BindingEpoch,
detached_transaction_order: TransactionOrder,
detached_delivery_seq: DeliverySeq,
) -> Self {
Self {
detach_attempt_token,
conversation_id,
participant_id,
committed_binding_epoch,
detached_transaction_order,
detached_delivery_seq,
}
}
#[must_use]
pub const fn detach_attempt_token(self) -> DetachAttemptToken {
self.detach_attempt_token
}
#[must_use]
pub const fn conversation_id(self) -> ConversationId {
self.conversation_id
}
#[must_use]
pub const fn participant_id(self) -> ParticipantId {
self.participant_id
}
#[must_use]
pub const fn committed_binding_epoch(self) -> BindingEpoch {
self.committed_binding_epoch
}
#[must_use]
pub const fn detached_transaction_order(self) -> TransactionOrder {
self.detached_transaction_order
}
#[must_use]
pub const fn detached_delivery_seq(self) -> DeliverySeq {
self.detached_delivery_seq
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LeftOperation {
committed: LeaveCommitted,
left_transaction_order: TransactionOrder,
}
impl LeftOperation {
#[must_use]
pub fn new<EF, V, LF>(retired: &RetiredIdentity<EF, V, LF>) -> Self {
Self {
committed: retired.committed_result().clone(),
left_transaction_order: retired.left_admission_order().transaction_order(),
}
}
pub(super) const fn from_decoded(
committed: LeaveCommitted,
left_transaction_order: TransactionOrder,
) -> Self {
Self {
committed,
left_transaction_order,
}
}
#[must_use]
pub const fn committed(&self) -> &LeaveCommitted {
&self.committed
}
#[must_use]
pub const fn left_transaction_order(&self) -> TransactionOrder {
self.left_transaction_order
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct BindingFateOperation {
conversation_id: ConversationId,
participant_id: ParticipantId,
last_dead_binding_epoch: BindingEpoch,
resulting_floor: DeliverySeq,
}
impl BindingFateOperation {
#[must_use]
pub const fn from_ordinary(fate: &OrdinaryBindingFate) -> Self {
Self {
conversation_id: fate.conversation_id(),
participant_id: fate.participant_id(),
last_dead_binding_epoch: fate.last_dead_binding_epoch(),
resulting_floor: fate.resulting_floor(),
}
}
#[must_use]
pub const fn from_recovered(fate: &RecoveredBindingFate) -> Self {
Self {
conversation_id: fate.conversation_id(),
participant_id: fate.participant_id(),
last_dead_binding_epoch: fate.last_dead_binding_epoch(),
resulting_floor: fate.resulting_floor(),
}
}
pub(super) const fn from_decoded(
conversation_id: ConversationId,
participant_id: ParticipantId,
last_dead_binding_epoch: BindingEpoch,
resulting_floor: DeliverySeq,
) -> Self {
Self {
conversation_id,
participant_id,
last_dead_binding_epoch,
resulting_floor,
}
}
#[must_use]
pub const fn conversation_id(self) -> ConversationId {
self.conversation_id
}
#[must_use]
pub const fn participant_id(self) -> ParticipantId {
self.participant_id
}
#[must_use]
pub const fn last_dead_binding_epoch(self) -> BindingEpoch {
self.last_dead_binding_epoch
}
#[must_use]
pub const fn resulting_floor(self) -> DeliverySeq {
self.resulting_floor
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct NonzeroDebtAckOperation {
conversation_id: ConversationId,
participant_id: ParticipantId,
capability_generation: Generation,
through_seq: DeliverySeq,
}
impl NonzeroDebtAckOperation {
#[must_use]
pub const fn new(commit: &NonzeroParticipantAckCommit) -> Self {
let request = commit.outcome().request();
Self {
conversation_id: request.conversation_id,
participant_id: request.participant_id,
capability_generation: request.capability_generation,
through_seq: request.through_seq,
}
}
pub(super) const fn from_decoded(
conversation_id: ConversationId,
participant_id: ParticipantId,
capability_generation: Generation,
through_seq: DeliverySeq,
) -> Self {
Self {
conversation_id,
participant_id,
capability_generation,
through_seq,
}
}
#[must_use]
pub const fn conversation_id(self) -> ConversationId {
self.conversation_id
}
#[must_use]
pub const fn participant_id(self) -> ParticipantId {
self.participant_id
}
#[must_use]
pub const fn capability_generation(self) -> Generation {
self.capability_generation
}
#[must_use]
pub const fn through_seq(self) -> DeliverySeq {
self.through_seq
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ConversationOperation {
Enrolled(EnrolledOperation),
Attached(AttachedOperation),
Detached(DetachedOperation),
Left(LeftOperation),
BindingFate(BindingFateOperation),
NonzeroDebtAck(NonzeroDebtAckOperation),
}
impl ConversationOperation {
pub(super) const fn conversation_id(&self) -> ConversationId {
match self {
Self::Enrolled(operation) => operation.conversation_id(),
Self::Attached(operation) => operation.conversation_id(),
Self::Detached(operation) => operation.conversation_id(),
Self::Left(operation) => operation.committed().conversation_id(),
Self::BindingFate(operation) => operation.conversation_id(),
Self::NonzeroDebtAck(operation) => operation.conversation_id(),
}
}
}