blocks_iterator/
pipe.rs

1use crate::bitcoin::consensus::{Decodable, Encodable};
2use crate::BlockExtra;
3use std::io;
4use std::io::Write;
5
6const MAX_BLOCK_EXTRA_SIZE: usize = 10 * 1024 * 1024;
7
8/// Iterator to use un Unix-style pipe composition when receiving BlockExtra from stdin and
9/// optionally propogating those to stdout
10pub struct PipeIterator {
11    stdin: io::Stdin, // from docs, stdin is buffered, non need to wrap in BufReader
12    stdout: Option<io::Stdout>,
13    buffer: Vec<u8>,
14}
15
16impl PipeIterator {
17    /// Creates new PipeIterator from stdin and stdout
18    pub fn new(stdin: io::Stdin, stdout: Option<io::Stdout>) -> Self {
19        let buffer = if stdout.is_some() {
20            vec![0u8; MAX_BLOCK_EXTRA_SIZE]
21        } else {
22            Vec::new()
23        };
24        PipeIterator {
25            stdin,
26            stdout,
27            buffer,
28        }
29    }
30}
31
32impl Iterator for PipeIterator {
33    type Item = BlockExtra;
34
35    fn next(&mut self) -> Option<Self::Item> {
36        let block_extra = BlockExtra::consensus_decode(&mut self.stdin).ok()?;
37
38        if let Some(stdout) = self.stdout.as_mut() {
39            // using StreamReader we can't send received bytes directly to stdout, thus we need to
40            // re-serialize back
41            let len = block_extra
42                .consensus_encode(&mut &mut self.buffer[..])
43                .unwrap(); // buffer is big enough, we can unwrap
44            stdout.write_all(&self.buffer[..len]).unwrap();
45        }
46
47        Some(block_extra)
48    }
49}