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