Skip to main content

io_http/
coroutine.rs

1//! Generator-shape coroutine driver mirroring `core::ops::Coroutine`:
2//! `Yield` associated type for intermediate progress, `Return` for
3//! terminal output, and a two-variant [`HttpCoroutineState`]
4//! (`Yielded` / `Complete`).
5
6use alloc::vec::Vec;
7
8/// State yielded by an [`HttpCoroutine::resume`] step.
9#[derive(Debug)]
10pub enum HttpCoroutineState<Y, R> {
11    Yielded(Y),
12    Complete(R),
13}
14
15/// Standard-shape HTTP coroutine: own internal state, declare per-step
16/// `Yield`, return `Result<Output, Error>` on completion.
17pub trait HttpCoroutine {
18    type Yield;
19    type Return;
20
21    /// Advances one step. Pass [`None`] initially or after [`HttpYield::WantsWrite`];
22    /// pass `Some(data)` after [`HttpYield::WantsRead`]; pass `Some(&[])` for EOF.
23    fn resume(&mut self, arg: Option<&[u8]>) -> HttpCoroutineState<Self::Yield, Self::Return>;
24}
25
26/// Standard I/O-only Yield; pick `type Yield = HttpYield` when the
27/// coroutine only reads or writes socket bytes.
28#[derive(Debug)]
29pub enum HttpYield {
30    WantsRead,
31    WantsWrite(Vec<u8>),
32}
33
34/// Coroutine `?`: forwards `Yielded` (via `Into`), short-circuits on
35/// `Err` (via `Into`), evaluates to the inner `Ok` value.
36#[macro_export]
37macro_rules! http_try {
38    ($coroutine:expr, $arg:expr $(,)?) => {
39        match $crate::coroutine::HttpCoroutine::resume($coroutine, $arg) {
40            $crate::coroutine::HttpCoroutineState::Yielded(y) => {
41                return $crate::coroutine::HttpCoroutineState::Yielded(y.into());
42            }
43            $crate::coroutine::HttpCoroutineState::Complete(Err(err)) => {
44                return $crate::coroutine::HttpCoroutineState::Complete(Err(err.into()));
45            }
46            $crate::coroutine::HttpCoroutineState::Complete(Ok(value)) => value,
47        }
48    };
49}