mini_io_queue/storage/
heap_buffer.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::cell::UnsafeCell;
4use core::fmt;
5
6/// Backing buffer for a queue, allocated on the heap.
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 heap. Compare this to [`StackBuffer`] which uses
10/// a contiguous array on the stack. Note that the [`asyncio`], [`blocking`] and [`nonblocking`]
11/// queues move their buffer to the heap anyway.
12///
13/// # Example
14///
15/// ```
16/// use mini_io_queue::nonblocking;
17/// use mini_io_queue::storage::HeapBuffer;
18///
19/// let buffer: HeapBuffer<u8> = HeapBuffer::new(100);
20/// let (reader, writer) = nonblocking::queue_from(buffer);
21/// ```
22///
23/// [`Storage`]: crate::storage::Storage
24/// [`StackBuffer`]: crate::storage::StackBuffer
25/// [`asyncio`]: crate::asyncio
26/// [`blocking`]: crate::blocking
27/// [`nonblocking`]: crate::nonblocking
28#[cfg_attr(docsrs, doc(cfg(feature = "heap-buffer")))]
29pub struct HeapBuffer<T>(Box<[UnsafeCell<T>]>);
30
31unsafe impl<T> Send for HeapBuffer<T> where T: Send {}
32unsafe impl<T> Sync for HeapBuffer<T> where T: Sync {}
33
34impl<T> HeapBuffer<T>
35where
36    T: Default,
37{
38    /// Creates a buffer with the provided capacity. All elements in the buffer will be initialized
39    /// to the item's default value.
40    pub fn new(capacity: usize) -> Self {
41        let mut vec = Vec::new();
42        vec.resize_with(capacity, Default::default);
43        HeapBuffer(vec.into_boxed_slice())
44    }
45}
46
47impl<T> AsRef<[UnsafeCell<T>]> for HeapBuffer<T> {
48    fn as_ref(&self) -> &[UnsafeCell<T>] {
49        self.0.as_ref()
50    }
51}
52
53impl<T> From<Box<[T]>> for HeapBuffer<T> {
54    fn from(boxed_slice: Box<[T]>) -> Self {
55        // Safety: UnsafeCell is repr(transparent) so this is safe.
56        // fixme: this might not be stable, ideally we should not rely on it.
57        let unsafe_cell_box: Box<[UnsafeCell<T>]> = unsafe { core::mem::transmute(boxed_slice) };
58        HeapBuffer(unsafe_cell_box)
59    }
60}
61
62impl<T> fmt::Debug for HeapBuffer<T>
63where
64    T: fmt::Debug,
65{
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        f.debug_tuple("HeapBuffer").finish()
68    }
69}