Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion fuzz/fuzz_targets/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,9 @@ fn test_with_inline_cap<const N: usize>(
small_vec = SmallVec::with_capacity(cap.0);
std_vec = Vec::with_capacity(cap.0);
}
#[allow(deprecated)]
Op::FromVec => {
small_vec = SmallVec::from(Into::<Vec<_>>::into(small_vec));
small_vec = SmallVec::from(small_vec.into_vec());
// No-op on `Vec`
}
Op::FromSlice(data) => {
Expand Down
319 changes: 274 additions & 45 deletions src/comparisons.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#[cfg(feature = "equivalent")]
use equivalent::{
Comparable,
Equivalent
};
use {
super::{
SmallVec,
Expand All @@ -11,68 +16,292 @@ use {
core::cmp::Ordering
};

macro_rules! __impl_slice_eq1 {
([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?) => {
impl<Item, U, Heap: Allocator, const INLINE: usize, $($vars)*> PartialEq<$rhs> for $lhs
where
Item: PartialEq<U>,
$($ty: $bound)?
{
macro_rules! implementation {
([$($generics:tt)*] for $left:ty =? $right:ty $(where $typename:ty: $bound:ident)?) => {
impl<
Item: PartialEq<Other>,
Other,
Heap: Allocator,
const INLINE: usize,
$($generics)*
> PartialEq<$right> for $left $(where $typename: $bound)? {
#[inline]
fn eq(&self, other: &$right) -> bool {
*AsRef::<[Item]>::as_ref(self) == *AsRef::<[Other]>::as_ref(other)
}
}
};
([$($generics:tt)*] for $left:ty =<> $right:ty $(where $typename:ty: $bound:ident)?) => {
impl<
Item: PartialOrd<Other>,
Other,
Heap: Allocator,
const INLINE: usize,
$($generics)*
> PartialOrd<$right> for $left $(where $typename: $bound)? {
#[inline]
fn partial_cmp(&self, other: &$right) -> Option<Ordering> {
AsRef::<[Item]>::as_ref(self).iter().partial_cmp(AsRef::<[Other]>::as_ref(other))
}
}
};
([$($generics:tt)*] for $left:ty =?+ $right:ty $(where $typename:ty: $bound:ident)?) => {
impl<
Item: Equivalent<Other>,
Other,
Heap: Allocator,
const INLINE: usize,
$($generics)*
> Equivalent<$right> for $left $(where $typename: $bound)? {
#[inline]
fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] }
fn equivalent(&self, key: &$right) -> bool {
self.len() == key.len() && self.iter()
.zip(AsRef::<[Other]>::as_ref(key))
.all(|(item, key)| item.equivalent(key))
}
}
};
([$($generics:tt)*] for $left:ty =<>+ $right:ty $(where $typename:ty: $bound:ident)?) => {
impl<
Item: Comparable<Other>,
Other,
Heap: Allocator,
const INLINE: usize,
$($generics)*
> Comparable<$right> for $left $(where $typename: $bound)? {
fn compare(&self, other: &$right) -> Ordering {
self.iter()
.zip(AsRef::<[Other]>::as_ref(other))
.map(|(item, key)| item.compare(key))
.find(|&ordering| ordering != Ordering::Equal)
.unwrap_or_else(|| self.len().cmp(&other.len()))
}
}
}
}

__impl_slice_eq1! { [const M: usize, A2: Allocator]
SmallVec<Item, M, Heap>,
SmallVec<U, INLINE, A2>
implementation!([const LENGTH: usize, Assigner: Allocator] for SmallVec<Item, INLINE, Heap> =? SmallVec<Other, LENGTH, Assigner>);
impl<Item: Eq, const INLINE: usize, Heap: Allocator> Eq for SmallVec<Item, INLINE, Heap> {}
implementation!([const LENGTH: usize, Assigner: Allocator] for SmallVec<Item, INLINE, Heap> =<> SmallVec<Other, LENGTH, Assigner>);
impl<Item: Ord, const INLINE: usize, Heap: Allocator> Ord for SmallVec<Item, INLINE, Heap> {
#[inline]
fn cmp(&self, other: &SmallVec<Item, INLINE, Heap>) -> Ordering {
self.as_ref().cmp(other.as_ref())
}
}
__impl_slice_eq1! { [const M: usize] SmallVec<Item, M, Heap>, [U; INLINE] }
__impl_slice_eq1! { [const M: usize] SmallVec<Item, M, Heap>, &[U; INLINE] }
__impl_slice_eq1! { [] SmallVec<Item, INLINE, Heap>, [U] }
__impl_slice_eq1! { [] SmallVec<Item, INLINE, Heap>, &[U] }
__impl_slice_eq1! { [] SmallVec<Item, INLINE, Heap>, &mut [U] }
__impl_slice_eq1! { [] [Item], SmallVec<U, INLINE, Heap> }
__impl_slice_eq1! { [] &[Item], SmallVec<U, INLINE, Heap> }
__impl_slice_eq1! { [] &mut [Item], SmallVec<U, INLINE, Heap> }
__impl_slice_eq1! { [] Vec<Item>, SmallVec<U, INLINE, Heap> }
__impl_slice_eq1! { [] SmallVec<Item, INLINE, Heap>, Vec<U> }
__impl_slice_eq1! { [] Cow<'_, [Item]>, SmallVec<U, INLINE, Heap> where Item: Clone }
__impl_slice_eq1! { [] SmallVec<Item, INLINE, Heap>, Cow<'_, [U]> where U: Clone }

impl<Item, U, const INLINE: usize, Heap: Allocator> PartialEq<SmallVec<U, INLINE, Heap>>
for VecDeque<Item>
where Item: PartialEq<U>
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =? [Other; LENGTH]);
implementation!([const LENGTH: usize] for [Item; INLINE] =? SmallVec<Other, LENGTH, Heap>);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =?+ [Other; LENGTH]);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for [Item; INLINE] =?+ SmallVec<Other, LENGTH, Heap>);
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =<> [Other; LENGTH]);
implementation!([const LENGTH: usize] for [Item; INLINE] =<> SmallVec<Other, LENGTH, Heap>);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =<>+ [Other; LENGTH]);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for [Item; INLINE] =<>+ SmallVec<Other, LENGTH, Heap>);

implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =? &[Other; LENGTH]);
implementation!([const LENGTH: usize] for &[Item; INLINE] =? SmallVec<Other, LENGTH, Heap>);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =?+ &[Other; LENGTH]);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for &[Item; INLINE] =?+ SmallVec<Other, LENGTH, Heap>);
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =<> &[Other; LENGTH]);
implementation!([const LENGTH: usize] for &[Item; INLINE] =<> SmallVec<Other, LENGTH, Heap>);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =<>+ &[Other; LENGTH]);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for &[Item; INLINE] =<>+ SmallVec<Other, LENGTH, Heap>);

implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =? &mut [Other; LENGTH]);
implementation!([const LENGTH: usize] for &mut [Item; INLINE] =? SmallVec<Other, LENGTH, Heap>);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =?+ &mut [Other; LENGTH]);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for &mut [Item; INLINE] =?+ SmallVec<Other, LENGTH, Heap>);
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =<> &mut [Other; LENGTH]);
implementation!([const LENGTH: usize] for &mut [Item; INLINE] =<> SmallVec<Other, LENGTH, Heap>);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for SmallVec<Item, INLINE, Heap> =<>+ &mut [Other; LENGTH]);
#[cfg(feature = "equivalent")]
implementation!([const LENGTH: usize] for &mut [Item; INLINE] =<>+ SmallVec<Other, LENGTH, Heap>);

implementation!([] for SmallVec<Item, INLINE, Heap> =? [Other]);
implementation!([] for [Item] =? SmallVec<Other, INLINE, Heap>);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =?+ [Other]);
implementation!([] for SmallVec<Item, INLINE, Heap> =<> [Other]);
implementation!([] for [Item] =<> SmallVec<Other, INLINE, Heap>);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =<>+ [Other]);

implementation!([] for SmallVec<Item, INLINE, Heap> =? &[Other]);
implementation!([] for &[Item] =? SmallVec<Other, INLINE, Heap>);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =?+ &[Other]);
#[cfg(feature = "equivalent")]
implementation!([] for &[Item] =?+ SmallVec<Other, INLINE, Heap>);
implementation!([] for SmallVec<Item, INLINE, Heap> =<> &[Other]);
implementation!([] for &[Item] =<> SmallVec<Other, INLINE, Heap>);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =<>+ &[Other]);
#[cfg(feature = "equivalent")]
implementation!([] for &[Item] =<>+ SmallVec<Other, INLINE, Heap>);

