commit 40fe779f4995e9bf4ae76ab1e0ad28f95e478faf
Author: Zack Newman <zack@philomathiclife.com>
Date: Sat, 26 Aug 2023 16:41:18 -0600
init
Diffstat:
A | .gitignore | | | 2 | ++ |
A | Cargo.toml | | | 31 | +++++++++++++++++++++++++++++++ |
A | README.md | | | 140 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | rust-toolchain.toml | | | 2 | ++ |
A | src/lib.rs | | | 163 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/superset_map.rs | | | 994 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/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 })
+ );
+ }
+}