Skip to main content

ferogram_crypto/
deque_buffer.rs

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