1use std::sync::atomic::{AtomicU64, Ordering};
7use std::sync::Arc;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct ModSeq(pub u64);
15
16impl ModSeq {
17 pub const fn zero() -> Self {
19 Self(0)
20 }
21
22 pub const fn one() -> Self {
24 Self(1)
25 }
26
27 pub const fn new(value: u64) -> Self {
29 Self(value)
30 }
31
32 pub const fn value(&self) -> u64 {
34 self.0
35 }
36
37 pub const fn is_valid(&self) -> bool {
39 self.0 > 0
40 }
41
42 pub fn increment(&mut self) -> Self {
44 self.0 += 1;
45 *self
46 }
47}
48
49impl std::fmt::Display for ModSeq {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 write!(f, "{}", self.0)
52 }
53}
54
55impl From<u64> for ModSeq {
56 fn from(value: u64) -> Self {
57 Self(value)
58 }
59}
60
61impl From<ModSeq> for u64 {
62 fn from(modseq: ModSeq) -> u64 {
63 modseq.0
64 }
65}
66
67#[derive(Debug, Clone)]
72pub struct ModSeqGenerator {
73 counter: Arc<AtomicU64>,
74}
75
76impl ModSeqGenerator {
77 pub fn new() -> Self {
79 Self {
80 counter: Arc::new(AtomicU64::new(1)),
81 }
82 }
83
84 pub fn with_start_value(start: u64) -> Self {
86 Self {
87 counter: Arc::new(AtomicU64::new(start.max(1))),
88 }
89 }
90
91 pub fn next(&self) -> ModSeq {
93 let value = self.counter.fetch_add(1, Ordering::SeqCst);
94 ModSeq(value)
95 }
96
97 pub fn current(&self) -> ModSeq {
99 let value = self.counter.load(Ordering::SeqCst);
100 ModSeq(value.saturating_sub(1).max(1))
101 }
102
103 pub fn highest(&self) -> ModSeq {
105 self.current()
106 }
107}
108
109impl Default for ModSeqGenerator {
110 fn default() -> Self {
111 Self::new()
112 }
113}
114
115#[derive(Debug, Clone)]
117pub struct MessageModSeq {
118 pub uid: u32,
120 pub modseq: ModSeq,
122}
123
124impl MessageModSeq {
125 pub fn new(uid: u32, modseq: ModSeq) -> Self {
127 Self { uid, modseq }
128 }
129}
130
131#[derive(Debug, Clone)]
133pub struct MailboxModSeq {
134 pub name: String,
136 pub highestmodseq: ModSeq,
138 pub uidvalidity: u32,
140 pub uidnext: u32,
142}
143
144impl MailboxModSeq {
145 pub fn new(name: String, uidvalidity: u32, uidnext: u32) -> Self {
147 Self {
148 name,
149 highestmodseq: ModSeq::one(),
150 uidvalidity,
151 uidnext,
152 }
153 }
154
155 pub fn update_modseq(&mut self, modseq: ModSeq) {
157 if modseq > self.highestmodseq {
158 self.highestmodseq = modseq;
159 }
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166 use std::collections::HashSet;
167
168 #[test]
169 fn test_modseq_creation() {
170 let modseq = ModSeq::zero();
171 assert_eq!(modseq.value(), 0);
172 assert!(!modseq.is_valid());
173
174 let modseq = ModSeq::one();
175 assert_eq!(modseq.value(), 1);
176 assert!(modseq.is_valid());
177
178 let modseq = ModSeq::new(42);
179 assert_eq!(modseq.value(), 42);
180 assert!(modseq.is_valid());
181 }
182
183 #[test]
184 fn test_modseq_increment() {
185 let mut modseq = ModSeq::one();
186 assert_eq!(modseq.value(), 1);
187
188 let new_modseq = modseq.increment();
189 assert_eq!(new_modseq.value(), 2);
190 assert_eq!(modseq.value(), 2);
191 }
192
193 #[test]
194 fn test_modseq_increment_multiple() {
195 let mut modseq = ModSeq::zero();
196 for i in 1..=10 {
197 let result = modseq.increment();
198 assert_eq!(result.value(), i);
199 assert_eq!(modseq.value(), i);
200 }
201 }
202
203 #[test]
204 fn test_modseq_ordering() {
205 let modseq1 = ModSeq::new(10);
206 let modseq2 = ModSeq::new(20);
207
208 assert!(modseq1 < modseq2);
209 assert!(modseq2 > modseq1);
210 assert_eq!(modseq1, modseq1.clone());
211 }
212
213 #[test]
214 fn test_modseq_ordering_edge_cases() {
215 let zero = ModSeq::zero();
216 let one = ModSeq::one();
217 let max = ModSeq::new(u64::MAX);
218
219 assert!(zero < one);
220 assert!(one < max);
221 assert!(zero < max);
222 }
223
224 #[test]
225 fn test_modseq_equality() {
226 let m1 = ModSeq::new(100);
227 let m2 = ModSeq::new(100);
228 let m3 = ModSeq::new(200);
229
230 assert_eq!(m1, m2);
231 assert_ne!(m1, m3);
232 }
233
234 #[test]
235 fn test_modseq_hash() {
236 let mut set = HashSet::new();
237 set.insert(ModSeq::new(1));
238 set.insert(ModSeq::new(2));
239 set.insert(ModSeq::new(1)); assert_eq!(set.len(), 2);
242 assert!(set.contains(&ModSeq::new(1)));
243 assert!(set.contains(&ModSeq::new(2)));
244 }
245
246 #[test]
247 fn test_modseq_generator() {
248 let gen = ModSeqGenerator::new();
249
250 let modseq1 = gen.next();
251 assert_eq!(modseq1.value(), 1);
252
253 let modseq2 = gen.next();
254 assert_eq!(modseq2.value(), 2);
255
256 let modseq3 = gen.next();
257 assert_eq!(modseq3.value(), 3);
258 }
259
260 #[test]
261 fn test_modseq_generator_with_start() {
262 let gen = ModSeqGenerator::with_start_value(100);
263
264 let modseq1 = gen.next();
265 assert_eq!(modseq1.value(), 100);
266
267 let modseq2 = gen.next();
268 assert_eq!(modseq2.value(), 101);
269 }
270
271 #[test]
272 fn test_modseq_generator_with_zero_start() {
273 let gen = ModSeqGenerator::with_start_value(0);
275 let modseq = gen.next();
276 assert_eq!(modseq.value(), 1);
277 }
278
279 #[test]
280 fn test_modseq_generator_current() {
281 let gen = ModSeqGenerator::new();
282
283 let _m1 = gen.next();
284 let _m2 = gen.next();
285 let _m3 = gen.next();
286
287 let current = gen.current();
288 assert_eq!(current.value(), 3);
289
290 let highest = gen.highest();
291 assert_eq!(highest, current);
292 }
293
294 #[test]
295 fn test_modseq_generator_current_before_first_next() {
296 let gen = ModSeqGenerator::new();
297 let current = gen.current();
298 assert_eq!(current.value(), 1);
299 }
300
301 #[test]
302 fn test_modseq_generator_clone() {
303 let gen1 = ModSeqGenerator::new();
304 let _m1 = gen1.next();
305 let _m2 = gen1.next();
306
307 let gen2 = gen1.clone();
309 let m3 = gen2.next();
310 let m4 = gen1.next();
311
312 assert_eq!(m3.value(), 3);
313 assert_eq!(m4.value(), 4); }
315
316 #[test]
317 fn test_modseq_generator_thread_safety() {
318 use std::thread;
319
320 let gen = ModSeqGenerator::new();
321 let gen1 = gen.clone();
322 let gen2 = gen.clone();
323
324 let handle1 = thread::spawn(move || {
325 let mut values = Vec::new();
326 for _ in 0..10 {
327 values.push(gen1.next().value());
328 }
329 values
330 });
331
332 let handle2 = thread::spawn(move || {
333 let mut values = Vec::new();
334 for _ in 0..10 {
335 values.push(gen2.next().value());
336 }
337 values
338 });
339
340 let values1 = handle1.join().unwrap();
341 let values2 = handle2.join().unwrap();
342
343 let mut all_values: Vec<_> = values1.into_iter().chain(values2).collect();
345 all_values.sort_unstable();
346 all_values.dedup();
347 assert_eq!(all_values.len(), 20);
348 }
349
350 #[test]
351 fn test_message_modseq() {
352 let msg = MessageModSeq::new(42, ModSeq::new(100));
353 assert_eq!(msg.uid, 42);
354 assert_eq!(msg.modseq.value(), 100);
355 }
356
357 #[test]
358 fn test_message_modseq_clone() {
359 let msg1 = MessageModSeq::new(42, ModSeq::new(100));
360 let msg2 = msg1.clone();
361 assert_eq!(msg1.uid, msg2.uid);
362 assert_eq!(msg1.modseq, msg2.modseq);
363 }
364
365 #[test]
366 fn test_mailbox_modseq_new() {
367 let mbox = MailboxModSeq::new("INBOX".to_string(), 123, 456);
368 assert_eq!(mbox.name, "INBOX");
369 assert_eq!(mbox.highestmodseq, ModSeq::one());
370 assert_eq!(mbox.uidvalidity, 123);
371 assert_eq!(mbox.uidnext, 456);
372 }
373
374 #[test]
375 fn test_mailbox_modseq_update() {
376 let mut mbox = MailboxModSeq::new("INBOX".to_string(), 1, 1);
377 assert_eq!(mbox.highestmodseq.value(), 1);
378
379 mbox.update_modseq(ModSeq::new(10));
380 assert_eq!(mbox.highestmodseq.value(), 10);
381
382 mbox.update_modseq(ModSeq::new(5));
384 assert_eq!(mbox.highestmodseq.value(), 10);
385
386 mbox.update_modseq(ModSeq::new(15));
388 assert_eq!(mbox.highestmodseq.value(), 15);
389 }
390
391 #[test]
392 fn test_mailbox_modseq_update_same_value() {
393 let mut mbox = MailboxModSeq::new("INBOX".to_string(), 1, 1);
394 mbox.update_modseq(ModSeq::new(10));
395 assert_eq!(mbox.highestmodseq.value(), 10);
396
397 mbox.update_modseq(ModSeq::new(10));
399 assert_eq!(mbox.highestmodseq.value(), 10);
400 }
401
402 #[test]
403 fn test_mailbox_modseq_clone() {
404 let mbox1 = MailboxModSeq::new("INBOX".to_string(), 123, 456);
405 let mbox2 = mbox1.clone();
406 assert_eq!(mbox1.name, mbox2.name);
407 assert_eq!(mbox1.highestmodseq, mbox2.highestmodseq);
408 assert_eq!(mbox1.uidvalidity, mbox2.uidvalidity);
409 assert_eq!(mbox1.uidnext, mbox2.uidnext);
410 }
411
412 #[test]
413 fn test_modseq_from_u64() {
414 let modseq: ModSeq = 42u64.into();
415 assert_eq!(modseq.value(), 42);
416
417 let value: u64 = modseq.into();
418 assert_eq!(value, 42);
419 }
420
421 #[test]
422 fn test_modseq_from_u64_max() {
423 let modseq: ModSeq = u64::MAX.into();
424 assert_eq!(modseq.value(), u64::MAX);
425 }
426
427 #[test]
428 fn test_modseq_display() {
429 let modseq = ModSeq::new(12345);
430 assert_eq!(modseq.to_string(), "12345");
431 }
432
433 #[test]
434 fn test_modseq_display_zero() {
435 let modseq = ModSeq::zero();
436 assert_eq!(modseq.to_string(), "0");
437 }
438
439 #[test]
440 fn test_modseq_display_large() {
441 let modseq = ModSeq::new(u64::MAX);
442 assert_eq!(modseq.to_string(), u64::MAX.to_string());
443 }
444
445 #[test]
446 fn test_modseq_generator_default() {
447 let gen = ModSeqGenerator::default();
448 let modseq = gen.next();
449 assert_eq!(modseq.value(), 1);
450 }
451
452 #[test]
453 fn test_modseq_const_functions() {
454 const ZERO: ModSeq = ModSeq::zero();
455 const ONE: ModSeq = ModSeq::one();
456 const CUSTOM: ModSeq = ModSeq::new(42);
457
458 assert_eq!(ZERO.value(), 0);
459 assert_eq!(ONE.value(), 1);
460 assert_eq!(CUSTOM.value(), 42);
461 }
462}