diff --git a/src/lib.rs b/src/lib.rs index 6a5365a..ad3d8e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -357,6 +357,11 @@ impl BufReader { fn should_read(&mut self) -> bool { self.policy.before_read(&mut self.buf).0 } + + #[inline] + fn is_paused(&mut self) -> bool { + self.policy.is_paused() + } } impl BufReader { @@ -383,6 +388,10 @@ impl BufReader { impl Read for BufReader { fn read(&mut self, out: &mut [u8]) -> io::Result { + // If reading is paused, returning 0 to send end reading signal + if self.is_paused() { + return Ok(0); + } // If we don't have any buffered data and we're doing a read matching // or exceeding the internal buffer's capacity, bypass the buffer. if self.buf.is_empty() && out.len() >= self.buf.capacity() { @@ -397,6 +406,10 @@ impl Read for BufReader { impl BufRead for BufReader { fn fill_buf(&mut self) -> io::Result<&[u8]> { + // If reading is paused, we are sending empty buffer to send signal - "no data any more" + if self.is_paused() { + return Ok(&[][..]); + } // If we've reached the end of our internal buffer then we need to fetch // some more data from the underlying reader. // This execution order is important; the policy may want to resize the buffer or move data diff --git a/src/policy.rs b/src/policy.rs index c2ab54b..64818f9 100644 --- a/src/policy.rs +++ b/src/policy.rs @@ -64,6 +64,23 @@ pub trait ReaderPolicy { /// /// This is a no-op by default. fn after_consume(&mut self, _buffer: &mut Buffer, _amt: usize) {} + + /// Consulted with `read` and `fill_buf` methods. + /// Return `bool` to continue (`true`) reading or pause it (`false`). + /// + /// ### Note + /// As soon as it was paused, the current position in the buffer isn't dropped. + /// The reader still can continue reading with the next iteration if the flag will + /// be changed again to `true`. + /// + /// Possible use-case. For example, we have a huge file, which we would like to + /// read and somehow manipulate with content (search in it for example). If we + /// are passing the reader into the searcher, we are losing control of it. Withing + /// `pausing` policy we can pass to a reader some kind of token and keep control + /// of the reading process. + fn is_paused(&mut self) -> bool { + false + } } /// Behavior of `std::io::BufReader`: the buffer will only be read into if it is empty.