diff --git a/src/rb/macros.rs b/src/rb/macros.rs index 3ec8dd3..7099b8a 100644 --- a/src/rb/macros.rs +++ b/src/rb/macros.rs @@ -20,12 +20,23 @@ macro_rules! rb_impl_init { pub fn try_new(capacity: usize) -> Result { let mut vec = alloc::vec::Vec::new(); vec.try_reserve_exact(capacity)?; - let ptr = vec.as_mut_ptr(); - core::mem::forget(vec); - let data = unsafe { Box::from_raw(core::ptr::slice_from_raw_parts_mut(ptr, capacity)) }; - assert_eq!(data.len(), capacity); - assert_eq!(ptr as *const _, data.as_ptr()); - Ok(unsafe { Self::from_raw_parts(data.into(), usize::default(), usize::default()) }) + Ok(unsafe { Self::from_raw_parts(vec.into(), usize::default(), usize::default()) }) + } + } + + #[cfg(feature = "alloc")] + impl From> for $type> { + fn from(value: alloc::vec::Vec) -> Self { + let (read, write) = (0, value.len()); + unsafe { Self::from_raw_parts(crate::utils::vec_to_uninit(value).into(), read, write) } + } + } + + #[cfg(feature = "alloc")] + impl From> for $type> { + fn from(value: alloc::boxed::Box<[T]>) -> Self { + let (read, write) = (0, value.len()); + unsafe { Self::from_raw_parts(crate::utils::boxed_slice_to_uninit(value).into(), read, write) } } } }; diff --git a/src/storage.rs b/src/storage.rs index 063c1e1..891af01 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -1,8 +1,8 @@ #[cfg(feature = "alloc")] use alloc::{boxed::Box, vec::Vec}; -#[cfg(feature = "alloc")] -use core::ptr; use core::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, ops::Range, ptr::NonNull, slice}; +#[cfg(feature = "alloc")] +use core::{mem::forget, ptr}; /// Abstract storage for the ring buffer. /// @@ -161,6 +161,15 @@ impl Heap { } } #[cfg(feature = "alloc")] +impl From>> for Heap { + fn from(mut value: Vec>) -> Self { + let len = value.capacity(); + let ptr = value.as_mut_ptr(); + forget(value); + Self { ptr, len } + } +} +#[cfg(feature = "alloc")] impl From]>> for Heap { fn from(value: Box<[MaybeUninit]>) -> Self { Self { diff --git a/src/tests/init.rs b/src/tests/init.rs new file mode 100644 index 0000000..0fcd511 --- /dev/null +++ b/src/tests/init.rs @@ -0,0 +1,54 @@ +use super::Rb; +use crate::{storage::Heap, traits::*}; +use alloc::{boxed::Box, vec::Vec}; + +#[test] +fn new() { + const CAP: usize = 2; + let rb = Rb::>::new(CAP); + let (mut prod, mut cons) = rb.split(); + + assert_eq!(prod.capacity().get(), CAP); + + assert_eq!(prod.try_push(0), Ok(())); + assert_eq!(prod.try_push(1), Ok(())); + assert_eq!(prod.try_push(2), Err(2)); + + assert_eq!(cons.try_pop(), Some(0)); + assert_eq!(cons.try_pop(), Some(1)); + assert_eq!(cons.try_pop(), None); +} + +#[test] +fn from_vec() { + let mut vec = Vec::with_capacity(2); + vec.push(123); + let rb = Rb::>::from(vec); + let (mut prod, mut cons) = rb.split(); + + assert_eq!(prod.capacity().get(), 2); + assert_eq!(cons.occupied_len(), 1); + + assert_eq!(prod.try_push(321), Ok(())); + assert_eq!(prod.try_push(444), Err(444)); + + assert_eq!(cons.try_pop(), Some(123)); + assert_eq!(cons.try_pop(), Some(321)); + assert_eq!(cons.try_pop(), None); +} + +#[test] +fn from_boxed_slice() { + let boxed_slice = Box::new([123, 321]) as Box<[i32]>; + let rb = Rb::>::from(boxed_slice); + let (mut prod, mut cons) = rb.split(); + + assert_eq!(prod.capacity().get(), 2); + assert_eq!(cons.occupied_len(), 2); + + assert_eq!(prod.try_push(444), Err(444)); + + assert_eq!(cons.try_pop(), Some(123)); + assert_eq!(cons.try_pop(), Some(321)); + assert_eq!(cons.try_pop(), None); +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 933a1ef..e0f15fa 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -10,6 +10,8 @@ mod drop; mod fmt_write; mod frozen; mod hold; +#[cfg(feature = "alloc")] +mod init; mod iter; mod overwrite; #[cfg(feature = "std")] diff --git a/src/utils.rs b/src/utils.rs index c6783f9..f6fc935 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, vec::Vec}; use core::mem::{self, MaybeUninit}; // TODO: Remove on `maybe_uninit_uninit_array` stabilization. @@ -26,3 +28,17 @@ pub unsafe fn write_uninit_slice<'a, T: Copy>(dst: &'a mut [T], src: &[MaybeUnin dst.copy_from_slice(slice_assume_init_ref(src)); dst } + +#[cfg(feature = "alloc")] +pub fn vec_to_uninit(value: Vec) -> Vec> { + let value = mem::ManuallyDrop::new(value); + let ptr = &value as *const _ as *const Vec>; + unsafe { ptr.read() } +} + +#[cfg(feature = "alloc")] +pub fn boxed_slice_to_uninit(value: Box<[T]>) -> Box<[MaybeUninit]> { + let value = mem::ManuallyDrop::new(value); + let ptr = &value as *const _ as *const Box<[MaybeUninit]>; + unsafe { ptr.read() } +}