Skip to main content

layer_crypto/
deque_buffer.rs

1// Copyright (c) Ankit Chaubey <ankitchaubey.dev@gmail.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4// NOTE:
5// The "Layer" project is no longer maintained or supported.
6// Its original purpose for personal SDK/APK experimentation and learning
7// has been fulfilled.
8//
9// Please use Ferogram instead:
10// https://github.com/ankit-chaubey/ferogram
11// Ferogram will receive future updates and development, although progress
12// may be slower.
13//
14// Ferogram is an async Telegram MTProto client library written in Rust.
15// Its implementation follows the behaviour of the official Telegram clients,
16// particularly Telegram Desktop and TDLib, and aims to provide a clean and
17// modern async interface for building Telegram clients and tools.
18
19//! A deque-like growable buffer that supports efficient prepend.
20
21use std::ops::{Index, IndexMut};
22use std::slice::SliceIndex;
23
24/// Growable byte buffer that supports efficient front-extension.
25#[derive(Clone, Debug)]
26pub struct DequeBuffer {
27    buf: Vec<u8>,
28    head: usize,
29    default_head: usize,
30}
31
32impl DequeBuffer {
33    /// Create with reserved space for `back` bytes in the back and `front` in the front.
34    pub fn with_capacity(back: usize, front: usize) -> Self {
35        let mut buf = Vec::with_capacity(front + back);
36        buf.resize(front, 0);
37        Self {
38            buf,
39            head: front,
40            default_head: front,
41        }
42    }
43
44    /// Reset the buffer to empty (but keep allocation).
45    pub fn clear(&mut self) {
46        self.buf.truncate(self.default_head);
47        self.buf[..self.head].fill(0);
48        self.head = self.default_head;
49    }
50
51    /// Prepend `slice` to the front.
52    pub fn extend_front(&mut self, slice: &[u8]) {
53        if self.head >= slice.len() {
54            self.head -= slice.len();
55        } else {
56            let shift = slice.len() - self.head;
57            self.buf.extend(std::iter::repeat_n(0, shift));
58            self.buf.rotate_right(shift);
59            self.head = 0;
60        }
61        self.buf[self.head..self.head + slice.len()].copy_from_slice(slice);
62    }
63
64    /// Number of bytes in the buffer.
65    pub fn len(&self) -> usize {
66        self.buf.len() - self.head
67    }
68
69    /// True if empty.
70    pub fn is_empty(&self) -> bool {
71        self.head == self.buf.len()
72    }
73}
74
75impl AsRef<[u8]> for DequeBuffer {
76    fn as_ref(&self) -> &[u8] {
77        &self.buf[self.head..]
78    }
79}
80impl AsMut<[u8]> for DequeBuffer {
81    fn as_mut(&mut self) -> &mut [u8] {
82        &mut self.buf[self.head..]
83    }
84}
85impl<I: SliceIndex<[u8]>> Index<I> for DequeBuffer {
86    type Output = I::Output;
87    fn index(&self, i: I) -> &Self::Output {
88        self.as_ref().index(i)
89    }
90}
91impl<I: SliceIndex<[u8]>> IndexMut<I> for DequeBuffer {
92    fn index_mut(&mut self, i: I) -> &mut Self::Output {
93        self.as_mut().index_mut(i)
94    }
95}
96impl Extend<u8> for DequeBuffer {
97    fn extend<T: IntoIterator<Item = u8>>(&mut self, iter: T) {
98        self.buf.extend(iter);
99    }
100}
101impl<'a> Extend<&'a u8> for DequeBuffer {
102    fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, iter: T) {
103        self.buf.extend(iter);
104    }
105}