ringbuf/
storage.rs
1#[cfg(feature = "alloc")]
2use alloc::{boxed::Box, vec::Vec};
3use core::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, ops::Range, ptr::NonNull, slice};
4#[cfg(feature = "alloc")]
5use core::{mem::forget, ptr};
6
7pub unsafe trait Storage {
20 type Item: Sized;
22
23 fn len(&self) -> usize;
25 fn is_empty(&self) -> bool {
26 self.len() == 0
27 }
28
29 fn as_ptr(&self) -> *const MaybeUninit<Self::Item> {
31 self.as_mut_ptr().cast_const()
32 }
33 fn as_mut_ptr(&self) -> *mut MaybeUninit<Self::Item>;
35
36 unsafe fn slice(&self, range: Range<usize>) -> &[MaybeUninit<Self::Item>] {
44 slice::from_raw_parts(self.as_ptr().add(range.start), range.len())
45 }
46 #[allow(clippy::mut_from_ref)]
52 unsafe fn slice_mut(&self, range: Range<usize>) -> &mut [MaybeUninit<Self::Item>] {
53 slice::from_raw_parts_mut(self.as_mut_ptr().add(range.start), range.len())
54 }
55}
56
57pub struct Ref<'a, T> {
58 _ghost: PhantomData<&'a mut [T]>,
59 ptr: *mut MaybeUninit<T>,
60 len: usize,
61}
62unsafe impl<'a, T> Send for Ref<'a, T> where T: Send {}
63unsafe impl<'a, T> Sync for Ref<'a, T> where T: Send {}
64unsafe impl<'a, T> Storage for Ref<'a, T> {
65 type Item = T;
66 #[inline]
67 fn as_mut_ptr(&self) -> *mut MaybeUninit<T> {
68 self.ptr
69 }
70 #[inline]
71 fn len(&self) -> usize {
72 self.len
73 }
74}
75impl<'a, T> From<&'a mut [MaybeUninit<T>]> for Ref<'a, T> {
76 fn from(value: &'a mut [MaybeUninit<T>]) -> Self {
77 Self {
78 _ghost: PhantomData,
79 ptr: value.as_mut_ptr(),
80 len: value.len(),
81 }
82 }
83}
84impl<'a, T> From<Ref<'a, T>> for &'a mut [MaybeUninit<T>] {
85 fn from(value: Ref<'a, T>) -> Self {
86 unsafe { slice::from_raw_parts_mut(value.ptr, value.len) }
87 }
88}
89
90pub struct Owning<T: ?Sized> {
91 data: UnsafeCell<T>,
92}
93unsafe impl<T: ?Sized> Sync for Owning<T> where T: Send {}
94impl<T> From<T> for Owning<T> {
95 fn from(value: T) -> Self {
96 Self {
97 data: UnsafeCell::new(value),
98 }
99 }
100}
101
102pub type Array<T, const N: usize> = Owning<[MaybeUninit<T>; N]>;
103unsafe impl<T, const N: usize> Storage for Array<T, N> {
104 type Item = T;
105 #[inline]
106 fn as_mut_ptr(&self) -> *mut MaybeUninit<T> {
107 self.data.get() as *mut _
108 }
109 #[inline]
110 fn len(&self) -> usize {
111 N
112 }
113}
114impl<T, const N: usize> From<Array<T, N>> for [MaybeUninit<T>; N] {
115 fn from(value: Array<T, N>) -> Self {
116 value.data.into_inner()
117 }
118}
119
120pub type Slice<T> = Owning<[MaybeUninit<T>]>;
121unsafe impl<T> Storage for Slice<T> {
122 type Item = T;
123 #[inline]
124 fn as_mut_ptr(&self) -> *mut MaybeUninit<T> {
125 self.data.get() as *mut _
126 }
127 #[inline]
128 fn len(&self) -> usize {
129 unsafe { NonNull::new_unchecked(self.data.get()) }.len()
130 }
131}
132
133#[cfg(feature = "alloc")]
134pub struct Heap<T> {
135 ptr: *mut MaybeUninit<T>,
136 len: usize,
137}
138#[cfg(feature = "alloc")]
139unsafe impl<T> Send for Heap<T> where T: Send {}
140#[cfg(feature = "alloc")]
141unsafe impl<T> Sync for Heap<T> where T: Send {}
142#[cfg(feature = "alloc")]
143unsafe impl<T> Storage for Heap<T> {
144 type Item = T;
145 #[inline]
146 fn as_mut_ptr(&self) -> *mut MaybeUninit<T> {
147 self.ptr
148 }
149 #[inline]
150 fn len(&self) -> usize {
151 self.len
152 }
153}
154#[cfg(feature = "alloc")]
155impl<T> Heap<T> {
156 pub fn new(capacity: usize) -> Self {
157 Self {
158 ptr: Vec::<T>::with_capacity(capacity).leak() as *mut _ as *mut MaybeUninit<T>,
159 len: capacity,
160 }
161 }
162}
163#[cfg(feature = "alloc")]
164impl<T> From<Vec<MaybeUninit<T>>> for Heap<T> {
165 fn from(mut value: Vec<MaybeUninit<T>>) -> Self {
166 let len = value.capacity();
167 let ptr = value.as_mut_ptr();
168 forget(value);
169 Self { ptr, len }
170 }
171}
172#[cfg(feature = "alloc")]
173impl<T> From<Box<[MaybeUninit<T>]>> for Heap<T> {
174 fn from(value: Box<[MaybeUninit<T>]>) -> Self {
175 Self {
176 len: value.len(),
177 ptr: Box::into_raw(value) as *mut MaybeUninit<T>,
178 }
179 }
180}
181#[cfg(feature = "alloc")]
182impl<T> From<Heap<T>> for Box<[MaybeUninit<T>]> {
183 fn from(value: Heap<T>) -> Self {
184 unsafe { Box::from_raw(ptr::slice_from_raw_parts_mut(value.ptr, value.len)) }
185 }
186}
187#[cfg(feature = "alloc")]
188impl<T> Drop for Heap<T> {
189 fn drop(&mut self) {
190 drop(unsafe { Box::from_raw(ptr::slice_from_raw_parts_mut(self.ptr, self.len)) });
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197 use core::{cell::Cell, marker::PhantomData};
198
199 struct Check<S: Storage + Send + Sync + ?Sized>(PhantomData<S>);
200
201 #[allow(dead_code)]
202 fn check_send_sync() {
203 let _: Check<Ref<Cell<i32>>>;
204 let _: Check<Array<Cell<i32>, 4>>;
205 let _: Check<Slice<Cell<i32>>>;
206 let _: Check<Heap<Cell<i32>>>;
207 }
208}