xref: /drstd/src/std/io/buffered/mod.rs (revision 0fe3ff0054d3aec7fbf9bddecfecb10bc7d23a51)
1 //! Buffering wrappers for I/O traits
2 
3 mod bufreader;
4 mod bufwriter;
5 mod linewriter;
6 mod linewritershim;
7 
8 #[cfg(test)]
9 mod tests;
10 
11 use crate::std::error;
12 use crate::std::fmt;
13 use crate::std::io::Error;
14 
15 pub use self::{bufreader::BufReader, bufwriter::BufWriter, linewriter::LineWriter};
16 use linewritershim::LineWriterShim;
17 
18 pub use bufwriter::WriterPanicked;
19 
20 /// An error returned by [`BufWriter::into_inner`] which combines an error that
21 /// happened while writing out the buffer, and the buffered writer object
22 /// which may be used to recover from the condition.
23 ///
24 /// # Examples
25 ///
26 /// ```no_run
27 /// use std::io::BufWriter;
28 /// use std::net::TcpStream;
29 ///
30 /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
31 ///
32 /// // do stuff with the stream
33 ///
34 /// // we want to get our `TcpStream` back, so let's try:
35 ///
36 /// let stream = match stream.into_inner() {
37 ///     Ok(s) => s,
38 ///     Err(e) => {
39 ///         // Here, e is an IntoInnerError
40 ///         panic!("An error occurred");
41 ///     }
42 /// };
43 /// ```
44 #[derive(Debug)]
45 pub struct IntoInnerError<W>(W, Error);
46 
47 impl<W> IntoInnerError<W> {
48     /// Construct a new IntoInnerError
49     fn new(writer: W, error: Error) -> Self {
50         Self(writer, error)
51     }
52 
53     /// Helper to construct a new IntoInnerError; intended to help with
54     /// adapters that wrap other adapters
55     fn new_wrapped<W2>(self, f: impl FnOnce(W) -> W2) -> IntoInnerError<W2> {
56         let Self(writer, error) = self;
57         IntoInnerError::new(f(writer), error)
58     }
59 
60     /// Returns the error which caused the call to [`BufWriter::into_inner()`]
61     /// to fail.
62     ///
63     /// This error was returned when attempting to write the internal buffer.
64     ///
65     /// # Examples
66     ///
67     /// ```no_run
68     /// use std::io::BufWriter;
69     /// use std::net::TcpStream;
70     ///
71     /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
72     ///
73     /// // do stuff with the stream
74     ///
75     /// // we want to get our `TcpStream` back, so let's try:
76     ///
77     /// let stream = match stream.into_inner() {
78     ///     Ok(s) => s,
79     ///     Err(e) => {
80     ///         // Here, e is an IntoInnerError, let's log the inner error.
81     ///         //
82     ///         // We'll just 'log' to stdout for this example.
83     ///         println!("{}", e.error());
84     ///
85     ///         panic!("An unexpected error occurred.");
86     ///     }
87     /// };
88     /// ```
89     pub fn error(&self) -> &Error {
90         &self.1
91     }
92 
93     /// Returns the buffered writer instance which generated the error.
94     ///
95     /// The returned object can be used for error recovery, such as
96     /// re-inspecting the buffer.
97     ///
98     /// # Examples
99     ///
100     /// ```no_run
101     /// use std::io::BufWriter;
102     /// use std::net::TcpStream;
103     ///
104     /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
105     ///
106     /// // do stuff with the stream
107     ///
108     /// // we want to get our `TcpStream` back, so let's try:
109     ///
110     /// let stream = match stream.into_inner() {
111     ///     Ok(s) => s,
112     ///     Err(e) => {
113     ///         // Here, e is an IntoInnerError, let's re-examine the buffer:
114     ///         let buffer = e.into_inner();
115     ///
116     ///         // do stuff to try to recover
117     ///
118     ///         // afterwards, let's just return the stream
119     ///         buffer.into_inner().unwrap()
120     ///     }
121     /// };
122     /// ```
123     pub fn into_inner(self) -> W {
124         self.0
125     }
126 
127     /// Consumes the [`IntoInnerError`] and returns the error which caused the call to
128     /// [`BufWriter::into_inner()`] to fail.  Unlike `error`, this can be used to
129     /// obtain ownership of the underlying error.
130     ///
131     /// # Example
132     /// ```
133     /// use std::io::{BufWriter, ErrorKind, Write};
134     ///
135     /// let mut not_enough_space = [0u8; 10];
136     /// let mut stream = BufWriter::new(not_enough_space.as_mut());
137     /// write!(stream, "this cannot be actually written").unwrap();
138     /// let into_inner_err = stream.into_inner().expect_err("now we discover it's too small");
139     /// let err = into_inner_err.into_error();
140     /// assert_eq!(err.kind(), ErrorKind::WriteZero);
141     /// ```
142     pub fn into_error(self) -> Error {
143         self.1
144     }
145 
146     /// Consumes the [`IntoInnerError`] and returns the error which caused the call to
147     /// [`BufWriter::into_inner()`] to fail, and the underlying writer.
148     ///
149     /// This can be used to simply obtain ownership of the underlying error; it can also be used for
150     /// advanced error recovery.
151     ///
152     /// # Example
153     /// ```
154     /// use std::io::{BufWriter, ErrorKind, Write};
155     ///
156     /// let mut not_enough_space = [0u8; 10];
157     /// let mut stream = BufWriter::new(not_enough_space.as_mut());
158     /// write!(stream, "this cannot be actually written").unwrap();
159     /// let into_inner_err = stream.into_inner().expect_err("now we discover it's too small");
160     /// let (err, recovered_writer) = into_inner_err.into_parts();
161     /// assert_eq!(err.kind(), ErrorKind::WriteZero);
162     /// assert_eq!(recovered_writer.buffer(), b"t be actually written");
163     /// ```
164     pub fn into_parts(self) -> (Error, W) {
165         (self.1, self.0)
166     }
167 }
168 
169 impl<W> From<IntoInnerError<W>> for Error {
170     fn from(iie: IntoInnerError<W>) -> Error {
171         iie.1
172     }
173 }
174 
175 impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
176     #[allow(deprecated, deprecated_in_future)]
177     fn description(&self) -> &str {
178         error::Error::description(self.error())
179     }
180 }
181 
182 impl<W> fmt::Display for IntoInnerError<W> {
183     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184         self.error().fmt(f)
185     }
186 }
187