core/io/write.rs
1use crate::fmt;
2use crate::io::{Error, IoSlice, Result};
3
4/// A trait for objects which are byte-oriented sinks.
5///
6/// Implementors of the `Write` trait are sometimes called 'writers'.
7///
8/// Writers are defined by two required methods, [`write`] and [`flush`]:
9///
10/// * The [`write`] method will attempt to write some data into the object,
11/// returning how many bytes were successfully written.
12///
13/// * The [`flush`] method is useful for adapters and explicit buffers
14/// themselves for ensuring that all buffered data has been pushed out to the
15/// 'true sink'.
16///
17/// Writers are intended to be composable with one another. Many implementors
18/// throughout [`std::io`] take and provide types which implement the `Write`
19/// trait.
20///
21/// [`write`]: Write::write
22/// [`flush`]: Write::flush
23/// [`std::io`]: crate::io
24///
25/// # Examples
26///
27/// ```no_run
28/// use std::io::prelude::*;
29/// use std::fs::File;
30///
31/// fn main() -> std::io::Result<()> {
32/// let data = b"some bytes";
33///
34/// let mut pos = 0;
35/// let mut buffer = File::create("foo.txt")?;
36///
37/// while pos < data.len() {
38/// let bytes_written = buffer.write(&data[pos..])?;
39/// pos += bytes_written;
40/// }
41/// Ok(())
42/// }
43/// ```
44///
45/// The trait also provides convenience methods like [`write_all`], which calls
46/// `write` in a loop until its entire input has been written.
47///
48/// [`write_all`]: Write::write_all
49#[stable(feature = "rust1", since = "1.0.0")]
50#[doc(notable_trait)]
51#[cfg_attr(not(test), rustc_diagnostic_item = "IoWrite")]
52pub trait Write {
53 /// Writes a buffer into this writer, returning how many bytes were written.
54 ///
55 /// This function will attempt to write the entire contents of `buf`, but
56 /// the entire write might not succeed, or the write may also generate an
57 /// error. Typically, a call to `write` represents one attempt to write to
58 /// any wrapped object.
59 ///
60 /// Calls to `write` are not guaranteed to block waiting for data to be
61 /// written, and a write which would otherwise block can be indicated through
62 /// an [`Err`] variant.
63 ///
64 /// If this method consumed `n > 0` bytes of `buf` it must return [`Ok(n)`].
65 /// If the return value is `Ok(n)` then `n` must satisfy `n <= buf.len()`.
66 /// A return value of `Ok(0)` typically means that the underlying object is
67 /// no longer able to accept bytes and will likely not be able to in the
68 /// future as well, or that the buffer provided is empty.
69 ///
70 /// # Errors
71 ///
72 /// Each call to `write` may generate an I/O error indicating that the
73 /// operation could not be completed. If an error is returned then no bytes
74 /// in the buffer were written to this writer.
75 ///
76 /// It is **not** considered an error if the entire buffer could not be
77 /// written to this writer.
78 ///
79 /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the
80 /// write operation should be retried if there is nothing else to do.
81 ///
82 /// [`ErrorKind::Interrupted`]: crate::io::ErrorKind::Interrupted
83 ///
84 /// # Examples
85 ///
86 /// ```no_run
87 /// use std::io::prelude::*;
88 /// use std::fs::File;
89 ///
90 /// fn main() -> std::io::Result<()> {
91 /// let mut buffer = File::create("foo.txt")?;
92 ///
93 /// // Writes some prefix of the byte string, not necessarily all of it.
94 /// buffer.write(b"some bytes")?;
95 /// Ok(())
96 /// }
97 /// ```
98 ///
99 /// [`Ok(n)`]: Ok
100 #[stable(feature = "rust1", since = "1.0.0")]
101 fn write(&mut self, buf: &[u8]) -> Result<usize>;
102
103 /// Like [`write`], except that it writes from a slice of buffers.
104 ///
105 /// Data is copied from each buffer in order, with the final buffer
106 /// read from possibly being only partially consumed. This method must
107 /// behave as a call to [`write`] with the buffers concatenated would.
108 ///
109 /// The default implementation calls [`write`] with either the first nonempty
110 /// buffer provided, or an empty one if none exists.
111 ///
112 /// # Examples
113 ///
114 /// ```no_run
115 /// use std::io::IoSlice;
116 /// use std::io::prelude::*;
117 /// use std::fs::File;
118 ///
119 /// fn main() -> std::io::Result<()> {
120 /// let data1 = [1; 8];
121 /// let data2 = [15; 8];
122 /// let io_slice1 = IoSlice::new(&data1);
123 /// let io_slice2 = IoSlice::new(&data2);
124 ///
125 /// let mut buffer = File::create("foo.txt")?;
126 ///
127 /// // Writes some prefix of the byte string, not necessarily all of it.
128 /// buffer.write_vectored(&[io_slice1, io_slice2])?;
129 /// Ok(())
130 /// }
131 /// ```
132 ///
133 /// [`write`]: Write::write
134 #[stable(feature = "iovec", since = "1.36.0")]
135 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
136 default_write_vectored(|b| self.write(b), bufs)
137 }
138
139 /// Determines if this `Write`r has an efficient [`write_vectored`]
140 /// implementation.
141 ///
142 /// If a `Write`r does not override the default [`write_vectored`]
143 /// implementation, code using it may want to avoid the method all together
144 /// and coalesce writes into a single buffer for higher performance.
145 ///
146 /// The default implementation returns `false`.
147 ///
148 /// [`write_vectored`]: Write::write_vectored
149 #[unstable(feature = "can_vector", issue = "69941")]
150 fn is_write_vectored(&self) -> bool {
151 false
152 }
153
154 /// Flushes this output stream, ensuring that all intermediately buffered
155 /// contents reach their destination.
156 ///
157 /// # Errors
158 ///
159 /// It is considered an error if not all bytes could be written due to
160 /// I/O errors or EOF being reached.
161 ///
162 /// # Examples
163 ///
164 /// ```no_run
165 /// use std::io::prelude::*;
166 /// use std::io::BufWriter;
167 /// use std::fs::File;
168 ///
169 /// fn main() -> std::io::Result<()> {
170 /// let mut buffer = BufWriter::new(File::create("foo.txt")?);
171 ///
172 /// buffer.write_all(b"some bytes")?;
173 /// buffer.flush()?;
174 /// Ok(())
175 /// }
176 /// ```
177 #[stable(feature = "rust1", since = "1.0.0")]
178 fn flush(&mut self) -> Result<()>;
179
180 /// Attempts to write an entire buffer into this writer.
181 ///
182 /// This method will continuously call [`write`] until there is no more data
183 /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
184 /// returned. This method will not return until the entire buffer has been
185 /// successfully written or such an error occurs. The first error that is
186 /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
187 /// returned.
188 ///
189 /// [`ErrorKind::Interrupted`]: crate::io::ErrorKind::Interrupted
190 ///
191 /// If the buffer contains no data, this will never call [`write`].
192 ///
193 /// # Errors
194 ///
195 /// This function will return the first error of
196 /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns.
197 ///
198 /// [`write`]: Write::write
199 ///
200 /// # Examples
201 ///
202 /// ```no_run
203 /// use std::io::prelude::*;
204 /// use std::fs::File;
205 ///
206 /// fn main() -> std::io::Result<()> {
207 /// let mut buffer = File::create("foo.txt")?;
208 ///
209 /// buffer.write_all(b"some bytes")?;
210 /// Ok(())
211 /// }
212 /// ```
213 #[stable(feature = "rust1", since = "1.0.0")]
214 fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
215 while !buf.is_empty() {
216 match self.write(buf) {
217 Ok(0) => {
218 return Err(Error::WRITE_ALL_EOF);
219 }
220 Ok(n) => buf = &buf[n..],
221 Err(ref e) if e.is_interrupted() => {}
222 Err(e) => return Err(e),
223 }
224 }
225 Ok(())
226 }
227
228 /// Attempts to write multiple buffers into this writer.
229 ///
230 /// This method will continuously call [`write_vectored`] until there is no
231 /// more data to be written or an error of non-[`ErrorKind::Interrupted`]
232 /// kind is returned. This method will not return until all buffers have
233 /// been successfully written or such an error occurs. The first error that
234 /// is not of [`ErrorKind::Interrupted`] kind generated from this method
235 /// will be returned.
236 ///
237 /// [`ErrorKind::Interrupted`]: crate::io::ErrorKind::Interrupted
238 ///
239 /// If the buffer contains no data, this will never call [`write_vectored`].
240 ///
241 /// # Notes
242 ///
243 /// Unlike [`write_vectored`], this takes a *mutable* reference to
244 /// a slice of [`IoSlice`]s, not an immutable one. That's because we need to
245 /// modify the slice to keep track of the bytes already written.
246 ///
247 /// Once this function returns, the contents of `bufs` are unspecified, as
248 /// this depends on how many calls to [`write_vectored`] were necessary. It is
249 /// best to understand this function as taking ownership of `bufs` and to
250 /// not use `bufs` afterwards. The underlying buffers, to which the
251 /// [`IoSlice`]s point (but not the [`IoSlice`]s themselves), are unchanged and
252 /// can be reused.
253 ///
254 /// [`write_vectored`]: Write::write_vectored
255 ///
256 /// # Examples
257 ///
258 /// ```
259 /// #![feature(write_all_vectored)]
260 /// # fn main() -> std::io::Result<()> {
261 ///
262 /// use std::io::{Write, IoSlice};
263 ///
264 /// let mut writer = Vec::new();
265 /// let bufs = &mut [
266 /// IoSlice::new(&[1]),
267 /// IoSlice::new(&[2, 3]),
268 /// IoSlice::new(&[4, 5, 6]),
269 /// ];
270 ///
271 /// writer.write_all_vectored(bufs)?;
272 /// // Note: the contents of `bufs` is now undefined, see the Notes section.
273 ///
274 /// assert_eq!(writer, &[1, 2, 3, 4, 5, 6]);
275 /// # Ok(()) }
276 /// ```
277 #[unstable(feature = "write_all_vectored", issue = "70436")]
278 fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> {
279 // Guarantee that bufs is empty if it contains no data,
280 // to avoid calling write_vectored if there is no data to be written.
281 IoSlice::advance_slices(&mut bufs, 0);
282 while !bufs.is_empty() {
283 match self.write_vectored(bufs) {
284 Ok(0) => {
285 return Err(Error::WRITE_ALL_EOF);
286 }
287 Ok(n) => IoSlice::advance_slices(&mut bufs, n),
288 Err(ref e) if e.is_interrupted() => {}
289 Err(e) => return Err(e),
290 }
291 }
292 Ok(())
293 }
294
295 /// Writes a formatted string into this writer, returning any error
296 /// encountered.
297 ///
298 /// This method is primarily used to interface with the
299 /// [`format_args!()`] macro, and it is rare that this should
300 /// explicitly be called. The [`write!()`] macro should be favored to
301 /// invoke this method instead.
302 ///
303 /// This function internally uses the [`write_all`] method on
304 /// this trait and hence will continuously write data so long as no errors
305 /// are received. This also means that partial writes are not indicated in
306 /// this signature.
307 ///
308 /// [`write_all`]: Write::write_all
309 ///
310 /// # Errors
311 ///
312 /// This function will return any I/O error reported while formatting.
313 ///
314 /// # Examples
315 ///
316 /// ```no_run
317 /// use std::io::prelude::*;
318 /// use std::fs::File;
319 ///
320 /// fn main() -> std::io::Result<()> {
321 /// let mut buffer = File::create("foo.txt")?;
322 ///
323 /// // this call
324 /// write!(buffer, "{:.*}", 2, 1.234567)?;
325 /// // turns into this:
326 /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?;
327 /// Ok(())
328 /// }
329 /// ```
330 #[stable(feature = "rust1", since = "1.0.0")]
331 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> {
332 if let Some(s) = args.as_statically_known_str() {
333 self.write_all(s.as_bytes())
334 } else {
335 default_write_fmt(self, args)
336 }
337 }
338
339 /// Creates a "by reference" adapter for this instance of `Write`.
340 ///
341 /// The returned adapter also implements `Write` and will simply borrow this
342 /// current writer.
343 ///
344 /// # Examples
345 ///
346 /// ```no_run
347 /// use std::io::Write;
348 /// use std::fs::File;
349 ///
350 /// fn main() -> std::io::Result<()> {
351 /// let mut buffer = File::create("foo.txt")?;
352 ///
353 /// let reference = buffer.by_ref();
354 ///
355 /// // we can use reference just like our original buffer
356 /// reference.write_all(b"some bytes")?;
357 /// Ok(())
358 /// }
359 /// ```
360 #[stable(feature = "rust1", since = "1.0.0")]
361 fn by_ref(&mut self) -> &mut Self
362 where
363 Self: Sized,
364 {
365 self
366 }
367}
368
369/// Default implementation of [`Write::write_vectored`], which is currently used
370/// in `libstd` for file system implementations of similar methods.
371#[doc(hidden)]
372#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
373pub fn default_write_vectored<F>(write: F, bufs: &[IoSlice<'_>]) -> Result<usize>
374where
375 F: FnOnce(&[u8]) -> Result<usize>,
376{
377 let buf = bufs.iter().find(|b| !b.is_empty()).map_or(&[][..], |b| &**b);
378 write(buf)
379}
380
381fn default_write_fmt<W: Write + ?Sized>(this: &mut W, args: fmt::Arguments<'_>) -> Result<()> {
382 // Create a shim which translates a `Write` to a `fmt::Write` and saves off
383 // I/O errors, instead of discarding them.
384 struct Adapter<'a, T: ?Sized + 'a> {
385 inner: &'a mut T,
386 error: Result<()>,
387 }
388
389 impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> {
390 fn write_str(&mut self, s: &str) -> fmt::Result {
391 match self.inner.write_all(s.as_bytes()) {
392 Ok(()) => Ok(()),
393 Err(e) => {
394 self.error = Err(e);
395 Err(fmt::Error)
396 }
397 }
398 }
399 }
400
401 let mut output = Adapter { inner: this, error: Ok(()) };
402 match fmt::write(&mut output, args) {
403 Ok(()) => Ok(()),
404 Err(..) => {
405 // Check whether the error came from the underlying `Write`.
406 if output.error.is_err() {
407 output.error
408 } else {
409 // This shouldn't happen: the underlying stream did not error,
410 // but somehow the formatter still errored?
411 panic!(
412 "a formatting trait implementation returned an error when the underlying stream did not"
413 );
414 }
415 }
416 }
417}