utf8_io/
write_str.rs

1use std::fmt::{self, Arguments};
2use std::io::{self, Write};
3
4/// Add a convenience and optimizing method for writing from `str`.
5pub trait WriteStr: Write {
6    /// Like [`Write::write_all`], but takes a `&str`, allowing implementors
7    /// which require valid UTF-8 to avoid re-validating the data.
8    #[inline]
9    fn write_str(&mut self, buf: &str) -> io::Result<()> {
10        default_write_str(self, buf)
11    }
12}
13
14/// Default implementation of [`WriteStr::write_str`], in terms of
15/// [`Write::write_all`].
16#[inline]
17pub fn default_write_str<Inner: Write + ?Sized>(inner: &mut Inner, buf: &str) -> io::Result<()> {
18    // Default to just writing it as bytes.
19    inner.write_all(buf.as_bytes())
20}
21
22/// Default implementation of [`Write::write_fmt`], in terms of
23/// [`WriteStr::write_str`].
24pub fn default_write_fmt<Inner: WriteStr + ?Sized>(
25    inner: &mut Inner,
26    fmt: Arguments,
27) -> io::Result<()> {
28    struct Adaptor<'a, Inner: ?Sized + 'a> {
29        inner: &'a mut Inner,
30        error: Option<io::Error>,
31    }
32
33    impl<Inner: WriteStr + ?Sized> fmt::Write for Adaptor<'_, Inner> {
34        fn write_str(&mut self, s: &str) -> fmt::Result {
35            match self.inner.write_str(s) {
36                Ok(()) => Ok(()),
37                Err(e) => {
38                    self.error = Some(e);
39                    Err(fmt::Error)
40                }
41            }
42        }
43    }
44
45    let mut adapter = Adaptor { inner, error: None };
46    match fmt::write(&mut adapter, fmt) {
47        Ok(()) => Ok(()),
48        Err(_) => Err(adapter
49            .error
50            .unwrap_or_else(|| io::Error::new(io::ErrorKind::Other, "formatter error"))),
51    }
52}