rc_u8_reader/
arc_u8_reader.rs

1use std::cmp;
2use std::fmt::{self, Debug, Formatter};
3use std::io::{self, BufRead, ErrorKind, Read, Seek, SeekFrom};
4use std::sync::Arc;
5
6#[cfg(feature = "tokio")]
7use std::pin::Pin;
8
9#[cfg(feature = "tokio")]
10use std::task::{Context, Poll};
11
12#[cfg(feature = "tokio")]
13use tokio::io::{AsyncRead, AsyncSeek, ReadBuf};
14
15pub struct ArcU8Reader<T: AsRef<[u8]> + ?Sized> {
16    data: Arc<T>,
17    pos: usize,
18}
19
20impl<T: AsRef<[u8]> + ?Sized> Debug for ArcU8Reader<T> {
21    #[inline]
22    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
23        debug_helper::impl_debug_for_struct!(ArcU8Reader, f, self, let .data = self.data.as_ref().as_ref(), .pos);
24    }
25}
26
27impl<T: AsRef<[u8]> + ?Sized> ArcU8Reader<T> {
28    #[inline]
29    pub fn new(data: Arc<T>) -> ArcU8Reader<T> {
30        ArcU8Reader {
31            data,
32            pos: 0,
33        }
34    }
35}
36
37impl<T: AsRef<[u8]> + ?Sized> BufRead for ArcU8Reader<T> {
38    #[inline]
39    fn fill_buf(&mut self) -> Result<&[u8], io::Error> {
40        let data = (*self.data).as_ref();
41
42        let amt = cmp::min(self.pos, data.len());
43
44        Ok(&data[amt..])
45    }
46
47    #[inline]
48    fn consume(&mut self, amt: usize) {
49        self.pos += amt;
50    }
51}
52
53impl<T: AsRef<[u8]> + ?Sized> Read for ArcU8Reader<T> {
54    #[inline]
55    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
56        let n = Read::read(&mut self.fill_buf()?, buf)?;
57
58        self.pos += n;
59
60        Ok(n)
61    }
62
63    #[inline]
64    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
65        let n = buf.len();
66
67        Read::read_exact(&mut self.fill_buf()?, buf)?;
68
69        self.pos += n;
70
71        Ok(())
72    }
73}
74
75impl<T: AsRef<[u8]> + ?Sized> Seek for ArcU8Reader<T> {
76    fn seek(&mut self, style: SeekFrom) -> Result<u64, io::Error> {
77        let (base_pos, offset) = match style {
78            SeekFrom::Start(n) => {
79                let n = if n > usize::MAX as u64 {
80                    usize::MAX
81                } else {
82                    n as usize
83                };
84
85                self.pos = n;
86
87                return Ok(n as u64);
88            }
89            SeekFrom::End(n) => ((*self.data).as_ref().len(), n),
90            SeekFrom::Current(n) => (self.pos, n),
91        };
92
93        let offset = if offset > isize::MAX as i64 {
94            isize::MAX
95        } else if offset < isize::MIN as i64 {
96            isize::MIN
97        } else {
98            offset as isize
99        };
100
101        let new_pos = if offset >= 0 {
102            base_pos.checked_add(offset as usize)
103        } else {
104            base_pos.checked_sub((offset.wrapping_neg()) as usize)
105        };
106
107        match new_pos {
108            Some(n) => {
109                self.pos = n;
110
111                Ok(self.pos as u64)
112            }
113            None => {
114                Err(io::Error::new(
115                    ErrorKind::InvalidInput,
116                    "invalid seek to a negative or overflowing position",
117                ))
118            }
119        }
120    }
121}
122
123#[cfg(feature = "tokio")]
124impl<T: AsRef<[u8]> + ?Sized> AsyncRead for ArcU8Reader<T> {
125    fn poll_read(
126        mut self: Pin<&mut Self>,
127        _: &mut Context<'_>,
128        buf: &mut ReadBuf<'_>,
129    ) -> Poll<Result<(), io::Error>> {
130        let data = (*self.data).as_ref();
131
132        let amt = cmp::min(self.pos, data.len());
133
134        let data = &data[amt..];
135
136        let read_size = cmp::min(data.len(), buf.remaining());
137
138        buf.put_slice(&data[..read_size]);
139
140        self.pos += read_size;
141
142        Poll::Ready(Ok(()))
143    }
144}
145
146#[cfg(feature = "tokio")]
147impl<T: AsRef<[u8]> + ?Sized> AsyncSeek for ArcU8Reader<T> {
148    #[inline]
149    fn start_seek(mut self: Pin<&mut Self>, pos: SeekFrom) -> Result<(), io::Error> {
150        Seek::seek(&mut *self, pos).map(drop)
151    }
152
153    #[inline]
154    fn poll_complete(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<u64>> {
155        Poll::Ready(Ok(self.pos as u64))
156    }
157}