Skip to main content

io_msgraph/
coroutine.rs

1//! Coroutine contract: the `MsgraphCoroutine` trait, its `MsgraphYield` /
2//! `MsgraphCoroutineState`, and the `msgraph_try!` macro (the coroutine
3//! equivalent of `?`).
4
5use alloc::vec::Vec;
6
7/// State returned by every [`MsgraphCoroutine::resume`] call: either an
8/// I/O request to fulfil, or the coroutine's final value.
9#[derive(Debug)]
10pub enum MsgraphCoroutineState<Y, R> {
11    /// The coroutine needs I/O before it can progress.
12    Yielded(Y),
13    /// The coroutine is done; resuming it again is a logic error.
14    Complete(R),
15}
16
17/// An I/O-free Microsoft Graph coroutine, resumed with the bytes read
18/// by the caller (or `None` when there is nothing to feed back).
19pub trait MsgraphCoroutine {
20    /// The I/O request type yielded while the coroutine progresses.
21    type Yield;
22
23    /// The final value produced on completion.
24    type Return;
25
26    /// Advances the coroutine with the outcome of the previous yield.
27    fn resume(&mut self, arg: Option<&[u8]>) -> MsgraphCoroutineState<Self::Yield, Self::Return>;
28}
29
30/// I/O request yielded by a Microsoft Graph coroutine: a Graph call is
31/// I/O-only, so reading and writing bytes are the only requests.
32#[derive(Debug)]
33pub enum MsgraphYield {
34    /// The caller reads from its stream and resumes with the bytes.
35    WantsRead,
36    /// The caller writes the given bytes to its stream and resumes.
37    WantsWrite(Vec<u8>),
38}
39
40/// Coroutine equivalent of `?`: forwards a `Yielded` state and
41/// short-circuits a `Complete(Err(_))`, unwrapping a `Complete(Ok(_))`.
42#[macro_export]
43macro_rules! msgraph_try {
44    ($coroutine:expr, $arg:expr $(,)?) => {
45        match $crate::coroutine::MsgraphCoroutine::resume($coroutine, $arg) {
46            $crate::coroutine::MsgraphCoroutineState::Yielded(y) => {
47                return $crate::coroutine::MsgraphCoroutineState::Yielded(y.into());
48            }
49            $crate::coroutine::MsgraphCoroutineState::Complete(Err(err)) => {
50                log::trace!("error during coroutine execution: {err}");
51                return $crate::coroutine::MsgraphCoroutineState::Complete(Err(err.into()));
52            }
53            $crate::coroutine::MsgraphCoroutineState::Complete(Ok(value)) => value,
54        }
55    };
56}