diff --git a/CHANGELOG.md b/CHANGELOG.md index 470ebb3..80e2720 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.14.0 +### Removed +- Helpers `any_value::move_out`, `any_value::move_out_w_size` removed as redundant. + ## 0.13.0 ### Added - `AnyVec` now can work with `AnyValueSizeless`. diff --git a/src/any_value/mod.rs b/src/any_value/mod.rs index 2ea9a3f..243f6d5 100644 --- a/src/any_value/mod.rs +++ b/src/any_value/mod.rs @@ -26,7 +26,7 @@ mod lazy_clone; pub use lazy_clone::LazyClone; pub use wrapper::AnyValueWrapper; -pub use raw::{AnyValueRaw, AnyValueTypelessRaw, AnyValueSizelessRaw}; +pub use raw::{AnyValueRaw, AnyValueSizelessRaw, AnyValueTypelessRaw}; use std::any::TypeId; use std::{mem, ptr}; @@ -80,48 +80,19 @@ pub trait AnyValueSizeless { /// /// # Safety /// - /// `bytes_size` must be correct object size. - /// `out` must have at least `bytes_size` bytes. - /// `KnownType` must be correct object type or [Unknown]. - /// - /// # Helpers - /// - /// Due to Rust limitations in generic department, you may found - /// useful helpers [move_out] and [move_out_w_size]. + /// - `bytes_size` must be correct object size. + /// - `out` must not overlap with `self`. + /// - `out` must have at least `bytes_size` bytes. + /// - `KnownType` must be correct object type or [Unknown]. #[inline] unsafe fn move_into(self, out: *mut u8, bytes_size: usize) where Self: Sized { - copy_bytes::(self.as_bytes_ptr(), out, bytes_size); + crate::copy_nonoverlapping_value::(self.as_bytes_ptr(), out, bytes_size); mem::forget(self); } } -/// Wrapper for AnyValueTypeless around [move_into]. -/// -/// You may need this because of Rust's generics limitations. -/// -/// [move_into]: AnyValueSizeless::move_into -#[inline] -pub unsafe fn move_out(this: T, out: *mut u8) { - let size = this.size(); - this.move_into::(out, size); -} - -/// Wrapper for AnyValueSizeless around [move_into]. -/// -/// You may need this because of Rust's generics limitations. -/// -/// N.B. For moving out values of [Unknown] type, of the same size, in tight loops - -/// this may perform faster then [move_out], since compiler will be -/// able to optimize better, knowing that all values have the same size. -/// -/// [move_into]: AnyValueSizeless::move_into -#[inline] -pub unsafe fn move_out_w_size(this: T, out: *mut u8, bytes_size: usize) { - this.move_into::(out, bytes_size); -} - /// [AnyValue] that doesn't know it's type, but know it's size. pub trait AnyValueTypeless: AnyValueSizeless { /// Aligned. @@ -164,26 +135,6 @@ pub trait AnyValue: AnyValueTypeless { } } -/// Helper function, which utilize type knowledge. -#[inline(always)] -pub(crate) unsafe fn copy_bytes( - input: *const u8, out: *mut u8, bytes_size: usize -) { - if !Unknown::is::() { - ptr::copy_nonoverlapping( - input as *const KnownType, - out as *mut KnownType, - 1 - ); - } else { - ptr::copy_nonoverlapping( - input, - out, - bytes_size - ); - } -} - /// Mutable [AnyValueSizeless]. pub trait AnyValueSizelessMut: AnyValueSizeless { // Rust MIRI requires mut pointer to actually come from mut self. diff --git a/src/element.rs b/src/element.rs index 4e07f84..ba8f876 100644 --- a/src/element.rs +++ b/src/element.rs @@ -21,7 +21,8 @@ use crate::traits::{Cloneable, None, Trait}; /// # Consuming /// /// Whenever you have `ElementPointer` as a value (from destructive [`AnyVec`] operations), -/// you can safely take pointed value, with [`AnyValue::downcast`] or [`any_value::move_out`]. +/// you can safely take pointed value with [`AnyValue::downcast`], or unsafely +/// take its content with [`AnyValue::move_into`]. /// Otherwise, it will be destructed with destruction of [`Element`]. /// /// # Notes diff --git a/src/lib.rs b/src/lib.rs index 04f95fe..6f19169 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -144,9 +144,9 @@ mod any_vec_typed; mod iter; use std::any::TypeId; -pub use crate::any_vec::{AnyVec, AnyVecMut, AnyVecRef, SatisfyTraits, traits, RawParts}; +pub use crate::any_vec::{AnyVec, AnyVecMut, AnyVecRef, RawParts, SatisfyTraits, traits}; pub use any_vec_typed::AnyVecTyped; -pub use iter::{ElementIterator, Iter, IterRef, IterMut}; +pub use iter::{ElementIterator, Iter, IterMut, IterRef}; pub mod mem; pub mod any_value; @@ -155,11 +155,13 @@ pub mod element; use std::ptr; use std::ops::{Bound, Range, RangeBounds}; +use crate::any_value::Unknown; -// TODO: remove -// This is faster then ptr::copy, -// when count is runtime value, and count is small. -#[inline] +/// This is faster then ptr::copy, +/// when count is runtime value, and count is small. +/// +/// Last time benchmarked on nightly 1.80 +#[inline(always)] unsafe fn copy_bytes(src: *const u8, dst: *mut u8, count: usize){ // MIRI hack if cfg!(miri) @@ -174,6 +176,26 @@ unsafe fn copy_bytes(src: *const u8, dst: *mut u8, count: usize){ } } +/// One element copy_nonoverlapping, that utilize type knowledge. +#[inline(always)] +pub(crate) unsafe fn copy_nonoverlapping_value( + input: *const u8, out: *mut u8, value_size: usize +) { + if !Unknown::is::() { + ptr::copy_nonoverlapping( + input as *const KnownType, + out as *mut KnownType, + 1 + ); + } else { + ptr::copy_nonoverlapping( + input, + out, + value_size + ); + } +} + #[inline] fn into_range( len: usize, @@ -197,4 +219,4 @@ fn into_range( #[inline] fn assert_types_equal(t1: TypeId, t2: TypeId){ assert_eq!(t1, t2, "Type mismatch!"); -} +} \ No newline at end of file diff --git a/src/ops/remove.rs b/src/ops/remove.rs index b7e4361..e7210ec 100644 --- a/src/ops/remove.rs +++ b/src/ops/remove.rs @@ -45,12 +45,12 @@ impl<'a, AnyVecPtr: IAnyVecRawPtr> Operation for Remove<'a, AnyVecPtr>{ if !Unknown::is::() { let dst = self.bytes() as *mut AnyVecPtr::Element; let src = dst.add(1); - ptr::copy(src, dst,self.last_index - self.index); + ptr::copy(src, dst, self.last_index - self.index); } else { let size = self.any_vec_ptr.any_vec_raw().element_layout().size(); let dst = self.bytes() as *mut u8; let src = dst.add(size); - crate::copy_bytes(src, dst,size * (self.last_index - self.index)); + crate::copy_bytes(src, dst, size * (self.last_index - self.index)); } // 3. shrink len `self.any_vec.len -= 1` diff --git a/src/ops/splice.rs b/src/ops/splice.rs index dfc9789..75e925b 100644 --- a/src/ops/splice.rs +++ b/src/ops/splice.rs @@ -1,6 +1,6 @@ use crate::any_vec_ptr::IAnyVecRawPtr; use crate::{any_vec_ptr, assert_types_equal, Iter}; -use crate::any_value::{AnyValue, move_out_w_size}; +use crate::any_value::{AnyValue, AnyValueSizeless}; use crate::ops::iter::Iterable; pub struct Splice<'a, AnyVecPtr: IAnyVecRawPtr, ReplaceIter: ExactSizeIterator> @@ -105,7 +105,9 @@ where let mut ptr = element_mut_ptr_at(any_vec_ptr, self.start); while let Some(replace_element) = self.replace_with.next() { assert_types_equal(type_id, replace_element.value_typeid()); - move_out_w_size(replace_element, ptr, element_size); + replace_element.move_into::< + ::Type + >(ptr, element_size); ptr = ptr.add(element_size); } } diff --git a/src/ops/swap_remove.rs b/src/ops/swap_remove.rs index 789bdb6..07b240e 100644 --- a/src/ops/swap_remove.rs +++ b/src/ops/swap_remove.rs @@ -1,5 +1,5 @@ use std::marker::PhantomData; -use crate::any_value::copy_bytes; +use crate::copy_nonoverlapping_value; use crate::any_vec_ptr::IAnyVecRawPtr; use crate::any_vec_ptr::utils::{element_mut_ptr_at, element_ptr_at}; use crate::any_vec_raw::AnyVecRaw; @@ -47,7 +47,7 @@ impl<'a, AnyVecPtr: IAnyVecRawPtr> Operation for SwapRemove<'a, AnyVecPtr>{ let any_vec_raw = self.any_vec_ptr.any_vec_raw_mut(); if self.element as *const u8 != last_element { - copy_bytes::( + copy_nonoverlapping_value::( last_element, self.element, any_vec_raw.element_layout().size() diff --git a/src/ops/temp.rs b/src/ops/temp.rs index 28144b6..a54794e 100644 --- a/src/ops/temp.rs +++ b/src/ops/temp.rs @@ -1,9 +1,9 @@ use std::any::TypeId; use std::{mem, ptr}; -use crate::any_value::{AnyValue, AnyValueCloneable, AnyValueMut, AnyValueTypelessMut, AnyValueTypeless, Unknown, AnyValueSizeless, copy_bytes, AnyValueSizelessMut}; +use crate::any_value::{AnyValue, AnyValueCloneable, AnyValueMut, AnyValueSizeless, AnyValueSizelessMut, AnyValueTypeless, AnyValueTypelessMut, Unknown}; use crate::any_vec_raw::AnyVecRaw; use crate::any_vec_ptr::{IAnyVecPtr, IAnyVecRawPtr}; -use crate::AnyVec; +use crate::{AnyVec, copy_nonoverlapping_value}; use crate::traits::Cloneable; pub trait Operation { @@ -58,7 +58,7 @@ impl AnyValueSizeless for TempValue { #[inline] unsafe fn move_into(mut self, out: *mut u8, bytes_size: usize) { - copy_bytes::(self.as_bytes_ptr(), out, bytes_size); + copy_nonoverlapping_value::(self.as_bytes_ptr(), out, bytes_size); self.op.consume(); mem::forget(self); }