use std::fmt;
use index_vec::Idx;
use crate::{
bitset::BitSet, pointer::PointerFamily, Captures, FromIndexicalIterator, IndexedDomain,
IndexedValue, ToIndex,
};
pub struct IndexSet<'a, T: IndexedValue + 'a, S: BitSet, P: PointerFamily<'a>> {
set: S,
domain: P::Pointer<IndexedDomain<T>>,
}
impl<'a, T, S, P> IndexSet<'a, T, S, P>
where
T: IndexedValue + 'a,
S: BitSet,
P: PointerFamily<'a>,
{
pub fn new(domain: &P::Pointer<IndexedDomain<T>>) -> Self {
IndexSet {
set: S::empty(domain.len()),
domain: domain.clone(),
}
}
#[inline]
pub fn indices(&self) -> impl Iterator<Item = T::Index> + '_ {
self.set.iter().map(T::Index::from_usize)
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &T> + Captures<'a> + '_ {
self.indices().map(move |idx| self.domain.value(idx))
}
#[inline]
pub fn iter_enumerated(&self) -> impl Iterator<Item = (T::Index, &T)> + Captures<'a> + '_ {
self.indices().map(move |idx| (idx, self.domain.value(idx)))
}
#[inline]
pub fn contains<M>(&self, index: impl ToIndex<T, M>) -> bool {
let elem = index.to_index(&self.domain);
self.set.contains(elem.index())
}
#[inline]
pub fn len(&self) -> usize {
self.set.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn is_superset(&self, other: &IndexSet<'a, T, S, P>) -> bool {
self.set.superset(&other.set)
}
#[inline]
pub fn insert<M>(&mut self, elt: impl ToIndex<T, M>) -> bool {
let elt = elt.to_index(&self.domain);
self.set.insert(elt.index())
}
#[inline]
pub fn union(&mut self, other: &IndexSet<'a, T, S, P>) {
self.set.union(&other.set);
}
#[inline]
pub fn union_changed(&mut self, other: &IndexSet<'a, T, S, P>) -> bool {
self.set.union_changed(&other.set)
}
#[inline]
pub fn subtract(&mut self, other: &IndexSet<'a, T, S, P>) {
self.set.subtract(&other.set)
}
#[inline]
pub fn subtract_changed(&mut self, other: &IndexSet<'a, T, S, P>) -> bool {
self.set.subtract_changed(&other.set)
}
#[inline]
pub fn intersect(&mut self, other: &IndexSet<'a, T, S, P>) {
self.set.intersect(&other.set)
}
#[inline]
pub fn intersect_changed(&mut self, other: &IndexSet<'a, T, S, P>) -> bool {
self.set.intersect_changed(&other.set)
}
#[inline]
pub fn insert_all(&mut self) {
self.set.insert_all()
}
#[inline]
pub fn clear(&mut self) {
self.set.clear();
}
#[inline]
pub fn inner(&self) -> &S {
&self.set
}
}
impl<'a, T, S, P> fmt::Debug for IndexSet<'a, T, S, P>
where
T: IndexedValue + fmt::Debug + 'a,
S: BitSet,
P: PointerFamily<'a>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
}
impl<'a, T, S, P> PartialEq for IndexSet<'a, T, S, P>
where
T: IndexedValue + 'a,
S: BitSet,
P: PointerFamily<'a>,
{
fn eq(&self, other: &Self) -> bool {
self.set == other.set
}
}
impl<'a, T, S, P> Eq for IndexSet<'a, T, S, P>
where
T: IndexedValue + 'a,
S: BitSet,
P: PointerFamily<'a>,
{
}
impl<'a, T, S, P> Clone for IndexSet<'a, T, S, P>
where
T: IndexedValue + 'a,
S: BitSet,
P: PointerFamily<'a>,
{
fn clone(&self) -> Self {
IndexSet {
set: self.set.clone(),
domain: self.domain.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.set.copy_from(&source.set);
self.domain = source.domain.clone();
}
}
impl<'a, T, U, S, M, P> FromIndexicalIterator<'a, T, P, M, U> for IndexSet<'a, T, S, P>
where
T: IndexedValue + 'a,
S: BitSet,
P: PointerFamily<'a>,
U: ToIndex<T, M>,
{
fn from_indexical_iter(
iter: impl Iterator<Item = U>,
domain: &P::Pointer<IndexedDomain<T>>,
) -> Self {
let mut set = IndexSet::new(domain);
for s in iter {
set.insert(s);
}
set
}
}
#[cfg(test)]
mod test {
use crate::{test_utils::TestIndexSet, IndexedDomain, IndexicalIteratorExt};
use std::rc::Rc;
fn mk(s: &str) -> String {
s.to_string()
}
#[test]
fn test_indexset() {
let d = Rc::new(IndexedDomain::from_iter([mk("a"), mk("b"), mk("c")]));
let mut s = TestIndexSet::new(&d);
s.insert(mk("a"));
let b = d.index(&mk("b"));
s.insert(b);
assert!(s.contains(mk("a")));
assert!(s.contains(mk("b")));
assert_eq!(s.len(), 2);
assert_eq!(
[mk("a"), mk("b")]
.into_iter()
.collect_indexical::<TestIndexSet<_>>(&d),
s
);
assert_eq!(format!("{s:?}"), r#"{"a", "b"}"#)
}
#[cfg(feature = "bitvec")]
#[test]
fn test_indexset_reffamily() {
let d = &IndexedDomain::from_iter([mk("a"), mk("b"), mk("c")]);
let mut s = crate::bitset::bitvec::RefIndexSet::new(&d);
s.insert(mk("a"));
assert!(s.contains(mk("a")));
let s2 = s.clone();
assert!(std::ptr::eq(s.domain, s2.domain));
}
}