use std::{
collections::HashMap,
fmt::Display,
hash::Hash,
};
use itertools::Itertools;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Variety<T> {
pub (super) elements: Vec<T>,
}
impl<T> Variety<T> {
pub fn new(roots: Vec<T>) -> Self {
Self {
elements: roots,
}
}
pub fn num_roots(&self) -> usize {
self.elements.len()
}
pub fn roots(&self) -> impl Iterator<Item=&T> {
self.elements.iter()
}
pub fn into_roots(self) -> impl Iterator<Item=T> {
self.elements.into_iter()
}
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
pub fn empty() -> Self {
Self {
elements: vec![],
}
}
}
impl<T> PartialEq for Variety<T>
where T: Eq + Hash {
fn eq(&self, other: &Self) -> bool {
let (mut hashmap0, mut hashmap1) = (HashMap::new(), HashMap::new());
for root in self.roots() {
*hashmap0.entry(root).or_insert(0) += 1;
}
for root in other.roots() {
*hashmap1.entry(root).or_insert(0) += 1;
}
hashmap0 == hashmap1
}
}
impl<T> Eq for Variety<T>
where T: Eq + Hash { }
impl<T> Extend<T> for Variety<T> {
fn extend<U: IntoIterator<Item = T>>(&mut self, iter: U) {
self.elements.extend(iter);
}
}
impl<T> Display for Variety<T>
where T: Display {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_empty() {
write!(f, "variety(empty)")
} else {
write!(f, "variety({})", self.elements.iter().map(ToString::to_string).join(", "))
}
}
}