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}