• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

duesee / imap-codec / 16085468327

05 Jul 2025 06:35AM UTC coverage: 90.913% (-0.8%) from 91.715%
16085468327

push

github

duesee
chore: fix Clippy lints

39 of 44 new or added lines in 17 files covered. (88.64%)

31 existing lines in 7 files now uncovered.

10315 of 11346 relevant lines covered (90.91%)

932.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.53
/imap-types/src/sequence.rs
1
use std::{
2
    cmp::max,
3
    collections::VecDeque,
4
    fmt::Debug,
5
    iter::Rev,
6
    num::NonZeroU32,
7
    ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
8
    str::FromStr,
9
};
10

11
#[cfg(feature = "arbitrary")]
12
use arbitrary::Arbitrary;
13
use bounded_static_derive::ToStatic;
14
#[cfg(feature = "serde")]
15
use serde::{Deserialize, Serialize};
16

17
use crate::{
18
    core::Vec1,
19
    error::{ValidationError, ValidationErrorKind},
20
};
21

22
pub const ONE: NonZeroU32 = match NonZeroU32::new(1) {
23
    Some(one) => one,
24
    None => panic!(),
25
};
26
pub const MIN: NonZeroU32 = ONE;
27
pub const MAX: NonZeroU32 = match NonZeroU32::new(u32::MAX) {
28
    Some(max) => max,
29
    None => panic!(),
30
};
31

32
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
296✔
33
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
×
34
#[derive(Debug, Clone, PartialEq, Eq, Hash, ToStatic)]
35
pub struct SequenceSet(pub Vec1<Sequence>);
36

37
impl From<Sequence> for SequenceSet {
38
    fn from(sequence: Sequence) -> Self {
1,063✔
39
        Self(Vec1::from(sequence))
1,063✔
40
    }
1,063✔
41
}
42

43
macro_rules! impl_from_t_for_sequence_set {
44
    ($thing:ty) => {
45
        impl From<$thing> for SequenceSet {
46
            fn from(value: $thing) -> Self {
208✔
47
                Self::from(Sequence::from(value))
208✔
48
            }
208✔
49
        }
50
    };
51
}
52

53
macro_rules! impl_try_from_t_for_sequence_set {
54
    ($thing:ty) => {
55
        impl TryFrom<$thing> for SequenceSet {
56
            type Error = ValidationError;
57

58
            fn try_from(value: $thing) -> Result<Self, Self::Error> {
26✔
59
                Ok(Self::from(Sequence::try_from(value)?))
26✔
60
            }
26✔
61
        }
62
    };
63
}
64

65
impl_from_t_for_sequence_set!(SeqOrUid);
66
impl_from_t_for_sequence_set!(NonZeroU32);
67
impl_from_t_for_sequence_set!(RangeFull);
68
impl_from_t_for_sequence_set!(RangeFrom<NonZeroU32>);
69
impl_try_from_t_for_sequence_set!(RangeTo<NonZeroU32>);
70
impl_from_t_for_sequence_set!(RangeToInclusive<NonZeroU32>);
71
impl_try_from_t_for_sequence_set!(Range<NonZeroU32>);
72
impl_from_t_for_sequence_set!(RangeInclusive<NonZeroU32>);
73

74
// `SequenceSet::try_from` implementations.
75

76
impl TryFrom<Vec<Sequence>> for SequenceSet {
77
    type Error = ValidationError;
78

79
    fn try_from(sequences: Vec<Sequence>) -> Result<Self, Self::Error> {
×
80
        Ok(Self(Vec1::try_from(sequences).map_err(|_| {
×
81
            ValidationError::new(ValidationErrorKind::Empty)
×
82
        })?))
×
83
    }
×
84
}
85

86
impl TryFrom<Vec<NonZeroU32>> for SequenceSet {
87
    type Error = ValidationError;
88

89
    fn try_from(sequences: Vec<NonZeroU32>) -> Result<Self, Self::Error> {
×
90
        Ok(Self(
91
            Vec1::try_from(
×
92
                sequences
×
93
                    .into_iter()
×
94
                    .map(Sequence::from)
×
95
                    .collect::<Vec<_>>(),
×
96
            )
97
            .map_err(|_| ValidationError::new(ValidationErrorKind::Empty))?,
×
98
        ))
99
    }
×
100
}
101

