From d50dda42ef24698ff199896a20934cea53c5db7f Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 17 Apr 2018 03:52:18 +0100 Subject: [PATCH 1/2] Rustfmt --- benches/bench.rs | 9 +- lib.rs | 393 +++++++++++++++++++++++++++++------------------ 2 files changed, 253 insertions(+), 149 deletions(-) diff --git a/benches/bench.rs b/benches/bench.rs index 9ffbb46..b9000db 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -4,8 +4,8 @@ extern crate smallvec; extern crate test; -use smallvec::SmallVec; use self::test::Bencher; +use smallvec::SmallVec; #[bench] fn bench_push(b: &mut Bencher) { @@ -42,8 +42,11 @@ fn bench_insert(b: &mut Bencher) { #[bench] fn bench_insert_many(b: &mut Bencher) { #[inline(never)] - fn insert_many_noinline>( - vec: &mut SmallVec<[u64; 16]>, index: usize, iterable: I) { + fn insert_many_noinline>( + vec: &mut SmallVec<[u64; 16]>, + index: usize, + iterable: I, + ) { vec.insert_many(index, iterable) } diff --git a/lib.rs b/lib.rs index eaa157a..8084cc8 100644 --- a/lib.rs +++ b/lib.rs @@ -19,7 +19,6 @@ #![cfg_attr(not(feature = "std"), feature(alloc))] #![deny(missing_docs)] - #[cfg(not(feature = "std"))] #[cfg_attr(test, macro_use)] extern crate alloc; @@ -35,25 +34,25 @@ mod std { pub use core::*; } +#[cfg(feature = "serde")] +use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; +#[cfg(feature = "serde")] +use serde::ser::{Serialize, SerializeSeq, Serializer}; use std::borrow::{Borrow, BorrowMut}; use std::cmp; use std::fmt; use std::hash::{Hash, Hasher}; -use std::iter::{IntoIterator, FromIterator, repeat}; -use std::mem; -use std::ops; -use std::ptr; -use std::slice; #[cfg(feature = "std")] use std::io; -#[cfg(feature = "serde")] -use serde::ser::{Serialize, Serializer, SerializeSeq}; -#[cfg(feature = "serde")] -use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; +use std::iter::{repeat, FromIterator, IntoIterator}; #[cfg(feature = "serde")] use std::marker::PhantomData; +use std::mem; +use std::ops; +use std::ptr; +use std::slice; -use SmallVecData::{Inline, Heap}; +use SmallVecData::{Heap, Inline}; /// Creates a [`SmallVec`] containing the arguments. /// @@ -127,19 +126,19 @@ macro_rules! smallvec { /// ``` #[deprecated(note = "Use `Extend` and `Deref<[T]>` instead")] pub trait VecLike: - ops::Index + - ops::IndexMut + - ops::Index, Output=[T]> + - ops::IndexMut> + - ops::Index, Output=[T]> + - ops::IndexMut> + - ops::Index, Output=[T]> + - ops::IndexMut> + - ops::Index + - ops::IndexMut + - ops::DerefMut + - Extend { - + ops::Index + + ops::IndexMut + + ops::Index, Output = [T]> + + ops::IndexMut> + + ops::Index, Output = [T]> + + ops::IndexMut> + + ops::Index, Output = [T]> + + ops::IndexMut> + + ops::Index + + ops::IndexMut + + ops::DerefMut + + Extend +{ /// Append an element to the vector. fn push(&mut self, value: T); } @@ -193,21 +192,17 @@ unsafe fn deallocate(ptr: *mut T, capacity: usize) { /// /// [1]: struct.SmallVec.html#method.drain pub struct Drain<'a, T: 'a> { - iter: slice::IterMut<'a,T>, + iter: slice::IterMut<'a, T>, } -impl<'a, T: 'a> Iterator for Drain<'a,T> { +impl<'a, T: 'a> Iterator for Drain<'a, T> { type Item = T; #[inline] fn next(&mut self) -> Option { match self.iter.next() { None => None, - Some(reference) => { - unsafe { - Some(ptr::read(reference)) - } - } + Some(reference) => unsafe { Some(ptr::read(reference)) }, } } @@ -222,18 +217,14 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> { fn next_back(&mut self) -> Option { match self.iter.next_back() { None => None, - Some(reference) => { - unsafe { - Some(ptr::read(reference)) - } - } + Some(reference) => unsafe { Some(ptr::read(reference)) }, } } } -impl<'a, T> ExactSizeIterator for Drain<'a, T> { } +impl<'a, T> ExactSizeIterator for Drain<'a, T> {} -impl<'a, T: 'a> Drop for Drain<'a,T> { +impl<'a, T: 'a> Drop for Drain<'a, T> { fn drop(&mut self) { // Destroy the remaining elements. for _ in self.by_ref() {} @@ -263,10 +254,13 @@ impl Drop for SmallVecData { match *self { ref mut inline @ Inline { .. } => { // Inhibit the array destructor. - ptr::write(inline, Heap { - ptr: ptr::null_mut(), - capacity: 0, - }); + ptr::write( + inline, + Heap { + ptr: ptr::null_mut(), + capacity: 0, + }, + ); } Heap { ptr, capacity } => deallocate(ptr, capacity), } @@ -312,7 +306,9 @@ impl SmallVec { unsafe { SmallVec { len: 0, - data: Inline { array: mem::uninitialized() }, + data: Inline { + array: mem::uninitialized(), + }, } } } @@ -357,8 +353,8 @@ impl SmallVec { len: len, data: SmallVecData::Heap { ptr: ptr, - capacity: cap - } + capacity: cap, + }, } } @@ -461,7 +457,7 @@ impl SmallVec { #[inline] pub fn pop(&mut self) -> Option { if self.len == 0 { - return None + return None; } let last_index = self.len - 1; if (last_index as isize) < 0 { @@ -490,10 +486,13 @@ impl SmallVec { Inline { .. } => {} Heap { ptr, capacity } => deallocate(ptr, capacity), } - ptr::write(&mut self.data, Heap { - ptr: new_alloc, - capacity: new_cap, - }); + ptr::write( + &mut self.data, + Heap { + ptr: new_alloc, + capacity: new_cap, + }, + ); } } @@ -507,7 +506,9 @@ impl SmallVec { pub fn reserve(&mut self, additional: usize) { let len = self.len(); if self.capacity() - len < additional { - match len.checked_add(additional).and_then(usize::checked_next_power_of_two) { + match len.checked_add(additional) + .and_then(usize::checked_next_power_of_two) + { Some(cap) => self.grow(cap), None => self.grow(usize::max_value()), } @@ -539,7 +540,12 @@ impl SmallVec { Inline { .. } => return, Heap { ptr, capacity } => (ptr, capacity), }; - ptr::write(&mut self.data, Inline { array: mem::uninitialized() }); + ptr::write( + &mut self.data, + Inline { + array: mem::uninitialized(), + }, + ); ptr::copy_nonoverlapping(ptr, self.as_mut_ptr(), len); deallocate(ptr, capacity); } @@ -635,11 +641,11 @@ 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(); let (lower_size_bound, _) = iter.size_hint(); - assert!(lower_size_bound <= std::isize::MAX as usize); // Ensure offset is indexable - assert!(index + lower_size_bound >= index); // Protect against overflow + assert!(lower_size_bound <= std::isize::MAX as usize); // Ensure offset is indexable + assert!(index + lower_size_bound >= index); // Protect against overflow self.reserve(lower_size_bound); unsafe { @@ -653,14 +659,18 @@ impl SmallVec { self.len = self.len + 1; } else { // Iterator provided more elements than the hint. - assert!(index + off >= index); // Protect against overflow. + assert!(index + off >= index); // Protect against overflow. self.insert(index + off, element); } } let num_added = self.len - old_len; if num_added < lower_size_bound { // Iterator provided fewer elements than the hint - ptr::copy(ptr.offset(lower_size_bound as isize), ptr.offset(num_added as isize), old_len - index); + ptr::copy( + ptr.offset(lower_size_bound as isize), + ptr.offset(num_added as isize), + old_len - index, + ); } } } @@ -674,7 +684,7 @@ impl SmallVec { let v = Vec::from_raw_parts(ptr, self.len, capacity); mem::forget(self); v - } + }, } } @@ -697,13 +707,17 @@ impl SmallVec { } /// Removes consecutive duplicate elements. - pub fn dedup(&mut self) where A::Item: PartialEq { + pub fn dedup(&mut self) + where + A::Item: PartialEq, + { self.dedup_by(|a, b| a == b); } /// 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 + pub fn dedup_by(&mut self, mut same_bucket: F) + where + F: FnMut(&mut A::Item, &mut A::Item) -> bool, { // See the implementation of Vec::dedup_by in the // standard library for an explanation of this algorithm. @@ -733,15 +747,19 @@ 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, - K: PartialEq + pub fn dedup_by_key(&mut self, mut key: F) + where + F: FnMut(&mut A::Item) -> K, + K: PartialEq, { self.dedup_by(|a, b| key(a) == key(b)); } } -impl SmallVec where A::Item: Copy { +impl SmallVec +where + A::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)`. @@ -780,7 +798,10 @@ impl SmallVec where A::Item: Copy { } } -impl SmallVec where A::Item: Clone { +impl SmallVec +where + A::Item: Clone, +{ /// Resizes the vector so that its length is equal to `len`. /// /// If `len` is less than the current length, the vector simply truncated. @@ -800,7 +821,7 @@ impl SmallVec where A::Item: Clone { /// Creates a `SmallVec` with `n` copies of `elem`. /// ``` /// use smallvec::SmallVec; - /// + /// /// let v = SmallVec::<[char; 128]>::from_elem('d', 2); /// assert_eq!(v, SmallVec::from_buf(['d', 'd'])); /// ``` @@ -819,9 +840,7 @@ impl ops::Deref for SmallVec { Inline { ref array } => array.ptr(), Heap { ptr, .. } => ptr, }; - unsafe { - slice::from_raw_parts(ptr, self.len) - } + unsafe { slice::from_raw_parts(ptr, self.len) } } } @@ -829,9 +848,7 @@ impl ops::DerefMut for SmallVec { #[inline] fn deref_mut(&mut self) -> &mut [A::Item] { let ptr = self.data.ptr_mut(); - unsafe { - slice::from_raw_parts_mut(ptr, self.len) - } + unsafe { slice::from_raw_parts_mut(ptr, self.len) } } } @@ -884,7 +901,10 @@ impl> io::Write for SmallVec { } #[cfg(feature = "serde")] -impl Serialize for SmallVec where A::Item: Serialize { +impl Serialize for SmallVec +where + A::Item: Serialize, +{ fn serialize(&self, serializer: S) -> Result { let mut state = serializer.serialize_seq(Some(self.len()))?; for item in self { @@ -895,20 +915,26 @@ impl Serialize for SmallVec where A::Item: Serialize { } #[cfg(feature = "serde")] -impl<'de, A: Array> Deserialize<'de> for SmallVec where A::Item: Deserialize<'de> { +impl<'de, A: Array> Deserialize<'de> for SmallVec +where + A::Item: Deserialize<'de>, +{ fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_seq(SmallVecVisitor{phantom: PhantomData}) + deserializer.deserialize_seq(SmallVecVisitor { + phantom: PhantomData, + }) } } #[cfg(feature = "serde")] struct SmallVecVisitor { - phantom: PhantomData + phantom: PhantomData, } #[cfg(feature = "serde")] impl<'de, A: Array> Visitor<'de> for SmallVecVisitor -where A::Item: Deserialize<'de>, +where + A::Item: Deserialize<'de>, { type Value = SmallVec; @@ -917,8 +943,8 @@ where A::Item: Deserialize<'de>, } fn visit_seq(self, mut seq: B) -> Result - where - B: SeqAccess<'de>, + where + B: SeqAccess<'de>, { let len = seq.size_hint().unwrap_or(0); let mut values = SmallVec::with_capacity(len); @@ -931,7 +957,10 @@ where A::Item: Deserialize<'de>, } } -impl<'a, A: Array> From<&'a [A::Item]> for SmallVec where A::Item: Clone { +impl<'a, A: Array> From<&'a [A::Item]> for SmallVec +where + A::Item: Clone, +{ #[inline] fn from(slice: &'a [A::Item]) -> SmallVec { slice.into_iter().cloned().collect() @@ -953,7 +982,7 @@ impl From for SmallVec { } macro_rules! impl_index { - ($index_type: ty, $output_type: ty) => { + ($index_type:ty, $output_type:ty) => { impl ops::Index<$index_type> for SmallVec { type Output = $output_type; #[inline] @@ -968,7 +997,7 @@ macro_rules! impl_index { &mut (&mut **self)[index] } } - } + }; } impl_index!(usize, A::Item); @@ -977,7 +1006,10 @@ impl_index!(ops::RangeFrom, [A::Item]); impl_index!(ops::RangeTo, [A::Item]); impl_index!(ops::RangeFull, [A::Item]); -impl ExtendFromSlice for SmallVec where A::Item: Copy { +impl ExtendFromSlice for SmallVec +where + A::Item: Copy, +{ fn extend_from_slice(&mut self, other: &[A::Item]) { SmallVec::extend_from_slice(self, other) } @@ -992,7 +1024,7 @@ impl VecLike for SmallVec { } impl FromIterator for SmallVec { - fn from_iter>(iterable: I) -> SmallVec { + fn from_iter>(iterable: I) -> SmallVec { let mut v = SmallVec::new(); v.extend(iterable); v @@ -1000,14 +1032,14 @@ impl FromIterator for SmallVec { } impl Extend for SmallVec { - fn extend>(&mut self, iterable: I) { + fn extend>(&mut self, iterable: I) { let iter = iterable.into_iter(); let (lower_size_bound, _) = iter.size_hint(); let target_len = self.len + lower_size_bound; if target_len > self.capacity() { - self.grow(target_len); + self.grow(target_len); } for elem in iter { @@ -1016,7 +1048,10 @@ impl Extend for SmallVec { } } -impl fmt::Debug for SmallVec where A::Item: fmt::Debug { +impl fmt::Debug for SmallVec +where + A::Item: fmt::Debug, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", &**self) } @@ -1035,14 +1070,17 @@ impl Drop for SmallVec { // but the inner SmallVecData destructor will still run unsafe { let ptr = self.as_ptr(); - for i in 0 .. self.len { + for i in 0..self.len { ptr::read(ptr.offset(i as isize)); } } } } -impl Clone for SmallVec where A::Item: Clone { +impl Clone for SmallVec +where + A::Item: Clone, +{ fn clone(&self) -> SmallVec { let mut new_vector = SmallVec::with_capacity(self.len()); for element in self.iter() { @@ -1053,36 +1091,59 @@ impl Clone for SmallVec where A::Item: Clone { } impl PartialEq> for SmallVec - where A::Item: PartialEq { +where + A::Item: PartialEq, +{ #[inline] - fn eq(&self, other: &SmallVec) -> bool { self[..] == other[..] } + fn eq(&self, other: &SmallVec) -> bool { + self[..] == other[..] + } #[inline] - fn ne(&self, other: &SmallVec) -> bool { self[..] != other[..] } + fn ne(&self, other: &SmallVec) -> bool { + self[..] != other[..] + } } -impl Eq for SmallVec where A::Item: Eq {} +impl Eq for SmallVec +where + A::Item: Eq, +{ +} -impl PartialOrd for SmallVec where A::Item: PartialOrd { +impl PartialOrd for SmallVec +where + A::Item: PartialOrd, +{ #[inline] fn partial_cmp(&self, other: &SmallVec) -> Option { PartialOrd::partial_cmp(&**self, &**other) } } -impl Ord for SmallVec where A::Item: Ord { +impl Ord for SmallVec +where + A::Item: Ord, +{ #[inline] fn cmp(&self, other: &SmallVec) -> cmp::Ordering { Ord::cmp(&**self, &**other) } } -impl Hash for SmallVec where A::Item: Hash { +impl Hash for SmallVec +where + A::Item: Hash, +{ fn hash(&self, state: &mut H) { (**self).hash(state) } } -unsafe impl Send for SmallVec where A::Item: Send {} +unsafe impl Send for SmallVec +where + A::Item: Send, +{ +} /// An iterator that consumes a `SmallVec` and yields its items by value. /// @@ -1097,7 +1158,7 @@ pub struct IntoIter { impl Drop for IntoIter { fn drop(&mut self) { - for _ in self { } + for _ in self {} } } @@ -1108,8 +1169,7 @@ impl Iterator for IntoIter { fn next(&mut self) -> Option { if self.current == self.end { None - } - else { + } else { unsafe { let current = self.current as isize; self.current += 1; @@ -1130,8 +1190,7 @@ impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { if self.current == self.end { None - } - else { + } else { unsafe { self.end -= 1; Some(ptr::read(self.data.ptr_mut().offset(self.end as isize))) @@ -1140,7 +1199,7 @@ impl DoubleEndedIterator for IntoIter { } } -impl ExactSizeIterator for IntoIter { } +impl ExactSizeIterator for IntoIter {} impl IntoIterator for SmallVec { type IntoIter = IntoIter; @@ -1201,9 +1260,11 @@ macro_rules! impl_array( } ); -impl_array!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, - 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, - 0x10000, 0x20000, 0x40000, 0x80000, 0x100000); +impl_array!( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, 0x100, + 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, + 0x100000 +); #[cfg(test)] mod tests { @@ -1211,18 +1272,18 @@ mod tests { use std::iter::FromIterator; - #[cfg(feature = "std")] - use std::borrow::ToOwned; #[cfg(not(feature = "std"))] use alloc::borrow::ToOwned; - #[cfg(feature = "std")] - use std::rc::Rc; - #[cfg(not(feature = "std"))] - use alloc::rc::Rc; #[cfg(not(feature = "std"))] use alloc::boxed::Box; #[cfg(not(feature = "std"))] + use alloc::rc::Rc; + #[cfg(not(feature = "std"))] use alloc::vec::Vec; + #[cfg(feature = "std")] + use std::borrow::ToOwned; + #[cfg(feature = "std")] + use std::rc::Rc; #[test] pub fn test_zero() { @@ -1240,10 +1301,7 @@ mod tests { let mut v = SmallVec::<[_; 16]>::new(); v.push("hello".to_owned()); v.push("there".to_owned()); - assert_eq!(&*v, &[ - "hello".to_owned(), - "there".to_owned(), - ][..]); + assert_eq!(&*v, &["hello".to_owned(), "there".to_owned()][..]); } #[test] @@ -1255,12 +1313,15 @@ mod tests { v.push("burma".to_owned()); assert_eq!(v[0], "hello"); v.push("shave".to_owned()); - assert_eq!(&*v, &[ - "hello".to_owned(), - "there".to_owned(), - "burma".to_owned(), - "shave".to_owned(), - ][..]); + assert_eq!( + &*v, + &[ + "hello".to_owned(), + "there".to_owned(), + "burma".to_owned(), + "shave".to_owned(), + ][..] + ); } #[test] @@ -1274,16 +1335,19 @@ mod tests { v.push("there".to_owned()); v.push("burma".to_owned()); v.push("shave".to_owned()); - assert_eq!(&*v, &[ - "hello".to_owned(), - "there".to_owned(), - "burma".to_owned(), - "shave".to_owned(), - "hello".to_owned(), - "there".to_owned(), - "burma".to_owned(), - "shave".to_owned(), - ][..]); + assert_eq!( + &*v, + &[ + "hello".to_owned(), + "there".to_owned(), + "burma".to_owned(), + "shave".to_owned(), + "hello".to_owned(), + "there".to_owned(), + "burma".to_owned(), + "shave".to_owned(), + ][..] + ); } /// https://github.com/servo/rust-smallvec/issues/4 @@ -1464,14 +1528,24 @@ mod tests { } assert_eq!(v.len(), 4); v.insert_many(1, [5, 6].iter().cloned()); - assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 5, 6, 1, 2, 3]); + assert_eq!( + &v.iter().map(|v| *v).collect::>(), + &[0, 5, 6, 1, 2, 3] + ); } - struct MockHintIter{x: T, hint: usize} + struct MockHintIter { + x: T, + hint: usize, + } impl Iterator for MockHintIter { type Item = T::Item; - fn next(&mut self) -> Option {self.x.next()} - fn size_hint(&self) -> (usize, Option) {(self.hint, None)} + fn next(&mut self) -> Option { + self.x.next() + } + fn size_hint(&self) -> (usize, Option) { + (self.hint, None) + } } #[test] @@ -1481,8 +1555,17 @@ mod tests { v.push(x); } assert_eq!(v.len(), 4); - v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 5}); - assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 5, 6, 1, 2, 3]); + v.insert_many( + 1, + MockHintIter { + x: [5, 6].iter().cloned(), + hint: 5, + }, + ); + assert_eq!( + &v.iter().map(|v| *v).collect::>(), + &[0, 5, 6, 1, 2, 3] + ); } #[test] @@ -1492,8 +1575,17 @@ mod tests { v.push(x); } assert_eq!(v.len(), 4); - v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 1}); - assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 5, 6, 1, 2, 3]); + v.insert_many( + 1, + MockHintIter { + x: [5, 6].iter().cloned(), + hint: 1, + }, + ); + assert_eq!( + &v.iter().map(|v| *v).collect::>(), + &[0, 5, 6, 1, 2, 3] + ); } #[test] @@ -1512,7 +1604,10 @@ mod tests { } assert_eq!(v.len(), 4); v.insert_from_slice(1, &[5, 6]); - assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 5, 6, 1, 2, 3]); + assert_eq!( + &v.iter().map(|v| *v).collect::>(), + &[0, 5, 6, 1, 2, 3] + ); } #[test] @@ -1523,7 +1618,10 @@ mod tests { } assert_eq!(v.len(), 4); v.extend_from_slice(&[5, 6]); - assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 1, 2, 3, 5, 6]); + assert_eq!( + &v.iter().map(|v| *v).collect::>(), + &[0, 1, 2, 3, 5, 6] + ); } #[test] @@ -1585,8 +1683,8 @@ mod tests { #[cfg(feature = "std")] #[test] fn test_hash() { - use std::hash::Hash; use std::collections::hash_map::DefaultHasher; + use std::hash::Hash; { let mut a: SmallVec<[u32; 2]> = SmallVec::new(); @@ -1690,7 +1788,10 @@ mod tests { #[test] fn test_from_slice() { assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]); - assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..], [1, 2, 3]); + assert_eq!( + &SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..], + [1, 2, 3] + ); } #[test] @@ -1856,7 +1957,7 @@ mod tests { #[cfg(feature = "serde")] #[test] fn test_serde() { - use self::bincode::{serialize, deserialize, Bounded}; + use self::bincode::{deserialize, serialize, Bounded}; let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new(); small_vec.push(1); let encoded = serialize(&small_vec, Bounded(100)).unwrap(); From 8f0a47e7c1a2839270477e09bfec500772741df3 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 17 Apr 2018 04:37:31 +0100 Subject: [PATCH 2/2] Use a union to reduce the size of SmallVec --- .travis.yml | 3 +- Cargo.toml | 1 + lib.rs | 326 ++++++++++++++++++++++++++++++++-------------------- 3 files changed, 204 insertions(+), 126 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7123702..27d5398 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,9 @@ rust: - stable script: | cargo build --verbose && - cargo build --all-features --verbose && cargo test --verbose && - cargo test --all-features --verbose && ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --no-default-features) && + ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --features union) && ([ $TRAVIS_RUST_VERSION != nightly ] || cargo bench --verbose bench) notifications: webhooks: http://build.servo.org:54856/travis diff --git a/Cargo.toml b/Cargo.toml index 6804204..7ad398f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ documentation = "http://doc.servo.org/smallvec/" [features] std = [] +union = [] default = ["std"] [lib] diff --git a/lib.rs b/lib.rs index 8084cc8..3d89562 100644 --- a/lib.rs +++ b/lib.rs @@ -17,6 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] +#![cfg_attr(feature = "union", feature(untagged_unions))] #![deny(missing_docs)] #[cfg(not(feature = "std"))] @@ -48,12 +49,12 @@ use std::iter::{repeat, FromIterator, IntoIterator}; #[cfg(feature = "serde")] use std::marker::PhantomData; use std::mem; +#[cfg(not(feature = "union"))] +use std::mem::ManuallyDrop; use std::ops; use std::ptr; use std::slice; -use SmallVecData::{Heap, Inline}; - /// Creates a [`SmallVec`] containing the arguments. /// /// `smallvec!` allows `SmallVec`s to be defined with the same syntax as array expressions. @@ -231,43 +232,90 @@ impl<'a, T: 'a> Drop for Drain<'a, T> { } } +#[cfg(feature = "union")] +#[allow(unions_with_drop_fields)] +union SmallVecData { + inline: A, + heap: (*mut A::Item, usize), +} + +#[cfg(feature = "union")] +impl SmallVecData { + #[inline] + unsafe fn inline(&self) -> &A { + &self.inline + } + #[inline] + unsafe fn inline_mut(&mut self) -> &mut A { + &mut self.inline + } + #[inline] + fn from_inline(inline: A) -> SmallVecData { + SmallVecData { inline } + } + #[inline] + unsafe fn heap(&self) -> (*mut A::Item, usize) { + self.heap + } + #[inline] + unsafe fn heap_mut(&mut self) -> &mut (*mut A::Item, usize) { + &mut self.heap + } + #[inline] + fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData { + SmallVecData { heap: (ptr, len) } + } +} + +#[cfg(not(feature = "union"))] enum SmallVecData { - Inline { array: A }, - Heap { ptr: *mut A::Item, capacity: usize }, + Inline(ManuallyDrop), + Heap((*mut A::Item, usize)), } +#[cfg(not(feature = "union"))] impl SmallVecData { - fn ptr_mut(&mut self) -> *mut A::Item { + #[inline] + unsafe fn inline(&self) -> &A { match *self { - Inline { ref mut array } => array.ptr_mut(), - Heap { ptr, .. } => ptr, + SmallVecData::Inline(ref a) => a, + _ => unreachable!(), } } + #[inline] + unsafe fn inline_mut(&mut self) -> &mut A { + match *self { + SmallVecData::Inline(ref mut a) => a, + _ => unreachable!(), + } + } + #[inline] + fn from_inline(inline: A) -> SmallVecData { + SmallVecData::Inline(ManuallyDrop::new(inline)) + } + #[inline] + unsafe fn heap(&self) -> (*mut A::Item, usize) { + match *self { + SmallVecData::Heap(data) => data, + _ => unreachable!(), + } + } + #[inline] + unsafe fn heap_mut(&mut self) -> &mut (*mut A::Item, usize) { + match *self { + SmallVecData::Heap(ref mut data) => data, + _ => unreachable!(), + } + } + #[inline] + fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData { + SmallVecData::Heap((ptr, len)) + } } unsafe impl Send for SmallVecData {} unsafe impl Sync for SmallVecData {} -impl Drop for SmallVecData { - fn drop(&mut self) { - unsafe { - match *self { - ref mut inline @ Inline { .. } => { - // Inhibit the array destructor. - ptr::write( - inline, - Heap { - ptr: ptr::null_mut(), - capacity: 0, - }, - ); - } - Heap { ptr, capacity } => deallocate(ptr, capacity), - } - } - } -} - /// 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 @@ -295,7 +343,7 @@ impl Drop for SmallVecData { /// assert!(v.spilled()); /// ``` pub struct SmallVec { - len: usize, + capacity: usize, data: SmallVecData, } @@ -305,10 +353,8 @@ impl SmallVec { pub fn new() -> SmallVec { unsafe { SmallVec { - len: 0, - data: Inline { - array: mem::uninitialized(), - }, + capacity: 0, + data: SmallVecData::from_inline(mem::uninitialized()), } } } @@ -346,15 +392,26 @@ impl SmallVec { /// ``` #[inline] pub fn from_vec(mut vec: Vec) -> SmallVec { - let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len()); - mem::forget(vec); + if vec.capacity() <= A::size() { + unsafe { + let mut data = SmallVecData::::from_inline(mem::uninitialized()); + let len = vec.len(); + vec.set_len(0); + ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut().ptr_mut(), len); + + SmallVec { + capacity: len, + data, + } + } + } else { + let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len()); + mem::forget(vec); - SmallVec { - len: len, - data: SmallVecData::Heap { - ptr: ptr, + SmallVec { capacity: cap, - }, + data: SmallVecData::from_heap(ptr, len), + } } } @@ -372,8 +429,8 @@ impl SmallVec { #[inline] pub fn from_buf(buf: A) -> SmallVec { SmallVec { - len: A::size(), - data: SmallVecData::Inline { array: buf }, + capacity: A::size(), + data: SmallVecData::from_inline(buf), } } @@ -383,7 +440,11 @@ impl SmallVec { /// modifying its buffers, so it is up to the caller to ensure that the /// vector is actually the specified size. pub unsafe fn set_len(&mut self, new_len: usize) { - self.len = new_len + if self.spilled() { + self.data.heap_mut().1 = new_len; + } else { + self.capacity = new_len; + } } /// The maximum number of elements this vector can hold inline @@ -395,41 +456,43 @@ impl SmallVec { /// The number of elements stored in the vector #[inline] pub fn len(&self) -> usize { - self.len + if self.spilled() { + unsafe { self.data.heap().1 } + } else { + self.capacity + } } /// Returns `true` if the vector is empty #[inline] pub fn is_empty(&self) -> bool { - self.len == 0 + self.len() == 0 } /// The number of items the vector can hold without reallocating #[inline] pub fn capacity(&self) -> usize { - match self.data { - Inline { .. } => A::size(), - Heap { capacity, .. } => capacity, + if self.spilled() { + self.capacity + } else { + A::size() } } /// Returns `true` if the data has spilled into a separate heap-allocated buffer. #[inline] pub fn spilled(&self) -> bool { - match self.data { - Inline { .. } => false, - Heap { .. } => true, - } + self.capacity > A::size() } /// Empty the vector and return an iterator over its former contents. pub fn drain(&mut self) -> Drain { unsafe { + let ptr = self.as_mut_ptr(); + let current_len = self.len(); self.set_len(0); - let ptr = self.data.ptr_mut(); - let slice = slice::from_raw_parts_mut(ptr, current_len); Drain { @@ -442,13 +505,13 @@ impl SmallVec { #[inline] pub fn push(&mut self, value: A::Item) { let cap = self.capacity(); - if self.len == cap { + if self.len() == cap { self.grow(cmp::max(cap * 2, 1)) } unsafe { - let end = self.as_mut_ptr().offset(self.len as isize); + let end = self.as_mut_ptr().offset(self.len() as isize); ptr::write(end, value); - let len = self.len; + let len = self.len(); self.set_len(len + 1) } } @@ -456,10 +519,10 @@ 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 { - if self.len == 0 { + if self.len() == 0 { return None; } - let last_index = self.len - 1; + let last_index = self.len() - 1; if (last_index as isize) < 0 { panic!("overflow") } @@ -471,28 +534,33 @@ impl SmallVec { } } - /// Re-allocate to set the capacity to `new_cap`. + /// Re-allocate to set the capacity to `max(new_cap, inline_size())`. /// /// Panics if `new_cap` is less than the vector's length. pub fn grow(&mut self, new_cap: usize) { - assert!(new_cap >= self.len); - let mut vec: Vec = Vec::with_capacity(new_cap); - let new_alloc = vec.as_mut_ptr(); + assert!(new_cap >= self.len()); unsafe { - mem::forget(vec); - ptr::copy_nonoverlapping(self.as_ptr(), new_alloc, self.len); - - match self.data { - Inline { .. } => {} - Heap { ptr, capacity } => deallocate(ptr, capacity), + if new_cap <= self.inline_size() { + if !self.spilled() { + return; + } + let (ptr, len) = self.data.heap(); + let mut vec = Vec::from_raw_parts(ptr, len, self.capacity); + self.data = SmallVecData::from_inline(mem::uninitialized()); + ptr::copy_nonoverlapping(vec.as_ptr(), self.as_mut_ptr(), len); + vec.set_len(0); + } else if new_cap != self.capacity { + let mut vec = Vec::with_capacity(new_cap); + let new_alloc = vec.as_mut_ptr(); + mem::forget(vec); + let len = self.len(); + ptr::copy_nonoverlapping(self.as_ptr(), new_alloc, len); + if self.spilled() { + deallocate(self.data.heap().0, self.capacity); + } + self.data = SmallVecData::from_heap(new_alloc, len); + self.capacity = new_cap; } - ptr::write( - &mut self.data, - Heap { - ptr: new_alloc, - capacity: new_cap, - }, - ); } } @@ -533,21 +601,17 @@ impl SmallVec { /// When possible, this will move data from an external heap buffer to the vector's inline /// storage. pub fn shrink_to_fit(&mut self) { - let len = self.len; + if !self.spilled() { + return; + } + let len = self.len(); if self.inline_size() >= len { unsafe { - let (ptr, capacity) = match self.data { - Inline { .. } => return, - Heap { ptr, capacity } => (ptr, capacity), - }; - ptr::write( - &mut self.data, - Inline { - array: mem::uninitialized(), - }, - ); - ptr::copy_nonoverlapping(ptr, self.as_mut_ptr(), len); - deallocate(ptr, capacity); + let (ptr, len) = self.data.heap(); + self.data = SmallVecData::from_inline(mem::uninitialized()); + ptr::copy_nonoverlapping(ptr, self.data.inline_mut().ptr_mut(), len); + deallocate(ptr, self.capacity); + self.capacity = len; } } else if self.capacity() > len { self.grow(len); @@ -563,9 +627,9 @@ impl SmallVec { /// `shrink_to_fit` after truncating. pub fn truncate(&mut self, len: usize) { let end_ptr = self.as_ptr(); - while len < self.len { + while len < self.len() { unsafe { - let last_index = self.len - 1; + let last_index = self.len() - 1; self.set_len(last_index); ptr::read(end_ptr.offset(last_index as isize)); } @@ -593,7 +657,7 @@ impl SmallVec { /// Panics if `index` is out of bounds. #[inline] pub fn swap_remove(&mut self, index: usize) -> A::Item { - let len = self.len; + let len = self.len(); self.swap(len - 1, index); self.pop().unwrap() } @@ -628,7 +692,7 @@ impl SmallVec { pub fn insert(&mut self, index: usize, element: A::Item) { self.reserve(1); - let len = self.len; + let len = self.len(); assert!(index <= len); unsafe { @@ -649,21 +713,22 @@ impl SmallVec { self.reserve(lower_size_bound); unsafe { - let old_len = self.len; + let old_len = self.len(); assert!(index <= old_len); let ptr = self.as_mut_ptr().offset(index as isize); ptr::copy(ptr, ptr.offset(lower_size_bound as isize), old_len - index); for (off, element) in iter.enumerate() { if off < lower_size_bound { ptr::write(ptr.offset(off as isize), element); - self.len = self.len + 1; + let len = self.len() + 1; + self.set_len(len); } else { // Iterator provided more elements than the hint. assert!(index + off >= index); // Protect against overflow. self.insert(index + off, element); } } - let num_added = self.len - old_len; + let num_added = self.len() - old_len; if num_added < lower_size_bound { // Iterator provided fewer elements than the hint ptr::copy( @@ -678,13 +743,15 @@ 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 { - match self.data { - Inline { .. } => self.into_iter().collect(), - Heap { ptr, capacity } => unsafe { - let v = Vec::from_raw_parts(ptr, self.len, capacity); + if self.spilled() { + unsafe { + let (ptr, len) = self.data.heap(); + let v = Vec::from_raw_parts(ptr, len, self.capacity); mem::forget(self); v - }, + } + } else { + self.into_iter().collect() } } @@ -695,7 +762,7 @@ impl SmallVec { /// elements. pub fn retain bool>(&mut self, mut f: F) { let mut del = 0; - let len = self.len; + let len = self.len(); for i in 0..len { if !f(&mut self[i]) { del += 1; @@ -721,7 +788,7 @@ impl SmallVec { { // See the implementation of Vec::dedup_by in the // standard library for an explanation of this algorithm. - let len = self.len; + let len = self.len(); if len <= 1 { return; } @@ -776,7 +843,7 @@ where pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) { self.reserve(slice.len()); - let len = self.len; + let len = self.len(); assert!(index <= len); unsafe { @@ -819,6 +886,7 @@ where } /// Creates a `SmallVec` with `n` copies of `elem`. + /// /// ``` /// use smallvec::SmallVec; /// @@ -836,19 +904,28 @@ impl ops::Deref for SmallVec { type Target = [A::Item]; #[inline] fn deref(&self) -> &[A::Item] { - let ptr: *const _ = match self.data { - Inline { ref array } => array.ptr(), - Heap { ptr, .. } => ptr, - }; - unsafe { slice::from_raw_parts(ptr, self.len) } + unsafe { + let ptr = if self.spilled() { + self.data.heap().0 + } else { + self.data.inline().ptr() + }; + slice::from_raw_parts(ptr, self.len()) + } } } impl ops::DerefMut for SmallVec { #[inline] fn deref_mut(&mut self) -> &mut [A::Item] { - let ptr = self.data.ptr_mut(); - unsafe { slice::from_raw_parts_mut(ptr, self.len) } + unsafe { + let ptr = if self.spilled() { + self.data.heap().0 + } else { + self.data.inline_mut().ptr_mut() + }; + slice::from_raw_parts_mut(ptr, self.len()) + } } } @@ -1036,7 +1113,7 @@ impl Extend for SmallVec { let iter = iterable.into_iter(); let (lower_size_bound, _) = iter.size_hint(); - let target_len = self.len + lower_size_bound; + let target_len = self.len() + lower_size_bound; if target_len > self.capacity() { self.grow(target_len); @@ -1066,12 +1143,15 @@ impl Default for SmallVec { impl Drop for SmallVec { fn drop(&mut self) { - // Note on panic safety: dropping an element may panic, - // but the inner SmallVecData destructor will still run unsafe { - let ptr = self.as_ptr(); - for i in 0..self.len { - ptr::read(ptr.offset(i as isize)); + if self.spilled() { + let (ptr, len) = self.data.heap(); + Vec::from_raw_parts(ptr, len, self.capacity); + } else { + let ptr = self.as_ptr(); + for i in 0..self.len() { + ptr::read(ptr.offset(i as isize)); + } } } } @@ -1151,7 +1231,7 @@ where /// /// [1]: struct.SmallVec.html#method.into_iter pub struct IntoIter { - data: SmallVecData, + data: SmallVec, current: usize, end: usize, } @@ -1173,7 +1253,7 @@ impl Iterator for IntoIter { unsafe { let current = self.current as isize; self.current += 1; - Some(ptr::read(self.data.ptr_mut().offset(current))) + Some(ptr::read(self.data.as_ptr().offset(current))) } } } @@ -1193,7 +1273,7 @@ impl DoubleEndedIterator for IntoIter { } else { unsafe { self.end -= 1; - Some(ptr::read(self.data.ptr_mut().offset(self.end as isize))) + Some(ptr::read(self.data.as_ptr().offset(self.end as isize))) } } } @@ -1205,13 +1285,11 @@ impl IntoIterator for SmallVec { type IntoIter = IntoIter; type Item = A::Item; fn into_iter(mut self) -> Self::IntoIter { - let len = self.len(); unsafe { - // Only grab the `data` field, the `IntoIter` type handles dropping of the elements - let data = ptr::read(&mut self.data); - mem::forget(self); + let len = self.len(); + self.set_len(0); IntoIter { - data: data, + data: self, current: 0, end: len, }