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