factorio_blueprint/
version_prefix.rs

1use std::io::prelude::*;
2
3struct VersionPrefix<W> {
4    version: u8,
5    has_seen_version: bool,
6    wrapped: W,
7}
8
9impl<W> VersionPrefix<W> {
10    fn new(version: char, wrapped: W) -> Self {
11        VersionPrefix {
12            version: version as u8,
13            has_seen_version: false,
14            wrapped,
15        }
16    }
17}
18
19pub struct VersionPrefixWriter<W>(VersionPrefix<W>);
20
21impl<W> VersionPrefixWriter<W>
22where
23    W: Write,
24{
25    pub fn new(version: char, wrapped: W) -> VersionPrefixWriter<W> {
26        VersionPrefixWriter(VersionPrefix::new(version, wrapped))
27    }
28}
29
30impl<W> Write for VersionPrefixWriter<W>
31where
32    W: Write,
33{
34    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
35        if self.0.has_seen_version {
36            self.0.wrapped.write(buf)
37        } else {
38            self.0.has_seen_version = true;
39            let mut new_buf = vec![0; buf.len() + 1];
40            new_buf[0] = self.0.version;
41            (&mut new_buf[1..]).copy_from_slice(buf);
42            self.0.wrapped.write(&new_buf).map(|n| n - 1)
43        }
44    }
45
46    fn flush(&mut self) -> std::io::Result<()> {
47        self.0.wrapped.flush()
48    }
49}
50
51pub struct VersionPrefixReader<R>(VersionPrefix<R>, Option<u8>);
52
53impl<R> VersionPrefixReader<R>
54where
55    R: Read,
56{
57    pub fn new(version: char, wrapped: R) -> VersionPrefixReader<R> {
58        VersionPrefixReader(VersionPrefix::new(version, wrapped), None)
59    }
60
61    /// return `None` when no bytes have been read, or the truth value
62    /// of the statement "the first byte read matched the expected version".
63    pub fn had_expected_version(&self) -> Option<bool> {
64        self.1.map(|found| found == self.0.version)
65    }
66}
67
68impl<R> Read for VersionPrefixReader<R>
69where
70    R: Read,
71{
72    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
73        if !self.0.has_seen_version {
74            self.0.has_seen_version = true;
75            let mut head_buf = vec![0];
76            self.0.wrapped.read_exact(&mut head_buf)?;
77            self.1 = Some(head_buf[0]);
78        }
79        self.0.wrapped.read(buf)
80    }
81}