scuffle_bytes_util/zero_copy/
reader.rs1use std::io::{self, Read};
4
5use crate::BytesCow;
6
7pub trait ZeroCopyReader<'a> {
9 fn try_read(&mut self, size: usize) -> Result<BytesCow<'a>, io::Error>;
14
15 fn as_std(&mut self) -> impl io::Read;
17
18 fn take(self, limit: usize) -> Take<Self>
20 where
21 Self: Sized,
22 {
23 Take::new(self, limit)
24 }
25
26 fn try_read_to_end(&mut self) -> Result<BytesCow<'a>, io::Error> {
28 let mut buf = Vec::new();
29 self.as_std().read_to_end(&mut buf)?;
30 Ok(BytesCow::from_vec(buf))
31 }
32}
33
34impl<'a, T: ZeroCopyReader<'a>> ZeroCopyReader<'a> for &mut T {
35 fn try_read(&mut self, size: usize) -> Result<BytesCow<'a>, io::Error> {
36 (*self).try_read(size)
37 }
38
39 fn as_std(&mut self) -> impl io::Read {
40 (*self).as_std()
41 }
42}
43
44pub struct BytesBuf<B>(B);
46
47impl<B: bytes::Buf> From<B> for BytesBuf<B> {
48 fn from(buf: B) -> Self {
49 Self(buf)
50 }
51}
52
53impl<'a, B: bytes::Buf> ZeroCopyReader<'a> for BytesBuf<B> {
54 fn try_read(&mut self, size: usize) -> Result<BytesCow<'a>, io::Error> {
55 if self.0.remaining() < size {
56 return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough data"));
57 }
58
59 Ok(BytesCow::from_bytes(self.0.copy_to_bytes(size)))
60 }
61
62 fn as_std(&mut self) -> impl io::Read {
63 bytes::Buf::reader(&mut self.0)
64 }
65}
66
67pub struct IoRead<R>(R);
73
74impl<R: io::Read> From<R> for IoRead<R> {
75 fn from(reader: R) -> Self {
76 Self(reader)
77 }
78}
79
80impl<'a, R: io::Read> ZeroCopyReader<'a> for IoRead<R> {
81 fn try_read(&mut self, size: usize) -> Result<BytesCow<'a>, io::Error> {
82 let mut buf = vec![0; size];
83 self.0.read_exact(&mut buf)?;
84 Ok(BytesCow::from_vec(buf))
85 }
86
87 fn as_std(&mut self) -> impl io::Read {
88 &mut self.0
89 }
90}
91
92pub struct Slice<'a>(io::Cursor<&'a [u8]>);
94
95impl<'a> From<&'a [u8]> for Slice<'a> {
96 fn from(slice: &'a [u8]) -> Self {
97 Self(io::Cursor::new(slice))
98 }
99}
100
101impl<'a> ZeroCopyReader<'a> for Slice<'a> {
102 fn try_read(&mut self, size: usize) -> Result<BytesCow<'a>, io::Error> {
103 let start = self.0.position() as usize;
104 let end = start + size;
105
106 if end > self.0.get_ref().len() {
107 return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Not enough data"));
108 }
109
110 let slice = &self.0.get_ref()[start..end];
111 self.0.set_position(end as u64);
112 Ok(BytesCow::from_slice(slice))
113 }
114
115 fn as_std(&mut self) -> impl io::Read {
116 &mut self.0
117 }
118}
119
120pub struct Take<R> {
124 inner: R,
125 limit: usize,
126}
127
128struct TakeAsStd<'a, R> {
129 inner: R,
130 limit: &'a mut usize,
131}
132
133impl<R: io::Read> io::Read for TakeAsStd<'_, R> {
134 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
135 if *self.limit == 0 {
136 return Ok(0);
137 }
138
139 let size = std::cmp::min(buf.len(), *self.limit);
140 let n = self.inner.read(&mut buf[..size])?;
141 *self.limit -= n;
142 Ok(n)
143 }
144}
145
146impl<R> Take<R> {
147 pub fn new(inner: R, limit: usize) -> Self {
149 Self { inner, limit }
150 }
151
152 pub fn into_inner(self) -> R {
154 self.inner
155 }
156}
157
158impl<'a, R> ZeroCopyReader<'a> for Take<R>
159where
160 R: ZeroCopyReader<'a>,
161{
162 fn as_std(&mut self) -> impl io::Read {
163 TakeAsStd {
164 inner: self.inner.as_std(),
165 limit: &mut self.limit,
166 }
167 }
168
169 fn try_read(&mut self, size: usize) -> Result<BytesCow<'a>, io::Error> {
170 let size = std::cmp::min(size, self.limit);
171 let result = self.inner.try_read(size)?;
172 self.limit -= result.len();
173 Ok(result)
174 }
175}
176
177#[cfg(test)]
178#[cfg_attr(all(test, coverage_nightly), coverage(off))]
179mod tests {
180 use super::{Slice, ZeroCopyReader};
181
182 #[test]
183 fn take_and_read_to_end() {
184 let data = b"Hello, world!";
185 let mut reader = Slice::from(&data[..]).take(5);
186 assert_eq!(reader.try_read_to_end().unwrap(), b"Hello");
187 }
188}