buffered_reader/
limitor.rs1use std::io;
2use std::cmp;
3
4use super::*;
5
6#[derive(Debug)]
9pub struct Limitor<T: BufferedReader<C>, C: fmt::Debug + Sync + Send> {
10 limit: u64,
11 cookie: C,
12 reader: T,
13}
14
15assert_send_and_sync!(Limitor<T, C>
16 where T: BufferedReader<C>,
17 C: fmt::Debug);
18
19impl<T: BufferedReader<C>, C: fmt::Debug + Sync + Send> fmt::Display for Limitor<T, C> {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 f.debug_struct("Limitor")
22 .field("limit", &self.limit)
23 .finish()
24 }
25}
26
27impl<T: BufferedReader<()>> Limitor<T, ()> {
28 pub fn new(reader: T, limit: u64) -> Self {
33 Self::with_cookie(reader, limit, ())
34 }
35}
36
37impl<T: BufferedReader<C>, C: fmt::Debug + Sync + Send> Limitor<T, C> {
38 pub fn with_cookie(reader: T, limit: u64, cookie: C)
43 -> Limitor<T, C> {
44 Limitor {
45 reader,
46 limit,
47 cookie,
48 }
49 }
50}
51
52impl<T: BufferedReader<C>, C: fmt::Debug + Sync + Send> io::Read for Limitor<T, C> {
53 fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
54 let len = cmp::min(self.limit, buf.len() as u64) as usize;
55 let result = self.reader.read(&mut buf[0..len]);
56 if let Ok(amount) = result {
57 self.limit -= amount as u64;
58 }
59 result
60 }
61}
62
63impl<T: BufferedReader<C>, C: fmt::Debug + Sync + Send> BufferedReader<C> for Limitor<T, C> {
64 fn buffer(&self) -> &[u8] {
65 let buf = self.reader.buffer();
66 &buf[..cmp::min(buf.len(),
67 cmp::min(std::usize::MAX as u64,
68 self.limit) as usize)]
69 }
70
71 fn data(&mut self, amount: usize) -> Result<&[u8], io::Error> {
74 let amount = cmp::min(amount as u64, self.limit) as usize;
75 let result = self.reader.data(amount);
76 match result {
77 Ok(buffer) =>
78 if buffer.len() as u64 > self.limit {
79 Ok(&buffer[0..self.limit as usize])
80 } else {
81 Ok(buffer)
82 },
83 Err(err) => Err(err),
84 }
85 }
86
87 fn consume(&mut self, amount: usize) -> &[u8] {
88 assert!(amount as u64 <= self.limit);
89 self.limit -= amount as u64;
90 let data = self.reader.consume(amount);
91 &data[..cmp::min(self.limit + amount as u64, data.len() as u64) as usize]
92 }
93
94 fn data_consume(&mut self, amount: usize) -> Result<&[u8], io::Error> {
95 let amount = cmp::min(amount as u64, self.limit) as usize;
96 let result = self.reader.data_consume(amount);
97 if let Ok(buffer) = result {
98 let amount = cmp::min(amount, buffer.len());
99 self.limit -= amount as u64;
100 return Ok(&buffer[
101 ..cmp::min(buffer.len() as u64, self.limit + amount as u64) as usize]);
102 }
103 result
104 }
105
106 fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
107 if amount as u64 > self.limit {
108 return Err(Error::new(ErrorKind::UnexpectedEof, "EOF"));
109 }
110 let result = self.reader.data_consume_hard(amount);
111 if let Ok(buffer) = result {
112 let amount = cmp::min(amount, buffer.len());
113 self.limit -= amount as u64;
114 return Ok(&buffer[
115 ..cmp::min(buffer.len() as u64, self.limit + amount as u64) as usize]);
116 }
117 result
118 }
119
120 fn consummated(&mut self) -> bool {
121 self.limit == 0
122 }
123
124 fn get_mut(&mut self) -> Option<&mut dyn BufferedReader<C>> {
125 Some(&mut self.reader)
126 }
127
128 fn get_ref(&self) -> Option<&dyn BufferedReader<C>> {
129 Some(&self.reader)
130 }
131
132 fn into_inner<'b>(self: Box<Self>) -> Option<Box<dyn BufferedReader<C> + 'b>>
133 where Self: 'b {
134 Some(self.reader.into_boxed())
135 }
136
137 fn cookie_set(&mut self, cookie: C) -> C {
138 use std::mem;
139
140 mem::replace(&mut self.cookie, cookie)
141 }
142
143 fn cookie_ref(&self) -> &C {
144 &self.cookie
145 }
146
147 fn cookie_mut(&mut self) -> &mut C {
148 &mut self.cookie
149 }
150}
151
152#[cfg(test)]
153mod test {
154 use super::*;
155
156 #[test]
157 fn buffered_reader_limitor_test() {
158 let data : &[u8] = b"01234567890123456789";
159
160 {
162 let mut bio : Box<dyn BufferedReader<()>>
163 = Box::new(Memory::new(data));
164
165 bio = {
166 let mut bio2 = Box::new(Limitor::new(bio, 5));
167 {
168 let result = bio2.data(5).unwrap();
169 assert_eq!(result.len(), 5);
170 assert_eq!(result, &b"01234"[..]);
171 }
172 bio2.consume(5);
173 {
174 let result = bio2.data(1).unwrap();
175 assert_eq!(result.len(), 0);
176 assert_eq!(result, &b""[..]);
177 }
178
179 bio2.into_inner().unwrap()
180 };
181
182 {
183 {
184 let result = bio.data(15).unwrap();
185 assert_eq!(result.len(), 15);
186 assert_eq!(result, &b"567890123456789"[..]);
187 }
188 bio.consume(15);
189 {
190 let result = bio.data(1).unwrap();
191 assert_eq!(result.len(), 0);
192 assert_eq!(result, &b""[..]);
193 }
194 }
195 }
196
197 {
200 let mut bio : Box<dyn BufferedReader<()>>
201 = Box::new(Memory::new(data));
202
203 bio = {
204 let bio2 : Box<dyn BufferedReader<()>>
205 = Box::new(Limitor::new(bio, 5));
206 let mut bio3 : Box<dyn BufferedReader<()>>
209 = Box::new(Limitor::new(bio2, 15));
210 {
211 let result = bio3.data(100).unwrap();
212 assert_eq!(result.len(), 5);
213 assert_eq!(result, &b"01234"[..]);
214 }
215 bio3.consume(5);
216 {
217 let result = bio3.data(1).unwrap();
218 assert_eq!(result.len(), 0);
219 assert_eq!(result, &b""[..]);
220 }
221
222 bio3.into_inner().unwrap().into_inner().unwrap()
223 };
224
225 {
226 {
227 let result = bio.data(15).unwrap();
228 assert_eq!(result.len(), 15);
229 assert_eq!(result, &b"567890123456789"[..]);
230 }
231 bio.consume(15);
232 {
233 let result = bio.data(1).unwrap();
234 assert_eq!(result.len(), 0);
235 assert_eq!(result, &b""[..]);
236 }
237 }
238 }
239 }
240
241 #[test]
243 fn buffer_test() {
244 let size = 10 * default_buf_size();
246 let mut input = Vec::with_capacity(size);
247 let mut v = 0u8;
248 for _ in 0..size {
249 input.push(v);
250 if v == std::u8::MAX {
251 v = 0;
252 } else {
253 v += 1;
254 }
255 }
256
257 let reader = Generic::new(&input[..], None);
258 let size = size / 2;
259 let input = &input[..size];
260 let mut reader = Limitor::new(reader, input.len() as u64);
261
262 let stats_count = 2 * default_buf_size();
265 let mut stats = vec![0usize; stats_count];
266
267 for i in 0..input.len() {
268 let data = reader.data(default_buf_size() + 1).unwrap().to_vec();
269 assert!(!data.is_empty());
270 assert_eq!(data, reader.buffer());
271 assert_eq!(data, &input[i..i+data.len()]);
274
275 stats[cmp::min(data.len(), stats_count - 1)] += 1;
276
277 reader.consume(1);
279 }
280
281 if false {
282 for i in 0..stats.len() {
283 if stats[i] > 0 {
284 if i == stats.len() - 1 {
285 eprint!(">=");
286 }
287 eprintln!("{}: {}", i, stats[i]);
288 }
289 }
290 }
291 }
292
293 #[test]
294 fn consummated() {
295 let data = b"0123456789";
296
297 let mut l = Limitor::new(Memory::new(data), 10);
298 l.drop_eof().unwrap();
299 assert!(l.consummated());
300
301 let mut l = Limitor::new(Memory::new(data), 20);
302 l.drop_eof().unwrap();
303 eprintln!("{:?}", l);
304 assert!(! l.consummated());
305 }
306}