s2n_quic_core/buffer/
deque.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::slice::deque;
5use alloc::{boxed::Box, vec::Vec};
6use core::{fmt, mem::MaybeUninit};
7
8mod storage;
9
10#[cfg(test)]
11mod tests;
12
13/// A fixed-capacity ring buffer for bytes
14#[derive(Clone)]
15pub struct Deque {
16    bytes: Box<[MaybeUninit<u8>]>,
17    head: usize,
18    len: usize,
19}
20
21impl fmt::Debug for Deque {
22    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23        f.debug_struct("Deque")
24            .field("len", &self.len())
25            .field("capacity", &self.capacity())
26            .finish()
27    }
28}
29
30impl From<Vec<u8>> for Deque {
31    #[inline]
32    fn from(mut buffer: Vec<u8>) -> Deque {
33        let len = buffer.len();
34        let mut capacity = buffer.capacity();
35        if !capacity.is_power_of_two() {
36            capacity = capacity.next_power_of_two();
37            buffer.reserve_exact(capacity - len);
38            debug_assert!(capacity.is_power_of_two());
39        }
40
41        unsafe {
42            buffer.set_len(capacity);
43        }
44
45        let bytes = buffer.into_boxed_slice();
46        let ptr = Box::into_raw(bytes);
47        let bytes = unsafe { Box::from_raw(ptr as *mut [MaybeUninit<u8>]) };
48
49        Self {
50            bytes,
51            head: 0,
52            len,
53        }
54    }
55}
56
57impl Deque {
58    #[inline]
59    pub fn new(mut capacity: usize) -> Self {
60        // Make sure capacity is set to a power of two
61        // https://doc.rust-lang.org/std/primitive.usize.html#method.next_power_of_two
62        //> Returns the smallest power of two greater than or equal to self.
63        capacity = capacity.next_power_of_two();
64
65        let mut bytes = Vec::<MaybeUninit<u8>>::with_capacity(capacity);
66        unsafe {
67            bytes.set_len(capacity);
68        }
69        let bytes = bytes.into_boxed_slice();
70
71        Self {
72            bytes,
73            head: 0,
74            len: 0,
75        }
76    }
77
78    #[inline]
79    pub fn capacity(&self) -> usize {
80        self.bytes.len()
81    }
82
83    #[inline]
84    pub fn remaining_capacity(&self) -> usize {
85        self.preconditions();
86        self.capacity() - self.len()
87    }
88
89    #[inline]
90    pub fn len(&self) -> usize {
91        self.len
92    }
93
94    #[inline]
95    pub fn is_empty(&self) -> bool {
96        self.len == 0
97    }
98
99    /// Resets the filled bytes in the buffer
100    ///
101    /// Note that data is not actually wiped with this method. If that behavior is desired then
102    /// calling [`Self::consume_filled`] should be preferred.
103    #[inline]
104    pub fn clear(&mut self) {
105        self.head = 0;
106        self.len = 0;
107    }
108
109    /// Consumes `len` bytes from the head of the buffer
110    ///
111    /// # Panics
112    ///
113    /// `len` MUST be less than or equal to [`Self::len`]
114    #[inline]
115    pub fn consume(&mut self, len: usize) {
116        self.preconditions();
117
118        assert!(self.len() >= len);
119
120        if len >= self.len() {
121            self.clear();
122            return;
123        }
124
125        // Wrap the head around the capacity
126        self.head = deque::wrap(&self.bytes, self.head, len);
127        self.len -= len;
128
129        self.postconditions()
130    }
131
132    /// Returns the filled bytes in the buffer
133    #[inline]
134    pub fn filled(&mut self) -> deque::Pair<&mut [u8]> {
135        self.preconditions();
136
137        unsafe {
138            // SAFETY: cursors guarantee memory is filled
139            deque::filled(&mut self.bytes, self.head, self.len).assume_init_mut()
140        }
141    }
142
143    /// Returns and consumes `len` filled bytes in the buffer
144    ///
145    /// # Panics
146    ///
147    /// `len` MUST be less than or equal to [`Self::len`]
148    #[inline]
149    pub fn consume_filled(&mut self, len: usize) -> deque::Pair<&mut [u8]> {
150        self.preconditions();
151
152        let head = self.head;
153
154        self.consume(len);
155
156        self.postconditions();
157
158        unsafe {
159            // SAFETY: cursors guarantee memory is filled
160            deque::filled(&mut self.bytes, head, len).assume_init_mut()
161        }
162    }
163
164    /// Returns the unfilled bytes in the buffer
165    ///
166    /// Callers will need to call [`Self::fill`] to indicate any writes that occurred to returned
167    /// slices.
168    #[inline]
169    pub fn unfilled(&mut self) -> deque::Pair<&mut [MaybeUninit<u8>]> {
170        self.preconditions();
171        deque::unfilled(&mut self.bytes, self.head, self.len)
172    }
173
174    /// Makes the buffer contiguous and contained in a single slice
175    #[inline]
176    pub fn make_contiguous(&mut self) -> &mut [u8] {
177        self.preconditions();
178        deque::make_contiguous(&mut self.bytes, &mut self.head, self.len);
179        self.postconditions();
180
181        let (head, tail) = self.filled().into();
182        debug_assert!(tail.is_empty());
183        head
184    }
185
186    /// Notifies the buffer that `len` bytes were written to it
187    ///
188    /// # Safety
189    ///
190    /// Callers must ensure the filled bytes were actually initialized
191    #[inline]
192    pub unsafe fn fill(&mut self, len: usize) -> Result<(), FillError> {
193        ensure!(self.remaining_capacity() >= len, Err(FillError(())));
194
195        self.len += len;
196
197        self.postconditions();
198
199        Ok(())
200    }
201
202    #[inline(always)]
203    fn preconditions(&self) {
204        unsafe {
205            assume!(deque::invariants(&self.bytes, self.head, self.len));
206            assume!(self.capacity().is_power_of_two());
207        }
208    }
209
210    #[inline(always)]
211    fn postconditions(&self) {
212        debug_assert!(deque::invariants(&self.bytes, self.head, self.len));
213    }
214}
215
216#[derive(Clone, Copy, Debug, Default)]
217pub struct FillError(());
218
219impl fmt::Display for FillError {
220    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221        write!(
222            f,
223            "the buffer does not have enough capacity for the provided fill amount"
224        )
225    }
226}
227
228#[cfg(feature = "std")]
229impl std::error::Error for FillError {}
230
231#[cfg(feature = "std")]
232impl From<FillError> for std::io::Error {
233    #[inline]
234    fn from(value: FillError) -> Self {
235        Self::new(std::io::ErrorKind::InvalidInput, value)
236    }
237}