Skip to main content

chapter_tgz/
independent.rs

1use std::io::{Cursor, Read, Result, Seek};
2
3/// Trait bound enabling `TgzReader::independent_read_chapter`.
4///
5/// See the example code on [`independent_read_chapter`].
6///
7/// [`independent_read_chapter`]: crate::TgzReader::independent_read_chapter
8///
9/// # Example
10///
11/// A reader that increments an [Indicatif] progress bar as bytes are read.
12///
13/// [Indicatif]: https://crates.io/crates/indicatif
14///
15/// ```
16/// use chapter_tgz::IndependentRead;
17/// use indicatif::ProgressBar;
18/// use std::io::{self, Read, Seek, SeekFrom};
19///
20/// pub struct ProgressRead<'a, R> {
21///     inner: R,
22///     progress: &'a ProgressBar,
23/// }
24///
25/// impl<R: Read> Read for ProgressRead<'_, R> {
26///     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
27///         let n = self.inner.read(buf)?;
28///         self.progress.inc(n as u64);
29///         Ok(n)
30///     }
31/// }
32///
33/// impl<R: Seek> Seek for ProgressRead<'_, R> {
34///     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
35///         self.inner.seek(pos)
36///     }
37/// }
38///
39/// impl<R: IndependentRead> IndependentRead for ProgressRead<'_, R> {
40///     fn independent_clone(&self) -> io::Result<Self> {
41///         Ok(ProgressRead {
42///             inner: self.inner.independent_clone()?,
43///             progress: self.progress,
44///         })
45///     }
46/// }
47/// ```
48pub trait IndependentRead: Read + Seek + Sized {
49    /// Produce a clone of self in such a way that `read` and `seek` operations
50    /// on the clone do not affect the position of reads from the original.
51    fn independent_clone(&self) -> Result<Self>;
52}
53
54impl<T> IndependentRead for Cursor<T>
55where
56    T: AsRef<[u8]> + Clone,
57{
58    fn independent_clone(&self) -> Result<Self> {
59        Ok(self.clone())
60    }
61}