#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SubscriptionState {
Idle,
Subscribing,
Active,
Done,
}
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
pub enum SubscriptionError {
#[error("invalid transition from {from:?} on event {event}")]
InvalidTransition {
from: SubscriptionState,
event: String,
},
}
pub struct SubscriptionStateMachine {
state: SubscriptionState,
}
impl Default for SubscriptionStateMachine {
fn default() -> Self {
Self::new()
}
}
impl SubscriptionStateMachine {
pub fn new() -> Self {
Self { state: SubscriptionState::Idle }
}
pub fn state(&self) -> SubscriptionState {
self.state
}
pub fn on_subscribe_sent(&mut self) -> Result<(), SubscriptionError> {
if self.state == SubscriptionState::Idle {
self.state = SubscriptionState::Subscribing;
Ok(())
} else {
Err(SubscriptionError::InvalidTransition {
from: self.state,
event: "on_subscribe_sent".to_string(),
})
}
}
pub fn on_subscribe_ok(&mut self) -> Result<(), SubscriptionError> {
if self.state == SubscriptionState::Subscribing {
self.state = SubscriptionState::Active;
Ok(())
} else {
Err(SubscriptionError::InvalidTransition {
from: self.state,
event: "on_subscribe_ok".to_string(),
})
}
}
pub fn on_subscribe_error(&mut self) -> Result<(), SubscriptionError> {
if self.state == SubscriptionState::Subscribing {
self.state = SubscriptionState::Done;
Ok(())
} else {
Err(SubscriptionError::InvalidTransition {
from: self.state,
event: "on_subscribe_error".to_string(),
})
}
}
pub fn on_unsubscribe(&mut self) -> Result<(), SubscriptionError> {
if self.state == SubscriptionState::Active {
self.state = SubscriptionState::Done;
Ok(())
} else {
Err(SubscriptionError::InvalidTransition {
from: self.state,
event: "on_unsubscribe".to_string(),
})
}
}
pub fn on_subscribe_update(&mut self) -> Result<(), SubscriptionError> {
if self.state == SubscriptionState::Active {
Ok(())
} else {
Err(SubscriptionError::InvalidTransition {
from: self.state,
event: "on_subscribe_update".to_string(),
})
}
}
pub fn on_publish_done(&mut self) -> Result<(), SubscriptionError> {
if self.state == SubscriptionState::Active {
self.state = SubscriptionState::Done;
Ok(())
} else {
Err(SubscriptionError::InvalidTransition {
from: self.state,
event: "on_publish_done".to_string(),
})
}
}
}