102
impl TryFrom<&str> for SequenceSet {
103
    type Error = ValidationError;
104

105
    fn try_from(value: &str) -> Result<Self, Self::Error> {
200✔
106
        value.parse()
200✔
107
    }
200✔
108
}
109

110
impl FromStr for SequenceSet {
111
    type Err = ValidationError;
112

113
    fn from_str(value: &str) -> Result<Self, Self::Err> {
200✔
114
        let mut results = vec![];
200✔
115

116
        for seq in value.split(',') {
262✔
117
            results.push(Sequence::try_from(seq)?);
262✔
118
        }
119

120
        Ok(SequenceSet(Vec1::try_from(results).map_err(|_| {
166✔
121
            ValidationError::new(ValidationErrorKind::Empty)
×
UNCOV
122
        })?))
×
123
    }
200✔
124
}
125

126
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2✔
127
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
×
128
#[derive(Debug, Clone, PartialEq, Eq, Hash, ToStatic)]
129
pub enum Sequence {
130
    Single(SeqOrUid),
131
    Range(SeqOrUid, SeqOrUid),
132
}
133

134
impl From<SeqOrUid> for Sequence {
135
    fn from(value: SeqOrUid) -> Self {
556✔
136
        Self::Single(value)
556✔
137
    }
556✔
138
}
139

140
impl From<NonZeroU32> for Sequence {
141
    fn from(value: NonZeroU32) -> Self {
52✔
142
        Self::Single(SeqOrUid::from(value))
52✔
143
    }
52✔
144
}
145

146
impl TryFrom<&str> for Sequence {
147
    type Error = ValidationError;
148

149
    fn try_from(value: &str) -> Result<Self, Self::Error> {
262✔
150
        value.parse()
262✔
151
    }
262✔
152
}
153

154
impl FromStr for Sequence {
155
    type Err = ValidationError;
156

157
    fn from_str(value: &str) -> Result<Self, Self::Err> {
262✔
158
        match value.split(':').count() {
262✔
159
            0 => Err(ValidationError::new(ValidationErrorKind::Empty)),
×
160
            1 => Ok(Sequence::Single(SeqOrUid::try_from(value)?)),
172✔
161
            2 => {
162
                let mut split = value.split(':');
88✔
163

164
                let start = split.next().unwrap();
88✔
165
                let end = split.next().unwrap();
88✔
166

167
                Ok(Sequence::Range(
168
                    SeqOrUid::try_from(start)?,
88✔
169
                    SeqOrUid::try_from(end)?,
84✔
170
                ))
171
            }
172
            _ => Err(ValidationError::new(ValidationErrorKind::Invalid)),
2✔
173
        }
174
    }
262✔
175
}
176

177
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
4✔
178
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
×
179
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, ToStatic)]
180
pub enum SeqOrUid {
181
    Value(NonZeroU32),
182
    Asterisk,
183
}
184

185
impl From<NonZeroU32> for SeqOrUid {
186
    fn from(value: NonZeroU32) -> Self {
864✔
187
        Self::Value(value)
864✔
188
    }
864✔
189
}
190

191
macro_rules! impl_try_from_num {
192
    ($num:ty) => {
193
        impl TryFrom<&[$num]> for SequenceSet {
194
            type Error = ValidationError;
195

196
            fn try_from(values: &[$num]) -> Result<Self, Self::Error> {
×
197
                let mut checked = Vec::new();
×
198

199
                for value in values {
×
200
                    checked.push(Sequence::try_from(*value)?);
×
201
                }
202

203
                Self::try_from(checked)
×
204
            }
×
205
        }
206

207
        impl TryFrom<$num> for SequenceSet {
208
            type Error = ValidationError;
209

210
            fn try_from(value: $num) -> Result<Self, Self::Error> {
454✔
211
                Ok(Self::from(Sequence::try_from(value)?))
454✔
212
            }
454✔
213
        }
214

215
        impl TryFrom<$num> for Sequence {
216
            type Error = ValidationError;
217

218
            fn try_from(value: $num) -> Result<Self, Self::Error> {
870✔
219
                Ok(Self::from(SeqOrUid::try_from(value)?))
870✔
220
            }
870✔
221
        }
222

223
        impl TryFrom<$num> for SeqOrUid {
224
            type Error = ValidationError;
225

226
            fn try_from(value: $num) -> Result<Self, Self::Error> {
3,967✔
227
                // TODO(590)
228
                #[allow(irrefutable_let_patterns)]
229
                if let Ok(value) = u32::try_from(value) {
3,967✔
230
                    if let Ok(value) = NonZeroU32::try_from(value) {
3,733✔
231
                        return Ok(Self::Value(value));
2,561✔
232
                    }
1,172✔
233
                }
234✔
234

235
                Err(ValidationError::new(ValidationErrorKind::Invalid))
1,406✔
236
            }
3,967✔
237
        }
238
    };
239
}
240

