#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SessionState {
Connecting,
SetupExchange,
Active,
Draining,
Closed,
}
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
pub enum SessionError {
#[error("invalid state transition from {from:?} to {to:?}")]
InvalidTransition {
from: SessionState,
to: SessionState,
},
}
pub struct SessionStateMachine {
state: SessionState,
}
impl Default for SessionStateMachine {
fn default() -> Self {
Self::new()
}
}
impl SessionStateMachine {
pub fn new() -> Self {
Self { state: SessionState::Connecting }
}
pub fn state(&self) -> SessionState {
self.state
}
pub fn on_connect(&mut self) -> Result<(), SessionError> {
if self.state == SessionState::Connecting {
self.state = SessionState::SetupExchange;
Ok(())
} else {
Err(SessionError::InvalidTransition {
from: self.state,
to: SessionState::SetupExchange,
})
}
}
pub fn on_setup_complete(&mut self) -> Result<(), SessionError> {
if self.state == SessionState::SetupExchange {
self.state = SessionState::Active;
Ok(())
} else {
Err(SessionError::InvalidTransition { from: self.state, to: SessionState::Active })
}
}
pub fn on_goaway(&mut self) -> Result<(), SessionError> {
if self.state == SessionState::Active {
self.state = SessionState::Draining;
Ok(())
} else {
Err(SessionError::InvalidTransition { from: self.state, to: SessionState::Draining })
}
}
pub fn on_close(&mut self) -> Result<(), SessionError> {
if self.state == SessionState::Active || self.state == SessionState::Draining {
self.state = SessionState::Closed;
Ok(())
} else {
Err(SessionError::InvalidTransition { from: self.state, to: SessionState::Closed })
}
}
}