bmap_parser/
discarder.rs

1use crate::{AsyncSeekForward, SeekForward};
2use async_trait::async_trait;
3use futures::io::{AsyncRead, AsyncReadExt};
4use std::io::Read;
5use std::io::Result as IOResult;
6use std::pin::Pin;
7use std::task::{Context, Poll};
8
9/// Adaptor that implements SeekForward on types only implementing Read by discarding data
10pub struct Discarder<R: Read> {
11    reader: R,
12}
13
14impl<R: Read> Discarder<R> {
15    pub fn new(reader: R) -> Self {
16        Self { reader }
17    }
18
19    pub fn into_inner(self) -> R {
20        self.reader
21    }
22}
23
24impl<R: Read> Read for Discarder<R> {
25    fn read(&mut self, buf: &mut [u8]) -> IOResult<usize> {
26        self.reader.read(buf)
27    }
28}
29
30impl<R: Read> SeekForward for Discarder<R> {
31    fn seek_forward(&mut self, forward: u64) -> IOResult<()> {
32        let mut buf = [0; 4096];
33        let mut left = forward as usize;
34        while left > 0 {
35            let toread = left.min(buf.len());
36            let r = self.reader.read(&mut buf[0..toread])?;
37            left -= r;
38        }
39        Ok(())
40    }
41}
42
43pub struct AsyncDiscarder<R: AsyncRead> {
44    reader: R,
45}
46
47impl<R: AsyncRead> AsyncDiscarder<R> {
48    pub fn new(reader: R) -> Self {
49        Self { reader }
50    }
51
52    pub fn into_inner(self) -> R {
53        self.reader
54    }
55}
56
57impl<R: AsyncRead + Unpin> AsyncRead for AsyncDiscarder<R> {
58    fn poll_read(
59        mut self: Pin<&mut Self>,
60        cx: &mut Context<'_>,
61        buf: &mut [u8],
62    ) -> Poll<IOResult<usize>> {
63        Pin::new(&mut self.reader).poll_read(cx, buf)
64    }
65}
66
67#[async_trait]
68impl<R: AsyncRead + Unpin + Send> AsyncSeekForward for AsyncDiscarder<R> {
69    async fn async_seek_forward(&mut self, forward: u64) -> IOResult<()> {
70        let mut buf = [0; 4096];
71        let mut left = forward as usize;
72        while left > 0 {
73            let toread = left.min(buf.len());
74            let r = self.read(&mut buf[0..toread]).await?;
75            left -= r;
76        }
77        Ok(())
78    }
79}
80
81#[cfg(test)]
82mod test {
83    use super::*;
84    use std::slice;
85
86    #[test]
87    fn discard() {
88        let mut data = Vec::with_capacity(256);
89        for byte in 0u8..=255 {
90            data.push(byte);
91        }
92
93        let mut discarder = Discarder::new(data.as_slice());
94        let _ = &[0u64, 5, 16, 31, 63, 200, 255]
95            .iter()
96            .fold(0, |pos, offset| {
97                let mut byte: u8 = 1;
98                discarder.seek_forward(offset - pos).unwrap();
99                assert_eq!(1, discarder.read(slice::from_mut(&mut byte)).unwrap());
100                assert_eq!(*offset, byte as u64);
101                *offset + 1
102            });
103    }
104}