241
impl_try_from_num!(i8);
242
impl_try_from_num!(i16);
243
impl_try_from_num!(i32);
244
impl_try_from_num!(i64);
245
impl_try_from_num!(isize);
246
impl_try_from_num!(u8);
247
impl_try_from_num!(u16);
248
impl_try_from_num!(u32);
249
impl_try_from_num!(u64);
250
impl_try_from_num!(usize);
251

252
impl TryFrom<&str> for SeqOrUid {
253
    type Error = ValidationError;
254

255
    fn try_from(value: &str) -> Result<Self, Self::Error> {
344✔
256
        value.parse()
344✔
257
    }
344✔
258
}
259

260
impl FromStr for SeqOrUid {
261
    type Err = ValidationError;
262

263
    fn from_str(value: &str) -> Result<Self, Self::Err> {
344✔
264
        if value == "*" {
344✔
265
            Ok(SeqOrUid::Asterisk)
74✔
266
        } else {
267
            // This is to align parsing here with the IMAP grammar:
268
            // Rust's `parse::<NonZeroU32>` function accepts numbers that start with 0.
269
            // For example, 00001, is interpreted as 1. But this is not allowed in IMAP.
270
            if value.starts_with('0') {
270✔
271
                Err(ValidationError::new(ValidationErrorKind::Invalid))
4✔
272
            } else {
273
                Ok(SeqOrUid::Value(NonZeroU32::from_str(value).map_err(
266✔
274
                    |_| ValidationError::new(ValidationErrorKind::Invalid),
28✔
275
                )?))
28✔
276
            }
277
        }
278
    }
344✔
279
}
280

281
// -------------------------------------------------------------------------------------------------
282

283
macro_rules! impl_try_from_num_range {
284
    ($num:ty) => {
285
        impl TryFrom<RangeFrom<$num>> for SequenceSet {
286
            type Error = ValidationError;
287

288
            fn try_from(range: RangeFrom<$num>) -> Result<Self, Self::Error> {
260✔
289
                Ok(Self::from(Sequence::try_from(range)?))
260✔
290
            }
260✔
291
        }
292

293
        impl TryFrom<RangeTo<$num>> for SequenceSet {
294
            type Error = ValidationError;
295

296
            fn try_from(range: RangeTo<$num>) -> Result<Self, Self::Error> {
156✔
297
                Ok(Self::from(Sequence::try_from(range)?))
156✔
298
            }
156✔
299
        }
300

301
        impl TryFrom<RangeToInclusive<$num>> for SequenceSet {
302
            type Error = ValidationError;
303

304
            fn try_from(range: RangeToInclusive<$num>) -> Result<Self, Self::Error> {
×
305
                Ok(Self::from(Sequence::try_from(range)?))
×
306
            }
×
307
        }
308

309
        impl TryFrom<Range<$num>> for SequenceSet {
310
            type Error = ValidationError;
311

312
            fn try_from(range: Range<$num>) -> Result<Self, Self::Error> {
572✔
313
                Ok(Self::from(Sequence::try_from(range)?))
572✔
314
            }
572✔
315
        }
316

317
        impl TryFrom<RangeInclusive<$num>> for SequenceSet {
318
            type Error = ValidationError;
319

320
            fn try_from(range: RangeInclusive<$num>) -> Result<Self, Self::Error> {
×
321
                Ok(Self::from(Sequence::try_from(range)?))
×
322
            }
×
323
        }
324

325
        // -----------------------------------------------------------------------------------------
326

327
        impl TryFrom<RangeFrom<$num>> for Sequence {
328
            type Error = ValidationError;
329

330
            fn try_from(range: RangeFrom<$num>) -> Result<Self, Self::Error> {
537✔
331
                Ok(Self::Range(
332
                    SeqOrUid::try_from(range.start)?,
537✔
333
                    SeqOrUid::Asterisk,
277✔
334
                ))
335
            }
537✔
336
        }
337

338
        impl TryFrom<RangeTo<$num>> for Sequence {
339
            type Error = ValidationError;
340

341
            fn try_from(range: RangeTo<$num>) -> Result<Self, Self::Error> {
314✔
342
                Ok(Self::Range(
343
                    SeqOrUid::from(ONE),
314✔
344
                    SeqOrUid::try_from(range.end.saturating_sub(1))?,
314✔
345
                ))
346
            }
314✔
347
        }
348

349
        impl TryFrom<RangeToInclusive<$num>> for Sequence {
350
            type Error = ValidationError;
351

352
            fn try_from(range: RangeToInclusive<$num>) -> Result<Self, Self::Error> {
2✔
353
                Ok(Self::Range(
354
                    SeqOrUid::from(ONE),
2✔
355
                    SeqOrUid::try_from(range.end)?,
2✔
356
                ))
357
            }
2✔
358
        }
359

360
        impl TryFrom<Range<$num>> for Sequence {
361
            type Error = ValidationError;
362

363
            fn try_from(range: Range<$num>) -> Result<Self, Self::Error> {
1,146✔
364
                Ok(Self::Range(
365
                    SeqOrUid::try_from(range.start)?,
1,146✔
366
                    SeqOrUid::try_from(range.end.saturating_sub(1))?,
626✔
367
                ))
368
            }
1,146✔
369
        }
370

371
        impl TryFrom<RangeInclusive<$num>> for Sequence {
372
            type Error = ValidationError;
373

374
            fn try_from(range: RangeInclusive<$num>) -> Result<Self, Self::Error> {
2✔
375
                Ok(Self::Range(
376
                    SeqOrUid::try_from(*range.start())?,
2✔
377
                    SeqOrUid::try_from(*range.end())?,
2✔
378
                ))
379
            }
2✔
380
        }
381
    };
382
}
383

