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}