use serde::{Deserialize, Serialize};
use std::collections::HashSet;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct GSet<T: Eq + std::hash::Hash + Clone> {
pub elements: HashSet<T>,
}
impl<T: Eq + std::hash::Hash + Clone> GSet<T> {
#[must_use]
pub fn new() -> Self {
Self {
elements: HashSet::new(),
}
}
pub fn insert(&mut self, element: T) {
self.elements.insert(element);
}
pub fn merge(&mut self, other: Self) {
for element in other.elements {
self.elements.insert(element);
}
}
pub fn contains(&self, element: &T) -> bool {
self.elements.contains(element)
}
#[must_use]
pub fn len(&self) -> usize {
self.elements.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gset_insert() {
let mut set = GSet::new();
set.insert("hash1".to_string());
set.insert("hash2".to_string());
assert_eq!(set.len(), 2);
assert!(set.contains(&"hash1".to_string()));
assert!(set.contains(&"hash2".to_string()));
}
#[test]
fn test_gset_idempotent_insert() {
let mut set = GSet::new();
set.insert("hash1".to_string());
set.insert("hash1".to_string());
assert_eq!(set.len(), 1);
}
#[test]
fn test_gset_merge() {
let mut a = GSet::new();
a.insert("hash1".to_string());
let mut b = GSet::new();
b.insert("hash2".to_string());
a.merge(b);
assert_eq!(a.len(), 2);
assert!(a.contains(&"hash1".to_string()));
assert!(a.contains(&"hash2".to_string()));
}
#[test]
fn test_gset_semilattice_commutative() {
let mut a = GSet::new();
a.insert("hash1".to_string());
let mut b = GSet::new();
b.insert("hash2".to_string());
let mut a_merge_b = a.clone();
a_merge_b.merge(b.clone());
let mut b_merge_a = b.clone();
b_merge_a.merge(a.clone());
assert_eq!(a_merge_b, b_merge_a);
}
#[test]
fn test_gset_semilattice_associative() {
let mut a = GSet::new();
a.insert("hash1".to_string());
let mut b = GSet::new();
b.insert("hash2".to_string());
let mut c = GSet::new();
c.insert("hash3".to_string());
let mut left = a.clone();
left.merge(b.clone());
left.merge(c.clone());
let mut right_inner = b.clone();
right_inner.merge(c.clone());
let mut right = a.clone();
right.merge(right_inner);
assert_eq!(left, right);
}
#[test]
fn test_gset_semilattice_idempotent() {
let mut a = GSet::new();
a.insert("hash1".to_string());
let mut a_merge_a = a.clone();
a_merge_a.merge(a.clone());
assert_eq!(a, a_merge_a);
}
}