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}