Skip to main content

ferogram_crypto/
deque_buffer.rs

1/*
2 * Copyright (c) 2026 Ankit Chaubey <ankitchaubey.dev@gmail.com>
3 * https://github.com/ankit-chaubey
4 *
5 * Project: ferogram
6 * Website: https://ferogram.dev
7 *
8 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
9 * https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
10 * <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
11 * This file may not be copied, modified, or distributed except according
12 * to those terms.
13 */
14
15use std::ops::{Index, IndexMut};
16use std::slice::SliceIndex;
17
18/// Growable byte buffer that supports efficient front-extension.
19#[derive(Clone, Debug)]
20pub struct DequeBuffer {
21    buf: Vec<u8>,
22    head: usize,
23    default_head: usize,
24}
25
26impl DequeBuffer {
27    /// Create with reserved space for `back` bytes in the back and `front` in the front.
28    pub fn with_capacity(back: usize, front: usize) -> Self {
29        let mut buf = Vec::with_capacity(front + back);
30        buf.resize(front, 0);
31        Self {
32            buf,
33            head: front,
34            default_head: front,
35        }
36    }
37
38    /// Reset the buffer to empty (but keep allocation).
39    pub fn clear(&mut self) {
40        self.buf.truncate(self.default_head);
41        self.buf[..self.head].fill(0);
42        self.head = self.default_head;
43    }
44
45    /// Prepend `slice` to the front.
46    pub fn extend_front(&mut self, slice: &[u8]) {
47        if self.head >= slice.len() {
48            self.head -= slice.len();
49        } else {
50            let shift = slice.len() - self.head;
51            self.buf.extend(std::iter::repeat_n(0, shift));
52            self.buf.rotate_right(shift);
53            self.head = 0;
54        }
55        self.buf[self.head..self.head + slice.len()].copy_from_slice(slice);
56    }
57
58    /// Number of bytes in the buffer.
59    pub fn len(&self) -> usize {
60        self.buf.len() - self.head
61    }
62
63    /// True if empty.
64    pub fn is_empty(&self) -> bool {
65        self.head == self.buf.len()
66    }
67}
68
69impl AsRef<[u8]> for DequeBuffer {
70    fn as_ref(&self) -> &[u8] {
71        &self.buf[self.head..]
72    }
73}
74impl AsMut<[u8]> for DequeBuffer {
75    fn as_mut(&mut self) -> &mut [u8] {
76        &mut self.buf[self.head..]
77    }
78}
79impl<I: SliceIndex<[u8]>> Index<I> for DequeBuffer {
80    type Output = I::Output;
81    fn index(&self, i: I) -> &Self::Output {
82        self.as_ref().index(i)
83    }
84}
85impl<I: SliceIndex<[u8]>> IndexMut<I> for DequeBuffer {
86    fn index_mut(&mut self, i: I) -> &mut Self::Output {
87        self.as_mut().index_mut(i)
88    }
89}
90impl Extend<u8> for DequeBuffer {
91    fn extend<T: IntoIterator<Item = u8>>(&mut self, iter: T) {
92        self.buf.extend(iter);
93    }
94}
95impl<'a> Extend<&'a u8> for DequeBuffer {
96    fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, iter: T) {
97        self.buf.extend(iter);
98    }
99}