384
impl_try_from_num_range!(i8);
385
impl_try_from_num_range!(i16);
386
impl_try_from_num_range!(i32);
387
impl_try_from_num_range!(i64);
388
impl_try_from_num_range!(isize);
389
impl_try_from_num_range!(u8);
390
impl_try_from_num_range!(u16);
391
impl_try_from_num_range!(u32);
392
impl_try_from_num_range!(u64);
393
impl_try_from_num_range!(usize);
394

395
impl From<RangeFull> for Sequence {
396
    fn from(_: RangeFull) -> Self {
288✔
397
        Self::from(MIN..)
288✔
398
    }
288✔
399
}
400

401
impl From<RangeFrom<NonZeroU32>> for Sequence {
402
    fn from(range: RangeFrom<NonZeroU32>) -> Self {
314✔
403
        Self::Range(SeqOrUid::from(range.start), SeqOrUid::Asterisk)
314✔
404
    }
314✔
405
}
406

407
impl TryFrom<RangeTo<NonZeroU32>> for Sequence {
408
    type Error = ValidationError;
409

410
    fn try_from(range: RangeTo<NonZeroU32>) -> Result<Self, Self::Error> {
26✔
411
        Self::try_from(MIN..range.end)
26✔
412
    }
26✔
413
}
414

415
impl From<RangeToInclusive<NonZeroU32>> for Sequence {
416
    fn from(range: RangeToInclusive<NonZeroU32>) -> Self {
×
417
        Self::from(MIN..=range.end)
×
418
    }
×
419
}
420

421
impl TryFrom<Range<NonZeroU32>> for Sequence {
422
    type Error = ValidationError;
423

424
    fn try_from(range: Range<NonZeroU32>) -> Result<Self, Self::Error> {
52✔
425
        Ok(Self::Range(
426
            SeqOrUid::from(MIN),
52✔
427
            SeqOrUid::try_from(range.end.get().saturating_sub(1))?,
52✔
428
        ))
429
    }
52✔
430
}
431

432
impl From<RangeInclusive<NonZeroU32>> for Sequence {
433
    fn from(range: RangeInclusive<NonZeroU32>) -> Self {
52✔
434
        Self::Range(SeqOrUid::from(*range.start()), SeqOrUid::from(*range.end()))
52✔
435
    }
52✔
436
}
437

438
// -------------------------------------------------------------------------------------------------
439

440
impl<'a> SequenceSet {
441
    /// Iterate over a sorted, deduplicated set of sequence numbers or UIDs.
442
    ///
443
    /// # Example
444
    ///
445
    /// ```
446
    /// use std::num::NonZeroU32;
447
    ///
448
    /// use imap_types::sequence::SequenceSet;
