From c574a43f3f9974383d2a5b58f83ad13687e56959 Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 15 Jun 2019 22:48:48 -0300 Subject: [PATCH] Adds the const_generics feature --- src/into_iter.rs | 40 +++- src/small_vec.rs | 457 ++++++++++++++++++++++++--------------- src/small_vec_data.rs | 73 +++++-- src/small_vec_visitor.rs | 23 +- src/spec_from.rs | 18 +- 5 files changed, 394 insertions(+), 217 deletions(-) diff --git a/src/into_iter.rs b/src/into_iter.rs index 1a62b64..16e69aa 100644 --- a/src/into_iter.rs +++ b/src/into_iter.rs @@ -3,28 +3,39 @@ use crate::Array; use crate::SmallVec; use core::ptr; +macro_rules! create_with_parts { +( + <$($({$s_impl_ty_prefix:ident})? $s_impl_ty:ident$(: $s_impl_ty_bound:ident)?),*>, + <$s_decl_ty:ident$(, {$s_decl_const_ty:ident})?>, + $array_item:ty +) => { + /// An iterator that consumes a `SmallVec` and yields its items by value. /// /// Returned from [`SmallVec::into_iter`][1]. /// /// [1]: struct.SmallVec.html#method.into_iter -pub struct IntoIter { - pub(crate) data: SmallVec, +pub struct IntoIter<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> { + pub(crate) data: SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?>, pub(crate) current: usize, pub(crate) end: usize, } -impl Drop for IntoIter { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Drop + for IntoIter<$s_decl_ty$(, {$s_decl_const_ty})?> +{ fn drop(&mut self) { for _ in self {} } } -impl Iterator for IntoIter { - type Item = A::Item; +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Iterator + for IntoIter<$s_decl_ty$(, {$s_decl_const_ty})?> +{ + type Item = $array_item; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option<$array_item> { if self.current == self.end { None } else { @@ -43,9 +54,11 @@ impl Iterator for IntoIter { } } -impl DoubleEndedIterator for IntoIter { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> DoubleEndedIterator + for IntoIter<$s_decl_ty$(, {$s_decl_const_ty})?> +{ #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option<$array_item> { if self.current == self.end { None } else { @@ -57,4 +70,13 @@ impl DoubleEndedIterator for IntoIter { } } -impl ExactSizeIterator for IntoIter {} +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> ExactSizeIterator + for IntoIter<$s_decl_ty$(, {$s_decl_const_ty})?> {} + + } +} + +#[cfg(feature = "const_generics")] +create_with_parts!(, , T); +#[cfg(not(feature = "const_generics"))] +create_with_parts!(, , A::Item); diff --git a/src/small_vec.rs b/src/small_vec.rs index 1dd2248..eac68aa 100644 --- a/src/small_vec.rs +++ b/src/small_vec.rs @@ -29,6 +29,15 @@ use std::io; #[cfg(feature = "serde")] use std::marker::PhantomData; +macro_rules! create_with_parts { +( + <$($({$s_impl_ty_prefix:ident})? $s_impl_ty:ident$(: $s_impl_ty_bound:ident)?),*>, + <$s_decl_ty:ident$(, {$s_decl_const_ty:ident})?>, + $array:ty, + $array_item:ty, + $array_size:expr +) => { + /// A `Vec`-like container that can store a small number of elements inline. /// /// `SmallVec` acts like a vector, but can store a limited amount of data inline within the @@ -55,18 +64,18 @@ use std::marker::PhantomData; /// assert_eq!(v.len(), 5); /// assert!(v.spilled()); /// ``` -pub struct SmallVec { +pub struct SmallVec<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> { // The capacity field is used to determine which of the storage variants is active: - // If capacity <= A::size() then the inline variant is used and capacity holds the current length of the vector (number of elements actually in use). - // If capacity > A::size() then the heap variant is used and capacity holds the size of the memory allocation. + // If capacity <= $array_size then the inline variant is used and capacity holds the current length of the vector (number of elements actually in use). + // If capacity > $array_size then the heap variant is used and capacity holds the size of the memory allocation. capacity: usize, - data: SmallVecData, + data: SmallVecData<$s_decl_ty$(, {$s_decl_const_ty})?>, } -impl SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> { /// Construct an empty vector #[inline] - pub fn new() -> SmallVec { + pub fn new() -> Self { unsafe { SmallVec { capacity: 0, @@ -95,9 +104,9 @@ impl SmallVec { v } - /// Construct a new `SmallVec` from a `Vec`. + /// Construct a new `SmallVec` from a `Vec<$array_item>`. /// - /// Elements will be copied to the inline buffer if vec.capacity() <= A::size(). + /// Elements will be copied to the inline buffer if vec.capacity() <= $array_size. /// /// ```rust /// use smallvec::SmallVec; @@ -108,10 +117,10 @@ impl SmallVec { /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] - pub fn from_vec(mut vec: Vec) -> SmallVec { - if vec.capacity() <= A::size() { + pub fn from_vec(mut vec: Vec<$array_item>) -> Self { + if vec.capacity() <= $array_size { unsafe { - let mut data = SmallVecData::::from_inline(mem::uninitialized()); + let mut data = SmallVecData::<$array>::from_inline(mem::uninitialized()); let len = vec.len(); vec.set_len(0); ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut().as_mut_ptr(), len); @@ -144,9 +153,9 @@ impl SmallVec { /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] - pub fn from_buf(buf: A) -> SmallVec { + pub fn from_buf(buf: $array) -> Self { SmallVec { - capacity: A::size(), + capacity: $array_size, data: SmallVecData::from_inline(MaybeUninit::new(buf)), } } @@ -164,14 +173,14 @@ impl SmallVec { /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] - pub fn from_buf_and_len(buf: A, len: usize) -> SmallVec { - assert!(len <= A::size()); + pub fn from_buf_and_len(buf: $array, len: usize) -> Self { + assert!(len <= $array_size); unsafe { SmallVec::from_buf_and_len_unchecked(buf, len) } } /// Constructs a new `SmallVec` on the stack from an `A` without /// copying elements. Also sets the length. The user is responsible - /// for ensuring that `len <= A::size()`. + /// for ensuring that `len <= $array_size`. /// /// ```rust /// use smallvec::SmallVec; @@ -184,7 +193,7 @@ impl SmallVec { /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] - pub unsafe fn from_buf_and_len_unchecked(buf: A, len: usize) -> SmallVec { + pub unsafe fn from_buf_and_len_unchecked(buf: $array, len: usize) -> Self { SmallVec { capacity: len, data: SmallVecData::from_inline(MaybeUninit::new(buf)), @@ -204,7 +213,7 @@ impl SmallVec { /// The maximum number of elements this vector can hold inline #[inline] pub fn inline_size(&self) -> usize { - A::size() + $array_size } /// The number of elements stored in the vector @@ -228,20 +237,20 @@ impl SmallVec { /// Returns a tuple with (data ptr, len, capacity) /// Useful to get all SmallVec properties with a single check of the current storage variant. #[inline] - fn triple(&self) -> (*const A::Item, usize, usize) { + fn triple(&self) -> (*const $array_item, usize, usize) { unsafe { if self.spilled() { let (ptr, len) = self.data.heap(); (ptr, len, self.capacity) } else { - (self.data.inline().as_ptr(), self.capacity, A::size()) + (self.data.inline().as_ptr(), self.capacity, $array_size) } } } /// Returns a tuple with (data ptr, len ptr, capacity) #[inline] - fn triple_mut(&mut self) -> (*mut A::Item, &mut usize, usize) { + fn triple_mut(&mut self) -> (*mut $array_item, &mut usize, usize) { unsafe { if self.spilled() { let (ptr, len_ptr) = self.data.heap_mut(); @@ -250,7 +259,7 @@ impl SmallVec { ( self.data.inline_mut().as_mut_ptr(), &mut self.capacity, - A::size(), + $array_size, ) } } @@ -259,11 +268,11 @@ impl SmallVec { /// Returns `true` if the data has spilled into a separate heap-allocated buffer. #[inline] pub fn spilled(&self) -> bool { - self.capacity > A::size() + self.capacity > $array_size } /// Empty the vector and return an iterator over its former contents. - pub fn drain(&mut self) -> Drain { + pub fn drain(&mut self) -> Drain<$array_item> { unsafe { let ptr = self.as_mut_ptr(); @@ -280,7 +289,7 @@ impl SmallVec { /// Append an item to the vector. #[inline] - pub fn push(&mut self, value: A::Item) { + pub fn push(&mut self, value: $array_item) { unsafe { let (_, &mut len, cap) = self.triple_mut(); if len == cap { @@ -294,7 +303,7 @@ impl SmallVec { /// Remove an item from the end of the vector and return it, or None if empty. #[inline] - pub fn pop(&mut self) -> Option { + pub fn pop(&mut self) -> Option<$array_item> { unsafe { let (ptr, len_ptr, _) = self.triple_mut(); if *len_ptr == 0 { @@ -416,14 +425,14 @@ impl SmallVec { /// Extracts a slice containing the entire vector. /// /// Equivalent to `&s[..]`. - pub fn as_slice(&self) -> &[A::Item] { + pub fn as_slice(&self) -> &[$array_item] { self } /// Extracts a mutable slice of the entire vector. /// /// Equivalent to `&mut s[..]`. - pub fn as_mut_slice(&mut self) -> &mut [A::Item] { + pub fn as_mut_slice(&mut self) -> &mut [$array_item] { self } @@ -433,7 +442,7 @@ impl SmallVec { /// /// Panics if `index` is out of bounds. #[inline] - pub fn swap_remove(&mut self, index: usize) -> A::Item { + pub fn swap_remove(&mut self, index: usize) -> $array_item { let len = self.len(); self.swap(len - 1, index); self.pop().unwrap_or_else(|| unsafe { unreachable_unchecked() }) @@ -449,7 +458,7 @@ impl SmallVec { /// left. /// /// Panics if `index` is out of bounds. - pub fn remove(&mut self, index: usize) -> A::Item { + pub fn remove(&mut self, index: usize) -> $array_item { unsafe { let (mut ptr, len_ptr, _) = self.triple_mut(); let len = *len_ptr; @@ -465,7 +474,7 @@ impl SmallVec { /// Insert an element at position `index`, shifting all elements after it to the right. /// /// Panics if `index` is out of bounds. - pub fn insert(&mut self, index: usize, element: A::Item) { + pub fn insert(&mut self, index: usize, element: $array_item) { self.reserve(1); unsafe { @@ -481,7 +490,7 @@ impl SmallVec { /// Insert multiple elements at position `index`, shifting all following elements toward the /// back. - pub fn insert_many>(&mut self, index: usize, iterable: I) { + pub fn insert_many>(&mut self, index: usize, iterable: I) { let iter = iterable.into_iter(); if index == self.len() { return self.extend(iter); @@ -531,7 +540,7 @@ impl SmallVec { /// Convert a SmallVec to a Vec, without reallocating if the SmallVec has already spilled onto /// the heap. - pub fn into_vec(self) -> Vec { + pub fn into_vec(self) -> Vec<$array_item> { if self.spilled() { unsafe { let (ptr, len) = self.data.heap(); @@ -548,8 +557,8 @@ impl SmallVec { /// /// This method returns `Err(Self)` if the SmallVec is too short (and the `A` contains uninitialized elements), /// or if the SmallVec is too long (and all the elements were spilled to the heap). - pub fn into_inner(self) -> Result { - if self.spilled() || self.len() != A::size() { + pub fn into_inner(self) -> Result<$array, Self> { + if self.spilled() || self.len() != $array_size { Err(self) } else { unsafe { @@ -565,7 +574,7 @@ impl SmallVec { /// In other words, remove all elements `e` such that `f(&e)` returns `false`. /// This method operates in place and preserves the order of the retained /// elements. - pub fn retain bool>(&mut self, mut f: F) { + pub fn retain bool>(&mut self, mut f: F) { let mut del = 0; let len = self.len(); for i in 0..len { @@ -581,7 +590,7 @@ impl SmallVec { /// Removes consecutive duplicate elements. pub fn dedup(&mut self) where - A::Item: PartialEq, + $array_item: PartialEq<$array_item>, { self.dedup_by(|a, b| a == b); } @@ -589,7 +598,7 @@ impl SmallVec { /// Removes consecutive duplicate elements using the given equality relation. pub fn dedup_by(&mut self, mut same_bucket: F) where - F: FnMut(&mut A::Item, &mut A::Item) -> bool, + F: FnMut(&mut $array_item, &mut $array_item) -> bool, { // See the implementation of Vec::dedup_by in the // standard library for an explanation of this algorithm. @@ -621,7 +630,7 @@ impl SmallVec { /// Removes consecutive elements that map to the same key. pub fn dedup_by_key(&mut self, mut key: F) where - F: FnMut(&mut A::Item) -> K, + F: FnMut(&mut $array_item) -> K, K: PartialEq, { self.dedup_by(|a, b| key(a) == key(b)); @@ -638,7 +647,7 @@ impl SmallVec { /// * `ptr` needs to have been previously allocated via `SmallVec` for its /// spilled storage (at least, it's highly likely to be incorrect if it /// wasn't). - /// * `ptr`'s `A::Item` type needs to be the same size and alignment that + /// * `ptr`'s `$array_item` type needs to be the same size and alignment that /// it was allocated with /// * `length` needs to be less than or equal to `capacity`. /// * `capacity` needs to be the capacity that the pointer was allocated @@ -695,8 +704,8 @@ impl SmallVec { /// assert_eq!(&*rebuilt, &[4, 5, 6]); /// } /// } - pub unsafe fn from_raw_parts(ptr: *mut A::Item, length: usize, capacity: usize) -> SmallVec { - assert!(capacity > A::size()); + pub unsafe fn from_raw_parts(ptr: *mut $array_item, length: usize, capacity: usize) -> Self { + assert!(capacity > $array_size); SmallVec { capacity, data: SmallVecData::from_heap(ptr, length), @@ -704,20 +713,20 @@ impl SmallVec { } } -impl SmallVec +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Copy, + $array_item: Copy, { /// Copy the elements from a slice into a new `SmallVec`. /// /// For slices of `Copy` types, this is more efficient than `SmallVec::from(slice)`. - pub fn from_slice(slice: &[A::Item]) -> Self { + pub fn from_slice(slice: &[$array_item]) -> Self { let len = slice.len(); - if len <= A::size() { + if len <= $array_size { SmallVec { capacity: len, data: SmallVecData::from_inline(unsafe { - let mut data = MaybeUninit::::uninit(); + let mut data = MaybeUninit::<$array>::uninit(); let slice_mut = &mut *data.as_mut_ptr(); ptr::copy_nonoverlapping(slice.as_ptr(), slice_mut.as_mut_ptr(), len); data @@ -737,7 +746,7 @@ where /// elements toward the back. /// /// For slices of `Copy` types, this is more efficient than `insert`. - pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) { + pub fn insert_from_slice(&mut self, index: usize, slice: &[$array_item]) { self.reserve(slice.len()); let len = self.len(); @@ -756,15 +765,16 @@ where /// /// For slices of `Copy` types, this is more efficient than `extend`. #[inline] - pub fn extend_from_slice(&mut self, slice: &[A::Item]) { + pub fn extend_from_slice(&mut self, slice: &[$array_item]) { let len = self.len(); self.insert_from_slice(len, slice); } } -impl SmallVec +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> + SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Clone, + $array_item: Clone, { /// Resizes the vector so that its length is equal to `len`. /// @@ -772,7 +782,7 @@ where /// /// If `len` is greater than the current length, `value` is appended to the /// vector until its length equals `len`. - pub fn resize(&mut self, len: usize, value: A::Item) { + pub fn resize(&mut self, len: usize, value: $array_item) { let old_len = self.len(); if len > old_len { @@ -789,11 +799,11 @@ where /// let v = SmallVec::<[char; 128]>::from_elem('d', 2); /// assert_eq!(v, SmallVec::from_buf(['d', 'd'])); /// ``` - pub fn from_elem(elem: A::Item, n: usize) -> Self { - if n > A::size() { + pub fn from_elem(elem: $array_item, n: usize) -> Self { + if n > $array_size { vec![elem; n].into() } else { - let mut v = SmallVec::::new(); + let mut v = SmallVec::<$array>::new(); unsafe { let (ptr, len_ptr, _) = v.triple_mut(); let mut local_len = SetLenOnDrop::new(len_ptr); @@ -808,10 +818,12 @@ where } } -impl Deref for SmallVec { - type Target = [A::Item]; +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Deref + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ + type Target = [$array_item]; #[inline] - fn deref(&self) -> &[A::Item] { + fn deref(&self) -> &[$array_item] { unsafe { let (ptr, len, _) = self.triple(); slice::from_raw_parts(ptr, len) @@ -819,9 +831,11 @@ impl Deref for SmallVec { } } -impl DerefMut for SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> DerefMut + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ #[inline] - fn deref_mut(&mut self) -> &mut [A::Item] { + fn deref_mut(&mut self) -> &mut [$array_item] { unsafe { let (ptr, &mut len, _) = self.triple_mut(); slice::from_raw_parts_mut(ptr, len) @@ -829,58 +843,46 @@ impl DerefMut for SmallVec { } } -impl AsRef<[A::Item]> for SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> AsRef<[$array_item]> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ #[inline] - fn as_ref(&self) -> &[A::Item] { + fn as_ref(&self) -> &[$array_item] { self } } -impl AsMut<[A::Item]> for SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> AsMut<[$array_item]> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ #[inline] - fn as_mut(&mut self) -> &mut [A::Item] { + fn as_mut(&mut self) -> &mut [$array_item] { self } } -impl Borrow<[A::Item]> for SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Borrow<[$array_item]> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ #[inline] - fn borrow(&self) -> &[A::Item] { + fn borrow(&self) -> &[$array_item] { self } } -impl BorrowMut<[A::Item]> for SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> BorrowMut<[$array_item]> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ #[inline] - fn borrow_mut(&mut self) -> &mut [A::Item] { + fn borrow_mut(&mut self) -> &mut [$array_item] { self } } -#[cfg(feature = "std")] -impl> io::Write for SmallVec { - #[inline] - fn write(&mut self, buf: &[u8]) -> io::Result { - self.extend_from_slice(buf); - Ok(buf.len()) - } - - #[inline] - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - self.extend_from_slice(buf); - Ok(()) - } - - #[inline] - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - #[cfg(feature = "serde")] impl Serialize for SmallVec where - A::Item: Serialize, + $array_item: Serialize, { fn serialize(&self, serializer: S) -> Result { let mut state = serializer.serialize_seq(Some(self.len()))?; @@ -892,9 +894,9 @@ where } #[cfg(feature = "serde")] -impl<'de, A: Array> Deserialize<'de> for SmallVec +impl<'de, A: Array> Deserialize<'de> for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Deserialize<'de>, + $array_item: Deserialize<'de>, { fn deserialize>(deserializer: D) -> Result { deserializer.deserialize_seq(SmallVecVisitor { @@ -904,102 +906,87 @@ where } #[cfg(feature = "specialization")] -impl<'a, A: Array> SpecFrom for SmallVec +impl<'a, A: Array> SpecFrom for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Clone, + $array_item: Clone, { #[inline] - default fn spec_from(slice: &'a [A::Item]) -> SmallVec { + default fn spec_from(slice: &'a [$array_item]) -> Self { slice.into_iter().cloned().collect() } } #[cfg(feature = "specialization")] -impl<'a, A: Array> SpecFrom for SmallVec +impl<'a, A: Array> SpecFrom for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Copy, + $array_item: Copy, { #[inline] - fn spec_from(slice: &'a [A::Item]) -> SmallVec { + fn spec_from(slice: &'a [$array_item]) -> Self { SmallVec::from_slice(slice) } } -impl<'a, A: Array> From<&'a [A::Item]> for SmallVec +impl<'a, $($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> From<&'a [$array_item]> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Clone, + $array_item: Clone, { #[cfg(not(feature = "specialization"))] #[inline] - fn from(slice: &'a [A::Item]) -> SmallVec { + fn from(slice: &'a [$array_item]) -> Self { slice.into_iter().cloned().collect() } #[cfg(feature = "specialization")] #[inline] - fn from(slice: &'a [A::Item]) -> SmallVec { + fn from(slice: &'a [$array_item]) -> Self { SmallVec::spec_from(slice) } } -impl From> for SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> From> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ #[inline] - fn from(vec: Vec) -> SmallVec { + fn from(vec: Vec<$array_item>) -> Self { SmallVec::from_vec(vec) } } -impl From for SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> From<$array> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ #[inline] - fn from(array: A) -> SmallVec { + fn from(array: $array) -> Self { SmallVec::from_buf(array) } } -macro_rules! impl_index { - ($index_type: ty, $output_type: ty) => { - impl Index<$index_type> for SmallVec { - type Output = $output_type; - #[inline] - fn index(&self, index: $index_type) -> &$output_type { - &(&**self)[index] - } - } - - impl IndexMut<$index_type> for SmallVec { - #[inline] - fn index_mut(&mut self, index: $index_type) -> &mut $output_type { - &mut (&mut **self)[index] - } - } - }; -} - -impl_index!(usize, A::Item); -impl_index!(Range, [A::Item]); -impl_index!(RangeFrom, [A::Item]); -impl_index!(RangeTo, [A::Item]); -impl_index!(RangeFull, [A::Item]); - -impl ExtendFromSlice for SmallVec +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> ExtendFromSlice<$array_item> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Copy, + $array_item: Copy, { - fn extend_from_slice(&mut self, other: &[A::Item]) { + fn extend_from_slice(&mut self, other: &[$array_item]) { SmallVec::extend_from_slice(self, other) } } -impl FromIterator for SmallVec { - fn from_iter>(iterable: I) -> SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> FromIterator<$array_item> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ + fn from_iter>(iterable: I) -> Self { let mut v = SmallVec::new(); v.extend(iterable); v } } -impl Extend for SmallVec { - fn extend>(&mut self, iterable: I) { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Extend<$array_item> + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ + fn extend>(&mut self, iterable: I) { let mut iter = iterable.into_iter(); let (lower_size_bound, _) = iter.size_hint(); self.reserve(lower_size_bound); @@ -1023,24 +1010,24 @@ impl Extend for SmallVec { } } -impl Debug for SmallVec +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Debug for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Debug, + $array_item: Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list().entries(self.iter()).finish() } } -impl Default for SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Default for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> { #[inline] - fn default() -> SmallVec { + fn default() -> Self { SmallVec::new() } } #[cfg(feature = "may_dangle")] -unsafe impl<#[may_dangle] A: Array> Drop for SmallVec { +unsafe impl<#[may_dangle] $($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Drop for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> { fn drop(&mut self) { unsafe { if self.spilled() { @@ -1054,7 +1041,8 @@ unsafe impl<#[may_dangle] A: Array> Drop for SmallVec { } #[cfg(not(feature = "may_dangle"))] -impl Drop for SmallVec { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Drop + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> { fn drop(&mut self) { unsafe { if self.spilled() { @@ -1067,11 +1055,12 @@ impl Drop for SmallVec { } } -impl Clone for SmallVec +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Clone + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Clone, + $array_item: Clone, { - fn clone(&self) -> SmallVec { + fn clone(&self) -> Self { let mut new_vector = SmallVec::with_capacity(self.len()); for element in self.iter() { new_vector.push((*element).clone()) @@ -1080,56 +1069,53 @@ where } } -impl PartialEq> for SmallVec +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Eq + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: PartialEq, -{ - #[inline] - fn eq(&self, other: &SmallVec) -> bool { - self[..] == other[..] - } - #[inline] - fn ne(&self, other: &SmallVec) -> bool { - self[..] != other[..] - } -} - -impl Eq for SmallVec where A::Item: Eq {} + $array_item: Eq {} -impl PartialOrd for SmallVec +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> PartialOrd + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: PartialOrd, + $array_item: PartialOrd, { #[inline] - fn partial_cmp(&self, other: &SmallVec) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { PartialOrd::partial_cmp(&**self, &**other) } } -impl Ord for SmallVec +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Ord + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Ord, + $array_item: Ord, { #[inline] - fn cmp(&self, other: &SmallVec) -> Ordering { + fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(&**self, &**other) } } -impl Hash for SmallVec +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Hash + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> where - A::Item: Hash, + $array_item: Hash, { fn hash(&self, state: &mut H) { (**self).hash(state) } } -unsafe impl Send for SmallVec where A::Item: Send {} +unsafe impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Send + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +where + $array_item: Send {} -impl IntoIterator for SmallVec { - type IntoIter = IntoIter; - type Item = A::Item; +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> IntoIterator + for SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ + type IntoIter = IntoIter<$s_decl_ty$(, {$s_decl_const_ty})?>; + type Item = $array_item; fn into_iter(mut self) -> Self::IntoIter { unsafe { // Set SmallVec len to zero as `IntoIter` drop handles dropping of the elements @@ -1144,18 +1130,133 @@ impl IntoIterator for SmallVec { } } -impl<'a, A: Array> IntoIterator for &'a SmallVec { - type IntoIter = slice::Iter<'a, A::Item>; - type Item = &'a A::Item; +impl<'a, $($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> IntoIterator + for &'a SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ + type IntoIter = slice::Iter<'a, $array_item>; + type Item = &'a $array_item; fn into_iter(self) -> Self::IntoIter { self.iter() } } -impl<'a, A: Array> IntoIterator for &'a mut SmallVec { - type IntoIter = slice::IterMut<'a, A::Item>; - type Item = &'a mut A::Item; +impl<'a, $($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> IntoIterator + for &'a mut SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?> +{ + type IntoIter = slice::IterMut<'a, $array_item>; + type Item = &'a mut $array_item; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } + + } +} + +#[cfg(feature = "const_generics")] +impl PartialEq for SmallVec +where + T: PartialEq +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + self[..] == other[..] + } + #[inline] + fn ne(&self, other: &Self) -> bool { + self[..] != other[..] + } +} + +#[cfg(not(feature = "const_generics"))] +impl PartialEq> for SmallVec +where + A::Item: PartialEq, +{ + #[inline] + fn eq(&self, other: &SmallVec) -> bool { + self[..] == other[..] + } + #[inline] + fn ne(&self, other: &SmallVec) -> bool { + self[..] != other[..] + } +} + +#[cfg(all(feature = "std", feature = "const_generics"))] +impl io::Write for SmallVec +{ + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.extend_from_slice(buf); + Ok(buf.len()) + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.extend_from_slice(buf); + Ok(()) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[cfg(all(feature = "std", not(feature = "const_generics")))] +impl> io::Write for SmallVec { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.extend_from_slice(buf); + Ok(buf.len()) + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.extend_from_slice(buf); + Ok(()) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[cfg(not(feature = "const_generics"))] +macro_rules! impl_index { + ($index_type: ty, $output_type: ty) => { + impl Index<$index_type> for SmallVec { + type Output = $output_type; + #[inline] + fn index(&self, index: $index_type) -> &$output_type { + &(&**self)[index] + } + } + + impl IndexMut<$index_type> for SmallVec { + #[inline] + fn index_mut(&mut self, index: $index_type) -> &mut $output_type { + &mut (&mut **self)[index] + } + } + } +} + +#[cfg(not(feature = "const_generics"))] +impl_index!(usize, A::Item); +#[cfg(not(feature = "const_generics"))] +impl_index!(Range, [A::Item]); +#[cfg(not(feature = "const_generics"))] +impl_index!(RangeFrom, [A::Item]); +#[cfg(not(feature = "const_generics"))] +impl_index!(RangeTo, [A::Item]); +#[cfg(not(feature = "const_generics"))] +impl_index!(RangeFull, [A::Item]); + +#[cfg(feature = "const_generics")] +create_with_parts!(, , [T; N], T, N); +#[cfg(not(feature = "const_generics"))] +create_with_parts!(, , A, A::Item, A::size()); + diff --git a/src/small_vec_data.rs b/src/small_vec_data.rs index 00fcd27..b743a84 100644 --- a/src/small_vec_data.rs +++ b/src/small_vec_data.rs @@ -2,40 +2,48 @@ use crate::Array; use core::{mem::MaybeUninit, ptr::NonNull}; +macro_rules! create_with_parts { +( + <$($({$s_impl_ty_prefix:ident})? $s_impl_ty:ident$(: $s_impl_ty_bound:ident)?),*>, + <$s_decl_ty:ident$(, {$s_decl_const_ty:ident})?>, + $array:ty, + $array_item:ty +) => { + #[cfg(feature = "union")] -pub union SmallVecData { - inline: MaybeUninit, - heap: (NonNull, usize), +pub union SmallVecData<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> { + inline: MaybeUninit<$s_decl_ty$(, {$s_decl_const_ty})?>, + heap: (NonNull<$array_item>, usize), } #[cfg(feature = "union")] -impl SmallVecData { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> SmallVecData<$s_decl_ty$(, {$s_decl_const_ty})?> { #[inline] - pub unsafe fn inline(&self) -> &A { + pub unsafe fn inline(&self) -> &$array { &*self.inline.as_ptr() } #[inline] - pub unsafe fn inline_mut(&mut self) -> &mut A { + pub unsafe fn inline_mut(&mut self) -> &mut $array { &mut *self.inline.as_mut_ptr() } #[inline] - pub fn from_inline(inline: MaybeUninit) -> SmallVecData { + pub fn from_inline(inline: MaybeUninit<$array>) -> Self { SmallVecData { inline } } #[inline] - pub unsafe fn into_inline(self) -> A { + pub unsafe fn into_inline(self) -> $array { self.inline.assume_init() } #[inline] - pub unsafe fn heap(&self) -> (*mut A::Item, usize) { + pub unsafe fn heap(&self) -> (*mut $array_item, usize) { (self.heap.0.as_ptr(), self.heap.1) } #[inline] - pub unsafe fn heap_mut(&mut self) -> (*mut A::Item, &mut usize) { + pub unsafe fn heap_mut(&mut self) -> (*mut $array_item, &mut usize) { (self.heap.0.as_ptr(), &mut self.heap.1) } #[inline] - pub fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData { + pub fn from_heap(ptr: *mut $array_item, len: usize) -> Self { SmallVecData { heap: (NonNull::new(ptr).unwrap(), len), } @@ -43,57 +51,74 @@ impl SmallVecData { } #[cfg(not(feature = "union"))] -pub enum SmallVecData { - Inline(MaybeUninit), - Heap((NonNull, usize)), +pub enum SmallVecData<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> { + Inline(MaybeUninit<$array>), + Heap((NonNull<$array_item>, usize)), } #[cfg(not(feature = "union"))] -impl SmallVecData { +impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> SmallVecData<$s_decl_ty$(, {$s_decl_const_ty})?> { #[inline] - pub unsafe fn inline(&self) -> &A { + pub unsafe fn inline(&self) -> &$array { match *self { SmallVecData::Inline(ref a) => &*a.as_ptr(), _ => debug_unreachable!(), } } #[inline] - pub unsafe fn inline_mut(&mut self) -> &mut A { + pub unsafe fn inline_mut(&mut self) -> &mut $array { match *self { SmallVecData::Inline(ref mut a) => &mut *a.as_mut_ptr(), _ => debug_unreachable!(), } } #[inline] - pub fn from_inline(inline: MaybeUninit) -> SmallVecData { + pub fn from_inline(inline: MaybeUninit<$array>) -> Self { SmallVecData::Inline(inline) } #[inline] - pub unsafe fn into_inline(self) -> A { + pub unsafe fn into_inline(self) -> $array { match self { SmallVecData::Inline(a) => a.assume_init(), _ => debug_unreachable!(), } } #[inline] - pub unsafe fn heap(&self) -> (*mut A::Item, usize) { + pub unsafe fn heap(&self) -> (*mut $array_item, usize) { match *self { SmallVecData::Heap(data) => (data.0.as_ptr(), data.1), _ => debug_unreachable!(), } } #[inline] - pub unsafe fn heap_mut(&mut self) -> (*mut A::Item, &mut usize) { + pub unsafe fn heap_mut(&mut self) -> (*mut $array_item, &mut usize) { match *self { SmallVecData::Heap(ref mut data) => (data.0.as_ptr(), &mut data.1), _ => debug_unreachable!(), } } #[inline] - pub fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData { + pub fn from_heap(ptr: *mut $array_item, len: usize) -> Self { SmallVecData::Heap((NonNull::new(ptr).unwrap(), len)) } } -unsafe impl Send for SmallVecData {} -unsafe impl Sync for SmallVecData {} +unsafe impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Send + for SmallVecData<$s_decl_ty$(, {$s_decl_const_ty})?> +where + $array_item: Send +{} + +unsafe impl<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Sync + for SmallVecData<$s_decl_ty$(, {$s_decl_const_ty})?> +where + $array_item: Send +{} + + } +} + +#[cfg(feature = "const_generics")] +create_with_parts!(, , [T; N], T); +#[cfg(not(feature = "const_generics"))] +create_with_parts!(, , A, A::Item); diff --git a/src/small_vec_visitor.rs b/src/small_vec_visitor.rs index 61a47a9..d480ed0 100644 --- a/src/small_vec_visitor.rs +++ b/src/small_vec_visitor.rs @@ -4,17 +4,24 @@ use crate::SmallVec; use core::{fmt, marker::PhantomData}; use serde::de::{Deserialize, SeqAccess, Visitor}; +macro_rules! create_with_parts { + ( + <$($({$s_impl_ty_prefix:ident})? $s_impl_ty:ident$(: $s_impl_ty_bound:ident)?),*>, + <$s_decl_ty:ident$(, {$s_decl_const_ty:ident})?> +) => { + #[cfg(feature = "serde")] -pub struct SmallVecVisitor { - pub(crate) phantom: PhantomData, +pub struct SmallVecVisitor<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> { + pub(crate) phantom: PhantomData<$s_decl_ty$(, {$s_decl_const_ty})?>, } #[cfg(feature = "serde")] -impl<'de, A: Array> Visitor<'de> for SmallVecVisitor +impl<'de, $($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*> Visitor<'de> + for SmallVecVisitor<$s_decl_ty$(, {$s_decl_const_ty})?> where A::Item: Deserialize<'de>, { - type Value = SmallVec; + type Value = SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence") @@ -34,3 +41,11 @@ where Ok(values) } } + + } +} + +#[cfg(feature = "const_generics")] +create_with_parts!(, ); +#[cfg(not(feature = "const_generics"))] +create_with_parts!(, ); diff --git a/src/spec_from.rs b/src/spec_from.rs index 26077a5..699f7f6 100644 --- a/src/spec_from.rs +++ b/src/spec_from.rs @@ -2,6 +2,20 @@ use crate::Array; use crate::SmallVec; -pub trait SpecFrom { - fn spec_from(slice: S) -> SmallVec; +macro_rules! create_with_parts { + ( + <$($({$s_impl_ty_prefix:ident})? $s_impl_ty:ident$(: $s_impl_ty_bound:ident)?),*>, + <$s_decl_ty:ident$(, {$s_decl_const_ty:ident})?> +) => { + +pub trait SpecFrom<$($($s_impl_ty_prefix)? $s_impl_ty$(: $s_impl_ty_bound)?),*, S> { + fn spec_from(slice: S) -> SmallVec<$s_decl_ty$(, {$s_decl_const_ty})?>; +} + + } } + +#[cfg(feature = "const_generics")] +create_with_parts!(); +#[cfg(not(feature = "const_generics"))] +create_with_parts!(, );