s2n_quic_core/buffer/reader/
limit.rs1use crate::{
5 buffer::{
6 reader::{storage::Chunk, Reader, Storage},
7 writer::{self, Storage as _},
8 },
9 varint::VarInt,
10};
11
12pub struct Limit<'a, R: Reader + ?Sized> {
16 len: usize,
17 reader: &'a mut R,
18}
19
20impl<'a, R: Reader + ?Sized> Limit<'a, R> {
21 #[inline]
22 pub fn new(reader: &'a mut R, max_buffered_len: usize) -> Self {
23 let len = max_buffered_len.min(reader.buffered_len());
24
25 Self { len, reader }
26 }
27}
28
29impl<R: Reader + ?Sized> Storage for Limit<'_, R> {
30 type Error = R::Error;
31
32 #[inline]
33 fn buffered_len(&self) -> usize {
34 self.len
35 }
36
37 #[inline]
38 fn read_chunk(&mut self, watermark: usize) -> Result<Chunk<'_>, Self::Error> {
39 let watermark = self.len.min(watermark);
40 let chunk = self.reader.read_chunk(watermark)?;
41 unsafe {
42 assume!(chunk.len() <= self.len);
43 }
44 self.len -= chunk.len();
45 Ok(chunk)
46 }
47
48 #[inline]
49 fn partial_copy_into<Dest>(&mut self, dest: &mut Dest) -> Result<Chunk<'_>, Self::Error>
50 where
51 Dest: writer::Storage + ?Sized,
52 {
53 let mut dest = dest.with_write_limit(self.len);
54 let mut dest = dest.track_write();
55 let chunk = self.reader.partial_copy_into(&mut dest)?;
56 let len = dest.written_len() + chunk.len();
57 unsafe {
58 assume!(len <= self.len);
59 }
60 self.len -= len;
61 Ok(chunk)
62 }
63
64 #[inline]
65 fn copy_into<Dest>(&mut self, dest: &mut Dest) -> Result<(), Self::Error>
66 where
67 Dest: writer::Storage + ?Sized,
68 {
69 let mut dest = dest.with_write_limit(self.len);
70 let mut dest = dest.track_write();
71 self.reader.copy_into(&mut dest)?;
72 let len = dest.written_len();
73 unsafe {
74 assume!(len <= self.len);
75 }
76 self.len -= len;
77 Ok(())
78 }
79}
80
81impl<R: Reader + ?Sized> Reader for Limit<'_, R> {
82 #[inline]
83 fn current_offset(&self) -> VarInt {
84 self.reader.current_offset()
85 }
86
87 #[inline]
88 fn final_offset(&self) -> Option<VarInt> {
89 self.reader.final_offset()
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use crate::stream::testing::Data;
97
98 #[test]
99 fn max_data_test() {
100 let mut reader = Data::new(1000);
101 assert_eq!(reader.buffered_len(), 1000);
102 let mut reader = reader.with_checks();
103
104 let max_data = 32usize;
105
106 let mut reader = reader.with_max_data(VarInt::from_u8(max_data as _));
107 assert_eq!(reader.buffered_len(), max_data);
108
109 let mut dest = &mut [0u8; 16][..];
110 let chunk = reader.partial_copy_into(&mut dest).unwrap();
111 assert_eq!(chunk.len(), 16);
112
113 assert_eq!(reader.buffered_len(), max_data - 16);
114
115 let mut dest = &mut [0u8; 16][..];
116 let chunk = reader.partial_copy_into(&mut dest).unwrap();
117 assert_eq!(chunk.len(), 16);
118 assert!(reader.buffer_is_empty());
119 }
120}