diff --git a/src/shared.rs b/src/shared.rs index 25f1d54..95be11b 100644 --- a/src/shared.rs +++ b/src/shared.rs @@ -667,6 +667,8 @@ impl, R: RefCount, A: Allocator> PartialEq<&[T]> for RefCountedV } } +impl Eq for RefCountedVector {} + impl AsRef<[T]> for RefCountedVector { fn as_ref(&self) -> &[T] { self.as_slice() @@ -679,6 +681,12 @@ impl Default for RefCountedVector { } } +impl FromIterator for RefCountedVector { + fn from_iter>(iter: I) -> Self { + Vector::from_iter(iter).into_shared_with_ref_count() + } +} + impl<'a, T, R: RefCount, A: Allocator> IntoIterator for &'a RefCountedVector { type Item = &'a T; type IntoIter = core::slice::Iter<'a, T>; @@ -734,6 +742,12 @@ impl DerefMut for RefCountedVector< } } +impl core::hash::Hash for RefCountedVector { + fn hash(&self, state: &mut H) where H: core::hash::Hasher { + self.as_slice().hash(state) + } +} + impl Debug for RefCountedVector { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { self.as_slice().fmt(f) @@ -836,6 +850,25 @@ fn grow() { assert_eq!(b.as_slice(), &[num(1), num(2), num(3)]); } +#[test] +fn eq_and_hash() { + use std::collections::HashMap; + + let mut map: HashMap>, u32> = HashMap::new(); + map.insert((0..3).map(num).collect(), 1); + map.insert((0..2).map(num).collect(), 2); + + let key: AtomicSharedVector> = (0..3).map(num).collect(); + assert_eq!(map.get(&key), Some(&1)); + // Distinct buffers with the same contents hash and compare equal. + assert!(!key.ptr_eq(map.keys().find(|k| **k == key).unwrap())); + + let mut set: std::collections::HashSet> = std::collections::HashSet::new(); + set.insert(SharedVector::from_slice(&[1, 2])); + assert!(set.contains(&SharedVector::from_slice(&[1, 2]))); + assert!(!set.contains(&SharedVector::from_slice(&[1, 3]))); +} + #[test] fn ensure_unique_empty() { let mut v: SharedVector = SharedVector::new(); diff --git a/src/vector.rs b/src/vector.rs index f4cf006..ab02b45 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -8,9 +8,9 @@ use crate::alloc::{AllocError, Allocator, Global}; use crate::drain::Drain; use crate::into_iter::IntoIter; use crate::raw::{ - self, buffer_layout, AtomicRefCount, BufferSize, Header, HeaderBuffer, RefCount, VecHeader, move_data, + self, buffer_layout, BufferSize, Header, HeaderBuffer, RefCount, VecHeader, move_data, }; -use crate::shared::{AtomicSharedVector, SharedVector}; +use crate::shared::{AtomicSharedVector, RefCountedVector, SharedVector}; use crate::splice::Splice; use crate::{grow_amortized, DefaultRefCount}; @@ -1149,13 +1149,7 @@ impl Vector { where A: Allocator + Clone, { - if self.raw.header.cap == 0 { - return SharedVector::try_with_capacity_in(0, self.allocator.clone()).unwrap(); - } - unsafe { - let inner = self.into_header_buffer::(); - SharedVector { inner } - } + self.into_shared_with_ref_count() } /// Make this vector immutable. @@ -1164,15 +1158,24 @@ impl Vector { /// to be reallocated. #[inline] pub fn into_shared_atomic(self) -> AtomicSharedVector + where + A: Allocator + Clone, + { + self.into_shared_with_ref_count() + } + + /// Make this vector immutable, with the reference counting scheme of the caller's choice. + #[inline] + pub(crate) fn into_shared_with_ref_count(self) -> RefCountedVector where A: Allocator + Clone, { if self.raw.header.cap == 0 { - return AtomicSharedVector::try_with_capacity_in(0, self.allocator.clone()).unwrap(); + return RefCountedVector::try_with_capacity_in(0, self.allocator.clone()).unwrap(); } unsafe { - let inner = self.into_header_buffer::(); - AtomicSharedVector { inner } + let inner = self.into_header_buffer::(); + RefCountedVector { inner } } } @@ -1493,6 +1496,8 @@ impl, A: Allocator> PartialEq<&[T]> for Vector { } } +impl Eq for Vector {} + impl AsRef<[T]> for Vector { fn as_ref(&self) -> &[T] { self.as_slice() @@ -1511,6 +1516,15 @@ impl Default for Vector { } } +impl FromIterator for Vector { + fn from_iter>(iter: I) -> Self { + let mut vector = Vector::new(); + vector.extend(iter); + + vector + } +} + impl IntoIterator for Vector { type Item = T; type IntoIter = IntoIter; @@ -1676,6 +1690,32 @@ fn basic_unique() { assert_eq!(d.as_slice(), &[num(0), num(1), num(2), num(3), num(4)]); } +#[test] +fn from_iterator() { + fn num(val: u32) -> Box { + Box::new(val) + } + + let v: Vector> = (0..4).map(num).collect(); + assert_eq!(v.as_slice(), &[num(0), num(1), num(2), num(3)]); + + let v: Vector> = Vector::from_iter([]); + assert!(v.is_empty()); + + let v: SharedVector> = (0..3).map(num).collect(); + assert_eq!(v.as_slice(), &[num(0), num(1), num(2)]); + + let v: AtomicSharedVector> = (0..3).map(num).collect(); + assert_eq!(v.as_slice(), &[num(0), num(1), num(2)]); + + // Iterators without an upper bound on their size hint. + let v: AtomicSharedVector> = (0..5).filter(|n| n % 2 == 0).map(num).collect(); + assert_eq!(v.as_slice(), &[num(0), num(2), num(4)]); + + let v: AtomicSharedVector> = std::iter::empty().collect(); + assert!(v.is_empty()); +} + #[test] fn shrink() { let mut v: Vector = Vector::with_capacity(32);