| 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 | |