Implement IDLE #72

Merged
quentin merged 9 commits from feat/idle into main 2024-01-19 14:04:04 +00:00
Showing only changes of commit 43b668531f - Show all commits

View file

@ -25,6 +25,18 @@ pub enum State {
Idle(Arc<User>, MailboxView, MailboxPerm, Tag<'static>, Arc<Notify>),
Logout,
}
impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use State::*;
match self {
NotAuthenticated => write!(f, "NotAuthenticated"),
Authenticated(..) => write!(f, "Authenticated"),
Selected(..) => write!(f, "Selected"),
Idle(..) => write!(f, "Idle"),
Logout => write!(f, "Logout"),
}
}
}
#[derive(Clone)]
pub enum MailboxPerm {
@ -41,13 +53,29 @@ pub enum Transition {
Unselect,
Logout,
}
impl fmt::Display for Transition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Transition::*;
match self {
None => write!(f, "None"),
Authenticate(..) => write!(f, "Authenticated"),
Select(..) => write!(f, "Selected"),
Idle(..) => write!(f, "Idle"),
UnIdle => write!(f, "UnIdle"),
Unselect => write!(f, "Unselect"),
Logout => write!(f, "Logout"),
}
}
}
// See RFC3501 section 3.
// https://datatracker.ietf.org/doc/html/rfc3501#page-13
impl State {
pub fn apply(&mut self, tr: Transition) -> Result<(), Error> {
let new_state = match (std::mem::replace(self, State::NotAuthenticated), tr) {
(_s, Transition::None) => return Ok(()),
tracing::debug!(state=%self, transition=%tr, "try change state");
let new_state = match (std::mem::replace(self, State::Logout), tr) {
(s, Transition::None) => s,
(State::NotAuthenticated, Transition::Authenticate(u)) => State::Authenticated(u),
(
State::Authenticated(u) | State::Selected(u, _, _),
@ -63,10 +91,13 @@ impl State {
State::Selected(u, m, p)
},
(_, Transition::Logout) => State::Logout,
_ => return Err(Error::ForbiddenTransition),
(s, t) => {
tracing::error!(state=%s, transition=%t, "forbidden transition");
return Err(Error::ForbiddenTransition)
}
};
*self = new_state;
tracing::debug!(state=%self, "transition succeeded");
Ok(())
}