use crate::PetitMap;
use crate::{map::SuccesfulMapInsertion, CapacityError};
#[derive(Debug, Clone, Hash)]
pub struct PetitSet<T, const CAP: usize> {
pub(crate) map: PetitMap<T, (), CAP>,
}
impl<T, const CAP: usize> Default for PetitSet<T, CAP> {
fn default() -> Self {
Self::new()
}
}
impl<T, const CAP: usize> PetitSet<T, CAP> {
pub fn new() -> Self {
Self {
map: PetitMap::new(),
}
}
pub fn next_filled_index(&self, cursor: usize) -> Option<usize> {
self.map.next_filled_index(cursor)
}
pub fn next_empty_index(&self, cursor: usize) -> Option<usize> {
self.map.next_empty_index(cursor)
}
pub const fn capacity(&self) -> usize {
CAP
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn is_full(&self) -> bool {
self.map.is_full()
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.map.iter().map(|(k, _v)| k)
}
pub fn get_at(&self, index: usize) -> Option<&T> {
self.map.get_at(index).map(|(k, _v)| k)
}
pub fn get_at_mut(&mut self, index: usize) -> Option<&mut T> {
self.map.get_at_mut(index).map(|(k, _v)| k)
}
pub fn clear(&mut self) {
self.map.clear()
}
pub fn remove_at(&mut self, index: usize) -> bool {
self.take_at(index).is_some()
}
#[must_use = "Use remove_at if the value is not needed."]
pub fn take_at(&mut self, index: usize) -> Option<T> {
self.map.take_at(index).map(|(k, _v)| k)
}
pub fn swap_at(&mut self, index_a: usize, index_b: usize) {
self.map.swap_at(index_a, index_b);
}
pub fn insert_unchecked(&mut self, element: T) -> Option<usize> {
self.map.insert_unchecked(element, ())
}
}
impl<T: Eq, const CAP: usize> Extend<T> for PetitSet<T, CAP> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for element in iter {
self.insert(element);
}
}
}
impl<T: Eq, const CAP: usize> PetitSet<T, CAP> {
pub fn find(&self, element: &T) -> Option<usize> {
self.map.find(element)
}
#[must_use]
pub fn contains(&self, element: &T) -> bool {
self.find(element).is_some()
}
pub fn try_insert(&mut self, element: T) -> Result<SuccesfulSetInsertion, CapacityError<T>> {
match self.map.try_insert(element, ()) {
Ok(sucess) => match sucess {
SuccesfulMapInsertion::NovelKey(index) => {
Ok(SuccesfulSetInsertion::NovelElenent(index))
}
SuccesfulMapInsertion::ExtantKey(_val, index) => {
Ok(SuccesfulSetInsertion::ExtantElement(index))
}
},
Err(CapacityError((key, _value))) => Err(CapacityError(key)),
}
}
pub fn insert(&mut self, element: T) -> SuccesfulSetInsertion {
self.try_insert(element)
.expect("Inserting this element would have overflowed the set!")
}
pub fn insert_at(&mut self, element: T, index: usize) -> Option<T> {
self.map.insert_at(element, (), index).map(|(k, _v)| k)
}
pub fn try_extend(
&mut self,
elements: impl IntoIterator<Item = T>,
) -> Result<(), CapacityError<T>> {
for element in elements {
self.try_insert(element)?;
}
Ok(())
}
pub fn remove(&mut self, element: &T) -> Option<usize> {
self.map.remove(element)
}
#[must_use = "Use remove if the value is not needed."]
pub fn take(&mut self, element: &T) -> Option<(usize, T)> {
self.map.take(element).map(|(i, v)| (i, v.0))
}
pub fn swap(&mut self, element_a: &T, element_b: &T) -> bool {
self.map.swap(element_a, element_b)
}
pub fn identical(&self, other: Self) -> bool {
self.map.identical(other.map)
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
self.map.retain(|e, ()| f(e));
}
pub fn try_from_iter<I: IntoIterator<Item = T>>(
element_iter: I,
) -> Result<Self, CapacityError<(Self, T)>> {
let iter_for_map = element_iter.into_iter().map(|e| (e, ()));
match PetitMap::try_from_iter(iter_for_map) {
Ok(map) => Ok(PetitSet { map }),
Err(CapacityError((map, failed_value))) => {
Err(CapacityError((PetitSet { map }, failed_value.0)))
}
}
}
pub fn from_raw_array_unchecked(values: [Option<T>; CAP]) -> Self {
let values_for_map = values.map(|v| v.map(|v| (v, ())));
Self {
map: PetitMap::from_raw_array_unchecked(values_for_map),
}
}
}
impl<T: Eq, const CAP: usize> FromIterator<T> for PetitSet<T, CAP> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
PetitSet::try_from_iter(iter).unwrap()
}
}
impl<T: Eq, const CAP: usize> IntoIterator for PetitSet<T, CAP> {
type Item = T;
type IntoIter = PetitSetIter<T, CAP>;
fn into_iter(self) -> Self::IntoIter {
PetitSetIter {
set: self,
cursor: 0,
}
}
}
#[derive(Clone, Debug)]
pub struct PetitSetIter<T: Eq, const CAP: usize> {
pub(crate) set: PetitSet<T, CAP>,
cursor: usize,
}
impl<T: Eq, const CAP: usize> PetitSetIter<T, CAP> {
#[must_use]
pub fn into_set(self) -> PetitSet<T, CAP> {
self.set
}
}
impl<T: Eq, const CAP: usize> Iterator for PetitSetIter<T, CAP> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if let Some(index) = self.set.next_filled_index(self.cursor) {
self.cursor = index + 1;
let result = self.set.take_at(index);
debug_assert!(result.is_some());
result
} else {
self.cursor = CAP;
None
}
}
}
impl<T: Eq, const CAP: usize, const OTHER_CAP: usize> PartialEq<PetitSet<T, OTHER_CAP>>
for PetitSet<T, CAP>
{
fn eq(&self, other: &PetitSet<T, OTHER_CAP>) -> bool {
if self.len() != other.len() {
return false;
}
for item in self.iter() {
let mut match_found = false;
for other_item in other.iter() {
if item == other_item {
match_found = true;
break;
}
}
if !match_found {
return false;
}
}
true
}
}
impl<T: Eq, const CAP: usize> Eq for PetitSet<T, CAP> {}
impl<T: Eq, const CAP: usize> Default for PetitSetIter<T, CAP> {
fn default() -> Self {
Self {
set: PetitSet::default(),
cursor: 0,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SuccesfulSetInsertion {
NovelElenent(usize),
ExtantElement(usize),
}