protoflow_blocks/blocks/sys/
write_stdout.rs

1// This is free and unencumbered software released into the public domain.
2
3extern crate std;
4
5use crate::{prelude::Bytes, StdioConfig, StdioError, StdioSystem, System};
6use protoflow_core::{Block, BlockResult, BlockRuntime, InputPort};
7use protoflow_derive::Block;
8use simple_mermaid::mermaid;
9
10/// A block that writes bytes to standard output (aka stdout).
11///
12/// # Block Diagram
13#[doc = mermaid!("../../../doc/sys/write_stdout.mmd")]
14///
15/// # Sequence Diagram
16#[doc = mermaid!("../../../doc/sys/write_stdout.seq.mmd" framed)]
17///
18/// # Examples
19///
20/// ## Using the block in a system
21///
22/// ```rust
23/// # use protoflow_blocks::*;
24/// # fn main() {
25/// System::build(|s| {
26///     let stdin = s.read_stdin();
27///     let stdout = s.write_stdout();
28///     s.connect(&stdin.output, &stdout.input);
29/// });
30/// # }
31/// ```
32///
33/// ## Running the block via the CLI
34///
35/// ```console
36/// $ protoflow execute WriteStdout < input.txt > output.txt
37/// ```
38///
39#[derive(Block, Clone)]
40pub struct WriteStdout {
41    /// The input message stream.
42    #[input]
43    pub input: InputPort<Bytes>,
44}
45
46impl WriteStdout {
47    pub fn new(input: InputPort<Bytes>) -> Self {
48        Self { input }
49    }
50
51    pub fn with_system(system: &System) -> Self {
52        use crate::SystemBuilding;
53        Self::new(system.input())
54    }
55}
56
57impl Block for WriteStdout {
58    fn execute(&mut self, runtime: &dyn BlockRuntime) -> BlockResult {
59        let mut stdout = std::io::stdout().lock();
60
61        runtime.wait_for(&self.input)?;
62
63        while let Some(message) = self.input.recv()? {
64            std::io::Write::write_all(&mut stdout, &message)?;
65        }
66
67        Ok(())
68    }
69}
70
71#[cfg(feature = "std")]
72impl StdioSystem for WriteStdout {
73    fn build_system(config: StdioConfig) -> Result<System, StdioError> {
74        use crate::SystemBuilding;
75
76        config.reject_any()?;
77
78        Ok(System::build(|s| {
79            let stdin = config.read_stdin(s);
80            let stdout = config.write_stdout(s);
81            s.connect(&stdin.output, &stdout.input);
82        }))
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::WriteStdout;
89    use crate::{System, SystemBuilding};
90
91    #[test]
92    fn instantiate_block() {
93        // Check that the block is constructible:
94        let _ = System::build(|s| {
95            let _ = s.block(WriteStdout::new(s.input()));
96        });
97    }
98}