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