Skip to content

Commit 519348b

Browse files
authored
feat(set): add VecSet::from_vec_unchecked (#27)
Followup to #16
1 parent 6bac8ca commit 519348b

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

src/set.rs

+34
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,40 @@ impl<T> VecSet<T> {
462462
pub fn into_vec(self) -> Vec<T> {
463463
self.into_iter().collect()
464464
}
465+
466+
/// Takes ownership of provided vector and converts it into `VecSet`.
467+
///
468+
/// # Safety
469+
///
470+
/// The vector must have no duplicate elements. One way to guarantee it is to sort the vector
471+
/// (e.g. by using [`[T]::sort`][slice-sort]) and then drop duplicate elements (e.g. by using
472+
/// [`Vec::dedup`]).
473+
///
474+
/// # Example
475+
///
476+
/// ```
477+
/// use vecmap::VecSet;
478+
///
479+
/// let mut vec = vec!["b", "a", "c", "b"];
480+
/// vec.sort();
481+
/// vec.dedup();
482+
/// // SAFETY: We've just deduplicated the vector.
483+
/// let set = unsafe { VecSet::from_vec_unchecked(vec) };
484+
///
485+
/// assert_eq!(set, VecSet::from(["b", "a", "c"]));
486+
/// ```
487+
///
488+
/// [slice-sort]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort
489+
pub unsafe fn from_vec_unchecked(mut vec: Vec<T>) -> Self {
490+
let (ptr, len, cap) = (vec.as_mut_ptr(), vec.len(), vec.capacity());
491+
core::mem::forget(vec);
492+
// SAFETY: `Vec<T>` and `Vec<(T, ())>` have the same memory layout.
493+
let base = unsafe { Vec::from_raw_parts(ptr.cast(), len, cap) };
494+
VecSet {
495+
// SAFETY: The caller ensures that the vector does not contain duplicate elements.
496+
base: unsafe { VecMap::from_vec_unchecked(base) },
497+
}
498+
}
465499
}
466500

467501
// Lookup operations.

src/set/impls.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,16 @@ impl<T> From<Vec<T>> for VecSet<T>
7070
where
7171
T: Eq,
7272
{
73-
fn from(vec: Vec<T>) -> Self {
74-
VecSet::from_iter(vec)
73+
/// Constructs set from a vector.
74+
///
75+
/// **Note**: This conversion has a quadratic complexity because the
76+
/// conversion preserves order of elements while at the same time having to
77+
/// make sure no duplicate elements exist. To avoid it, sort and deduplicate
78+
/// the vector and use [`VecSet::from_vec_unchecked`] instead.
79+
fn from(mut vec: Vec<T>) -> Self {
80+
crate::dedup(&mut vec, |rhs, lhs| rhs == lhs);
81+
// SAFETY: We've just deduplicated the elements.
82+
unsafe { Self::from_vec_unchecked(vec) }
7583
}
7684
}
7785

0 commit comments

Comments
 (0)