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