use core::borrow::Borrow;
use core::fmt::Debug;
use core::iter::FusedIterator;
use core::slice::Iter;
use crate::collections::vec::{Vec, Drain};
use crate::storage::{ArrayLayout, Capacity, Storage, InlineStorage};
pub struct ListSet<T, S: Storage<ArrayLayout<T>>, I: Capacity> {
vec: Vec<T, S, I>,
}
impl<T, S: Storage<ArrayLayout<T>>, I: Capacity> From<S> for ListSet<T, S, I> {
fn from(buf: S) -> Self {
ListSet { vec: Vec::from(buf) }
}
}
impl<T: Eq, S: Storage<ArrayLayout<T>>, I: Capacity> From<Vec<T, S, I>> for ListSet<T, S, I> {
fn from(mut vec: Vec<T, S, I>) -> Self {
let mut i = 1;
'outer: while i < vec.len() {
for j in 0..i {
let i = I::from_usize(i);
let j = I::from_usize(j);
if vec[i] == vec[j] {
vec.swap_remove(i);
continue 'outer;
}
}
i += 1;
}
ListSet { vec }
}
}
impl<T: Eq, S: Storage<ArrayLayout<T>>, I: Capacity> ListSet<T, S, I> {
#[inline]
pub fn from_vec_unchecked(vec: Vec<T, S, I>) -> Self {
ListSet { vec }
}
#[inline]
pub fn capacity(&self) -> usize {
self.vec.capacity()
}
#[inline]
pub fn len(&self) -> usize {
self.vec.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.vec.is_empty()
}
#[inline]
pub fn is_full(&self) -> bool {
self.vec.is_full()
}
#[inline]
pub fn clear(&mut self) {
self.vec.clear();
}
#[inline]
pub fn into_vec(self) -> Vec<T, S, I> {
self.vec
}
#[inline]
pub fn as_slice(&self) -> &[T] {
self.vec.as_slice()
}
#[inline]
pub fn iter(&self) -> Iter<'_, T> {
self.vec.iter()
}
#[inline]
pub fn difference<'a, S2: Storage<ArrayLayout<T>>, I2: Capacity>(&'a self, other: &'a ListSet<T, S2, I2>) -> Difference<'a, T> {
Difference { this: self.as_slice(), other: other.as_slice(), front: 0 }
}
#[inline]
pub fn symmetric_difference<'a, S2: Storage<ArrayLayout<T>>, I2: Capacity>(&'a self, other: &'a ListSet<T, S2, I2>) -> SymmetricDifference<'a, T> {
SymmetricDifference { this: self.as_slice(), other: other.as_slice(), front: 0 }
}
#[inline]
pub fn intersection<'a, S2: Storage<ArrayLayout<T>>, I2: Capacity>(&'a self, other: &'a ListSet<T, S2, I2>) -> Intersection<'a, T> {
Intersection { this: self.as_slice(), other: other.as_slice(), front: 0 }
}
#[inline]
pub fn union<'a, S2: Storage<ArrayLayout<T>>, I2: Capacity>(&'a self, other: &'a ListSet<T, S2, I2>) -> Union<'a, T> {
Union { this: self.as_slice(), other: other.as_slice(), front: 0 }
}
#[inline]
pub fn drain(&mut self) -> Drain<'_, T, S, I> {
self.vec.drain(..)
}
#[inline]
pub fn contains<Q: ?Sized + Eq>(&self, value: &Q) -> bool where T: Borrow<Q> {
self.vec.iter().any(|item| item.borrow() == value)
}
#[inline]
pub fn get<Q: ?Sized + Eq>(&self, value: &Q) -> Option<&T> where T: Borrow<Q> {
self.vec.iter().find(|item| (*item).borrow() == value)
}
pub fn is_disjoint<S2: Storage<ArrayLayout<T>>, I2: Capacity>(&self, other: &ListSet<T, S2, I2>) -> bool {
for item in other.iter() {
if self.contains(item) { return false; }
}
true
}
pub fn is_subset_of<S2: Storage<ArrayLayout<T>>, I2: Capacity>(&self, other: &ListSet<T, S2, I2>) -> bool {
for item in self.iter() {
if !other.contains(item) { return false; }
}
true
}
#[inline]
pub fn is_superset_of<S2: Storage<ArrayLayout<T>>, I2: Capacity>(&self, other: &ListSet<T, S2, I2>) -> bool {
other.is_subset_of(self)
}
#[inline]
pub fn insert(&mut self, value: T) -> bool {
self.try_insert(value).ok().expect("insufficient capacity")
}
pub fn try_insert(&mut self, value: T) -> Result<bool, T> {
if self.contains(&value) { return Ok(false); }
self.vec.try_push(value).map(|_| true)
}
#[inline]
pub fn insert_unique_unchecked(&mut self, value: T) -> &T {
self.try_insert_unique_unchecked(value).ok().expect("insufficient capacity")
}
pub fn try_insert_unique_unchecked(&mut self, value: T) -> Result<&T, T> {
if self.vec.is_full() {
Err(value)
} else {
self.vec.push(value);
self.vec.last().ok_or_else(|| unreachable!())
}
}
pub fn replace(&mut self, value: T) -> Option<T> {
self.try_replace(value).ok().expect("insufficient capacity")
}
pub fn try_replace(&mut self, value: T) -> Result<Option<T>, T> {
if let Some((idx, _)) = self.vec.iter().enumerate().find(|(_, item)| *item == &value) {
Ok(Some(self.vec.replace(I::from_usize(idx), value)))
} else if self.is_full() {
Err(value)
} else {
self.vec.push(value);
Ok(None)
}
}
pub fn remove<Q: ?Sized + Eq>(&mut self, value: &Q) -> bool where T: Borrow<Q> {
if let Some((idx, _)) = self.vec.iter().enumerate().find(|(_, item)| (*item).borrow() == value) {
self.vec.swap_remove(I::from_usize(idx));
true
} else {
false
}
}
pub fn take<Q: ?Sized + Eq>(&mut self, value: &Q) -> Option<T> where T: Borrow<Q> {
if let Some((idx, _)) = self.vec.iter().enumerate().find(|(_, item)| (*item).borrow() == value) {
Some(self.vec.swap_remove(I::from_usize(idx)))
} else {
None
}
}
#[inline]
pub fn retain<F: FnMut(&T) -> bool>(&mut self, pred: F) {
self.vec.retain(pred);
}
}
impl<T: Eq, S1, S2, I1, I2> core::ops::BitAndAssign<&'_ ListSet<T, S2, I2>> for ListSet<T, S1, I1>
where
S1: Storage<ArrayLayout<T>>,
S2: Storage<ArrayLayout<T>>,
I1: Capacity,
I2: Capacity,
{
fn bitand_assign(&mut self, rhs: &ListSet<T, S2, I2>) {
let mut i = 0;
while i < self.len() {
if rhs.contains(&self.vec.as_slice()[i]) {
i += 1;
} else {
self.vec.swap_remove(I1::from_usize(i));
}
}
}
}
impl<T, S1, S2, I1, I2> core::ops::BitOrAssign<&'_ ListSet<T, S2, I2>> for ListSet<T, S1, I1>
where
T: Clone + Eq,
S1: Storage<ArrayLayout<T>>,
S2: Storage<ArrayLayout<T>>,
I1: Capacity,
I2: Capacity,
{
fn bitor_assign(&mut self, rhs: &ListSet<T, S2, I2>) {
for x in rhs.iter() {
if !self.contains(x) {
self.insert_unique_unchecked(x.clone());
}
}
}
}
impl<T: Debug, S: Storage<ArrayLayout<T>>, I: Capacity> Debug for ListSet<T, S, I> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_set().entries(self.vec.as_slice()).finish()
}
}
impl<T: Eq, S: Storage<ArrayLayout<T>>, I: Capacity> Extend<T> for ListSet<T, S, I> {
fn extend<It: IntoIterator<Item = T>>(&mut self, iter: It) {
iter.into_iter().for_each(|x| { self.insert(x); });
}
}
impl<'a, T: Clone + Eq, S: Storage<ArrayLayout<T>>, I: Capacity> Extend<&'a T> for ListSet<T, S, I> {
fn extend<It: IntoIterator<Item = &'a T>>(&mut self, iter: It) {
iter.into_iter().for_each(|x| { self.insert(x.clone()); });
}
}
impl<T, S: Storage<ArrayLayout<T>>, I: Capacity> IntoIterator for ListSet<T, S, I> {
type IntoIter = crate::collections::vec::IntoIterator<T, S, I>;
type Item = T;
fn into_iter(self) -> Self::IntoIter {
self.vec.into_iter()
}
}
impl<'a, T: Eq, S: Storage<ArrayLayout<T>>, I: Capacity> IntoIterator for &'a ListSet<T, S, I> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_slice().iter()
}
}
impl<T, S1, S2, I1, I2> PartialEq<ListSet<T, S2, I2>> for ListSet<T, S1, I1>
where
S1: Storage<ArrayLayout<T>>,
S2: Storage<ArrayLayout<T>>,
I1: Capacity,
I2: Capacity,
T: Eq,
{
fn eq(&self, other: &ListSet<T, S2, I2>) -> bool {
self.is_subset_of(other) && self.is_superset_of(other)
}
}
impl<T: Eq, S: Storage<ArrayLayout<T>>, I: Capacity> Eq for ListSet<T, S, I> {}
#[cfg(feature = "alloc")]
#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))]
impl<T, I: Capacity> crate::collections::AllocListSet<T, I> {
pub fn with_capacity(capacity: usize) -> Self {
let storage = crate::storage::AllocStorage::with_capacity(capacity);
Self::from(storage)
}
}
impl<T, I: Capacity, const N: usize> ListSet<T, InlineStorage<T, N>, I> {
pub fn new() -> Self {
ListSet { vec: crate::collections::InlineVec::<T, N, I>::new() }
}
}
impl<T, I: Capacity, const N: usize> Default for ListSet<T, InlineStorage<T, N>, I> {
fn default() -> Self {
Self::new()
}
}
pub struct Difference<'a, T> {
this: &'a [T],
other: &'a [T],
front: usize,
}
impl<'a, T: Eq> Iterator for Difference<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
'outer: while self.front < self.this.len() {
let my_item = &self.this[self.front];
self.front += 1;
for their_item in self.other {
if my_item == their_item {
continue 'outer;
}
}
return Some(my_item);
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
let max_len = self.this.len() - self.front;
(0, Some(max_len))
}
}
impl<T: Eq> FusedIterator for Difference<'_, T> {}
pub struct SymmetricDifference<'a, T> {
this: &'a [T],
other: &'a [T],
front: usize,
}
impl<'a, T: Eq> Iterator for SymmetricDifference<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
'outer1: while self.front < self.this.len() {
let my_item = &self.this[self.front];
self.front += 1;
for their_item in self.other {
if my_item == their_item {
continue 'outer1;
}
}
return Some(my_item);
}
'outer2: while (self.front - self.this.len()) < self.other.len() {
let their_item = &self.other[self.front - self.this.len()];
self.front += 1;
for my_item in self.this {
if my_item == their_item {
continue 'outer2;
}
}
return Some(their_item);
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
let max_len = if self.front < self.this.len() {
(self.this.len() - self.front) + self.other.len()
} else {
self.other.len() - (self.front - self.this.len())
};
(0, Some(max_len))
}
}
impl<T: Eq> FusedIterator for SymmetricDifference<'_, T> {}
pub struct Intersection<'a, T> {
this: &'a [T],
other: &'a [T],
front: usize,
}
impl<'a, T: Eq> Iterator for Intersection<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
while self.front < self.this.len() {
let my_item = &self.this[self.front];
self.front += 1;
for their_item in self.other {
if my_item == their_item {
return Some(my_item);
}
}
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
let max_len = self.this.len() - self.front;
(0, Some(max_len))
}
}
impl<T: Eq> FusedIterator for Intersection<'_, T> {}
pub struct Union<'a, T> {
this: &'a [T],
other: &'a [T],
front: usize,
}
impl<'a, T: Eq> Iterator for Union<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.front < self.this.len() {
let result = &self.this[self.front];
self.front += 1;
return Some(result);
}
'outer: while (self.front - self.this.len()) < self.other.len() {
let their_item = &self.other[self.front - self.this.len()];
self.front += 1;
for my_item in self.this {
if my_item == their_item {
continue 'outer;
}
}
return Some(their_item);
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
let min_len = self.this.len().saturating_sub(self.front);
let max_len = if self.front < self.this.len() {
self.other.len() + min_len
} else {
self.other.len() - self.front
};
(min_len, Some(max_len))
}
}
impl<T: Eq> FusedIterator for Union<'_, T> {}