use crate::errors::NonEmptyError;
use std::collections::hash_set::{IntoIter, Iter};
use std::collections::HashSet;
use std::hash::Hash;
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct NESet<T: Eq + Hash>(HashSet<T>);
impl<T: Eq + Hash> NESet<T> {
pub fn new(head: T, tail: Vec<T>) -> Self {
let mut set = HashSet::with_capacity(1 + tail.len());
set.insert(head);
set.extend(tail);
Self(set)
}
pub fn singleton(value: T) -> Self {
let mut set = HashSet::new();
set.insert(value);
Self(set)
}
pub fn from(set: HashSet<T>) -> Result<Self, NonEmptyError> {
match set.is_empty() {
true => Err(NonEmptyError::Empty),
false => Ok(Self(set)),
}
}
#[doc(hidden)]
pub fn __from_set_unsafe(set: HashSet<T>) -> Self {
debug_assert!(!set.is_empty());
Self(set)
}
pub fn into_set(self) -> HashSet<T> {
self.0
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
false
}
pub fn insert(&mut self, value: T) -> bool {
self.0.insert(value)
}
pub fn remove(&mut self, value: &T) -> bool {
self.0.remove(value)
}
pub fn contains(&self, value: &T) -> bool {
self.0.contains(value)
}
}
impl<T: Eq + Hash> From<NESet<T>> for HashSet<T> {
fn from(value: NESet<T>) -> Self {
value.into_set()
}
}
impl<T: Eq + Hash> TryFrom<HashSet<T>> for NESet<T> {
type Error = NonEmptyError;
fn try_from(set: HashSet<T>) -> Result<Self, Self::Error> {
NESet::from(set)
}
}
impl<T: Eq + Hash> From<T> for NESet<T> {
fn from(value: T) -> Self {
Self::singleton(value)
}
}
impl<'a, T: Eq + Hash> IntoIterator for &'a NESet<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<T: Eq + Hash> IntoIterator for NESet<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}