1use std::collections::HashSet;
7use std::hash::Hash;
8use crate::MapletResult;
9
10pub trait MergeOperator<V>: Clone + Send + Sync {
12 fn merge(&self, left: V, right: V) -> MapletResult<V>;
18
19 fn identity(&self) -> V;
21
22 fn is_associative(&self) -> bool {
24 true }
26
27 fn is_commutative(&self) -> bool {
29 true }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
35pub struct CounterOperator;
36
37impl MergeOperator<u64> for CounterOperator {
38 fn merge(&self, left: u64, right: u64) -> MapletResult<u64> {
39 Ok(left.saturating_add(right))
40 }
41
42 fn identity(&self) -> u64 {
43 0
44 }
45}
46
47impl MergeOperator<u32> for CounterOperator {
48 fn merge(&self, left: u32, right: u32) -> MapletResult<u32> {
49 Ok(left.saturating_add(right))
50 }
51
52 fn identity(&self) -> u32 {
53 0
54 }
55}
56
57impl MergeOperator<i64> for CounterOperator {
58 fn merge(&self, left: i64, right: i64) -> MapletResult<i64> {
59 Ok(left.saturating_add(right))
60 }
61
62 fn identity(&self) -> i64 {
63 0
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
69pub struct SetOperator;
70
71impl<T: Clone + Hash + Eq> MergeOperator<HashSet<T>> for SetOperator {
72 fn merge(&self, mut left: HashSet<T>, right: HashSet<T>) -> MapletResult<HashSet<T>> {
73 left.extend(right);
74 Ok(left)
75 }
76
77 fn identity(&self) -> HashSet<T> {
78 HashSet::new()
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
84pub struct StringOperator;
85
86impl MergeOperator<String> for StringOperator {
87 fn merge(&self, _left: String, right: String) -> MapletResult<String> {
88 Ok(right)
90 }
91
92 fn identity(&self) -> String {
93 String::new()
94 }
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
99pub struct MaxOperator;
100
101impl MergeOperator<u64> for MaxOperator {
102 fn merge(&self, left: u64, right: u64) -> MapletResult<u64> {
103 Ok(left.max(right))
104 }
105
106 fn identity(&self) -> u64 {
107 0
108 }
109}
110
111impl MergeOperator<f64> for MaxOperator {
112 fn merge(&self, left: f64, right: f64) -> MapletResult<f64> {
113 Ok(left.max(right))
114 }
115
116 fn identity(&self) -> f64 {
117 f64::NEG_INFINITY
118 }
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
123pub struct MinOperator;
124
125impl MergeOperator<u64> for MinOperator {
126 fn merge(&self, left: u64, right: u64) -> MapletResult<u64> {
127 Ok(left.min(right))
128 }
129
130 fn identity(&self) -> u64 {
131 u64::MAX
132 }
133}
134
135impl MergeOperator<f64> for MinOperator {
136 fn merge(&self, left: f64, right: f64) -> MapletResult<f64> {
137 Ok(left.min(right))
138 }
139
140 fn identity(&self) -> f64 {
141 f64::INFINITY
142 }
143}
144
145#[derive(Clone)]
147pub struct CustomOperator<F> {
148 #[allow(dead_code)]
149 merge_fn: F,
150}
151
152impl<F> CustomOperator<F> {
153 pub const fn new(merge_fn: F) -> Self {
155 Self {
156 merge_fn,
157 }
158 }
159}
160
161#[derive(Debug, Clone, Copy, PartialEq, Eq)]
163pub struct StringConcatOperator;
164
165impl MergeOperator<String> for StringConcatOperator {
166 fn merge(&self, left: String, right: String) -> MapletResult<String> {
167 Ok(format!("{left}{right}"))
168 }
169
170 fn identity(&self) -> String {
171 String::new()
172 }
173}
174
175#[derive(Debug, Clone, Copy, PartialEq, Eq)]
177pub struct VectorConcatOperator;
178
179impl<T: Clone> MergeOperator<Vec<T>> for VectorConcatOperator {
180 fn merge(&self, mut left: Vec<T>, right: Vec<T>) -> MapletResult<Vec<T>> {
181 left.extend(right);
182 Ok(left)
183 }
184
185 fn identity(&self) -> Vec<T> {
186 Vec::new()
187 }
188}
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192pub struct BoolOrOperator;
193
194impl MergeOperator<bool> for BoolOrOperator {
195 fn merge(&self, left: bool, right: bool) -> MapletResult<bool> {
196 Ok(left || right)
197 }
198
199 fn identity(&self) -> bool {
200 false
201 }
202}
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq)]
206pub struct BoolAndOperator;
207
208impl MergeOperator<bool> for BoolAndOperator {
209 fn merge(&self, left: bool, right: bool) -> MapletResult<bool> {
210 Ok(left && right)
211 }
212
213 fn identity(&self) -> bool {
214 true
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221 use std::collections::HashSet;
222
223 #[test]
224 fn test_counter_operator() {
225 let op: CounterOperator = CounterOperator;
226
227 assert_eq!(op.merge(5u64, 3u64).unwrap(), 8);
228 assert_eq!(op.merge(0u64, 10u64).unwrap(), 10);
229
230 assert_eq!(op.merge(u64::MAX, 1).unwrap(), u64::MAX);
232 }
233
234 #[test]
235 fn test_set_operator() {
236 let op = SetOperator;
237
238 let mut set1 = HashSet::new();
239 set1.insert("a".to_string());
240 set1.insert("b".to_string());
241
242 let mut set2 = HashSet::new();
243 set2.insert("b".to_string());
244 set2.insert("c".to_string());
245
246 let result = op.merge(set1, set2).unwrap();
247 assert_eq!(result.len(), 3);
248 assert!(result.contains("a"));
249 assert!(result.contains("b"));
250 assert!(result.contains("c"));
251 }
252
253 #[test]
254 fn test_max_operator() {
255 let op: MaxOperator = MaxOperator;
256
257 assert_eq!(op.merge(5u64, 3u64).unwrap(), 5);
258 assert_eq!(op.merge(3u64, 5u64).unwrap(), 5);
259 assert_eq!(op.merge(5.0, 3.0).unwrap(), 5.0);
260 }
261
262 #[test]
263 fn test_min_operator() {
264 let op: MinOperator = MinOperator;
265
266 assert_eq!(op.merge(5u64, 3u64).unwrap(), 3);
267 assert_eq!(op.merge(3u64, 5u64).unwrap(), 3);
268 assert_eq!(op.merge(5.0, 3.0).unwrap(), 3.0);
269 }
270
271 #[test]
272 fn test_string_concat_operator() {
273 let op = StringConcatOperator;
274
275 assert_eq!(op.merge("hello".to_string(), "world".to_string()).unwrap(), "helloworld");
276 assert_eq!(op.identity(), "");
277 }
278
279 #[test]
280 fn test_vector_concat_operator() {
281 let op = VectorConcatOperator;
282
283 let vec1 = vec![1, 2, 3];
284 let vec2 = vec![4, 5, 6];
285 let result = op.merge(vec1, vec2).unwrap();
286 assert_eq!(result, vec![1, 2, 3, 4, 5, 6]);
287 }
288
289 #[test]
290 fn test_bool_operators() {
291 let or_op = BoolOrOperator;
292 let and_op = BoolAndOperator;
293
294 assert_eq!(or_op.merge(false, true).unwrap(), true);
295 assert_eq!(or_op.merge(false, false).unwrap(), false);
296 assert_eq!(or_op.identity(), false);
297
298 assert_eq!(and_op.merge(true, false).unwrap(), false);
299 assert_eq!(and_op.merge(true, true).unwrap(), true);
300 assert_eq!(and_op.identity(), true);
301 }
302}