io_webdav/coroutine.rs
1//! Generator-shape coroutine driver. Mirrors `core::ops::Coroutine`: a `Yield`
2//! associated type for intermediate progress, a `Return` for terminal output,
3//! and a two-variant [`WebdavCoroutineState`].
4//!
5//! Most coroutines pick the standard [`WebdavYield`] (I/O-only); redirect-aware
6//! ones declare their own (e.g. [`WebdavRedirectYield`]).
7//!
8//! [`WebdavRedirectYield`]: crate::rfc4918::coroutine::WebdavRedirectYield
9
10use alloc::vec::Vec;
11
12/// State yielded by a [`WebdavCoroutine::resume`] step.
13#[derive(Debug)]
14pub enum WebdavCoroutineState<Y, R> {
15 /// Intermediate yield: the driver reacts and resumes.
16 Yielded(Y),
17 /// Terminal yield. By convention `R = Result<Output, Error>`.
18 Complete(R),
19}
20
21/// Standard-shape WebDAV coroutine.
22pub trait WebdavCoroutine {
23 /// Intermediate value handed back on every step.
24 type Yield;
25 /// Terminal value. By convention `Result<Output, Error>`.
26 type Return;
27
28 /// Advances the coroutine one step.
29 ///
30 /// Pass [`None`] on the initial call or after a
31 /// [`WebdavYield::WantsWrite`]. Pass `Some(data)` after a
32 /// [`WebdavYield::WantsRead`]; `Some(&[])` signals EOF.
33 fn resume(&mut self, arg: Option<&[u8]>) -> WebdavCoroutineState<Self::Yield, Self::Return>;
34}
35
36/// Standard I/O-only Yield for coroutines that only read/write socket bytes.
37#[derive(Debug)]
38pub enum WebdavYield {
39 /// Driver should read more bytes and feed them back on the next resume.
40 WantsRead,
41 /// Driver should write these bytes; the next resume typically takes `None`.
42 WantsWrite(Vec<u8>),
43}
44
45/// Coroutine `?`: forwards `Yielded` (via `Into`), short-circuits on `Err` (via
46/// `Into`), evaluates to the inner `Ok` value.
47#[macro_export]
48macro_rules! webdav_try {
49 ($coroutine:expr, $arg:expr $(,)?) => {
50 match $crate::coroutine::WebdavCoroutine::resume($coroutine, $arg) {
51 $crate::coroutine::WebdavCoroutineState::Yielded(y) => {
52 return $crate::coroutine::WebdavCoroutineState::Yielded(y.into());
53 }
54 $crate::coroutine::WebdavCoroutineState::Complete(Err(err)) => {
55 return $crate::coroutine::WebdavCoroutineState::Complete(Err(err.into()));
56 }
57 $crate::coroutine::WebdavCoroutineState::Complete(Ok(value)) => value,
58 }
59 };
60}