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