use core::fmt;
use equivalent::Comparable;
use std::{
cmp::Ordering,
hash::{Hash, Hasher},
iter::FusedIterator,
ops::Index,
};
use crate::{
map::{self, BTreeIndexMap},
util::entries_as_slice,
};
#[derive(Clone)]
pub struct BTreeIndexSet<T> {
map: BTreeIndexMap<T, ()>,
}
impl<T> Default for BTreeIndexSet<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> BTreeIndexSet<T> {
pub fn new() -> Self {
Self {
map: BTreeIndexMap::new(),
}
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn as_slice(&self) -> &[T] {
entries_as_slice(self.map.as_entries())
}
pub fn get_full<Q>(&self, value: &Q) -> Option<(usize, &T)>
where
Q: ?Sized + Comparable<T>,
{
self.map.get_full(value).map(|(i, t, ())| (i, t))
}
pub fn get_index_of<Q>(&self, value: &Q) -> Option<usize>
where
Q: ?Sized + Comparable<T>,
{
self.get_full(value).map(|(i, _)| i)
}
pub fn get<Q>(&self, value: &Q) -> Option<&T>
where
Q: ?Sized + Comparable<T>,
{
self.map.get_entry(value).map(|(t, ())| t)
}
pub fn contains<Q>(&self, value: &Q) -> bool
where
Q: ?Sized + Comparable<T>,
{
self.map.get(value).is_some()
}
pub fn insert_full(&mut self, value: T) -> (usize, bool)
where
T: Ord,
{
let (i, old) = self.map.insert_full(value, ());
(i, old.is_none())
}
pub fn insert(&mut self, value: T) -> bool
where
T: Ord,
{
self.insert_full(value).1
}
pub fn shift_remove_full<Q>(&mut self, value: &Q) -> Option<(usize, T)>
where
Q: ?Sized + Comparable<T>,
{
self.map.shift_remove_full(value).map(|(i, t, ())| (i, t))
}
pub fn shift_take<Q>(&mut self, value: &Q) -> Option<T>
where
Q: ?Sized + Comparable<T>,
{
self.shift_remove_full(value).map(|(_, t)| t)
}
pub fn shift_remove<Q>(&mut self, value: &Q) -> bool
where
Q: ?Sized + Comparable<T>,
{
self.map.shift_remove(value).is_some()
}
pub fn swap_remove_full<Q>(&mut self, value: &Q) -> Option<(usize, T)>
where
Q: ?Sized + Comparable<T>,
T: Ord,
{
self.map.swap_remove_full(value).map(|(i, t, ())| (i, t))
}
pub fn swap_take<Q>(&mut self, value: &Q) -> Option<T>
where
Q: ?Sized + Comparable<T>,
T: Ord,
{
self.swap_remove_full(value).map(|(_, t)| t)
}
pub fn swap_remove<Q>(&mut self, value: &Q) -> bool
where
Q: ?Sized + Comparable<T>,
T: Ord,
{
self.map.swap_remove(value).is_some()
}
pub fn iter(&self) -> Iter<'_, T> {
self.as_slice().iter()
}
pub fn iter_sorted(&self) -> IterSorted<'_, T> {
IterSorted(self.map.iter_sorted())
}
pub fn into_iter_sorted(self) -> IntoIterSorted<T> {
IntoIterSorted(self.map.into_iter_sorted())
}
}
impl<T> Index<usize> for BTreeIndexSet<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.as_slice()[index]
}
}
impl<T> IntoIterator for BTreeIndexSet<T> {
type IntoIter = IntoIter<T>;
type Item = T;
fn into_iter(self) -> Self::IntoIter {
IntoIter(self.map.into_iter())
}
}
impl<T: PartialEq> PartialEq for BTreeIndexSet<T> {
fn eq(&self, other: &Self) -> bool {
self.iter_sorted().eq(other.iter_sorted())
}
}
impl<T: Eq> Eq for BTreeIndexSet<T> {}
impl<T: PartialOrd> PartialOrd for BTreeIndexSet<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.iter_sorted().partial_cmp(other.iter_sorted())
}
}
impl<T: Ord> Ord for BTreeIndexSet<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.iter_sorted().cmp(other.iter_sorted())
}
}
impl<T: Hash> Hash for BTreeIndexSet<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_usize(self.len());
for item in self.iter_sorted() {
item.hash(state);
}
}
}
impl<T: fmt::Debug> fmt::Debug for BTreeIndexSet<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
}
impl<T: Ord> Extend<T> for BTreeIndexSet<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for value in iter {
self.insert(value);
}
}
}
impl<T: Ord> FromIterator<T> for BTreeIndexSet<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut result = Self::new();
result.extend(iter);
result
}
}
pub type Iter<'a, T> = std::slice::Iter<'a, T>;
impl<'a, T> IntoIterator for &'a BTreeIndexSet<T> {
type IntoIter = Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct IterSorted<'a, T>(map::IterSorted<'a, T, ()>);
impl<'a, T> Iterator for IterSorted<'a, T> {
type Item = &'a T;
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(t, ())| t)
}
}
impl<T> DoubleEndedIterator for IterSorted<'_, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(|(t, ())| t)
}
}
impl<T> ExactSizeIterator for IterSorted<'_, T> {}
impl<T> FusedIterator for IterSorted<'_, T> {}
pub struct IntoIterSorted<T>(map::IntoIterSorted<T, ()>);
impl<T> Iterator for IntoIterSorted<T> {
type Item = T;
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(t, ())| t)
}
}
impl<T> DoubleEndedIterator for IntoIterSorted<T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(|(t, ())| t)
}
}
impl<T> ExactSizeIterator for IntoIterSorted<T> {}
impl<T> FusedIterator for IntoIterSorted<T> {}
pub struct IntoIter<T>(std::vec::IntoIter<(T, ())>);
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(t, ())| t)
}
}
impl<T> DoubleEndedIterator for IntoIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(|(t, ())| t)
}
}
impl<T> ExactSizeIterator for IntoIter<T> {}
impl<T> FusedIterator for IntoIter<T> {}