]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
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 | pub use bufreader::BufReader; | |
16 | pub use bufwriter::BufWriter; | |
94222f64 XL |
17 | #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] |
18 | pub use bufwriter::WriterPanicked; | |
29967ef6 XL |
19 | pub use linewriter::LineWriter; |
20 | use linewritershim::LineWriterShim; | |
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 | } | |
fc512014 XL |
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 | /// ``` | |
fc512014 XL |
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 | /// ``` | |
136023e0 | 147 | #[stable(feature = "io_into_inner_error_parts", since = "1.55.0")] |
fc512014 XL |
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 | /// ``` | |
fc512014 XL |
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 | /// ``` | |
136023e0 | 170 | #[stable(feature = "io_into_inner_error_parts", since = "1.55.0")] |
fc512014 XL |
171 | pub fn into_parts(self) -> (Error, W) { |
172 | (self.1, self.0) | |
173 | } | |
29967ef6 XL |
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 | } |