use crate::CrdtMerge;
use fxhash::FxHashSet;
use serde::{Deserialize, Serialize};
use std::hash::Hash;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct GSet<T: Hash + Eq + Clone> {
elements: FxHashSet<T>,
}
impl<T: Hash + Eq + Clone> Default for GSet<T> {
fn default() -> Self {
Self {
elements: FxHashSet::default(),
}
}
}
impl<T: Hash + Eq + Clone> GSet<T> {
pub fn new() -> Self {
Self::default()
}
pub fn add(&mut self, element: T) {
self.elements.insert(element);
}
pub fn contains(&self, element: &T) -> bool {
self.elements.contains(element)
}
pub fn elements(&self) -> impl Iterator<Item = &T> {
self.elements.iter()
}
pub fn len(&self) -> usize {
self.elements.len()
}
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
}
impl<T: Hash + Eq + Clone> CrdtMerge for GSet<T> {
fn merge(&mut self, other: &Self) {
for element in &other.elements {
self.elements.insert(element.clone());
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
let mut gs = GSet::new();
gs.add("apple".to_string());
gs.add("banana".to_string());
assert!(gs.contains(&"apple".to_string()));
assert!(gs.contains(&"banana".to_string()));
assert!(!gs.contains(&"cherry".to_string()));
assert_eq!(gs.len(), 2);
}
#[test]
fn test_merge() {
let mut a = GSet::new();
a.add(1);
a.add(2);
let mut b = GSet::new();
b.add(2);
b.add(3);
a.merge(&b);
assert!(a.contains(&1));
assert!(a.contains(&2));
assert!(a.contains(&3));
assert_eq!(a.len(), 3);
}
}