pipe_io/emit.rs
1//! The [`Emit`] trait and its error type.
2//!
3//! Stages receive a `&mut dyn Emit<Item = Output>` from the driver and
4//! emit zero or more outputs per input. Backpressure surfaces through
5//! [`EmitError`]: drivers either block until space is available
6//! ([`crate::driver::ThreadedDriver`]) or return
7//! [`EmitError::WouldBlock`] for the caller to retry
8//! ([`crate::driver::SyncDriver`]).
9
10use core::fmt;
11
12/// Errors returned by [`Emit::emit`].
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum EmitError {
15 /// The downstream is closed and will not accept further items.
16 /// Stages should stop emitting and return cleanly from `process`.
17 Closed,
18 /// The downstream buffer is currently full; the caller should
19 /// retry later. Only returned by drivers that do not block on
20 /// backpressure.
21 WouldBlock,
22}
23
24impl fmt::Display for EmitError {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 match self {
27 Self::Closed => f.write_str("downstream closed"),
28 Self::WouldBlock => f.write_str("downstream would block"),
29 }
30 }
31}
32
33#[cfg(feature = "std")]
34impl std::error::Error for EmitError {}
35
36/// Object-safe handle to push items downstream from inside
37/// [`crate::Stage::process`].
38pub trait Emit {
39 /// The type of item this handle accepts.
40 type Item;
41 /// Push one item downstream.
42 ///
43 /// # Errors
44 ///
45 /// Returns [`EmitError::Closed`] when the downstream has shut down
46 /// (often because a later stage produced an error and the driver
47 /// is unwinding). Returns [`EmitError::WouldBlock`] under a
48 /// non-blocking driver if the downstream buffer is full.
49 fn emit(&mut self, item: Self::Item) -> Result<(), EmitError>;
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use alloc::string::ToString;
56
57 #[test]
58 fn emit_error_display() {
59 assert_eq!(EmitError::Closed.to_string(), "downstream closed");
60 assert_eq!(EmitError::WouldBlock.to_string(), "downstream would block");
61 }
62}