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