Skip to content
This repository was archived by the owner on Feb 14, 2023. It is now read-only.

Commit 6eabdbb

Browse files
Reading cancelation
1 parent 4c59a0f commit 6eabdbb

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/lib.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ pub struct BufReader<R, P = StdPolicy>{
203203
buf: Buffer,
204204
inner: R,
205205
policy: P,
206+
// We need field "empty" to return empty &[u8] in case of reader is paused
207+
// This field is never used, never filled.
208+
empty: Vec<u8>,
206209
}
207210

208211
impl<R> BufReader<R, StdPolicy> {
@@ -262,7 +265,7 @@ impl<R> BufReader<R, StdPolicy> {
262265
/// then it will be returned in `read()` and `fill_buf()` ahead of any data from `inner`.
263266
pub fn with_buffer(buf: Buffer, inner: R) -> Self {
264267
BufReader {
265-
buf, inner, policy: StdPolicy
268+
buf, inner, policy: StdPolicy, empty: vec![]
266269
}
267270
}
268271
}
@@ -273,6 +276,7 @@ impl<R, P> BufReader<R, P> {
273276
BufReader {
274277
inner: self.inner,
275278
buf: self.buf,
279+
empty: self.empty,
276280
policy
277281
}
278282
}
@@ -357,6 +361,11 @@ impl<R, P: ReaderPolicy> BufReader<R, P> {
357361
fn should_read(&mut self) -> bool {
358362
self.policy.before_read(&mut self.buf).0
359363
}
364+
365+
#[inline]
366+
fn is_paused(&mut self) -> bool {
367+
self.policy.is_paused()
368+
}
360369
}
361370

362371
impl<R: Read, P> BufReader<R, P> {
@@ -377,12 +386,17 @@ impl<R: Read, P> BufReader<R, P> {
377386
inner,
378387
buf: self.buf,
379388
policy: self.policy,
389+
empty: self.empty,
380390
}
381391
}
382392
}
383393

384394
impl<R: Read, P: ReaderPolicy> Read for BufReader<R, P> {
385395
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
396+
// If reading is paused, returning 0 to send end reading signal
397+
if self.is_paused() {
398+
return Ok(0);
399+
}
386400
// If we don't have any buffered data and we're doing a read matching
387401
// or exceeding the internal buffer's capacity, bypass the buffer.
388402
if self.buf.is_empty() && out.len() >= self.buf.capacity() {
@@ -397,6 +411,10 @@ impl<R: Read, P: ReaderPolicy> Read for BufReader<R, P> {
397411

398412
impl<R: Read, P: ReaderPolicy> BufRead for BufReader<R, P> {
399413
fn fill_buf(&mut self) -> io::Result<&[u8]> {
414+
// If reading is paused, we are sending empty buffer to send signal - "no data any more"
415+
if self.is_paused() {
416+
return Ok(&self.empty);
417+
}
400418
// If we've reached the end of our internal buffer then we need to fetch
401419
// some more data from the underlying reader.
402420
// This execution order is important; the policy may want to resize the buffer or move data

src/policy.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,23 @@ pub trait ReaderPolicy {
6464
///
6565
/// This is a no-op by default.
6666
fn after_consume(&mut self, _buffer: &mut Buffer, _amt: usize) {}
67+
68+
/// Consulted with `read` and `fill_buf` methods.
69+
/// Return `bool` to continue (`true`) reading or pause it (`false`).
70+
///
71+
/// ### Note
72+
/// As soon as it was paused, the current position in the buffer isn't dropped.
73+
/// The reader still can continue reading with the next iteration if the flag will
74+
/// be changed again to `true`.
75+
///
76+
/// Possible use-case. For example, we have a huge file, which we would like to
77+
/// read and somehow manipulate with content (search in it for example). If we
78+
/// are passing the reader into the searcher, we are losing control of it. Withing
79+
/// `pausing` policy we can pass to a reader some kind of token and keep control
80+
/// of the reading process.
81+
fn is_paused(&mut self) -> bool {
82+
false
83+
}
6784
}
6885

6986
/// Behavior of `std::io::BufReader`: the buffer will only be read into if it is empty.

0 commit comments

Comments
 (0)