Skip to main content

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}