mini_io_queue/storage/
stack_buffer.rs

1use array_init::array_init;
2use core::cell::UnsafeCell;
3use core::fmt;
4use core::mem::MaybeUninit;
5
6/// Backing buffer for a queue, allocated on the stack.
7///
8/// All queues require a backing buffer which implements the [`Storage`] trait. This buffer stores
9/// values in a contiguous array allocated on the stack. Compare this to [`HeapBuffer`] which uses
10/// a contiguous array on the heap. Note that both the [`asyncio`] and [`nonblocking`] queues move
11/// their buffer to the heap anyway.
12///
13/// # Example
14///
15/// ```
16/// use mini_io_queue::nonblocking;
17/// use mini_io_queue::storage::StackBuffer;
18///
19/// let buffer: StackBuffer<u8, 100> = StackBuffer::default();
20/// let (reader, writer) = nonblocking::queue_from(buffer);
21/// ```
22///
23/// [`Storage`]: crate::storage::Storage
24/// [`HeapBuffer`]: crate::storage::HeapBuffer
25/// [`asyncio`]: crate::asyncio
26/// [`nonblocking`]: crate::nonblocking
27#[cfg_attr(docsrs, doc(cfg(feature = "stack-buffer")))]
28pub struct StackBuffer<T, const N: usize>([UnsafeCell<T>; N]);
29
30unsafe impl<T, const N: usize> Send for StackBuffer<T, N> where T: Send {}
31unsafe impl<T, const N: usize> Sync for StackBuffer<T, N> where T: Sync {}
32
33impl<T, const N: usize> Default for StackBuffer<T, N>
34where
35    T: Default,
36{
37    fn default() -> Self {
38        StackBuffer(array_init(|_| Default::default()))
39    }
40}
41
42impl<T, const N: usize> AsRef<[UnsafeCell<T>]> for StackBuffer<T, N> {
43    fn as_ref(&self) -> &[UnsafeCell<T>] {
44        &self.0
45    }
46}
47
48impl<T, const N: usize> From<[T; N]> for StackBuffer<T, N> {
49    fn from(arr: [T; N]) -> Self {
50        let arr = MaybeUninit::new(arr);
51        let unsafe_cell_arr_ptr = arr.as_ptr() as *const [UnsafeCell<T>; N];
52
53        // Safety: UnsafeCell is repr(transparent), so has the same alignment as T.
54        let unsafe_cell_arr = unsafe { core::ptr::read(unsafe_cell_arr_ptr) };
55        StackBuffer(unsafe_cell_arr)
56    }
57}
58
59impl<T, const N: usize> fmt::Debug for StackBuffer<T, N>
60where
61    T: fmt::Debug,
62{
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        f.debug_tuple("StackBuffer").finish()
65    }
66}