embedded_tls/
read_buffer.rs1#[must_use]
3pub struct ReadBuffer<'a> {
4 data: &'a [u8],
5 consumed: usize,
6 used: bool,
7
8 decrypted_consumed: &'a mut usize,
9}
10
11impl<'a> ReadBuffer<'a> {
12 #[inline]
13 pub(crate) fn new(buffer: &'a [u8], decrypted_consumed: &'a mut usize) -> Self {
14 Self {
15 data: buffer,
16 consumed: 0,
17 used: false,
18 decrypted_consumed,
19 }
20 }
21
22 #[inline]
23 #[must_use]
24 pub fn len(&self) -> usize {
25 self.data.len() - self.consumed
26 }
27
28 #[inline]
29 #[must_use]
30 pub fn is_empty(&self) -> bool {
31 self.len() == 0
32 }
33
34 #[inline]
36 pub fn peek(&mut self, count: usize) -> &'a [u8] {
37 let count = self.len().min(count);
38 let start = self.consumed;
39
40 self.used = true;
42
43 &self.data[start..start + count]
44 }
45
46 #[inline]
48 pub fn peek_all(&mut self) -> &'a [u8] {
49 self.peek(self.len())
50 }
51
52 #[inline]
54 pub fn pop(&mut self, count: usize) -> &'a [u8] {
55 let count = self.len().min(count);
56 let start = self.consumed;
57 self.consumed += count;
58 self.used = true;
59
60 &self.data[start..start + count]
61 }
62
63 #[inline]
65 pub fn pop_all(&mut self) -> &'a [u8] {
66 self.pop(self.len())
67 }
68
69 #[inline]
71 pub fn revert(self) {
72 core::mem::forget(self);
73 }
74
75 #[inline]
77 pub fn pop_into(&mut self, buf: &mut [u8]) -> usize {
78 let to_copy = self.pop(buf.len());
79
80 buf[..to_copy.len()].copy_from_slice(to_copy);
81
82 to_copy.len()
83 }
84}
85
86impl Drop for ReadBuffer<'_> {
87 #[inline]
88 fn drop(&mut self) {
89 *self.decrypted_consumed += if self.used {
90 self.consumed
91 } else {
92 self.data.len()
94 };
95 }
96}
97
98#[cfg(test)]
99mod test {
100 use super::*;
101
102 #[test]
103 fn dropping_unused_buffer_consumes_all() {
104 let mut consumed = 1000;
105 let buffer = [0, 1, 2, 3];
106
107 _ = ReadBuffer::new(&buffer, &mut consumed);
108
109 assert_eq!(consumed, 1004);
110 }
111
112 #[test]
113 fn pop_moves_internal_cursor() {
114 let mut consumed = 0;
115
116 let mut buffer = ReadBuffer::new(&[0, 1, 2, 3], &mut consumed);
117
118 assert_eq!(buffer.pop(1), &[0]);
119 assert_eq!(buffer.pop(1), &[1]);
120 assert_eq!(buffer.pop(1), &[2]);
121 }
122
123 #[test]
124 fn dropping_consumes_as_many_bytes_as_used() {
125 let mut consumed = 0;
126
127 let mut buffer = ReadBuffer::new(&[0, 1, 2, 3], &mut consumed);
128
129 assert_eq!(buffer.pop(1), &[0]);
130 assert_eq!(buffer.pop(1), &[1]);
131 assert_eq!(buffer.pop(1), &[2]);
132
133 core::mem::drop(buffer);
134
135 assert_eq!(consumed, 3);
136 }
137
138 #[test]
139 fn pop_returns_fewer_bytes_if_requested_more_than_what_it_has() {
140 let mut consumed = 0;
141
142 let mut buffer = ReadBuffer::new(&[0, 1, 2, 3], &mut consumed);
143
144 assert_eq!(buffer.pop(1), &[0]);
145 assert_eq!(buffer.pop(1), &[1]);
146 assert_eq!(buffer.pop(4), &[2, 3]);
147 assert_eq!(buffer.pop(1), &[]);
148
149 core::mem::drop(buffer);
150
151 assert_eq!(consumed, 4);
152 }
153
154 #[test]
155 fn peek_does_not_consume() {
156 let mut consumed = 0;
157
158 let mut buffer = ReadBuffer::new(&[0, 1, 2, 3], &mut consumed);
159
160 assert_eq!(buffer.peek(1), &[0]);
161 assert_eq!(buffer.peek(1), &[0]);
162
163 core::mem::drop(buffer);
164
165 assert_eq!(consumed, 0);
166 }
167
168 #[test]
169 fn revert_undoes_pop() {
170 let mut consumed = 0;
171
172 let mut buffer = ReadBuffer::new(&[0, 1, 2, 3], &mut consumed);
173
174 assert_eq!(buffer.pop(4), &[0, 1, 2, 3]);
175
176 buffer.revert();
177
178 assert_eq!(consumed, 0);
179 }
180}