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