implementation!([] for SmallVec<Item, INLINE, Heap> =? &mut [Other]);
implementation!([] for &mut [Item] =? SmallVec<Other, INLINE, Heap>);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =?+ &mut [Other]);
#[cfg(feature = "equivalent")]
implementation!([] for &mut [Item] =?+ SmallVec<Other, INLINE, Heap>);
implementation!([] for SmallVec<Item, INLINE, Heap> =<> &mut [Other]);
implementation!([] for &mut [Item] =<> SmallVec<Other, INLINE, Heap>);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =<>+ &mut [Other]);
#[cfg(feature = "equivalent")]
implementation!([] for &mut [Item] =<>+ SmallVec<Other, INLINE, Heap>);

implementation!([] for SmallVec<Item, INLINE, Heap> =? Vec<Other>);
implementation!([] for Vec<Item> =? SmallVec<Other, INLINE, Heap>);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =?+ Vec<Other>);
#[cfg(feature = "equivalent")]
implementation!([] for Vec<Item> =?+ SmallVec<Other, INLINE, Heap>);
implementation!([] for SmallVec<Item, INLINE, Heap> =<> Vec<Other>);
implementation!([] for Vec<Item> =<> SmallVec<Other, INLINE, Heap>);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =<>+ Vec<Other>);
#[cfg(feature = "equivalent")]
implementation!([] for Vec<Item> =<>+ SmallVec<Other, INLINE, Heap>);

