Skip to main content

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}