1use std::{
19 cmp, fmt,
20 io::{self, Read, Write},
21 mem, ptr,
22};
23
24use pool::Reset;
25use zeroize::Zeroize;
26
27#[derive(PartialEq, Eq, Clone)]
28pub struct Buffer {
29 memory: Vec<u8>,
30 capacity: usize,
31 position: usize,
32 end: usize,
33}
34
35impl fmt::Debug for Buffer {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 f.debug_struct("Buffer")
38 .field("capacity", &self.capacity)
39 .field("position", &self.position)
40 .field("end", &self.end)
41 .finish_non_exhaustive()
42 }
43}
44
45impl Drop for Buffer {
46 fn drop(&mut self) {
47 self.memory.zeroize();
48 }
49}
50
51impl Buffer {
52 pub fn with_capacity(capacity: usize) -> Buffer {
53 Buffer {
54 memory: vec![0; capacity],
55 capacity,
56 position: 0,
57 end: 0,
58 }
59 }
60
61 pub fn from_slice(sl: &[u8]) -> Buffer {
62 Buffer {
63 memory: Vec::from(sl),
64 capacity: sl.len(),
65 position: 0,
66 end: sl.len(),
67 }
68 }
69
70 pub fn grow(&mut self, new_size: usize) -> bool {
71 if self.capacity >= new_size {
72 return false;
73 }
74
75 self.reallocate(new_size);
76 self.capacity = new_size;
77 true
78 }
79
80 pub fn shrink(&mut self, target_size: usize) -> bool {
83 if target_size >= self.capacity {
84 return false;
85 }
86 self.shift();
87 if self.end > target_size {
88 return false;
89 }
90 self.reallocate(target_size);
91 self.capacity = target_size;
92 true
93 }
94
95 fn reallocate(&mut self, size: usize) {
102 debug_assert!(
103 self.end <= size,
104 "the pending window must fit the new allocation"
105 );
106 debug_assert!(
107 self.position <= self.end,
108 "the pending window must not be inverted"
109 );
110 let mut destination = vec![0; size];
111 destination[self.position..self.end].copy_from_slice(&self.memory[self.position..self.end]);
112 let mut previous = mem::replace(&mut self.memory, destination);
113 previous.zeroize();
114 }
115
116 fn erase(&mut self, from: usize, to: usize) {
118 debug_assert!(from <= to, "the erased range must not be inverted");
119 debug_assert!(
120 to <= self.memory.len(),
121 "the erased range must be in bounds"
122 );
123 self.memory[from..to].zeroize();
124 }
125
126 pub fn available_data(&self) -> usize {
127 self.end - self.position
128 }
129
130 pub fn available_space(&self) -> usize {
131 self.capacity - self.end
132 }
133
134 pub fn capacity(&self) -> usize {
135 self.capacity
136 }
137
138 pub fn empty(&self) -> bool {
139 self.position == self.end
140 }
141
142 pub fn consume(&mut self, count: usize) -> usize {
143 let cnt = cmp::min(count, self.available_data());
144 self.erase(self.position, self.position + cnt);
145 self.position += cnt;
146 if self.position > self.capacity / 2 {
147 self.shift();
149 }
150 cnt
151 }
152
153 pub fn fill(&mut self, count: usize) -> usize {
155 let cnt = cmp::min(count, self.available_space());
156 self.end += cnt;
157 if self.available_space() < self.available_data() + cnt {
158 self.shift();
160 }
161
162 cnt
163 }
164
165 pub fn reset(&mut self) {
166 self.erase(self.position, self.end);
167 self.position = 0;
168 self.end = 0;
169 }
170
171 pub fn data(&self) -> &[u8] {
172 &self.memory[self.position..self.end]
173 }
174
175 pub fn space(&mut self) -> &mut [u8] {
176 &mut self.memory[self.end..self.capacity]
177 }
178
179 pub fn shift(&mut self) {
180 if self.position > 0 {
181 let previous_end = self.end;
182 unsafe {
187 let length = self.end - self.position;
188 ptr::copy(
189 self.memory[self.position..self.end].as_ptr(),
190 self.memory[..length].as_mut_ptr(),
191 length,
192 );
193 self.position = 0;
194 self.end = length;
195 }
196 self.erase(self.end, previous_end);
199 }
200 }
201
202 pub fn delete_slice(&mut self, start: usize, length: usize) -> Option<usize> {
203 if start + length >= self.available_data() {
204 return None;
205 }
206
207 let previous_end = self.end;
208 unsafe {
214 let begin = self.position + start;
215 let next_end = self.end - length;
216 ptr::copy(
217 self.memory[begin + length..self.end].as_ptr(),
218 self.memory[begin..next_end].as_mut_ptr(),
219 self.end - (begin + length),
220 );
221 self.end = next_end;
222 }
223 self.erase(self.end, previous_end);
226 Some(self.available_data())
227 }
228
229 pub fn replace_slice(&mut self, data: &[u8], start: usize, length: usize) -> Option<usize> {
230 let data_len = data.len();
231 if start + length > self.available_data()
232 || self.position + start + data_len > self.capacity
233 {
234 return None;
235 }
236
237 let previous_end = self.end;
238 unsafe {
244 let begin = self.position + start;
245 let slice_end = begin + data_len;
246 if data_len < length {
248 ptr::copy(
249 data.as_ptr(),
250 self.memory[begin..slice_end].as_mut_ptr(),
251 data_len,
252 );
253
254 ptr::copy(
255 self.memory[start + length..self.end].as_ptr(),
256 self.memory[slice_end..].as_mut_ptr(),
257 self.end - (start + length),
258 );
259 self.end -= length - data_len;
260
261 } else {
263 ptr::copy(
264 self.memory[start + length..self.end].as_ptr(),
265 self.memory[start + data_len..].as_mut_ptr(),
266 self.end - (start + length),
267 );
268 ptr::copy(
269 data.as_ptr(),
270 self.memory[begin..slice_end].as_mut_ptr(),
271 data_len,
272 );
273 self.end += data_len - length;
274 }
275 }
276 if self.end < previous_end {
279 self.erase(self.end, previous_end);
280 }
281 Some(self.available_data())
282 }
283
284 pub fn insert_slice(&mut self, data: &[u8], start: usize) -> Option<usize> {
285 let data_len = data.len();
286 if start > self.available_data() || self.position + self.end + data_len > self.capacity {
287 return None;
288 }
289
290 unsafe {
296 let begin = self.position + start;
297 let slice_end = begin + data_len;
298 ptr::copy(
299 self.memory[start..self.end].as_ptr(),
300 self.memory[start + data_len..].as_mut_ptr(),
301 self.end - start,
302 );
303 ptr::copy(
304 data.as_ptr(),
305 self.memory[begin..slice_end].as_mut_ptr(),
306 data_len,
307 );
308 self.end += data_len;
309 }
310 Some(self.available_data())
311 }
312}
313
314impl Write for Buffer {
315 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
316 match self.space().write(buf) {
317 Ok(size) => {
318 self.fill(size);
319 Ok(size)
320 }
321 err => err,
322 }
323 }
324
325 fn flush(&mut self) -> io::Result<()> {
326 Ok(())
327 }
328}
329
330impl Read for Buffer {
331 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
332 let len = cmp::min(self.available_data(), buf.len());
333 unsafe {
339 ptr::copy(
340 self.memory[self.position..self.position + len].as_ptr(),
341 buf.as_mut_ptr(),
342 len,
343 );
344 }
345 self.erase(self.position, self.position + len);
347 self.position += len;
348 Ok(len)
349 }
350}
351
352impl Reset for Buffer {
353 fn reset(&mut self) {
354 self.reset();
355 }
356}
357
358#[cfg(test)]
359mod tests {
360 use std::io::Write;
361
362 use super::*;
363
364 #[test]
365 fn fill_and_consume() {
366 let mut b = Buffer::with_capacity(10);
367 assert_eq!(b.available_data(), 0);
368 assert_eq!(b.available_space(), 10);
369 let res = b.write(&b"abcd"[..]);
370 assert_eq!(res.ok(), Some(4));
371 assert_eq!(b.available_data(), 4);
372 assert_eq!(b.available_space(), 6);
373
374 assert_eq!(b.data(), &b"abcd"[..]);
375
376 b.consume(2);
377 assert_eq!(b.available_data(), 2);
378 assert_eq!(b.available_space(), 6);
379 assert_eq!(b.data(), &b"cd"[..]);
380
381 b.shift();
382 assert_eq!(b.available_data(), 2);
383 assert_eq!(b.available_space(), 8);
384 assert_eq!(b.data(), &b"cd"[..]);
385
386 assert_eq!(b.write(&b"efghijklmnop"[..]).ok(), Some(8));
387 assert_eq!(b.available_data(), 10);
388 assert_eq!(b.available_space(), 0);
389 assert_eq!(b.data(), &b"cdefghijkl"[..]);
390 b.shift();
391 assert_eq!(b.available_data(), 10);
392 assert_eq!(b.available_space(), 0);
393 assert_eq!(b.data(), &b"cdefghijkl"[..]);
394 }
395
396 #[test]
397 fn delete() {
398 let mut b = Buffer::with_capacity(10);
399 let _ = b.write(&b"abcdefgh"[..]).expect("should write");
400 assert_eq!(b.available_data(), 8);
401 assert_eq!(b.available_space(), 2);
402
403 assert_eq!(b.delete_slice(2, 3), Some(5));
404 assert_eq!(b.available_data(), 5);
405 assert_eq!(b.available_space(), 5);
406 assert_eq!(b.data(), &b"abfgh"[..]);
407
408 assert_eq!(b.delete_slice(5, 2), None);
409 assert_eq!(b.delete_slice(4, 2), None);
410 }
411
412 #[test]
413 fn replace() {
414 let mut b = Buffer::with_capacity(10);
415 let _ = b.write(&b"abcdefgh"[..]).expect("should write");
416 assert_eq!(b.available_data(), 8);
417 assert_eq!(b.available_space(), 2);
418
419 assert_eq!(b.replace_slice(&b"ABC"[..], 2, 3), Some(8));
420 assert_eq!(b.available_data(), 8);
421 assert_eq!(b.available_space(), 2);
422 assert_eq!(b.data(), &b"abABCfgh"[..]);
423
424 assert_eq!(b.replace_slice(&b"XYZ"[..], 8, 3), None);
425 assert_eq!(b.replace_slice(&b"XYZ"[..], 6, 3), None);
426
427 assert_eq!(b.replace_slice(&b"XYZ"[..], 2, 4), Some(7));
428 assert_eq!(b.available_data(), 7);
429 assert_eq!(b.available_space(), 3);
430 assert_eq!(b.data(), &b"abXYZgh"[..]);
431
432 assert_eq!(b.replace_slice(&b"123"[..], 2, 2), Some(8));
433 assert_eq!(b.available_data(), 8);
434 assert_eq!(b.available_space(), 2);
435 assert_eq!(b.data(), &b"ab123Zgh"[..]);
436 }
437}