implementation!([] for SmallVec<Item, INLINE, Heap> =? Cow<'_, [Other]> where Other: Clone);
implementation!([] for Cow<'_, [Item]> =? SmallVec<Other, INLINE, Heap> where Item: Clone);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =?+ Cow<'_, [Other]> where Other: Clone);
#[cfg(feature = "equivalent")]
implementation!([] for Cow<'_, [Item]> =?+ SmallVec<Other, INLINE, Heap> where Item: Clone);
implementation!([] for SmallVec<Item, INLINE, Heap> =<> Cow<'_, [Other]> where Other: Clone);
implementation!([] for Cow<'_, [Item]> =<> SmallVec<Other, INLINE, Heap> where Item: Clone);
#[cfg(feature = "equivalent")]
implementation!([] for SmallVec<Item, INLINE, Heap> =<>+ Cow<'_, [Other]> where Other: Clone);
#[cfg(feature = "equivalent")]
implementation!([] for Cow<'_, [Item]> =<>+ SmallVec<Other, INLINE, Heap> where Item: Clone);

impl<Item: PartialEq<Other>, Other, const INLINE: usize, Heap: Allocator>
PartialEq<SmallVec<Other, INLINE, Heap>> for VecDeque<Item>
{
#[inline]
fn eq(&self, other: &SmallVec<U, INLINE, Heap>) -> bool {
let other = other.as_ref();
if self.len() != other.len() {
fn eq(&self, other: &SmallVec<Other, INLINE, Heap>) -> bool {
let (first, second) = self.as_slices();
let Some((before, after)) = other.split_at_checked(first.len()) else {
return false;
}
let (sa, sb) = self.as_slices();
let (oa, ob) = other[..].split_at(sa.len());
sa == oa && sb == ob
};
first == before && second == after
}
}

impl<Item: Eq, const INLINE: usize, Heap: Allocator> Eq for SmallVec<Item, INLINE, Heap> {}

impl<Item, const INLINE: usize, Heap: Allocator> PartialOrd for SmallVec<Item, INLINE, Heap>
where Item: PartialOrd
impl<Item: PartialEq<Other>, Other, const INLINE: usize, Heap: Allocator> PartialEq<VecDeque<Other>>
for SmallVec<Item, INLINE, Heap>
{
#[inline]
fn partial_cmp(&self, other: &SmallVec<Item, INLINE, Heap>) -> Option<Ordering> {
self.as_ref().partial_cmp(other.as_ref())
fn eq(&self, other: &VecDeque<Other>) -> bool {
let (first, second) = other.as_slices();
let Some((before, after)) = self.split_at_checked(first.len()) else {
return false;
};
before == first && after == second
}
}

impl<Item, const INLINE: usize, Heap: Allocator> Ord for SmallVec<Item, INLINE, Heap>
where Item: Ord
#[cfg(feature = "equivalent")]
impl<Item: Equivalent<Other>, Other, const INLINE: usize, Heap: Allocator>
Equivalent<SmallVec<Other, INLINE, Heap>> for VecDeque<Item>
{
#[inline]
fn cmp(&self, other: &SmallVec<Item, INLINE, Heap>) -> Ordering {
self.as_ref().cmp(other.as_ref())
fn equivalent(&self, key: &SmallVec<Other, INLINE, Heap>) -> bool {
let (first, second) = self.as_slices();
let Some((before, after)) = key.split_at_checked(first.len()) else {
return false;
};
first.len() == before.len()
&& first
.iter()
.zip(before)
.all(|(item, key)| item.equivalent(key))
&& second.len() == after.len()
&& second
.iter()
.zip(after)
.all(|(item, key)| item.equivalent(key))
}
}
#[cfg(feature = "equivalent")]
impl<Item: Equivalent<Other>, Other, const INLINE: usize, Heap: Allocator>
Equivalent<VecDeque<Other>> for SmallVec<Item, INLINE, Heap>
{
#[inline]
fn equivalent(&self, key: &VecDeque<Other>) -> bool {
let (first, second) = key.as_slices();
let Some((before, after)) = self.split_at_checked(first.len()) else {
return false;
};
first.len() == before.len()
&& first
.iter()
.zip(before)
.all(|(item, key)| key.equivalent(item))
&& second.len() == after.len()
&& second
.iter()
.zip(after)
.all(|(item, key)| key.equivalent(item))
}
}
impl<Item: PartialOrd<Other>, Other, const INLINE: usize, Heap: Allocator>
PartialOrd<SmallVec<Other, INLINE, Heap>> for VecDeque<Item>
{
#[inline]
fn partial_cmp(&self, other: &SmallVec<Other, INLINE, Heap>) -> Option<Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<Item: PartialOrd<Other>, Other, const INLINE: usize, Heap: Allocator>
PartialOrd<VecDeque<Other>> for SmallVec<Item, INLINE, Heap>
{
#[inline]
fn partial_cmp(&self, other: &VecDeque<Other>) -> Option<Ordering> {
self.iter().partial_cmp(other.iter())
}
}
#[cfg(feature = "equivalent")]
impl<Item: Comparable<Other>, Other, const INLINE: usize, Heap: Allocator>
Comparable<SmallVec<Other, INLINE, Heap>> for VecDeque<Item>
{
#[inline]
fn compare(&self, key: &SmallVec<Other, INLINE, Heap>) -> Ordering {
let (first, second) = self.as_slices();
first
.iter()
.chain(second.iter())
.map(|item| item)
.zip(key.iter())
.map(|(item, key)| item.compare(key))
.find(|&ordering| ordering != Ordering::Equal)
.unwrap_or_else(|| self.len().cmp(&key.len()))
}
}
#[cfg(feature = "equivalent")]
impl<Item: Comparable<Other>, Other, const INLINE: usize, Heap: Allocator>
Comparable<VecDeque<Other>> for SmallVec<Item, INLINE, Heap>
{
#[inline]
fn compare(&self, key: &VecDeque<Other>) -> Ordering {
let (first, second) = key.as_slices();
self.iter()
.zip(first.iter().chain(second.iter()))
.map(|(item, key)| item.compare(key))
.find(|&ordering| ordering != Ordering::Equal)
.unwrap_or_else(|| self.len().cmp(&key.len()))
}
}
11 changes: 0 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1833,17 +1833,6 @@ impl<Item: Debug, const INLINE: usize, Heap: Allocator> Debug for SmallVec<Item,
}
}

#[cfg(feature = "equivalent")]
#[cfg_attr(docsrs, doc(cfg(feature = "equivalent")))]
impl<Item, Other, const INLINE: usize, Heap: Allocator> equivalent::Equivalent<[Other]>
for SmallVec<Item, INLINE, Heap>
where Item: equivalent::Equivalent<Other>
{
fn equivalent(&self, key: &[Other]) -> bool {
self.len() == key.len() && self.iter().zip(key).all(|(item, key)| item.equivalent(key))
}
}

#[cfg(feature = "zeroize")]
impl<Item: Zeroize, const INLINE: usize, Heap: Allocator> Zeroize for SmallVec<Item, INLINE, Heap> {
fn zeroize(&mut self) {
Expand Down
Loading