superset_map

B-tree-backed map whose keys are distinct supersets.
git clone https://git.philomathiclife.com/repos/superset_map
Log | Files | Refs | README

commit 40fe779f4995e9bf4ae76ab1e0ad28f95e478faf
Author: Zack Newman <zack@philomathiclife.com>
Date:   Sat, 26 Aug 2023 16:41:18 -0600

init

Diffstat:
A.gitignore | 2++
ACargo.toml | 31+++++++++++++++++++++++++++++++
AREADME.md | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arust-toolchain.toml | 2++
Asrc/lib.rs | 163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/superset_map.rs | 994+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/superset_set.rs | 974+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 2306 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target/** diff --git a/Cargo.toml b/Cargo.toml @@ -0,0 +1,31 @@ +[package] +authors = ["Zack Newman <zack@philomathiclife.com>"] +categories = ["data-structures", "mathematics", "no-std"] +description = "Map that stores distinct supersets based on the total order defined." +documentation = "https://docs.rs/superset_map/latest/superset_map/" +edition = "2021" +keywords = ["btree", "map", "ordered", "set", "subset"] +license = "MIT OR Apache-2.0" +name = "superset_map" +readme = "README.md" +repository = "https://git.philomathiclife.com/repos/superset_map/" +rust-version = "1.69" +version = "0.1.0" + +[lib] +name = "superset_map" +path = "src/lib.rs" + +[dependencies] +zfc = { version = "0.1.0", default-features = false } + +[dev-dependencies] +num-bigint = { version = "0.4.4", default-features = false } + +[badges] +maintenance = { status = "actively-developed" } + +[profile.release] +lto = true +panic = 'abort' +strip = true diff --git a/README.md b/README.md @@ -0,0 +1,140 @@ +# `superset_map` + +`superset_map` is a library for [`Set`](https://docs.rs/zfc/latest/zfc/trait.Set.html)s that have an order defined on them. +It's main data structure is [`SupersetMap`](https://docs.rs/superset_map/latest/superset_map/superset_map/struct.SupersetMap.html) +which is a specialized version of [`BTreeMap`](https://doc.rust-lang.org/alloc/collections/btree_map/struct.BTreeMap.html) +where only supersets are stored. This can be useful when the keys don't fit well or at all with the concept of +[`RangeBounds`](https://doc.rust-lang.org/stable/core/ops/trait.RangeBounds.html). + +## Example + +```rust +use core::borrow::Borrow; +use core::cmp::Ordering; +use num_bigint::BigUint; +use superset_map::{SetOrd, SupersetSet}; +use zfc::{Cardinality, Set}; +#[derive(Clone, Copy, Eq, PartialEq)] +struct ShortAscii<'a> { + val: &'a [u8], +} +impl<'a> ShortAscii<'a> { + fn new(val: &'a [u8]) -> Option<ShortAscii<'a>> { + (val.len() <= 255 && val.is_ascii()).then_some(Self { val }) + } + fn len(self) -> u8 { + self.val.len().try_into().expect("The ShortAscii instance was not constructed properly and contains more than 255 bytes.") + } +} +#[derive(Clone, Copy, Eq, PartialEq)] +enum WildcardAscii<'a> { + Plain(ShortAscii<'a>), + // Represents a ShortAscii<'a> with an implicit wildcard at the end + // meaning it's all ShortAscii<'a>s that begin with the contained ShortAscii<'a>.val. + Wildcard(ShortAscii<'a>), +} +impl<'a> WildcardAscii<'a> { + const fn val(self) -> ShortAscii<'a> { + match self { + WildcardAscii::Plain(s) | WildcardAscii::Wildcard(s) => s, + } + } + const fn is_plain(self) -> bool { + match self { + WildcardAscii::Plain(_) => true, + WildcardAscii::Wildcard(_) => false, + } + } + const fn is_wildcard(self) -> bool { + !self.is_plain() + } +} +impl<'a> PartialOrd<Self> for WildcardAscii<'a> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} +impl<'a> Ord for WildcardAscii<'a> { + fn cmp(&self, other: &Self) -> Ordering { + let len = u8::min(self.val().len(), other.val().len()) as usize; + match self.val().val[..len].cmp(&other.val().val[..len]) { + Ordering::Less => Ordering::Less, + Ordering::Equal => { + if self.is_wildcard() { + if other.is_wildcard() { + self.val().len().cmp(&other.val().len()).reverse() + } else { + Ordering::Greater + } + } else if other.is_wildcard() { + Ordering::Less + } else { + self.val().len().cmp(&other.val().len()) + } + } + Ordering::Greater => Ordering::Greater, + } + } +} +impl<'a> Set for WildcardAscii<'a> { + type Elem = ShortAscii<'a>; + fn cardinality(&self) -> Cardinality { + Cardinality::Finite(match *self { + WildcardAscii::Plain(_) => BigUint::new(vec![1]), + // Geometric series. + WildcardAscii::Wildcard(v) => { + (BigUint::new(vec![128]).pow((u8::MAX - v.len()) as u32 + 1) + - BigUint::new(vec![1])) + / BigUint::new(vec![127]) + } + }) + } + fn contains<Q>(&self, elem: &Q) -> bool + where + Q: Borrow<Self::Elem> + Eq + ?Sized, + { + match *self { + WildcardAscii::Plain(v) => v == *elem.borrow(), + WildcardAscii::Wildcard(v) => { + v.len() <= elem.borrow().len() && *v.val == elem.borrow().val[..v.len() as usize] + } + } + } + fn is_proper_subset(&self, val: &Self) -> bool { + val.is_wildcard() + && match val.val().len().cmp(&self.val().len()) { + Ordering::Less => val.val().val == &self.val().val[..val.val().len() as usize], + Ordering::Equal => self.is_plain() && self.val() == val.val(), + Ordering::Greater => false, + } + } + fn is_subset(&self, val: &Self) -> bool { + self == val || self.is_proper_subset(val) + } +} +impl<'a> SetOrd for WildcardAscii<'a> {} +fn main() { + let mut set = SupersetSet::new(); + set.insert(WildcardAscii::Plain(ShortAscii::new(b"foo").unwrap())); + set.insert(WildcardAscii::Plain(ShortAscii::new(b"bar").unwrap())); + set.insert(WildcardAscii::Wildcard(ShortAscii::new(b"b").unwrap())); + set.insert(WildcardAscii::Wildcard(ShortAscii::new(b"bar").unwrap())); + let mut iter = set.into_iter(); + assert!(iter.next().map_or(false, |s| s + == WildcardAscii::Wildcard(ShortAscii::new(b"b").unwrap()))); + assert!(iter.next().map_or(false, |s| s + == WildcardAscii::Plain(ShortAscii::new(b"foo").unwrap()))); + assert!(iter.next().is_none()); +} +``` + +### Status + +This package will be actively maintained until it is deemed “feature complete”. + +The crates are only tested on the `x86_64-unknown-linux-gnu` and `x86_64-unknown-openbsd` targets, but +they should work on any [Tier 1 with Host Tools](https://doc.rust-lang.org/beta/rustc/platform-support.html) +target. + +Version `1.69.0` or newer of nightly `rustc` is required. Once `BTreeMap` +[cursors are stablilized](https://github.com/rust-lang/rust/issues/107540), stable `rustc` will work. diff --git a/rust-toolchain.toml b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/src/lib.rs b/src/lib.rs @@ -0,0 +1,163 @@ +//! # `superset_map` +//! +//! `superset_map` is a library for [`Set`]s that have an order defined on them. +//! It's main data structure is [`SupersetMap`] which is a specialized version of +//! [`BTreeMap`](https://doc.rust-lang.org/alloc/collections/btree_map/struct.BTreeMap.html) +//! where only supersets are stored. This can be useful when the keys don't fit well or at all with the concept of +//! [`RangeBounds`](https://doc.rust-lang.org/stable/core/ops/trait.RangeBounds.html). +//! +//! ## Example +//! +//! ```rust +//! use core::borrow::Borrow; +//! use core::cmp::Ordering; +//! use num_bigint::BigUint; +//! use superset_map::{SetOrd, SupersetSet}; +//! use zfc::{Cardinality, Set}; +//! #[derive(Clone, Copy, Eq, PartialEq)] +//! struct ShortAscii<'a> { +//! val: &'a [u8], +//! } +//! impl<'a> ShortAscii<'a> { +//! fn new(val: &'a [u8]) -> Option<ShortAscii<'a>> { +//! (val.len() <= 255 && val.is_ascii()).then_some(Self { val }) +//! } +//! fn len(self) -> u8 { +//! self.val.len().try_into().expect("The ShortAscii instance was not constructed properly and contains more than 255 bytes.") +//! } +//! } +//! #[derive(Clone, Copy, Eq, PartialEq)] +//! enum WildcardAscii<'a> { +//! Plain(ShortAscii<'a>), +//! // Represents a ShortAscii<'a> with an implicit wildcard at the end +//! // meaning it's all ShortAscii<'a>s that begin with the contained ShortAscii<'a>.val. +//! Wildcard(ShortAscii<'a>), +//! } +//! impl<'a> WildcardAscii<'a> { +//! const fn val(self) -> ShortAscii<'a> { +//! match self { +//! WildcardAscii::Plain(s) | WildcardAscii::Wildcard(s) => s, +//! } +//! } +//! const fn is_plain(self) -> bool { +//! match self { +//! WildcardAscii::Plain(_) => true, +//! WildcardAscii::Wildcard(_) => false, +//! } +//! } +//! const fn is_wildcard(self) -> bool { +//! !self.is_plain() +//! } +//! } +//! impl<'a> PartialOrd<Self> for WildcardAscii<'a> { +//! fn partial_cmp(&self, other: &Self) -> Option<Ordering> { +//! Some(self.cmp(other)) +//! } +//! } +//! impl<'a> Ord for WildcardAscii<'a> { +//! fn cmp(&self, other: &Self) -> Ordering { +//! let len = u8::min(self.val().len(), other.val().len()) as usize; +//! match self.val().val[..len].cmp(&other.val().val[..len]) { +//! Ordering::Less => Ordering::Less, +//! Ordering::Equal => { +//! if self.is_wildcard() { +//! if other.is_wildcard() { +//! self.val().len().cmp(&other.val().len()).reverse() +//! } else { +//! Ordering::Greater +//! } +//! } else if other.is_wildcard() { +//! Ordering::Less +//! } else { +//! self.val().len().cmp(&other.val().len()) +//! } +//! } +//! Ordering::Greater => Ordering::Greater, +//! } +//! } +//! } +//! impl<'a> Set for WildcardAscii<'a> { +//! type Elem = ShortAscii<'a>; +//! fn cardinality(&self) -> Cardinality { +//! Cardinality::Finite(match *self { +//! WildcardAscii::Plain(_) => BigUint::new(vec![1]), +//! // Geometric series. +//! WildcardAscii::Wildcard(v) => { +//! (BigUint::new(vec![128]).pow((u8::MAX - v.len()) as u32 + 1) +//! - BigUint::new(vec![1])) +//! / BigUint::new(vec![127]) +//! } +//! }) +//! } +//! fn contains<Q>(&self, elem: &Q) -> bool +//! where +//! Q: Borrow<Self::Elem> + Eq + ?Sized, +//! { +//! match *self { +//! WildcardAscii::Plain(v) => v == *elem.borrow(), +//! WildcardAscii::Wildcard(v) => { +//! v.len() <= elem.borrow().len() && *v.val == elem.borrow().val[..v.len() as usize] +//! } +//! } +//! } +//! fn is_proper_subset(&self, val: &Self) -> bool { +//! val.is_wildcard() +//! && match val.val().len().cmp(&self.val().len()) { +//! Ordering::Less => val.val().val == &self.val().val[..val.val().len() as usize], +//! Ordering::Equal => self.is_plain() && self.val() == val.val(), +//! Ordering::Greater => false, +//! } +//! } +//! fn is_subset(&self, val: &Self) -> bool { +//! self == val || self.is_proper_subset(val) +//! } +//! } +//! impl<'a> SetOrd for WildcardAscii<'a> {} +//! fn main() { +//! let mut set = SupersetSet::new(); +//! set.insert(WildcardAscii::Plain(ShortAscii::new(b"foo").unwrap())); +//! set.insert(WildcardAscii::Plain(ShortAscii::new(b"bar").unwrap())); +//! set.insert(WildcardAscii::Wildcard(ShortAscii::new(b"b").unwrap())); +//! set.insert(WildcardAscii::Wildcard(ShortAscii::new(b"bar").unwrap())); +//! let mut iter = set.into_iter(); +//! assert!(iter.next().map_or(false, |s| s +//! == WildcardAscii::Wildcard(ShortAscii::new(b"b").unwrap()))); +//! assert!(iter.next().map_or(false, |s| s +//! == WildcardAscii::Plain(ShortAscii::new(b"foo").unwrap()))); +//! assert!(iter.next().is_none()); +//! } +//! ``` +#![no_std] +#![feature(btree_cursors)] +#![deny( + unsafe_code, + unused, + warnings, + clippy::all, + clippy::cargo, + clippy::complexity, + clippy::correctness, + clippy::nursery, + clippy::pedantic, + clippy::perf, + clippy::restriction, + clippy::style, + clippy::suspicious +)] +#![allow(clippy::blanket_clippy_restriction_lints, clippy::pub_use)] +use zfc::Set; +/// A map of keys and values where the keys implement [`SetOrd`]. The map is backed by a B-tree. +pub mod superset_map; +/// A set of values where the values implement [`SetOrd`]. The set is backed by a B-tree. +pub mod superset_set; +pub use superset_map::SupersetMap; +pub use superset_set::SupersetSet; +/// Must conform to the following properties ∀`a`, `b`, `c`: `Self`: +/// * `a.is_subset(b)` ⇒ `a <= b`. +/// * `a.is_subset(b) && !(a.is_subset(c) || c.is_subset(b))` ⇒ `c` `<` `a` `<=` `b` ∨ `a` `<=` `b` `<` `c`. +/// +/// In American English prose, the above simply states that one only need to check for the "next" element of `a` +/// in an ordered sequence of `Self`s to determine if there exists any superset of `a` in the entire sequence beside +/// `a` itself. Put in a different way, the "distance" between a set and a proper supserset is "less" than the "distance" +/// between the same set and a non-superset that is greater. +pub trait SetOrd: Ord + Set {} diff --git a/src/superset_map.rs b/src/superset_map.rs @@ -0,0 +1,994 @@ +#![deny( + unsafe_code, + unused, + warnings, + clippy::all, + clippy::cargo, + clippy::complexity, + clippy::correctness, + clippy::nursery, + clippy::pedantic, + clippy::perf, + clippy::restriction, + clippy::style, + clippy::suspicious +)] +#![allow( + clippy::blanket_clippy_restriction_lints, + clippy::implicit_return, + clippy::min_ident_chars, + clippy::missing_trait_methods, + clippy::semicolon_outside_block, + clippy::single_char_lifetime_names +)] +extern crate alloc; +use crate::SetOrd; +use alloc::collections::btree_map::{ + BTreeMap, CursorMut, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, OccupiedEntry, Range, + RangeMut, Values, ValuesMut, +}; +use core::borrow::Borrow; +use core::ops::{Bound, Index, RangeBounds}; +/// A minimal collection of `(K, V)`s. +/// Internally it is based on a [`BTreeMap`]. +/// When a `(K, V)` is [`SupersetMap::insert`]ed, +/// it won't actually be inserted unless +/// there isn't a `K` already in +/// the map that is a superset of it. +/// In such event, all `K`s that +/// are subsets of the to-be-inserted `K` +/// are removed before inserting the `K`. +/// Note this can have quite good performance due to the +/// fact that a single search is necessary to detect +/// if insertion should occur; furthermore since all +/// subsets occur immediately before where the key +/// will be inserted, a simple linear scan is sufficient +/// to remove subsets avoiding the need to search +/// the entire map. +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct SupersetMap<K, V> { + /// Collection of `(K, V)`s. + map: BTreeMap<K, V>, +} +impl<K, V> Default for SupersetMap<K, V> { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl<K, V> SupersetMap<K, V> { + /// Read [`BTreeMap::clear`]. + #[inline] + pub fn clear(&mut self) { + self.map.clear(); + } + /// Read [`BTreeMap::into_keys`]. + #[inline] + pub fn into_keys(self) -> IntoKeys<K, V> { + self.map.into_keys() + } + /// Read [`BTreeMap::into_values`]. + #[inline] + pub fn into_values(self) -> IntoValues<K, V> { + self.map.into_values() + } + /// Read [`BTreeMap::is_empty`]. + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + /// Read [`BTreeMap::iter`]. + #[inline] + pub fn iter(&self) -> Iter<'_, K, V> { + self.map.iter() + } + /// Read [`BTreeMap::iter_mut`]. + #[inline] + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { + self.map.iter_mut() + } + /// Read [`BTreeMap::keys`]. + #[inline] + pub fn keys(&self) -> Keys<'_, K, V> { + self.map.keys() + } + /// Read [`BTreeMap::len`]. + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.map.len() + } + /// Makes a new, empty `SupersetMap`. + /// Does not allocate anything on its own. + #[inline] + #[must_use] + pub const fn new() -> Self { + Self { + map: BTreeMap::new(), + } + } + /// Read [`BTreeMap::values`]. + #[inline] + pub fn values(&self) -> Values<'_, K, V> { + self.map.values() + } + /// Read [`BTreeMap::values_mut`]. + #[inline] + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { + self.map.values_mut() + } +} +impl<K, V> SupersetMap<K, V> +where + K: Ord, +{ + /// Read [`BTreeMap::contains_key`]. + #[inline] + pub fn contains_key<Q>(&self, key: &Q) -> bool + where + K: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.contains_key(key) + } + /// Read [`BTreeMap::first_entry`]. + #[inline] + pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> { + self.map.first_entry() + } + /// Read [`BTreeMap::first_key_value`]. + #[inline] + #[must_use] + pub fn first_key_value(&self) -> Option<(&K, &V)> { + self.map.first_key_value() + } + /// Read [`BTreeMap::get`]. + #[inline] + pub fn get<Q>(&self, key: &Q) -> Option<&V> + where + K: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.get(key) + } + /// Read [`BTreeMap::get_key_value`]. + #[inline] + pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)> + where + K: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.get_key_value(key) + } + /// Read [`BTreeMap::get_mut`]. + #[inline] + pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V> + where + K: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.get_mut(key) + } + /// Read [`BTreeMap::last_entry`]. + #[inline] + pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> { + self.map.last_entry() + } + /// Read [`BTreeMap::last_key_value`]. + #[inline] + #[must_use] + pub fn last_key_value(&self) -> Option<(&K, &V)> { + self.map.last_key_value() + } + /// Read [`BTreeMap::pop_first`]. + #[inline] + pub fn pop_first(&mut self) -> Option<(K, V)> { + self.map.pop_first() + } + /// Read [`BTreeMap::pop_last`]. + #[inline] + pub fn pop_last(&mut self) -> Option<(K, V)> { + self.map.pop_last() + } + /// Read [`BTreeMap::range`]. + #[inline] + pub fn range<T, R>(&self, range: R) -> Range<'_, K, V> + where + K: Borrow<T>, + T: Ord + ?Sized, + R: RangeBounds<T>, + { + self.map.range(range) + } + /// Read [`BTreeMap::range_mut`]. + #[inline] + pub fn range_mut<T, R>(&mut self, range: R) -> RangeMut<'_, K, V> + where + K: Borrow<T>, + T: Ord + ?Sized, + R: RangeBounds<T>, + { + self.map.range_mut(range) + } + /// Read [`BTreeMap::remove`]. + #[inline] + pub fn remove<Q>(&mut self, key: &Q) -> Option<V> + where + K: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.remove(key) + } + /// Read [`BTreeMap::remove_entry`]. + #[inline] + pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)> + where + K: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.remove_entry(key) + } + /// Read [`BTreeMap::split_off`]. + #[inline] + #[must_use] + pub fn split_off<Q>(&mut self, key: &Q) -> Self + where + K: Borrow<Q>, + Q: Ord + ?Sized, + { + Self { + map: self.map.split_off(key), + } + } +} +impl<K, V> SupersetMap<K, V> +where + K: SetOrd, +{ + /// Moves all elements from `other` into `self`, consuming `other`. + /// If a key from `other` is a proper superset of a key in `self`, the respective key and value from `self` will be removed before inserting + /// the key and value from `other`. + /// If a key from `other` is a subset of a key in `self`, it won't be inserted. + #[inline] + pub fn append(&mut self, other: Self) { + if self.is_empty() { + *self = other; + } else { + other.into_iter().fold((), |(), (key, val)| { + self.insert(key, val); + }); + } + } + /// Returns `true` if the map contains a value for a proper subset of the specified key. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn contains_proper_subset<Q>(&self, key: &Q) -> bool + where + K: Borrow<Q>, + Q: SetOrd, + { + self.get_greatest_proper_subset(key).is_some() + } + /// Returns `true` if the map contains a value for a proper superset of the specified key. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn contains_proper_superset<Q>(&self, key: &Q) -> bool + where + K: Borrow<Q>, + Q: SetOrd, + { + self.get_least_proper_superset(key).is_some() + } + /// Returns `true` if the map contains a value for a subset of the specified key. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn contains_subset<Q>(&self, key: &Q) -> bool + where + K: Borrow<Q>, + Q: SetOrd, + { + self.get_greatest_subset(key).is_some() + } + /// Returns `true` if the map contains a value for a superset of the specified key. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn contains_superset<Q>(&self, key: &Q) -> bool + where + K: Borrow<Q>, + Q: SetOrd, + { + self.get_least_superset(key).is_some() + } + /// Returns a reference to the value corresponding to the greatest proper subset of key. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn get_greatest_proper_subset<Q>(&self, key: &Q) -> Option<&V> + where + K: Borrow<Q>, + Q: SetOrd, + { + self.get_greatest_proper_subset_key_value(key) + .map(|(_, val)| val) + } + /// Returns a reference to the key-value pair corresponding to the greatest proper subset of the supplied key. + /// The supplied key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type + #[inline] + pub fn get_greatest_proper_subset_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)> + where + K: Borrow<Q>, + Q: SetOrd, + { + self.map + .upper_bound(Bound::Excluded(key)) + .key_value() + .and_then(|pair| pair.0.borrow().is_proper_subset(key).then_some(pair)) + } + /// Returns a reference to the value corresponding to the greatest subset of key. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn get_greatest_subset<Q>(&self, key: &Q) -> Option<&V> + where + K: Borrow<Q>, + Q: SetOrd, + { + self.get_greatest_subset_key_value(key).map(|(_, val)| val) + } + /// Returns a reference to the key-value pair corresponding to the greatest subset of the supplied key. + /// The supplied key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type + #[inline] + pub fn get_greatest_subset_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)> + where + K: Borrow<Q>, + Q: SetOrd, + { + self.map + .upper_bound(Bound::Included(key)) + .key_value() + .and_then(|pair| pair.0.borrow().is_subset(key).then_some(pair)) + } + /// Returns a reference to the value corresponding to the least proper superset of key. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn get_least_proper_superset<Q>(&self, key: &Q) -> Option<&V> + where + K: Borrow<Q>, + Q: SetOrd, + { + self.get_least_proper_superset_key_value(key) + .map(|(_, val)| val) + } + /// Returns a reference to the key-value pair corresponding to the least proper superset of the supplied key. + /// The supplied key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type + #[inline] + pub fn get_least_proper_superset_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)> + where + K: Borrow<Q>, + Q: SetOrd, + { + self.map + .lower_bound(Bound::Excluded(key)) + .key_value() + .and_then(|pair| pair.0.borrow().is_proper_superset(key).then_some(pair)) + } + /// Returns a reference to the value corresponding to the least superset of key. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn get_least_superset<Q>(&self, key: &Q) -> Option<&V> + where + K: Borrow<Q>, + Q: SetOrd, + { + self.get_least_superset_key_value(key).map(|(_, val)| val) + } + /// Returns a reference to the key-value pair corresponding to the least superset of the supplied key. + /// The supplied key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type + #[inline] + pub fn get_least_superset_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)> + where + K: Borrow<Q>, + Q: SetOrd, + { + self.map + .lower_bound(Bound::Included(key)) + .key_value() + .and_then(|pair| pair.0.borrow().is_superset(key).then_some(pair)) + } + /// `(key, value)` is inserted iff there doesn't already + /// exist a `K` that is a superset of `key`. + /// In the event `(key, value)` will be inserted, all `(K, V)`s + /// where the `K` is a subset of `key` are first removed before + /// inserting. + #[inline] + #[allow(unsafe_code)] + pub fn insert(&mut self, key: K, value: V) -> bool { + // Since the only way to `insert` a `(K, V)` is via this function, + // the following is true: + // The smallest value greater than or equal to `key` will be a superset + // of `key` iff there exists a superset of `key`. + // This means that we simply have to check this one value to decide + // if `(key, value)` needs to be inserted; furthermore, in the event `(key, value)` + // does need to be inserted, we only have to traverse backwards until + // the beginning of `map` or a `K` is not a subset of `key` + // removing all `(K, V)`s where the `K` is a subset before we insert `(key, value)`. + let mut cursor = self.map.lower_bound_mut(Bound::Included(&key)); + if let Some(ge) = cursor.key() { + if ge.is_superset(&key) { + return false; + } + } + cursor.move_prev(); + while let Some(lt) = cursor.key() { + if key.is_proper_superset(lt) { + cursor.remove_current_and_move_back(); + } else { + break; + } + } + // SAFETY: + // If `key` already existed in the map, then cursor + // would begin pointing at it. Since `Set::is_superset` + // returns true when both values are the same, we would + // immediately return from this function. This guarantees + // that `key` is unique before inserting. + // Since we only move to smaller values and each time we do + // we remove said value (or stop), the insert of `key` will occur after + // all smaller values and before larger values ensuring the sorted + // order of `map` is retained. + // Note that due to the requirements of `SetOrd`, a `K` that + // `is_proper_superset` another `K` is also strictly greater. + unsafe { + cursor.insert_after_unchecked(key, value); + } + true + } + /// Allows for `SupersetSet::replace` to be implemented for supersets. + #[inline] + pub(crate) fn lower_bound_mut<Q>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V> + where + K: Borrow<Q>, + Q: SetOrd, + { + self.map.lower_bound_mut(bound) + } + /// Removes the greatest proper subset of key from the map, returning the key and value if such a subset exists. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn remove_greatest_proper_subset<Q>(&mut self, key: &Q) -> Option<(K, V)> + where + K: Borrow<Q>, + Q: SetOrd, + { + let mut cursor = self.map.upper_bound_mut(Bound::Excluded(key)); + if let Some(lt) = cursor.key() { + if lt.borrow().is_proper_subset(key) { + return cursor.remove_current(); + } + } + None + } + /// Removes the greatest subset of key from the map, returning the key and value if such a subset exists. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn remove_greatest_subset<Q>(&mut self, key: &Q) -> Option<(K, V)> + where + K: Borrow<Q>, + Q: SetOrd, + { + let mut cursor = self.map.upper_bound_mut(Bound::Included(key)); + if let Some(le) = cursor.key() { + if le.borrow().is_subset(key) { + return cursor.remove_current(); + } + } + None + } + /// Removes the least proper superset of key from the map, returning the key and value if such a superset exists. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn remove_least_proper_superset<Q>(&mut self, key: &Q) -> Option<(K, V)> + where + K: Borrow<Q>, + Q: SetOrd, + { + let mut cursor = self.map.lower_bound_mut(Bound::Excluded(key)); + if let Some(gt) = cursor.key() { + if gt.borrow().is_proper_superset(key) { + return cursor.remove_current(); + } + } + None + } + /// Removes the least superset of key from the map, returning the key and value if such a superset exists. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + #[inline] + pub fn remove_least_superset<Q>(&mut self, key: &Q) -> Option<(K, V)> + where + K: Borrow<Q>, + Q: SetOrd, + { + let mut cursor = self.map.lower_bound_mut(Bound::Included(key)); + if let Some(ge) = cursor.key() { + if ge.borrow().is_superset(key) { + return cursor.remove_current(); + } + } + None + } + /// Removes all proper subsets of key from the map, returning the count removed. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so the removal of more than `usize::MAX` elements either produces the wrong result or panics. If debug assertions are enabled, a panic is guaranteed. + /// # Panics + /// + /// This function might panic if then number of elements removed is greater than `usize::MAX`. + #[inline] + #[allow(clippy::arithmetic_side_effects)] + pub fn remove_proper_subsets<Q>(&mut self, key: &Q) -> usize + where + K: Borrow<Q>, + Q: SetOrd, + { + let mut cursor = self.map.upper_bound_mut(Bound::Excluded(key)); + let mut count = 0; + while let Some(lt) = cursor.key() { + if lt.borrow().is_proper_subset(key) { + cursor.remove_current_and_move_back(); + count += 1; + } else { + return count; + } + } + count + } + /// Removes all proper supersets of key from the map, returning the count removed. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so the removal of more than `usize::MAX` elements either produces the wrong result or panics. If debug assertions are enabled, a panic is guaranteed. + /// # Panics + /// + /// This function might panic if then number of elements removed is greater than `usize::MAX`. + #[inline] + #[allow(clippy::arithmetic_side_effects)] + pub fn remove_proper_supersets<Q>(&mut self, key: &Q) -> usize + where + K: Borrow<Q>, + Q: SetOrd, + { + let mut cursor = self.map.lower_bound_mut(Bound::Excluded(key)); + let mut count = 0; + while let Some(gt) = cursor.key() { + if gt.borrow().is_proper_superset(key) { + cursor.remove_current(); + count += 1; + } else { + return count; + } + } + count + } + /// Removes all subsets of key from the map, returning the count removed. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so the removal of more than `usize::MAX` elements either produces the wrong result or panics. If debug assertions are enabled, a panic is guaranteed. + /// # Panics + /// + /// This function might panic if then number of elements removed is greater than `usize::MAX`. + #[inline] + #[allow(clippy::arithmetic_side_effects)] + pub fn remove_subsets<Q>(&mut self, key: &Q) -> usize + where + K: Borrow<Q>, + Q: SetOrd, + { + let mut cursor = self.map.upper_bound_mut(Bound::Included(key)); + let mut count = 0; + // To avoid unnecessary checks for equivalence, + // we separately call `is_subset` on the first element + // while calling `is_proper_subset` on the other elements. + if let Some(le) = cursor.key() { + if le.borrow().is_subset(key) { + cursor.remove_current_and_move_back(); + count += 1; + while let Some(lt) = cursor.key() { + if lt.borrow().is_proper_subset(key) { + cursor.remove_current_and_move_back(); + count += 1; + } else { + return count; + } + } + } else { + return count; + } + } + count + } + /// Removes all supersets of key from the map, returning the count removed. + /// The key may be any borrowed form of the map’s key type, but the ordering on the borrowed form must match the ordering on the key type. + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so the removal of more than `usize::MAX` elements either produces the wrong result or panics. If debug assertions are enabled, a panic is guaranteed. + /// # Panics + /// + /// This function might panic if then number of elements removed is greater than `usize::MAX`. + #[inline] + #[allow(clippy::arithmetic_side_effects)] + pub fn remove_supersets<Q>(&mut self, key: &Q) -> usize + where + K: Borrow<Q>, + Q: SetOrd, + { + let mut cursor = self.map.lower_bound_mut(Bound::Included(key)); + let mut count = 0; + // To avoid unnecessary checks for equivalence, + // we separately call `is_superset` on the first element + // while calling `is_proper_superset` on the other elements. + if let Some(ge) = cursor.key() { + if ge.borrow().is_superset(key) { + cursor.remove_current(); + count += 1; + while let Some(gt) = cursor.key() { + if gt.borrow().is_proper_superset(key) { + cursor.remove_current(); + count += 1; + } else { + return count; + } + } + } else { + return count; + } + } + count + } + /// Retains only the elements specified by the predicate. + /// In other words, remove all pairs `(k, v)` for which `f(&k, &mut v)` returns `false`. The elements are visited in ascending key order. + #[inline] + pub fn retain<F>(&mut self, f: F) + where + F: FnMut(&K, &mut V) -> bool, + { + self.map.retain(f); + } +} +impl<K, V> Extend<(K, V)> for SupersetMap<K, V> +where + K: SetOrd, +{ + #[inline] + fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) { + iter.into_iter().fold((), |(), (k, v)| { + self.insert(k, v); + }); + } +} +impl<'a, K, V> Extend<(&'a K, &'a V)> for SupersetMap<K, V> +where + K: SetOrd + Copy, + V: Copy, +{ + #[inline] + fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) { + iter.into_iter().fold((), |(), (k, v)| { + self.insert(*k, *v); + }); + } +} +impl<K, V, const N: usize> From<[(K, V); N]> for SupersetMap<K, V> +where + K: SetOrd, +{ + #[inline] + fn from(value: [(K, V); N]) -> Self { + let mut map = Self::new(); + map.extend(value); + map + } +} +impl<K, V> FromIterator<(K, V)> for SupersetMap<K, V> +where + K: SetOrd, +{ + #[inline] + fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self { + let mut map = Self::new(); + map.extend(iter); + map + } +} +impl<K, Q, V> Index<&Q> for SupersetMap<K, V> +where + K: Borrow<Q> + Ord, + Q: Ord + ?Sized, +{ + type Output = V; + #[inline] + fn index(&self, index: &Q) -> &Self::Output { + self.map.index(index) + } +} +impl<K, V> IntoIterator for SupersetMap<K, V> { + type Item = (K, V); + type IntoIter = IntoIter<K, V>; + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.map.into_iter() + } +} +impl<'a, K, V> IntoIterator for &'a SupersetMap<K, V> { + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +impl<'a, K, V> IntoIterator for &'a mut SupersetMap<K, V> { + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} +#[cfg(test)] +mod tests { + use super::SupersetMap; + use crate::SetOrd; + use core::borrow::Borrow; + use core::cmp::Ordering; + use num_bigint::BigUint; + use zfc::{Cardinality, Set}; + #[derive(PartialEq, Eq)] + struct ClosedInterval { + min: usize, + max: usize, + } + impl PartialOrd<Self> for ClosedInterval { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } + } + impl Ord for ClosedInterval { + fn cmp(&self, other: &Self) -> Ordering { + match self.min.cmp(&other.min) { + Ordering::Less => { + if self.max >= other.max { + Ordering::Greater + } else { + Ordering::Less + } + } + Ordering::Equal => self.max.cmp(&other.max), + Ordering::Greater => { + if self.max > other.max { + Ordering::Greater + } else { + Ordering::Less + } + } + } + } + } + impl Set for ClosedInterval { + type Elem = usize; + fn cardinality(&self) -> Cardinality { + Cardinality::Finite(BigUint::from(self.max - self.min) + BigUint::from(1usize)) + } + fn contains<Q>(&self, elem: &Q) -> bool + where + Q: ?Sized + Borrow<Self::Elem> + Eq, + { + self.min <= *elem.borrow() && self.max >= *elem.borrow() + } + fn is_proper_subset(&self, val: &Self) -> bool { + match self.min.cmp(&val.min) { + Ordering::Less => false, + Ordering::Equal => self.max < val.max, + Ordering::Greater => self.max <= val.max, + } + } + fn is_subset(&self, val: &Self) -> bool { + self.min >= val.min && self.max <= val.max + } + } + impl SetOrd for ClosedInterval {} + #[test] + fn test_insert() { + let mut map = SupersetMap::new(); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 4 }, ()); + map.insert(ClosedInterval { min: 1, max: 4 }, ()); + map.insert(ClosedInterval { min: 4, max: 6 }, ()); + map.insert(ClosedInterval { min: 2, max: 7 }, ()); + map.insert(ClosedInterval { min: 10, max: 17 }, ()); + let mut keys = map.into_keys(); + assert!(keys + .next() + .map_or(false, |set| set == ClosedInterval { min: 0, max: 4 })); + assert!(keys + .next() + .map_or(false, |set| set == ClosedInterval { min: 2, max: 7 })); + assert!(keys + .next() + .map_or(false, |set| set == ClosedInterval { min: 10, max: 17 })); + assert!(keys.next().is_none()); + assert!(keys.next().is_none()); + assert!(keys.next().is_none()); + } + #[test] + fn test_append() { + let mut map = SupersetMap::new(); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 4 }, ()); + map.insert(ClosedInterval { min: 1, max: 4 }, ()); + map.insert(ClosedInterval { min: 4, max: 6 }, ()); + map.insert(ClosedInterval { min: 2, max: 7 }, ()); + map.insert(ClosedInterval { min: 10, max: 17 }, ()); + let mut map2 = SupersetMap::new(); + map2.insert(ClosedInterval { min: 0, max: 1 }, ()); + map2.insert(ClosedInterval { min: 1, max: 14 }, ()); + map2.insert(ClosedInterval { min: 11, max: 18 }, ()); + map.append(map2); + let mut keys = map.into_keys(); + assert!(keys + .next() + .map_or(false, |set| set == ClosedInterval { min: 0, max: 4 })); + assert!(keys + .next() + .map_or(false, |set| set == ClosedInterval { min: 1, max: 14 })); + assert!(keys + .next() + .map_or(false, |set| set == ClosedInterval { min: 10, max: 17 })); + assert!(keys + .next() + .map_or(false, |set| set == ClosedInterval { min: 11, max: 18 })); + assert!(keys.next().is_none()); + assert!(keys.next().is_none()); + assert!(keys.next().is_none()); + } + #[test] + fn test_contains() { + let mut map = SupersetMap::new(); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 4 }, ()); + map.insert(ClosedInterval { min: 1, max: 4 }, ()); + map.insert(ClosedInterval { min: 4, max: 6 }, ()); + map.insert(ClosedInterval { min: 2, max: 7 }, ()); + map.insert(ClosedInterval { min: 10, max: 17 }, ()); + assert!(map.contains_proper_subset(&ClosedInterval { min: 0, max: 10 })); + assert!(!map.contains_proper_subset(&ClosedInterval { min: 10, max: 17 })); + assert!(!map.contains_proper_subset(&ClosedInterval { min: 210, max: 217 })); + assert!(map.contains_proper_superset(&ClosedInterval { min: 0, max: 1 })); + assert!(!map.contains_proper_superset(&ClosedInterval { min: 10, max: 17 })); + assert!(!map.contains_proper_superset(&ClosedInterval { min: 210, max: 217 })); + assert!(map.contains_subset(&ClosedInterval { min: 0, max: 10 })); + assert!(map.contains_subset(&ClosedInterval { min: 10, max: 17 })); + assert!(!map.contains_subset(&ClosedInterval { min: 210, max: 217 })); + assert!(map.contains_superset(&ClosedInterval { min: 0, max: 1 })); + assert!(map.contains_superset(&ClosedInterval { min: 10, max: 17 })); + assert!(!map.contains_superset(&ClosedInterval { min: 210, max: 217 })); + } + #[test] + fn test_get() { + let mut map = SupersetMap::new(); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 4 }, ()); + map.insert(ClosedInterval { min: 1, max: 4 }, ()); + map.insert(ClosedInterval { min: 4, max: 6 }, ()); + map.insert(ClosedInterval { min: 2, max: 7 }, ()); + map.insert(ClosedInterval { min: 10, max: 17 }, ()); + assert!(map + .get_greatest_proper_subset_key_value(&ClosedInterval { min: 0, max: 10 }) + .map_or(false, |(key, _)| *key == ClosedInterval { min: 2, max: 7 })); + assert!(map + .get_greatest_proper_subset_key_value(&ClosedInterval { min: 10, max: 17 }) + .map_or(true, |_| false)); + assert!(map + .get_greatest_proper_subset_key_value(&ClosedInterval { min: 210, max: 217 }) + .map_or(true, |_| false)); + assert!(map + .get_least_proper_superset_key_value(&ClosedInterval { min: 3, max: 4 }) + .map_or(false, |(key, _)| *key == ClosedInterval { min: 0, max: 4 })); + assert!(map + .get_least_proper_superset_key_value(&ClosedInterval { min: 10, max: 17 }) + .map_or(true, |_| false)); + assert!(map + .get_least_proper_superset_key_value(&ClosedInterval { min: 210, max: 217 }) + .map_or(true, |_| false)); + assert!(map + .get_greatest_subset_key_value(&ClosedInterval { min: 0, max: 10 }) + .map_or(false, |(key, _)| *key == ClosedInterval { min: 2, max: 7 })); + assert!(map + .get_greatest_subset_key_value(&ClosedInterval { min: 10, max: 17 }) + .map_or(false, |(key, _)| *key + == ClosedInterval { min: 10, max: 17 })); + assert!(map + .get_greatest_subset_key_value(&ClosedInterval { min: 210, max: 217 }) + .map_or(true, |_| false)); + assert!(map + .get_least_superset_key_value(&ClosedInterval { min: 3, max: 4 }) + .map_or(false, |(key, _)| *key == ClosedInterval { min: 0, max: 4 })); + assert!(map + .get_least_superset_key_value(&ClosedInterval { min: 10, max: 17 }) + .map_or(false, |(key, _)| *key + == ClosedInterval { min: 10, max: 17 })); + assert!(map + .get_least_superset_key_value(&ClosedInterval { min: 210, max: 217 }) + .map_or(true, |_| false)); + } + #[test] + fn test_remove() { + let mut map = SupersetMap::new(); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 3 }, ()); + map.insert(ClosedInterval { min: 0, max: 4 }, ()); + map.insert(ClosedInterval { min: 1, max: 4 }, ()); + map.insert(ClosedInterval { min: 4, max: 6 }, ()); + map.insert(ClosedInterval { min: 2, max: 7 }, ()); + map.insert(ClosedInterval { min: 10, max: 17 }, ()); + assert!(map + .remove_greatest_proper_subset(&ClosedInterval { min: 0, max: 10 }) + .map_or(false, |(key, _)| key == ClosedInterval { min: 2, max: 7 })); + assert!(map + .remove_greatest_proper_subset(&ClosedInterval { min: 10, max: 17 }) + .map_or(true, |_| false)); + assert!(map + .remove_greatest_proper_subset(&ClosedInterval { min: 210, max: 217 }) + .map_or(true, |_| false)); + assert!(map + .remove_least_proper_superset(&ClosedInterval { min: 3, max: 4 }) + .map_or(false, |(key, _)| key == ClosedInterval { min: 0, max: 4 })); + assert!(map + .remove_least_proper_superset(&ClosedInterval { min: 10, max: 17 }) + .map_or(true, |_| false)); + assert!(map + .remove_least_proper_superset(&ClosedInterval { min: 210, max: 217 }) + .map_or(true, |_| false)); + assert!(map + .remove_greatest_subset(&ClosedInterval { min: 0, max: 10 }) + .map_or(true, |_| false)); + assert!(map + .remove_greatest_subset(&ClosedInterval { min: 10, max: 17 }) + .map_or(false, |(key, _)| key == ClosedInterval { min: 10, max: 17 })); + assert!(map + .remove_greatest_subset(&ClosedInterval { min: 210, max: 217 }) + .map_or(true, |_| false)); + assert!(map + .remove_least_superset(&ClosedInterval { min: 3, max: 4 }) + .map_or(true, |_| false)); + assert!(map + .remove_least_superset(&ClosedInterval { min: 10, max: 17 }) + .map_or(true, |_| false)); + assert!(map + .remove_least_superset(&ClosedInterval { min: 210, max: 217 }) + .map_or(true, |_| false)); + let mut map2 = SupersetMap::new(); + map2.insert(ClosedInterval { min: 0, max: 3 }, ()); + map2.insert(ClosedInterval { min: 0, max: 3 }, ()); + map2.insert(ClosedInterval { min: 0, max: 4 }, ()); + map2.insert(ClosedInterval { min: 1, max: 4 }, ()); + map2.insert(ClosedInterval { min: 4, max: 6 }, ()); + map2.insert(ClosedInterval { min: 2, max: 7 }, ()); + map2.insert(ClosedInterval { min: 10, max: 17 }, ()); + assert!(map2.remove_supersets(&ClosedInterval { min: 0, max: 20 }) == 0); + assert!(map2.remove_subsets(&ClosedInterval { min: 0, max: 1 }) == 0); + assert!(map2.remove_subsets(&ClosedInterval { min: 0, max: 20 }) == 3); + map2.insert(ClosedInterval { min: 0, max: 3 }, ()); + map2.insert(ClosedInterval { min: 0, max: 3 }, ()); + map2.insert(ClosedInterval { min: 0, max: 4 }, ()); + map2.insert(ClosedInterval { min: 1, max: 4 }, ()); + map2.insert(ClosedInterval { min: 4, max: 6 }, ()); + map2.insert(ClosedInterval { min: 2, max: 7 }, ()); + map2.insert(ClosedInterval { min: 10, max: 17 }, ()); + assert!(map2.remove_supersets(&ClosedInterval { min: 3, max: 4 }) == 2); + } +} diff --git a/src/superset_set.rs b/src/superset_set.rs @@ -0,0 +1,974 @@ +#![deny( + unsafe_code, + unused, + warnings, + clippy::all, + clippy::cargo, + clippy::complexity, + clippy::correctness, + clippy::nursery, + clippy::pedantic, + clippy::perf, + clippy::restriction, + clippy::style, + clippy::suspicious +)] +#![allow( + clippy::blanket_clippy_restriction_lints, + clippy::implicit_return, + clippy::min_ident_chars, + clippy::missing_trait_methods, + clippy::same_name_method, + clippy::semicolon_outside_block, + clippy::shadow_unrelated, + clippy::single_char_lifetime_names +)] +extern crate alloc; +use crate::{SetOrd, SupersetMap}; +use alloc::collections::btree_map::{self, IntoKeys, Keys}; +use core::borrow::Borrow; +use core::hash::{Hash, Hasher}; +use core::iter::FusedIterator; +use core::ops::{BitAnd, BitOr, Bound, RangeBounds}; +use zfc::{Cardinality, Set}; +/// A lazy iterator producing elements in the intersection of `SupersetSet`s. +/// +/// This `struct` is created by [`SupersetSet::intersection`]. +#[derive(Clone)] +pub struct Intersection<'a, T: 'a> { + /// Iterator for the first `SupersetSet`. + iter_1: Iter<'a, T>, + /// Iterator for the second `SupersetSet`. + iter_2: Iter<'a, T>, + /// Previous value iterated from `iter_1`. + /// `prev_1` and `prev_2` will never both be `Some`. + prev_1: Option<&'a T>, + /// Previous value iterated from `iter_2`. + prev_2: Option<&'a T>, +} +impl<'a, T> FusedIterator for Intersection<'a, T> where T: SetOrd {} +impl<'a, T> Iterator for Intersection<'a, T> +where + T: SetOrd, +{ + type Item = &'a T; + #[allow(clippy::else_if_without_else)] + #[inline] + fn next(&mut self) -> Option<Self::Item> { + loop { + if let Some(prev1) = self.prev_1 { + if let Some(cur2) = self.iter_2.next() { + if prev1 <= cur2 { + self.prev_1 = None; + self.prev_2 = Some(cur2); + if prev1.is_subset(cur2) { + return Some(prev1); + } + } else if cur2.is_proper_subset(prev1) { + return Some(cur2); + } + } else { + self.prev_1 = None; + return None; + } + } else if let Some(prev2) = self.prev_2 { + if let Some(cur1) = self.iter_1.next() { + if prev2 <= cur1 { + self.prev_2 = None; + self.prev_1 = Some(cur1); + if prev2.is_subset(cur1) { + return Some(prev2); + } + } else if cur1.is_proper_subset(prev2) { + return Some(cur1); + } + } else { + self.prev_1 = None; + return None; + } + } else if let Some(cur1) = self.iter_1.next() { + if let Some(cur2) = self.iter_2.next() { + if cur1 <= cur2 { + self.prev_2 = Some(cur2); + if cur1.is_subset(cur2) { + return Some(cur1); + } + } else if cur2.is_proper_subset(cur1) { + self.prev_1 = Some(cur1); + return Some(cur2); + } + } else { + return None; + } + } else { + return None; + } + } + } +} +/// An owning iterator over the items of a `SupersetSet`. +/// +/// This `struct` is created by [`SupersetSet::into_iter`] (provided by [`IntoIterator`]). +pub struct IntoIter<T> { + /// Iterator of the values in a `SupersetSet`. + iter: IntoKeys<T, ()>, +} +impl<T> Default for IntoIter<T> { + #[inline] + fn default() -> Self { + Self { + iter: IntoKeys::default(), + } + } +} +impl<T> DoubleEndedIterator for IntoIter<T> { + #[inline] + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back() + } +} +impl<T> ExactSizeIterator for IntoIter<T> { + #[inline] + fn len(&self) -> usize { + self.iter.len() + } +} +impl<T> FusedIterator for IntoIter<T> {} +impl<T> Iterator for IntoIter<T> { + type Item = T; + #[inline] + fn next(&mut self) -> Option<Self::Item> { + self.iter.next() + } +} +/// An iterator over the items of a `SupersetSet`. +/// +/// This `struct` is created by [`SupersetSet::iter`]. +#[derive(Clone)] +pub struct Iter<'a, T: 'a> { + /// Iterator of the values in a `SupersetSet`. + iter: Keys<'a, T, ()>, +} +impl<'a, T> Default for Iter<'a, T> { + #[inline] + fn default() -> Self { + Self { + iter: Keys::default(), + } + } +} +impl<'a, T> DoubleEndedIterator for Iter<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back() + } +} +impl<'a, T> ExactSizeIterator for Iter<'a, T> { + #[inline] + fn len(&self) -> usize { + self.iter.len() + } +} +impl<'a, T> FusedIterator for Iter<'a, T> {} +impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + #[inline] + fn next(&mut self) -> Option<Self::Item> { + self.iter.next() + } +} +/// An iterator over a sub-range of items in a `SupersetSet`. +/// +/// This `struct` is created by [`SupersetSet::range`]. +#[derive(Clone)] +pub struct Range<'a, T: 'a> { + /// Range iterator for a `SupersetSet`. + iter: btree_map::Range<'a, T, ()>, +} +impl<'a, T> Default for Range<'a, T> { + #[inline] + fn default() -> Self { + Self { + iter: btree_map::Range::default(), + } + } +} +impl<'a, T> DoubleEndedIterator for Range<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back().map(|(key, _)| key) + } +} +impl<'a, T> FusedIterator for Range<'a, T> {} +impl<'a, T> Iterator for Range<'a, T> { + type Item = &'a T; + #[inline] + fn next(&mut self) -> Option<Self::Item> { + self.iter.next().map(|(key, _)| key) + } +} +/// A minimal collection of `T`s. +/// Internally it is based on a [`SupersetMap`]. +/// When a `T` is [`SupersetSet::insert`]ed, +/// it won't actually be inserted unless +/// there isn't a `T` already in +/// the set that is a superset of it. +/// In such event, all `T`s that +/// are subsets of the to-be-inserted `T` +/// are removed before inserting the `T`. +/// Note this can have quite good performance due to the +/// fact that a single search is necessary to detect +/// if insertion should occur; furthermore since all +/// subsets occur immediately before where the value +/// will be inserted, a simple linear scan is sufficient +/// to remove subsets avoiding the need to search +/// the entire set. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct SupersetSet<T> { + /// Collection of `T`s. + map: SupersetMap<T, ()>, +} +impl<T> SupersetSet<T> { + /// Read [`BTreeSet::clear`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.clear). + #[inline] + pub fn clear(&mut self) { + self.map.clear(); + } + /// Read [`BTreeSet::is_empty`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.is_empty). + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + /// Read [`BTreeSet::iter`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.iter). + #[inline] + #[must_use] + pub fn iter(&self) -> Iter<'_, T> { + Iter { + iter: self.map.keys(), + } + } + /// Read [`BTreeSet::len`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.len). + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.map.len() + } + /// Makes a new, empty `SupersetSet`. + /// Does not allocate anything on its own. + #[inline] + #[must_use] + pub const fn new() -> Self { + Self { + map: SupersetMap::new(), + } + } +} +impl<T> SupersetSet<T> +where + T: Ord, +{ + /// Read [`BTreeSet::contains`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.contains). + #[inline] + pub fn contains<Q>(&self, value: &Q) -> bool + where + T: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.contains_key(value) + } + /// Read [`BTreeSet::first`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.first). + #[inline] + #[must_use] + pub fn first(&self) -> Option<&T> { + self.map.first_key_value().map(|(key, _)| key) + } + /// Read [`BTreeSet::get`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.get). + #[inline] + pub fn get<Q>(&self, value: &Q) -> Option<&T> + where + T: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.get_key_value(value).map(|(key, _)| key) + } + /// Read [`BTreeSet::last`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.last). + #[inline] + #[must_use] + pub fn last(&self) -> Option<&T> { + self.map.last_key_value().map(|(key, _)| key) + } + /// Read [`BTreeSet::pop_first`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.pop_first). + #[inline] + pub fn pop_first(&mut self) -> Option<T> { + self.map.pop_first().map(|(key, ())| key) + } + /// Read [`BTreeSet::pop_last`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.pop_last). + #[inline] + pub fn pop_last(&mut self) -> Option<T> { + self.map.pop_last().map(|(key, ())| key) + } + /// Read [`BTreeSet::range`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.range). + #[inline] + pub fn range<K, R>(&self, range: R) -> Range<'_, T> + where + T: Borrow<K>, + K: Ord + ?Sized, + R: RangeBounds<K>, + { + Range { + iter: self.map.range(range), + } + } + /// Read [`BTreeSet::remove`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.remove). + #[inline] + pub fn remove<Q>(&mut self, value: &Q) -> bool + where + T: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.remove(value).is_some() + } + /// Read [`BTreeSet::split_off`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.split_off). + #[inline] + #[must_use] + pub fn split_off<Q>(&mut self, value: &Q) -> Self + where + T: Borrow<Q>, + Q: Ord + ?Sized, + { + Self { + map: self.map.split_off(value), + } + } + /// Read [`BTreeSet::take`](https://doc.rust-lang.org/alloc/collections/btree_set/struct.BTreeSet.html#method.take). + #[inline] + pub fn take<Q>(&mut self, value: &Q) -> Option<T> + where + T: Borrow<Q>, + Q: Ord + ?Sized, + { + self.map.remove_entry(value).map(|(key, ())| key) + } +} +impl<T> SupersetSet<T> +where + T: SetOrd, +{ + /// Moves all elements from `other` into `self`, consuming `other`. + /// If a value from `other` is a proper superset of a value in `self`, the respective value from `self` will be removed before inserting + /// the value from `other`. + /// If a value from `other` is a subset of a value in `self`, it won't be inserted. + #[inline] + pub fn append(&mut self, other: Self) { + self.map.append(other.map); + } + /// Returns `true` if the set contains a proper subset of the specified value. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn contains_proper_subset<Q>(&self, value: &Q) -> bool + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.contains_proper_subset(value) + } + /// Returns `true` if the set contains a proper superset of the specified value. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn contains_proper_superset<Q>(&self, value: &Q) -> bool + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.contains_proper_superset(value) + } + /// Returns `true` if the set contains a subset of the specified value. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn contains_subset<Q>(&self, value: &Q) -> bool + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.contains_subset(value) + } + /// Returns `true` if the set contains a superset of the specified value. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn contains_superset<Q>(&self, value: &Q) -> bool + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.contains_superset(value) + } + /// Returns a reference to the value corresponding to the greatest proper subset of the passed value. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn get_greatest_proper_subset<Q>(&self, value: &Q) -> Option<&T> + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map + .get_greatest_proper_subset_key_value(value) + .map(|(key, _)| key) + } + /// Returns a reference to the value corresponding to the greatest subset of the passed value. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn get_greatest_subset<Q>(&self, value: &Q) -> Option<&T> + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map + .get_greatest_subset_key_value(value) + .map(|(key, _)| key) + } + /// Returns a reference to the value corresponding to the least proper superset of the passed value. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn get_least_proper_superset<Q>(&self, value: &Q) -> Option<&T> + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map + .get_least_proper_superset_key_value(value) + .map(|(key, _)| key) + } + /// Returns a reference to the value corresponding to the least superset of the passed value. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn get_least_superset<Q>(&self, value: &Q) -> Option<&T> + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map + .get_least_superset_key_value(value) + .map(|(key, _)| key) + } + /// `value` is inserted iff there doesn't already + /// exist a `T` that is a superset of `value`. + /// In the event `value` will be inserted, all `T`s + /// where the `T` is a subset of `value` are first removed before + /// inserting. + #[inline] + pub fn insert(&mut self, value: T) -> bool { + self.map.insert(value, ()) + } + /// Visits the elements representing the intersection, i.e., the subsets of elements that are both in `self` and `other`, in ascending order. + /// For example if `self` contains a sequence of sets each of which being a subset of the same set in `other`, then only the subsets in `self` will be iterated. + #[inline] + #[must_use] + pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T> { + Intersection { + iter_1: self.into_iter(), + iter_2: other.into_iter(), + prev_1: None, + prev_2: None, + } + } + /// Removes the greatest proper subset of value from the set, returning the value if one existed. + /// The value may be any borrowed form of the set's value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn remove_greatest_proper_subset<Q>(&mut self, value: &Q) -> Option<T> + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map + .remove_greatest_proper_subset(value) + .map(|(key, ())| key) + } + /// Removes the greatest subset of value from the set, returning the value if one existed. + /// The value may be any borrowed form of the set's value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn remove_greatest_subset<Q>(&mut self, value: &Q) -> Option<T> + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.remove_greatest_subset(value).map(|(key, ())| key) + } + /// Removes the least proper superset of value from the set, returning the value if one existed. + /// The value may be any borrowed form of the set's value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn remove_least_proper_superset<Q>(&mut self, value: &Q) -> Option<T> + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map + .remove_least_proper_superset(value) + .map(|(key, ())| key) + } + /// Removes the least superset of value from the set, returning the value if one existed. + /// The value may be any borrowed form of the set's value type, but the ordering on the borrowed form must match the ordering on the value type. + #[inline] + pub fn remove_least_superset<Q>(&mut self, value: &Q) -> Option<T> + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.remove_least_superset(value).map(|(key, ())| key) + } + /// Removes all proper subsets of value from the set, returning the count removed. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so the removal of more than `usize::MAX` elements either produces the wrong result or panics. If debug assertions are enabled, a panic is guaranteed. + /// # Panics + /// + /// This function might panic if then number of elements removed is greater than `usize::MAX`. + #[inline] + pub fn remove_proper_subsets<Q>(&mut self, value: &Q) -> usize + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.remove_proper_subsets(value) + } + /// Removes all proper supersets of value from the set, returning the count removed. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so the removal of more than `usize::MAX` elements either produces the wrong result or panics. If debug assertions are enabled, a panic is guaranteed. + /// # Panics + /// + /// This function might panic if then number of elements removed is greater than `usize::MAX`. + #[inline] + pub fn remove_proper_supersets<Q>(&mut self, value: &Q) -> usize + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.remove_proper_supersets(value) + } + /// Removes all subsets of value from the set, returning the count removed. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so the removal of more than `usize::MAX` elements either produces the wrong result or panics. If debug assertions are enabled, a panic is guaranteed. + /// # Panics + /// + /// This function might panic if then number of elements removed is greater than `usize::MAX`. + #[inline] + pub fn remove_subsets<Q>(&mut self, value: &Q) -> usize + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.remove_subsets(value) + } + /// Removes all supersets of value from the set, returning the count removed. + /// The value may be any borrowed form of the set’s value type, but the ordering on the borrowed form must match the ordering on the value type. + /// # Overflow Behavior + /// + /// The method does no guarding against overflows, so the removal of more than `usize::MAX` elements either produces the wrong result or panics. If debug assertions are enabled, a panic is guaranteed. + /// # Panics + /// + /// This function might panic if then number of elements removed is greater than `usize::MAX`. + #[inline] + pub fn remove_supersets<Q>(&mut self, value: &Q) -> usize + where + T: Borrow<Q>, + Q: SetOrd, + { + self.map.remove_supersets(value) + } + /// Adds a value to the set iff there doesn't already exist a proper superset of it. + /// In the event a value that is equal to it already exists, then it is replaced and returned. + #[allow(clippy::option_if_let_else)] + #[inline] + pub fn replace(&mut self, value: T) -> Option<T> { + let prev = { + let mut cursor = self.map.lower_bound_mut(Bound::Included(&value)); + if let Some(ge) = cursor.key() { + if *ge == value { + cursor.remove_current().map(|(key, ())| key) + } else { + None + } + } else { + None + } + }; + self.insert(value); + prev + } + /// Retains only the elements specified by the predicate. + /// In other words, remove all `t`s for which `f(&t)` returns `false`. The elements are visited in ascending value order. + #[inline] + pub fn retain<F>(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + self.map.retain(|key, _| f(key)); + } + /// Visits the elements representing the union, i.e., the supersets of elements that are in `self` or `other`, in ascending order. + /// For example if `self` contains a sequence of sets each of which being a subset of the same set in `other`, then only the superset in `other` will be iterated. + /// The items iterated and the order in which they are iterated will match exactly as if one iterated `self` after `append`ing `other` to it. + #[inline] + #[must_use] + pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T> { + Union { + iter_1: self.into_iter(), + iter_2: other.into_iter(), + prev_1: None, + prev_2: None, + } + } +} +impl<T> BitAnd<Self> for &SupersetSet<T> +where + T: Clone + SetOrd, +{ + type Output = SupersetSet<T>; + #[inline] + fn bitand(self, rhs: Self) -> Self::Output { + self.intersection(rhs).cloned().collect() + } +} +impl<T> BitOr<Self> for &SupersetSet<T> +where + T: Clone + SetOrd, +{ + type Output = SupersetSet<T>; + #[inline] + fn bitor(self, rhs: Self) -> Self::Output { + self.union(rhs).cloned().collect() + } +} +impl<T> Default for SupersetSet<T> { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl<T> Extend<T> for SupersetSet<T> +where + T: SetOrd, +{ + #[inline] + fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { + self.map.extend(iter.into_iter().map(|val| (val, ()))); + } +} +impl<'a, T> Extend<&'a T> for SupersetSet<T> +where + T: SetOrd + Copy, +{ + #[inline] + fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { + self.map.extend(iter.into_iter().map(|val| (val, &()))); + } +} +impl<T, const N: usize> From<[T; N]> for SupersetSet<T> +where + T: SetOrd, +{ + #[inline] + fn from(value: [T; N]) -> Self { + let mut set = Self::new(); + set.extend(value); + set + } +} +impl<T> FromIterator<T> for SupersetSet<T> +where + T: SetOrd, +{ + #[inline] + fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { + let mut set = Self::new(); + set.extend(iter); + set + } +} +impl<T> Hash for SupersetSet<T> +where + T: Hash, +{ + #[inline] + fn hash<H: Hasher>(&self, state: &mut H) { + self.map.hash(state); + } +} +impl<T> IntoIterator for SupersetSet<T> { + type Item = T; + type IntoIter = IntoIter<T>; + #[inline] + fn into_iter(self) -> Self::IntoIter { + IntoIter { + iter: self.map.into_keys(), + } + } +} +impl<'a, T> IntoIterator for &'a SupersetSet<T> { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +impl<T> Set for SupersetSet<T> +where + T: SetOrd, +{ + type Elem = T; + #[inline] + fn cardinality(&self) -> Cardinality { + Cardinality::Finite(self.len().into()) + } + #[inline] + fn contains<Q>(&self, elem: &Q) -> bool + where + Q: Borrow<Self::Elem> + Eq + ?Sized, + { + self.contains(elem.borrow()) + } + #[inline] + fn is_proper_subset(&self, val: &Self) -> bool { + self.len() < val.len() && self.intersection(val).count() == val.len() + } + #[inline] + fn is_subset(&self, val: &Self) -> bool { + self.len() <= val.len() && self.intersection(val).count() == val.len() + } +} +/// A lazy iterator producing elements in the union of `SupersetSet`s. +/// +/// This `struct` is created by [`SupersetSet::union`]. +#[derive(Clone)] +pub struct Union<'a, T: 'a> { + /// Iterator from the first `SupersetSet`. + iter_1: Iter<'a, T>, + /// Iterator from the second `SupersetSet`. + iter_2: Iter<'a, T>, + /// Previous value iterated form `iter_1`. + /// `prev_1` and `prev_2` are never both `Some`. + prev_1: Option<&'a T>, + /// Previous value iterated form `iter_2`. + prev_2: Option<&'a T>, +} +impl<'a, T> FusedIterator for Union<'a, T> where T: SetOrd {} +impl<'a, T> Iterator for Union<'a, T> +where + T: SetOrd, +{ + type Item = &'a T; + #[allow(clippy::else_if_without_else)] + #[inline] + fn next(&mut self) -> Option<Self::Item> { + loop { + if let Some(prev1) = self.prev_1 { + if let Some(cur2) = self.iter_2.next() { + if prev1 >= cur2 { + if !prev1.is_superset(cur2) { + return Some(cur2); + } + } else if cur2.is_proper_superset(prev1) { + self.prev_1 = None; + self.prev_2 = Some(cur2); + } else { + self.prev_2 = Some(cur2); + return self.prev_1.take(); + } + } else { + return self.prev_1.take(); + } + } else if let Some(prev2) = self.prev_2 { + if let Some(cur1) = self.iter_1.next() { + if prev2 >= cur1 { + if !prev2.is_superset(cur1) { + return Some(cur1); + } + } else if cur1.is_proper_superset(prev2) { + self.prev_1 = Some(cur1); + self.prev_2 = None; + } else { + self.prev_1 = Some(cur1); + return self.prev_2.take(); + } + } else { + return self.prev_2.take(); + } + } else if let Some(cur1) = self.iter_1.next() { + if let Some(cur2) = self.iter_2.next() { + if cur1 >= cur2 { + self.prev_1 = Some(cur1); + if !cur1.is_superset(cur2) { + return Some(cur2); + } + } else if cur2.is_proper_superset(cur1) { + self.prev_2 = Some(cur2); + } else { + self.prev_2 = Some(cur2); + return Some(cur1); + } + } else { + return Some(cur1); + } + } else { + return self.iter_2.next(); + } + } + } +} +#[cfg(test)] +mod tests { + use super::SupersetSet; + use crate::SetOrd; + use core::borrow::Borrow; + use core::cmp::Ordering; + use num_bigint::BigUint; + use zfc::{Cardinality, Set}; + #[derive(PartialEq, Eq)] + struct ClosedInterval { + min: usize, + max: usize, + } + impl PartialOrd<Self> for ClosedInterval { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } + } + impl Ord for ClosedInterval { + fn cmp(&self, other: &Self) -> Ordering { + match self.min.cmp(&other.min) { + Ordering::Less => { + if self.max >= other.max { + Ordering::Greater + } else { + Ordering::Less + } + } + Ordering::Equal => self.max.cmp(&other.max), + Ordering::Greater => { + if self.max > other.max { + Ordering::Greater + } else { + Ordering::Less + } + } + } + } + } + impl Set for ClosedInterval { + type Elem = usize; + fn cardinality(&self) -> Cardinality { + Cardinality::Finite(BigUint::from(self.max - self.min) + BigUint::from(1usize)) + } + fn contains<Q>(&self, elem: &Q) -> bool + where + Q: ?Sized + Borrow<Self::Elem> + Eq, + { + self.min <= *elem.borrow() && self.max >= *elem.borrow() + } + fn is_proper_subset(&self, val: &Self) -> bool { + match self.min.cmp(&val.min) { + Ordering::Less => false, + Ordering::Equal => self.max < val.max, + Ordering::Greater => self.max <= val.max, + } + } + fn is_subset(&self, val: &Self) -> bool { + self.min >= val.min && self.max <= val.max + } + } + impl SetOrd for ClosedInterval {} + #[test] + fn test_union() { + let mut set1 = SupersetSet::new(); + set1.insert(ClosedInterval { min: 14, max: 19 }); + set1.insert(ClosedInterval { min: 10, max: 12 }); + set1.insert(ClosedInterval { min: 0, max: 3 }); + set1.insert(ClosedInterval { min: 0, max: 2 }); + set1.insert(ClosedInterval { min: 1, max: 4 }); + set1.insert(ClosedInterval { min: 20, max: 22 }); + set1.insert(ClosedInterval { min: 25, max: 26 }); + set1.insert(ClosedInterval { min: 26, max: 27 }); + let mut set2 = SupersetSet::new(); + set2.insert(ClosedInterval { min: 10, max: 12 }); + set2.insert(ClosedInterval { min: 14, max: 16 }); + set2.insert(ClosedInterval { min: 0, max: 3 }); + set2.insert(ClosedInterval { min: 3, max: 4 }); + set2.insert(ClosedInterval { min: 23, max: 25 }); + set2.insert(ClosedInterval { min: 25, max: 27 }); + let mut union = set1.union(&set2); + assert!(union.next() == Some(&ClosedInterval { min: 0, max: 3 })); + assert!(union.next() == Some(&ClosedInterval { min: 1, max: 4 })); + assert!(union.next() == Some(&ClosedInterval { min: 10, max: 12 })); + assert!(union.next() == Some(&ClosedInterval { min: 14, max: 19 })); + assert!(union.next() == Some(&ClosedInterval { min: 20, max: 22 })); + assert!(union.next() == Some(&ClosedInterval { min: 23, max: 25 })); + assert!(union.next() == Some(&ClosedInterval { min: 25, max: 27 })); + assert!(union.next().is_none()); + assert!(union.next().is_none()); + assert!(union.next().is_none()); + } + #[test] + fn test_intersection() { + let mut set1 = SupersetSet::new(); + set1.insert(ClosedInterval { min: 14, max: 19 }); + set1.insert(ClosedInterval { min: 10, max: 12 }); + set1.insert(ClosedInterval { min: 0, max: 3 }); + set1.insert(ClosedInterval { min: 0, max: 2 }); + set1.insert(ClosedInterval { min: 1, max: 4 }); + set1.insert(ClosedInterval { min: 20, max: 22 }); + set1.insert(ClosedInterval { min: 25, max: 26 }); + set1.insert(ClosedInterval { min: 26, max: 27 }); + let mut set2 = SupersetSet::new(); + set2.insert(ClosedInterval { min: 10, max: 12 }); + set2.insert(ClosedInterval { min: 14, max: 16 }); + set2.insert(ClosedInterval { min: 0, max: 3 }); + set2.insert(ClosedInterval { min: 3, max: 4 }); + set2.insert(ClosedInterval { min: 23, max: 25 }); + set2.insert(ClosedInterval { min: 25, max: 27 }); + let mut intersection = set1.intersection(&set2); + assert!(intersection.next() == Some(&ClosedInterval { min: 0, max: 3 })); + assert!(intersection.next() == Some(&ClosedInterval { min: 3, max: 4 })); + assert!(intersection.next() == Some(&ClosedInterval { min: 10, max: 12 })); + assert!(intersection.next() == Some(&ClosedInterval { min: 14, max: 16 })); + assert!(intersection.next() == Some(&ClosedInterval { min: 25, max: 26 })); + assert!(intersection.next() == Some(&ClosedInterval { min: 26, max: 27 })); + assert!(intersection.next().is_none()); + assert!(intersection.next().is_none()); + assert!(intersection.next().is_none()); + } + #[test] + fn test_replace() { + let mut set = SupersetSet::new(); + set.insert(ClosedInterval { min: 14, max: 19 }); + set.insert(ClosedInterval { min: 10, max: 12 }); + set.insert(ClosedInterval { min: 0, max: 3 }); + set.insert(ClosedInterval { min: 0, max: 2 }); + set.insert(ClosedInterval { min: 1, max: 4 }); + set.insert(ClosedInterval { min: 20, max: 22 }); + set.insert(ClosedInterval { min: 25, max: 26 }); + set.insert(ClosedInterval { min: 26, max: 27 }); + // Does not replace proper supersets. + assert!( + set.replace(ClosedInterval { min: 20, max: 21 }).is_none() + && set.contains(&ClosedInterval { min: 20, max: 22 }) + && set.contains_proper_superset(&ClosedInterval { min: 20, max: 21 }) + && !set.contains(&ClosedInterval { min: 20, max: 21 }) + ); + // Successful replace. + assert!( + set.replace(ClosedInterval { min: 0, max: 3 }) + == Some(ClosedInterval { min: 0, max: 3 }) + && set.contains(&ClosedInterval { min: 0, max: 3 }) + ); + // Replace is just an insert when a superset does not exist. + assert!( + set.replace(ClosedInterval { min: 100, max: 300 }).is_none() + && set.contains(&ClosedInterval { min: 100, max: 300 }) + ); + } +}