449
    ///
450
    /// let seq = SequenceSet::try_from("1:5,10:3,10,10,10,1").unwrap();
451
    /// let largest = NonZeroU32::new(10).unwrap();
452
    ///
453
    /// assert_eq!(
454
    ///     seq.iter(largest).collect::<Vec<_>>(),
455
    ///     [1u32, 2, 3, 4, 5, 6, 7, 8, 9, 10]
456
    ///         .into_iter()
457
    ///         .map(|e| NonZeroU32::new(e).unwrap())
458
    ///         .collect::<Vec<_>>()
459
    /// );
460
    /// ```
461
    pub fn iter(&'a self, largest: NonZeroU32) -> impl Iterator<Item = NonZeroU32> + 'a {
22✔
462
        let ranges = simplify(self.clone(), largest, true);
22✔
463
        let ranges = cleanup(ranges);
22✔
464

465
        SequenceSetIter {
22✔
466
            ranges,
22✔
467
            active_range: None,
22✔
468
        }
22✔
469
    }
22✔
470

471
    /// Iterate over the given set of sequence numbers or UIDs.
472
    ///
473
    /// Note: This method expands the sequence set keeping duplicates and ordering.
474
    ///
475
    /// # Example
476
    ///
477
    /// ```
478
    /// use std::num::NonZeroU32;
479
    ///
480
    /// use imap_types::sequence::SequenceSet;
481
    ///
482
    /// let seq = SequenceSet::try_from("1:3,1:3,3:1,1").unwrap();
483
    /// let largest = NonZeroU32::new(10).unwrap();
484
    ///
485
    /// assert_eq!(
486
    ///     seq.iter_naive(largest).collect::<Vec<_>>(),
487
    ///     [1u32, 2, 3, 1, 2, 3, 3, 2, 1, 1]
488
    ///         .into_iter()
489
    ///         .map(|e| NonZeroU32::new(e).unwrap())
490
    ///         .collect::<Vec<_>>()
491
    /// );
492
    /// ```
493
    pub fn iter_naive(&'a self, largest: NonZeroU32) -> impl Iterator<Item = NonZeroU32> + 'a {
34✔
494
        let ranges = simplify(self.clone(), largest, false);
34✔
495

496
        SequenceSetIter {
34✔
497
            ranges,
34✔
498
            active_range: None,
34✔
499
        }
34✔
500
    }
34✔
501
}
502

503
impl SeqOrUid {
504
    pub fn expand(&self, largest: NonZeroU32) -> NonZeroU32 {
284✔
505
        match self {
284✔
506
            SeqOrUid::Value(value) => *value,
224✔
507
            SeqOrUid::Asterisk => largest,
60✔
508
        }
509
    }
284✔
510
}
511

512
// -------------------------------------------------------------------------------------------------
513

514
struct SequenceSetIter {
515
    ranges: VecDeque<(u32, u32)>,
516
    active_range: Option<Sorting>,
517
}
518

519
impl Iterator for SequenceSetIter {
520
    type Item = NonZeroU32;
521

522
    fn next(&mut self) -> Option<Self::Item> {
722✔
523
        loop {
524
            match self.active_range {
926✔
525
                Some(ref mut range) => match range.next() {
768✔
526
                    // We know here that `next >= 1`.
527
                    Some(next) => break Some(NonZeroU32::new(next).unwrap()),
666✔
528
                    None => self.active_range = None,
102✔
529
                },
530
                None => match self.ranges.pop_front() {
158✔
531
                    Some((a, b)) => {
102✔
532
                        if a <= b {
102✔
533
                            self.active_range = Some(Sorting::Ascending(a..=b));
90✔
534
                        } else {
90✔
535
                            self.active_range = Some(Sorting::Descending((b..=a).rev()));
12✔
536
                        }
12✔
537
                    }
538
                    None => break None,
56✔
539
                },
540
            }
541
        }
542
    }
722✔
543
}
544

545
enum Sorting {
546
    Ascending(RangeInclusive<u32>),
547
    Descending(Rev<RangeInclusive<u32>>),
548
}
549

550
impl Iterator for Sorting {
551
    type Item = u32;
552

553
    fn next(&mut self) -> Option<Self::Item> {
768✔
554
        match self {
768✔
555
            Sorting::Ascending(iter) => iter.next(),
710✔
556
            Sorting::Descending(iter) => iter.next(),
58✔
557
        }
558
    }
768✔
559
}
560

561
// Simplify sequence set into VecDeque<(u32, u32)>:
562
// * Use u32 instead of NonZeroU32 (for internal purposes)
563
// * Expand Single(a) to (a, a)
564
// * Sort Range(a, b) so that a <= b
565
fn simplify(sequence_set: SequenceSet, largest: NonZeroU32, sort: bool) -> VecDeque<(u32, u32)> {
56✔
566
    sequence_set
56✔
567
        .0
56✔
568
         .0
56✔
569
        .into_iter()
56✔
570
        .map(|seq| match seq {
170✔
571
            Sequence::Single(a) => (u32::from(a.expand(largest)), u32::from(a.expand(largest))),
70✔
572
            Sequence::Range(a, b) => {
72✔
573
                let a = u32::from(a.expand(largest));
72✔
574
                let b = u32::from(b.expand(largest));
72✔
575

576
                if sort {
72✔
577
                    if a <= b {
30✔
578
                        (a, b)
20✔
579
                    } else {
580
                        (b, a)
10✔
581
                    }
582
                } else {
583
                    (a, b)
42✔
584
                }
585
            }
586
        })
142✔
587
        .collect()
56✔
588
}
56✔
589

590
fn cleanup(remaining: VecDeque<(u32, u32)>) -> VecDeque<(u32, u32)> {
22✔
591
    let mut remaining = {
22✔
592
        let mut tmp = Vec::from(remaining);
22✔
593
        tmp.sort();
22✔
594
        VecDeque::from(tmp)
22✔
595
    };
596

597
    let mut stack = VecDeque::new();
22✔
598
    stack.push_back(remaining.pop_front().unwrap());
22✔
599

600
    for (x, y) in remaining.into_iter() {
40✔
601
        let last = stack.back_mut().unwrap();
40✔
602

603
        if last.0 <= x && x <= last.1.saturating_add(1) {
40✔
604
            last.1 = max(last.1, y);
40✔
605
        } else {
40✔
606
            stack.push_back((x, y));
×
607
        }
×
608
    }
609

610
    stack
22✔
611
}
22✔
612

613
#[cfg(test)]
614
mod tests {
615
    use std::num::NonZeroU32;
616

617
    use super::*;
618
    use crate::core::Vec1;
619

620
    #[test]
621
    fn test_creation_of_sequence_from_u32() {
2✔
622
        assert_eq!(
2✔
623
            SequenceSet::try_from(1),
2✔
624
            Ok(SequenceSet(Vec1::from(Sequence::Single(SeqOrUid::Value(
2✔
625
                NonZeroU32::new(1).unwrap()
2✔
626
            )))))
2✔
627
        );
628
        assert_eq!(
2✔
629
            SequenceSet::try_from(0),
2✔
630
            Err(ValidationError::new(ValidationErrorKind::Invalid))
2✔
631
        );
632
    }
2✔
633

634
    #[test]
635
    fn test_creation_of_sequence_from_range() {
2✔
636
        // 1:*
637
        let range = ..;
2✔
638
        let seq = Sequence::from(range);
2✔
639
        assert_eq!(
2✔
640
            seq,
641
            Sequence::Range(
2✔
642
                SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
2✔
643
                SeqOrUid::Asterisk
2✔
644
            )
2✔
645
        );
646

647
        // 1:*
648
        let range = 1..;
2✔
649
        let seq = Sequence::try_from(range).unwrap();
2✔
650
        assert_eq!(
2✔
651
            seq,
652
            Sequence::Range(
2✔
653
                SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
2✔
654
                SeqOrUid::Asterisk
2✔
655
            )
2✔
656
        );
657

658
        // 1337:*
659
        let range = 1337..;
2✔
660
        let seq = Sequence::try_from(range).unwrap();
2✔
661
        assert_eq!(
2✔
662
            seq,
663
            Sequence::Range(
2✔
664
                SeqOrUid::Value(NonZeroU32::new(1337).unwrap()),
2✔
665
                SeqOrUid::Asterisk
2✔
666
            )
2✔
667
        );
668

669
        // 1:1336
670
        let range = 1..1337;
2✔
671
        let seq = Sequence::try_from(range).unwrap();
2✔
672
        assert_eq!(
2✔
673
            seq,
674
            Sequence::Range(
2✔
675
                SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
2✔
676
                SeqOrUid::Value(NonZeroU32::new(1336).unwrap())
2✔
677
            )
2✔
678
        );
679

680
        // 1:1337
681
        let range = 1..=1337;
2✔
682
        let seq = Sequence::try_from(range).unwrap();
2✔
683
        assert_eq!(
2✔
684
            seq,
685
            Sequence::Range(
2✔
686
                SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
2✔
687
                SeqOrUid::Value(NonZeroU32::new(1337).unwrap())
2✔
688
            )
2✔
689
        );
690

691
        // 1:1336
692
        let range = ..1337;
2✔
693
        let seq = Sequence::try_from(range).unwrap();
2✔
694
        assert_eq!(
2✔
695
            seq,
696
            Sequence::Range(
2✔
697
                SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
2✔
698
                SeqOrUid::Value(NonZeroU32::new(1336).unwrap())
2✔
699
            )
2✔
700
        );
701

702
        // 1:1337
703
        let range = ..=1337;
2✔
704
        let seq = Sequence::try_from(range).unwrap();
2✔
705
        assert_eq!(
2✔
706
            seq,
707
            Sequence::Range(
2✔
708
                SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
2✔
709
                SeqOrUid::Value(NonZeroU32::new(1337).unwrap())
2✔
710
            )
2✔
711
        );
712
    }
2✔
713

714
    #[test]
715
    fn test_creation_of_sequence_set_from_str_positive() {
2✔
716
        let tests = &[
2✔
717
            (
2✔
718
                "1",
2✔
719
                SequenceSet(
2✔
720
                    vec![Sequence::Single(SeqOrUid::Value(1.try_into().unwrap()))]
2✔
721
                        .try_into()
2✔
722
                        .unwrap(),
2✔
723
                ),
2✔
724
            ),
2✔
725
            (
2✔
726
                "1,2,3",
2✔
727
                SequenceSet(
2✔
728
                    vec![
2✔
729
                        Sequence::Single(SeqOrUid::Value(1.try_into().unwrap())),
2✔
730
                        Sequence::Single(SeqOrUid::Value(2.try_into().unwrap())),
2✔
731
                        Sequence::Single(SeqOrUid::Value(3.try_into().unwrap())),
2✔
732
                    ]
2✔
733
                    .try_into()
2✔
734
                    .unwrap(),
2✔
735
                ),
2✔
736
            ),
2✔
737
            (
2✔
738
                "*",
2✔
739
                SequenceSet(
2✔
740
                    vec![Sequence::Single(SeqOrUid::Asterisk)]
2✔
741
                        .try_into()
2✔
742
                        .unwrap(),
2✔
743
                ),
2✔
744
            ),
2✔
745
            (
2✔
746
                "1:2",
2✔
747
                SequenceSet(
2✔
748
                    vec![Sequence::Range(
2✔
749
                        SeqOrUid::Value(1.try_into().unwrap()),
2✔
750
                        SeqOrUid::Value(2.try_into().unwrap()),
2✔
751
                    )]
2✔
752
                    .try_into()
2✔
753
                    .unwrap(),
2✔
754
                ),
2✔
755
            ),
2✔
756
            (
2✔
757
                "1:2,3",
2✔
758
                SequenceSet(
2✔
759
                    vec![
2✔
760
                        Sequence::Range(
2✔
761
                            SeqOrUid::Value(1.try_into().unwrap()),
2✔
762
                            SeqOrUid::Value(2.try_into().unwrap()),
2✔
763
                        ),
2✔
764
                        Sequence::Single(SeqOrUid::Value(3.try_into().unwrap())),
2✔
765
                    ]
2✔
766
                    .try_into()
2✔
767
                    .unwrap(),
2✔
768
                ),
2✔
769
            ),
2✔
770
            (
2✔
771
                "1:2,3,*",
2✔
772
                SequenceSet(
2✔
773
                    vec![
2✔
774
                        Sequence::Range(
2✔
775
                            SeqOrUid::Value(1.try_into().unwrap()),
2✔
776
                            SeqOrUid::Value(2.try_into().unwrap()),
2✔
777
                        ),
2✔
778
                        Sequence::Single(SeqOrUid::Value(3.try_into().unwrap())),
2✔
779
                        Sequence::Single(SeqOrUid::Asterisk),
2✔
780
                    ]
2✔
781
                    .try_into()
2✔
782
                    .unwrap(),
2✔
783
                ),
2✔
784
            ),
2✔
785
        ];
2✔
786

787
        for (test, expected) in tests.iter() {
12✔
788
            let got = SequenceSet::try_from(*test).unwrap();
12✔
789
            assert_eq!(*expected, got);
12✔
790
        }
791
    }
2✔
792

793
    #[test]
794
    fn test_creation_of_sequence_set_from_str_negative() {
2✔
795
        let tests = &[
2✔
796
            "", "* ", " *", " * ", "1 ", " 1", " 1 ", "01", " 01", "01 ", " 01 ", "*1", ":", ":*",
2✔
797
            "*:", "*: ", "1:2:3",
2✔
798
        ];
2✔
799

800
        for test in tests {
36✔
801
            let got = SequenceSet::try_from(*test);
34✔
802
            print!("\"{}\" | {:?} | ", test, got.clone().unwrap_err());
34✔
803
            println!("{}", got.unwrap_err());
34✔
804
        }
34✔
805
    }
2✔
806

807
    #[test]
808
    fn test_iteration_over_some_sequence_sets() {
2✔
809
        let tests = vec![
2✔
810
            ("*", vec![3]),
2✔
811
            ("1:*", vec![1, 2, 3]),
2✔
812
            ("5,1:*,2:*", vec![5, 1, 2, 3, 2, 3]),
2✔
813
            ("*:2", vec![3, 2]),
2✔
814
            ("*:*", vec![3]),
2✔
815
            ("4:6,*", vec![4, 5, 6, 3]),
2✔
816
        ]
817
        .into_iter()
2✔
818
        .map(|(raw, vec)| {
13✔
819
            (
820
                raw,
12✔
821
                vec.into_iter()
12✔
822
                    .map(|num| num.try_into().unwrap())
34✔
823
                    .collect::<Vec<NonZeroU32>>(),
12✔
824
            )
825
        })
12✔
826
        .collect::<Vec<(&str, Vec<NonZeroU32>)>>();
2✔
827

828
        for (test, expected) in tests {
14✔
829
            let seq_set = SequenceSet::try_from(test).unwrap();
12✔
830
            let got: Vec<NonZeroU32> = seq_set.iter_naive(3.try_into().unwrap()).collect();
12✔
831
            assert_eq!(*expected, got);
12✔
832
        }
833
    }
2✔
834

835
    /// See https://github.com/duesee/imap-codec/issues/411
836
    #[test]
837
    fn test_issue_411() {
2✔
838
        let seq = SequenceSet::try_from("22,21,22,*:20").unwrap();
2✔
839
        let largest = NonZeroU32::new(23).unwrap();
2✔
840

841
        // Naive
842
        {
843
            let expected = [22, 21, 22, 23, 22, 21, 20]
2✔
844
                .map(|n| NonZeroU32::new(n).unwrap())
15✔
845
                .to_vec();
2✔
846
            let got: Vec<_> = seq.iter_naive(largest).collect();
2✔
847

848
            assert_eq!(expected, got);
2✔
849
        }
850

851
        // Clean
852
        {
853
            let expected = [20, 21, 22, 23]
2✔
854
                .map(|n| NonZeroU32::new(n).unwrap())
9✔
855
                .to_vec();
2✔
856
            let got: Vec<_> = seq.iter(largest).collect();
2✔
857

858
            assert_eq!(expected, got);
2✔
859
        }
860
    }
2✔
861

862
    #[test]
863
    fn test_clean() {
2✔
864
        let tests = vec![
2✔
865
            "1",
866
            "2",
2✔
867
            "*",
2✔
868
            "1:*",
2✔
869
            "2:*",
2✔
870
            "*:*",
2✔
871
            "3,2,1",
2✔
872
            "3,2,2,2,1,1,1",
2✔
873
            "3:1,5:1,1:2,1:1",
2✔
874
            "4:5,5:1,1:2,1:1,*:*,*:10,1:100",
2✔
875
        ];
876

877
        for test in tests {
22✔
878
            let seq = SequenceSet::try_from(test).unwrap();
20✔
879
            let largest = NonZeroU32::new(13).unwrap();
20✔
880

881
            let naive = {
20✔
882
                let mut naive: Vec<_> = seq.iter_naive(largest).collect();
20✔
883
                naive.sort();
20✔
884
                naive.dedup();
20✔
885
                naive
20✔
886
            };
887
            let clean: Vec<_> = seq.iter(largest).collect();
20✔
888

889
            assert_eq!(naive, clean);
20✔
890
        }
891
    }
2✔
892
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc