zencodec_io/
destination.rs1use std::io::{self, Seek, SeekFrom, Write};
4
5mod sealed {
6 pub trait Sealed {}
7}
8pub trait Destination: Write + sealed::Sealed {
11 fn can_patch(&self) -> bool;
13 fn position(&mut self, relative: u64) -> io::Result<()>;
15}
16
17pub struct Forward<W>(pub W);
19impl<W> sealed::Sealed for Forward<W> {}
20impl<W: Write> Write for Forward<W> {
21 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
22 self.0.write(bytes)
23 }
24 fn flush(&mut self) -> io::Result<()> {
25 self.0.flush()
26 }
27}
28impl<W: Write> Destination for Forward<W> {
29 fn can_patch(&self) -> bool {
30 false
31 }
32 fn position(&mut self, _: u64) -> io::Result<()> {
33 Err(io::ErrorKind::Unsupported.into())
34 }
35}
36
37pub struct SeekBack<W> {
40 writer: W,
41 start: u64,
42}
43impl<W> sealed::Sealed for SeekBack<W> {}
44impl<W: Write + Seek> SeekBack<W> {
45 pub fn new(mut writer: W) -> io::Result<Self> {
47 let start = writer.stream_position()?;
48 Ok(Self { writer, start })
49 }
50}
51impl<W: Write> Write for SeekBack<W> {
52 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
53 self.writer.write(bytes)
54 }
55 fn flush(&mut self) -> io::Result<()> {
56 self.writer.flush()
57 }
58}
59impl<W: Write + Seek> Destination for SeekBack<W> {
60 fn can_patch(&self) -> bool {
61 true
62 }
63 fn position(&mut self, relative: u64) -> io::Result<()> {
64 let absolute = self
65 .start
66 .checked_add(relative)
67 .ok_or(io::ErrorKind::InvalidInput)?;
68 let actual = self.writer.seek(SeekFrom::Start(absolute))?;
69 if actual != absolute {
70 return Err(io::Error::from(io::ErrorKind::InvalidData));
71 }
72 Ok(())
73 }
74}