Skip to main content

io_imap/
coroutine.rs

1//! Generator-shape coroutine contract, mirroring `core::ops::Coroutine`.
2//!
3//! `Yield` covers intermediate progress, `Return` the terminal output,
4//! [`ImapCoroutineState`] both.
5
6use alloc::vec::Vec;
7
8use imap_codec::fragmentizer::Fragmentizer;
9
10/// Result of one [`ImapCoroutine::resume`] step.
11#[derive(Debug)]
12pub enum ImapCoroutineState<Y, R> {
13    /// The coroutine needs I/O (or emitted an event) before it can
14    /// progress.
15    Yielded(Y),
16    /// The coroutine is done; resuming it again is a logic error.
17    Complete(R),
18}
19
20/// An I/O-free IMAP coroutine, resumed with the connection-wide
21/// `Fragmentizer` and the bytes read by the caller.
22pub trait ImapCoroutine {
23    /// The request type yielded while the coroutine progresses.
24    type Yield;
25
26    /// The final value produced on completion.
27    type Return;
28
29    /// Pass `None` initially or after a `WantsWrite`, `Some(bytes)`
30    /// after a `WantsRead`, `Some(&[])` on EOF.
31    fn resume(
32        &mut self,
33        fragmentizer: &mut Fragmentizer,
34        arg: Option<&[u8]>,
35    ) -> ImapCoroutineState<Self::Yield, Self::Return>;
36}
37
38/// Standard socket-I/O yield variants; pick another type when extra
39/// variants (events, etc.) are needed.
40#[derive(Debug)]
41pub enum ImapYield {
42    /// The caller reads from its stream and resumes with the bytes.
43    WantsRead,
44    /// The caller writes the given bytes to its stream and resumes.
45    WantsWrite(Vec<u8>),
46}
47
48/// Coroutine `?`: forwards `Yielded` (via `Into`), short-circuits on
49/// `Err`, evaluates to the inner `Ok` value.
50#[macro_export]
51macro_rules! imap_try {
52    ($coroutine:expr, $frag:expr, $arg:expr $(,)?) => {
53        match $crate::coroutine::ImapCoroutine::resume($coroutine, $frag, $arg) {
54            $crate::coroutine::ImapCoroutineState::Yielded(y) => {
55                return $crate::coroutine::ImapCoroutineState::Yielded(y.into());
56            }
57            $crate::coroutine::ImapCoroutineState::Complete(Err(err)) => {
58                return $crate::coroutine::ImapCoroutineState::Complete(Err(err.into()));
59            }
60            $crate::coroutine::ImapCoroutineState::Complete(Ok(value)) => value,
61        }
62    };
63}