swap_buffer_queue/buffer/
vec.rs

1use alloc::boxed::Box;
2use core::{cell::Cell, mem::MaybeUninit, ops::Range};
3
4use crate::buffer::{Buffer, CellBuffer, Drain, Resize};
5
6/// A simple vector buffer.
7pub struct VecBuffer<T>(Box<[Cell<MaybeUninit<T>>]>);
8
9impl<T> Default for VecBuffer<T> {
10    fn default() -> Self {
11        Self(Default::default())
12    }
13}
14
15// SAFETY: `VecBuffer::clear` does clear the inserted range from the buffer
16unsafe impl<T> Buffer for VecBuffer<T> {
17    type Slice<'a> = &'a mut [T]
18    where
19        T: 'a;
20
21    #[inline]
22    fn capacity(&self) -> usize {
23        self.0.len()
24    }
25
26    #[inline]
27    unsafe fn slice(&mut self, range: Range<usize>) -> Self::Slice<'_> {
28        // SAFETY: [Cell<MaybeUninit<T>>] has the same layout as [T]
29        // and function contract guarantees that the range is initialized
30        unsafe { &mut *(&mut self.0[range] as *mut _ as *mut [T]) }
31    }
32
33    #[inline]
34    unsafe fn clear(&mut self, range: Range<usize>) {
35        for index in range {
36            // SAFETY: function contract guarantees that the range is initialized
37            unsafe { self.remove(index) };
38        }
39    }
40}
41
42// SAFETY: `insert` does initialize the index in the buffer
43unsafe impl<T> CellBuffer<T> for VecBuffer<T> {
44    unsafe fn insert(&self, index: usize, value: T) {
45        self.0[index].set(MaybeUninit::new(value));
46    }
47}
48
49impl<T> Resize for VecBuffer<T> {
50    fn resize(&mut self, capacity: usize) {
51        self.0 = (0..capacity)
52            .map(|_| Cell::new(MaybeUninit::uninit()))
53            .collect();
54    }
55}
56
57// SAFETY: `VecBuffer::remove` does remove the index from the buffer
58unsafe impl<T> Drain for VecBuffer<T> {
59    type Value = T;
60    #[inline]
61    unsafe fn remove(&mut self, index: usize) -> Self::Value {
62        // SAFETY: function contract guarantees that the index has been inserted and is then initialized
63        unsafe { self.0[index].get_mut().assume_init_read() }
64    }
65}