diff --git a/src/guard.rs b/src/guard.rs index 282a663..08acffb 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -47,6 +47,10 @@ impl<'vec, T> ContentGuard<'vec, T> { self.erased.capacity() } + pub fn push(&mut self, value: T) { + self.with(|vec| vec.push(value)); + } + #[must_use] pub fn length(&self) -> usize { self.erased.length() @@ -68,4 +72,16 @@ impl<'vec, T> ContentGuard<'vec, T> { // SAFETY: The pointer and length correctly represent the currently initialized elements. unsafe { self.erased.parts.as_slice_mut() } } + + #[must_use] + pub fn into_slice(self) -> &'vec [T] { + // SAFETY: The pointer and length correctly represent the currently initialized elements. + unsafe { self.erased.parts.as_slice() } + } + + #[must_use] + pub fn into_slice_mut(self) -> &'vec mut [T] { + // SAFETY: The pointer and length correctly represent the currently initialized elements. + unsafe { self.erased.parts.as_slice_mut() } + } } diff --git a/src/lib.rs b/src/lib.rs index 6de0532..5d58360 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,7 +101,7 @@ impl TypeErasedVec { /// Clears all elements currently stored in the `TypeErasedVec`. /// /// Will fail if `T` does not have the same `Layout` as the underlying capacity. - pub fn try_to_type(&mut self) -> Option> { + pub fn try_as_type(&mut self) -> Option> { self.clear(); // SAFETY: The vector has been cleared, meaning there are no existing elements // that could be invalidated or improperly dropped by the cast. @@ -113,9 +113,9 @@ impl TypeErasedVec { /// /// # Panics /// Panics if `T` does not have the same `Layout` as the underlying capacity. - pub fn to_type(&mut self) -> ContentGuard<'_, T> { + pub fn as_type(&mut self) -> ContentGuard<'_, T> { let layout = self.layout; - self.try_to_type().unwrap_or_else(|| { + self.try_as_type().unwrap_or_else(|| { panic!( "Target type layout must exactly match the erased layout. Capacity is reserved for {:?} but {} has {:?}", layout, @@ -130,13 +130,13 @@ impl TypeErasedVec { /// /// # Safety /// `T` must have the same `Layout` as the underlying capacity. - pub unsafe fn to_type_unchecked(&mut self) -> ContentGuard<'_, T> { + pub unsafe fn as_type_unchecked(&mut self) -> ContentGuard<'_, T> { let layout = self.layout; - let res = self.try_to_type(); + let res = self.try_as_type(); if cfg!(debug_assertions) && res.is_none() { unreachable!( - "Calling `to_type_unchecked` with an incompatible layout is UB! Target type layout must exactly match the erased layout. Capacity is reserved for {:?} but {} has {:?}", + "Calling `as_type_unchecked` with an incompatible layout is UB! Target type layout must exactly match the erased layout. Capacity is reserved for {:?} but {} has {:?}", layout, std::any::type_name::(), Layout::new::() @@ -152,7 +152,7 @@ impl TypeErasedVec { /// # Errors /// Returns the original `TypeErasedVec` if `T` does not have the same `Layout`. pub fn try_into_vec(mut self) -> Result, Self> { - if let Some(mut guard) = self.try_to_type::() { + if let Some(mut guard) = self.try_as_type::() { Ok(guard.take()) } else { Err(self) @@ -165,7 +165,7 @@ impl TypeErasedVec { /// Panics if `T` does not have the same `Layout` as the underlying capacity. #[must_use] pub fn into_vec(mut self) -> Vec { - self.to_type::().take() + self.as_type::().take() } /// Convert the capacity of the erased `Vec` into a `Vec`. @@ -175,7 +175,7 @@ impl TypeErasedVec { #[must_use] pub unsafe fn into_vec_unchecked(mut self) -> Vec { // SAFETY: Ensured by the caller. - unsafe { self.to_type_unchecked().take() } + unsafe { self.as_type_unchecked().take() } } /// Clear a type erased vec allowing it be safely shared across threads, preserving the capacity diff --git a/src/tests.rs b/src/tests.rs index f7500f2..5f5033a 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -128,7 +128,7 @@ fn test_cast_type_success_and_mutation() { } #[test] -fn test_try_to_type_clears_elements() { +fn test_try_as_type_clears_elements() { let drop_count = Rc::new(Cell::new(0)); let mut vec = Vec::with_capacity(5); @@ -140,8 +140,8 @@ fn test_try_to_type_clears_elements() { let mut erased = TypeErasedVec::new(vec); assert_erased_state(&erased, 3, Layout::new::()); - let Some(guard) = erased.try_to_type::() else { - panic!("try_to_type failed despite matching layouts"); + let Some(guard) = erased.try_as_type::() else { + panic!("try_as_type failed despite matching layouts"); }; assert_guard_state(&guard, 0); @@ -190,7 +190,7 @@ fn test_conversion_methods() { assert!(restored.capacity() >= initial_cap); let mut erased2 = TypeErasedVec::new(restored); - let mut guard = erased2.to_type::(); + let mut guard = erased2.as_type::(); guard.reserve(20); let new_cap = guard.capacity(); @@ -222,10 +222,10 @@ fn test_try_into_vec_failure_and_recovery() { #[test] #[should_panic(expected = "Target type layout must exactly match")] -fn test_to_type_panics_on_layout_mismatch() { +fn test_as_type_panics_on_layout_mismatch() { let vec = Vec::::new(); let mut erased = TypeErasedVec::new(vec); - let _ = erased.to_type::(); + let _ = erased.as_type::(); } #[test] @@ -238,18 +238,18 @@ fn test_into_vec_panics_on_layout_mismatch() { #[test] #[cfg(debug_assertions)] -#[should_panic(expected = "Calling `to_type_unchecked` with an incompatible layout is UB!")] -fn test_to_type_unchecked_panics_on_layout_mismatch_in_debug() { +#[should_panic(expected = "Calling `as_type_unchecked` with an incompatible layout is UB!")] +fn test_as_type_unchecked_panics_on_layout_mismatch_in_debug() { let vec = Vec::::new(); let mut erased = TypeErasedVec::new(vec); unsafe { - let _ = erased.to_type_unchecked::(); + let _ = erased.as_type_unchecked::(); } } #[test] #[cfg(debug_assertions)] -#[should_panic(expected = "Calling `to_type_unchecked` with an incompatible layout is UB!")] +#[should_panic(expected = "Calling `as_type_unchecked` with an incompatible layout is UB!")] fn test_into_vec_unchecked_panics_on_layout_mismatch_in_debug() { let vec = Vec::::new(); let erased = TypeErasedVec::new(vec);