zopfli/
io.rs

1use alloc::vec::Vec;
2use core::{
3    cmp, fmt,
4    fmt::{Display, Formatter},
5    mem,
6};
7
8/// A trait for objects which are byte-oriented sinks, modeled after its
9/// `std::io::Write` counterpart.
10///
11/// The documentation for this trait is taken from the aforementioned `std` trait.
12pub trait Write {
13    /// Write a buffer into this writer, returning how many bytes were written.
14    ///
15    /// This function will attempt to write the entire contents of `buf`, but
16    /// the entire write might not succeed, or the write may also generate an
17    /// error. A call to `write` represents *at most one* attempt to write to
18    /// any wrapped object.
19    ///
20    /// Calls to `write` are not guaranteed to block waiting for data to be
21    /// written, and a write which would otherwise block can be indicated through
22    /// an [`Err`] variant.
23    ///
24    /// If the return value is `Ok(n)` then it must be guaranteed that
25    /// `n <= buf.len()`. A return value of `0` typically means that the
26    /// underlying object is no longer able to accept bytes and will likely not
27    /// be able to in the future as well, or that the buffer provided is empty.
28    ///
29    /// # Errors
30    ///
31    /// Each call to `write` may generate an I/O error indicating that the
32    /// operation could not be completed. If an error is returned then no bytes
33    /// in the buffer were written to this writer.
34    ///
35    /// It is **not** considered an error if the entire buffer could not be
36    /// written to this writer.
37    ///
38    /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the
39    /// write operation should be retried if there is nothing else to do.
40    fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
41
42    /// Flush this output stream, ensuring that all intermediately buffered
43    /// contents reach their destination.
44    ///
45    /// # Errors
46    ///
47    /// It is considered an error if not all bytes could be written due to
48    /// I/O errors or EOF being reached.
49    fn flush(&mut self) -> Result<(), Error>;
50
51    /// Attempts to write an entire buffer into this writer.
52    ///
53    /// This method will continuously call [`write`] until there is no more data
54    /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
55    /// returned. This method will not return until the entire buffer has been
56    /// successfully written or such an error occurs. The first error that is
57    /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
58    /// returned.
59    ///
60    /// If the buffer contains no data, this will never call [`write`].
61    ///
62    /// # Errors
63    ///
64    /// This function will return the first error of
65    /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns.
66    ///
67    /// [`write`]: Write::write
68    // Implementation taken from Rust's stdlib
69    fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Error> {
70        while !buf.is_empty() {
71            match self.write(buf) {
72                Ok(0) => {
73                    return Err(ErrorKind::WriteZero.into());
74                }
75                Ok(n) => buf = &buf[n..],
76                Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
77                Err(e) => return Err(e),
78            }
79        }
80        Ok(())
81    }
82
83    /// Creates a "by reference" adapter for this instance of `Write`.
84    ///
85    /// The returned adapter also implements `Write` and will simply borrow this
86    /// current writer.
87    // Implementation taken from Rust's stdlib
88    fn by_ref(&mut self) -> &mut Self
89    where
90        Self: Sized,
91    {
92        self
93    }
94}
95
96impl Write for &mut [u8] {
97    // Implementation taken from Rust's stdlib
98    #[inline]
99    fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
100        let amt = cmp::min(data.len(), self.len());
101        let (a, b) = mem::take(self).split_at_mut(amt);
102        a.copy_from_slice(&data[..amt]);
103        *self = b;
104        Ok(amt)
105    }
106
107    #[inline]
108    fn flush(&mut self) -> Result<(), Error> {
109        Ok(())
110    }
111
112    // Implementation taken from Rust's stdlib
113    #[inline]
114    fn write_all(&mut self, data: &[u8]) -> Result<(), Error> {
115        if self.write(data)? == data.len() {
116            Ok(())
117        } else {
118            Err(ErrorKind::WriteZero.into())
119        }
120    }
121}
122
123impl Write for Vec<u8> {
124    // Implementation taken from Rust's stdlib
125    #[inline]
126    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
127        self.extend_from_slice(buf);
128        Ok(buf.len())
129    }
130
131    #[inline]
132    fn flush(&mut self) -> Result<(), Error> {
133        Ok(())
134    }
135
136    // Implementation taken from Rust's stdlib
137    #[inline]
138    fn write_all(&mut self, buf: &[u8]) -> Result<(), Error> {
139        self.extend_from_slice(buf);
140        Ok(())
141    }
142}
143
144impl<W: Write + ?Sized> Write for &mut W {
145    fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
146        (**self).write(buf)
147    }
148
149    fn flush(&mut self) -> Result<(), Error> {
150        (**self).flush()
151    }
152
153    fn write_all(&mut self, buf: &[u8]) -> Result<(), Error> {
154        (**self).write_all(buf)
155    }
156}
157
158/// The error type for I/O operations of the `Write` trait.
159#[derive(Debug)]
160pub struct Error {
161    kind: ErrorKind,
162}
163
164impl Error {
165    /// Returns the corresponding `ErrorKind` for this error.
166    pub fn kind(&self) -> ErrorKind {
167        self.kind
168    }
169}
170
171impl Display for Error {
172    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
173        f.write_fmt(format_args!("{:?}", self.kind))
174    }
175}
176
177impl From<ErrorKind> for Error {
178    fn from(value: ErrorKind) -> Self {
179        Self { kind: value }
180    }
181}
182
183#[cfg(feature = "nightly")]
184impl core::error::Error for Error {}
185
186/// A list specifying general categories of I/O error.
187///
188/// This list is intended to grow over time and it is not recommended to
189/// exhaustively match against it.
190///
191/// The documentation for this enum is taken from the `std::io::ErrorKind`.
192#[derive(Debug, Copy, Clone, Eq, PartialEq)]
193#[non_exhaustive]
194pub enum ErrorKind {
195    /// This operation was interrupted.
196    ///
197    /// Interrupted operations can typically be retried.
198    Interrupted,
199    /// An error returned when an operation could not be completed because a
200    /// call to [`write`] returned [`Ok(0)`].
201    ///
202    /// This typically means that an operation could only succeed if it wrote a
203    /// particular number of bytes but only a smaller number of bytes could be
204    /// written.
205    ///
206    /// [`write`]: Write::write
207    /// [`Ok(0)`]: Ok
208    WriteZero,
209    /// An error that does not fall under any other I/O error kind.
210    Other,
211}