diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-10-20 14:26:32 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-10-20 16:09:58 +0200 |
commit | 999e0fce62eb13ee7a9b289a14c24c9552aface1 (patch) | |
tree | fb2b38c442ff5a307332666298702c34d9b8c3ae | |
parent | 6a425698b77253afdba1b3b937af98273edfcfa2 (diff) |
buffered-reader: Fix error propagation.
- If reading from the wrapped reader returns an error, but we still
can satisfy the request in Generic::data_helper, we do so. But, it
is important to keep the error and return it next time the function
is called. Otherwise, error conditions are mis-reported as end of
file.
-rw-r--r-- | buffered-reader/src/generic.rs | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/buffered-reader/src/generic.rs b/buffered-reader/src/generic.rs index 408ab93b..12c28d3b 100644 --- a/buffered-reader/src/generic.rs +++ b/buffered-reader/src/generic.rs @@ -21,6 +21,8 @@ pub struct Generic<T: io::Read, C> { preferred_chunk_size: usize, // The wrapped reader. reader: T, + // Stashed error, if any. + error: Option<Error>, // The user settable cookie. cookie: C, @@ -71,6 +73,7 @@ impl<T: io::Read, C> Generic<T, C> { if let Some(s) = preferred_chunk_size { s } else { DEFAULT_BUF_SIZE }, reader, + error: None, cookie, } } @@ -102,6 +105,11 @@ impl<T: io::Read, C> Generic<T, C> { // else { None }); + // See if there is an error from the last invocation. + if let Some(e) = self.error.take() { + return Err(e); + } + if let Some(ref buffer) = self.buffer { // We have a buffer. Make sure `cursor` is sane. assert!(self.cursor <= buffer.len()); @@ -110,8 +118,6 @@ impl<T: io::Read, C> Generic<T, C> { assert_eq!(self.cursor, 0); } - let mut error = None; - let amount_buffered = self.buffer.as_ref().map(|b| b.len() - self.cursor).unwrap_or(0); if amount > amount_buffered { @@ -141,7 +147,7 @@ impl<T: io::Read, C> Generic<T, C> { Err(err) => { // Don't return yet, because we may have // actually read something. - error = Some(err); + self.error = Some(err); break; }, } @@ -167,14 +173,14 @@ impl<T: io::Read, C> Generic<T, C> { let amount_buffered = self.buffer.as_ref().map(|b| b.len() - self.cursor).unwrap_or(0); - if let Some(error) = error { + if self.error.is_some() { // An error occurred. If we have enough data to fulfill // the caller's request, then don't return the error. if hard && amount > amount_buffered { - return Err(error); + return Err(self.error.take().unwrap()); } if !hard && amount_buffered == 0 { - return Err(error); + return Err(self.error.take().unwrap()); } } |