imap_client/tasks/
resolver.rsuse imap_next::{
client::Client as ClientNext,
imap_types::response::{Response, Status},
Interrupt, State,
};
use tracing::{debug, warn};
use super::{Scheduler, SchedulerError, SchedulerEvent, Task, TaskHandle};
pub struct Resolver {
pub scheduler: Scheduler,
}
impl Resolver {
pub fn new(client_next: ClientNext) -> Self {
Self {
scheduler: Scheduler::new(client_next),
}
}
pub fn resolve<T: Task>(&mut self, task: T) -> ResolvingTask<T> {
let handle = self.scheduler.enqueue_task(task);
ResolvingTask {
resolver: self,
handle,
}
}
}
impl State for Resolver {
type Event = SchedulerEvent;
type Error = SchedulerError;
fn enqueue_input(&mut self, bytes: &[u8]) {
self.scheduler.enqueue_input(bytes);
}
fn next(&mut self) -> Result<Self::Event, Interrupt<Self::Error>> {
self.scheduler.progress()
}
}
pub struct ResolvingTask<'a, T: Task> {
resolver: &'a mut Resolver,
handle: TaskHandle<T>,
}
impl<T: Task> State for ResolvingTask<'_, T> {
type Event = T::Output;
type Error = SchedulerError;
fn enqueue_input(&mut self, bytes: &[u8]) {
self.resolver.enqueue_input(bytes);
}
fn next(&mut self) -> Result<Self::Event, Interrupt<Self::Error>> {
loop {
match self.resolver.next()? {
SchedulerEvent::GreetingReceived(greeting) => {
debug!("received greeting: {greeting:?}");
}
SchedulerEvent::TaskFinished(mut token) => {
if let Some(output) = self.handle.resolve(&mut token) {
break Ok(output);
} else {
warn!(?token, "received unexpected task token")
}
}
SchedulerEvent::Unsolicited(unsolicited) => {
if let Response::Status(Status::Bye(bye)) = unsolicited {
let err = SchedulerError::UnexpectedByeResponse(bye);
break Err(Interrupt::Error(err));
} else {
warn!(?unsolicited, "received unsolicited");
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use static_assertions::assert_impl_all;
use super::Resolver;
assert_impl_all!(Resolver: Send);
}