1use crate::CrdtMerge;
5use fxhash::FxHashSet;
6use serde::{Deserialize, Serialize};
7use std::hash::Hash;
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
14pub struct GSet<T: Hash + Eq + Clone> {
15 elements: FxHashSet<T>,
16}
17
18impl<T: Hash + Eq + Clone> Default for GSet<T> {
19 fn default() -> Self {
20 Self {
21 elements: FxHashSet::default(),
22 }
23 }
24}
25
26impl<T: Hash + Eq + Clone> GSet<T> {
27 pub fn new() -> Self {
29 Self::default()
30 }
31
32 pub fn add(&mut self, element: T) {
34 self.elements.insert(element);
35 }
36
37 pub fn contains(&self, element: &T) -> bool {
39 self.elements.contains(element)
40 }
41
42 pub fn elements(&self) -> impl Iterator<Item = &T> {
44 self.elements.iter()
45 }
46
47 pub fn len(&self) -> usize {
49 self.elements.len()
50 }
51
52 pub fn is_empty(&self) -> bool {
54 self.elements.is_empty()
55 }
56}
57
58impl<T: Hash + Eq + Clone> CrdtMerge for GSet<T> {
59 fn merge(&mut self, other: &Self) {
60 for element in &other.elements {
61 self.elements.insert(element.clone());
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_add() {
72 let mut gs = GSet::new();
73 gs.add("apple".to_string());
74 gs.add("banana".to_string());
75 assert!(gs.contains(&"apple".to_string()));
76 assert!(gs.contains(&"banana".to_string()));
77 assert!(!gs.contains(&"cherry".to_string()));
78 assert_eq!(gs.len(), 2);
79 }
80
81 #[test]
82 fn test_merge() {
83 let mut a = GSet::new();
84 a.add(1);
85 a.add(2);
86
87 let mut b = GSet::new();
88 b.add(2);
89 b.add(3);
90
91 a.merge(&b);
92
93 assert!(a.contains(&1));
94 assert!(a.contains(&2));
95 assert!(a.contains(&3));
96 assert_eq!(a.len(), 3);
97 }
98}