1use std::{
2 num::NonZeroU32,
3 ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
4 str::FromStr,
5};
6
7#[cfg(feature = "arbitrary")]
8use arbitrary::Arbitrary;
9#[cfg(feature = "bounded-static")]
10use bounded_static::ToStatic;
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14use crate::{
15 core::NonEmptyVec,
16 error::{ValidationError, ValidationErrorKind},
17};
18
19pub const ONE: NonZeroU32 = match NonZeroU32::new(1) {
20 Some(one) => one,
21 None => panic!(),
22};
23pub const MIN: NonZeroU32 = ONE;
24pub const MAX: NonZeroU32 = match NonZeroU32::new(u32::MAX) {
25 Some(max) => max,
26 None => panic!(),
27};
28
29#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
30#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32#[derive(Debug, Clone, PartialEq, Eq, Hash)]
33pub struct SequenceSet(pub NonEmptyVec<Sequence>);
34
35impl From<Sequence> for SequenceSet {
36 fn from(sequence: Sequence) -> Self {
37 Self(NonEmptyVec::from(sequence))
38 }
39}
40
41macro_rules! impl_from_t_for_sequence_set {
42 ($thing:ty) => {
43 impl From<$thing> for SequenceSet {
44 fn from(value: $thing) -> Self {
45 Self::from(Sequence::from(value))
46 }
47 }
48 };
49}
50
51macro_rules! impl_try_from_t_for_sequence_set {
52 ($thing:ty) => {
53 impl TryFrom<$thing> for SequenceSet {
54 type Error = ValidationError;
55
56 fn try_from(value: $thing) -> Result<Self, Self::Error> {
57 Ok(Self::from(Sequence::try_from(value)?))
58 }
59 }
60 };
61}
62
63impl_from_t_for_sequence_set!(SeqOrUid);
64impl_from_t_for_sequence_set!(NonZeroU32);
65impl_from_t_for_sequence_set!(RangeFull);
66impl_from_t_for_sequence_set!(RangeFrom<NonZeroU32>);
67impl_try_from_t_for_sequence_set!(RangeTo<NonZeroU32>);
68impl_from_t_for_sequence_set!(RangeToInclusive<NonZeroU32>);
69impl_try_from_t_for_sequence_set!(Range<NonZeroU32>);
70impl_from_t_for_sequence_set!(RangeInclusive<NonZeroU32>);
71
72impl TryFrom<Vec<Sequence>> for SequenceSet {
75 type Error = ValidationError;
76
77 fn try_from(sequences: Vec<Sequence>) -> Result<Self, Self::Error> {
78 Ok(Self(NonEmptyVec::try_from(sequences).map_err(|_| {
79 ValidationError::new(ValidationErrorKind::Empty)
80 })?))
81 }
82}
83
84impl TryFrom<Vec<NonZeroU32>> for SequenceSet {
85 type Error = ValidationError;
86
87 fn try_from(sequences: Vec<NonZeroU32>) -> Result<Self, Self::Error> {
88 Ok(Self(
89 NonEmptyVec::try_from(
90 sequences
91 .into_iter()
92 .map(Sequence::from)
93 .collect::<Vec<_>>(),
94 )
95 .map_err(|_| ValidationError::new(ValidationErrorKind::Empty))?,
96 ))
97 }
98}
99
100impl TryFrom<&str> for SequenceSet {
101 type Error = ValidationError;
102
103 fn try_from(value: &str) -> Result<Self, Self::Error> {
104 value.parse()
105 }
106}
107
108impl FromStr for SequenceSet {
109 type Err = ValidationError;
110
111 fn from_str(value: &str) -> Result<Self, Self::Err> {
112 let mut results = vec![];
113
114 for seq in value.split(',') {
115 results.push(Sequence::try_from(seq)?);
116 }
117
118 Ok(SequenceSet(NonEmptyVec::try_from(results).map_err(
119 |_| ValidationError::new(ValidationErrorKind::Empty),
120 )?))
121 }
122}
123
124#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
125#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
126#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
127#[derive(Debug, Clone, PartialEq, Eq, Hash)]
128pub enum Sequence {
129 Single(SeqOrUid),
130 Range(SeqOrUid, SeqOrUid),
131}
132
133impl From<SeqOrUid> for Sequence {
134 fn from(value: SeqOrUid) -> Self {
135 Self::Single(value)
136 }
137}
138
139impl From<NonZeroU32> for Sequence {
140 fn from(value: NonZeroU32) -> Self {
141 Self::Single(SeqOrUid::from(value))
142 }
143}
144
145impl TryFrom<&str> for Sequence {
146 type Error = ValidationError;
147
148 fn try_from(value: &str) -> Result<Self, Self::Error> {
149 value.parse()
150 }
151}
152
153impl FromStr for Sequence {
154 type Err = ValidationError;
155
156 fn from_str(value: &str) -> Result<Self, Self::Err> {
157 match value.split(':').count() {
158 0 => Err(ValidationError::new(ValidationErrorKind::Empty)),
159 1 => Ok(Sequence::Single(SeqOrUid::try_from(value)?)),
160 2 => {
161 let mut split = value.split(':');
162
163 let start = split.next().unwrap();
164 let end = split.next().unwrap();
165
166 Ok(Sequence::Range(
167 SeqOrUid::try_from(start)?,
168 SeqOrUid::try_from(end)?,
169 ))
170 }
171 _ => Err(ValidationError::new(ValidationErrorKind::Invalid)),
172 }
173 }
174}
175
176#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
177#[cfg_attr(feature = "bounded-static", derive(ToStatic))]
178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
179#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
180pub enum SeqOrUid {
181 Value(NonZeroU32),
182 Asterisk,
183}
184
185impl From<NonZeroU32> for SeqOrUid {
186 fn from(value: NonZeroU32) -> Self {
187 Self::Value(value)
188 }
189}
190
191macro_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> {
211 Ok(Self::from(Sequence::try_from(value)?))
212 }
213 }
214
215 impl TryFrom<$num> for Sequence {
216 type Error = ValidationError;
217
218 fn try_from(value: $num) -> Result<Self, Self::Error> {
219 Ok(Self::from(SeqOrUid::try_from(value)?))
220 }
221 }
222
223 impl TryFrom<$num> for SeqOrUid {
224 type Error = ValidationError;
225
226 fn try_from(value: $num) -> Result<Self, Self::Error> {
227 if let Ok(value) = u32::try_from(value) {
228 if let Ok(value) = NonZeroU32::try_from(value) {
229 return Ok(Self::Value(value));
230 }
231 }
232
233 Err(ValidationError::new(ValidationErrorKind::Invalid))
234 }
235 }
236 };
237}
238
239impl_try_from_num!(i8);
240impl_try_from_num!(i16);
241impl_try_from_num!(i32);
242impl_try_from_num!(i64);
243impl_try_from_num!(isize);
244impl_try_from_num!(u8);
245impl_try_from_num!(u16);
246impl_try_from_num!(u32);
247impl_try_from_num!(u64);
248impl_try_from_num!(usize);
249
250impl TryFrom<&str> for SeqOrUid {
251 type Error = ValidationError;
252
253 fn try_from(value: &str) -> Result<Self, Self::Error> {
254 value.parse()
255 }
256}
257
258impl FromStr for SeqOrUid {
259 type Err = ValidationError;
260
261 fn from_str(value: &str) -> Result<Self, Self::Err> {
262 if value == "*" {
263 Ok(SeqOrUid::Asterisk)
264 } else {
265 if value.starts_with('0') {
269 Err(ValidationError::new(ValidationErrorKind::Invalid))
270 } else {
271 Ok(SeqOrUid::Value(NonZeroU32::from_str(value).map_err(
272 |_| ValidationError::new(ValidationErrorKind::Invalid),
273 )?))
274 }
275 }
276 }
277}
278
279macro_rules! impl_try_from_num_range {
282 ($num:ty) => {
283 impl TryFrom<RangeFrom<$num>> for SequenceSet {
284 type Error = ValidationError;
285
286 fn try_from(range: RangeFrom<$num>) -> Result<Self, Self::Error> {
287 Ok(Self::from(Sequence::try_from(range)?))
288 }
289 }
290
291 impl TryFrom<RangeTo<$num>> for SequenceSet {
292 type Error = ValidationError;
293
294 fn try_from(range: RangeTo<$num>) -> Result<Self, Self::Error> {
295 Ok(Self::from(Sequence::try_from(range)?))
296 }
297 }
298
299 impl TryFrom<RangeToInclusive<$num>> for SequenceSet {
300 type Error = ValidationError;
301
302 fn try_from(range: RangeToInclusive<$num>) -> Result<Self, Self::Error> {
303 Ok(Self::from(Sequence::try_from(range)?))
304 }
305 }
306
307 impl TryFrom<Range<$num>> for SequenceSet {
308 type Error = ValidationError;
309
310 fn try_from(range: Range<$num>) -> Result<Self, Self::Error> {
311 Ok(Self::from(Sequence::try_from(range)?))
312 }
313 }
314
315 impl TryFrom<RangeInclusive<$num>> for SequenceSet {
316 type Error = ValidationError;
317
318 fn try_from(range: RangeInclusive<$num>) -> Result<Self, Self::Error> {
319 Ok(Self::from(Sequence::try_from(range)?))
320 }
321 }
322
323 impl TryFrom<RangeFrom<$num>> for Sequence {
326 type Error = ValidationError;
327
328 fn try_from(range: RangeFrom<$num>) -> Result<Self, Self::Error> {
329 Ok(Self::Range(
330 SeqOrUid::try_from(range.start)?,
331 SeqOrUid::Asterisk,
332 ))
333 }
334 }
335
336 impl TryFrom<RangeTo<$num>> for Sequence {
337 type Error = ValidationError;
338
339 fn try_from(range: RangeTo<$num>) -> Result<Self, Self::Error> {
340 Ok(Self::Range(
341 SeqOrUid::from(ONE),
342 SeqOrUid::try_from(range.end.saturating_sub(1))?,
343 ))
344 }
345 }
346
347 impl TryFrom<RangeToInclusive<$num>> for Sequence {
348 type Error = ValidationError;
349
350 fn try_from(range: RangeToInclusive<$num>) -> Result<Self, Self::Error> {
351 Ok(Self::Range(
352 SeqOrUid::from(ONE),
353 SeqOrUid::try_from(range.end)?,
354 ))
355 }
356 }
357
358 impl TryFrom<Range<$num>> for Sequence {
359 type Error = ValidationError;
360
361 fn try_from(range: Range<$num>) -> Result<Self, Self::Error> {
362 Ok(Self::Range(
363 SeqOrUid::try_from(range.start)?,
364 SeqOrUid::try_from(range.end.saturating_sub(1))?,
365 ))
366 }
367 }
368
369 impl TryFrom<RangeInclusive<$num>> for Sequence {
370 type Error = ValidationError;
371
372 fn try_from(range: RangeInclusive<$num>) -> Result<Self, Self::Error> {
373 Ok(Self::Range(
374 SeqOrUid::try_from(*range.start())?,
375 SeqOrUid::try_from(*range.end())?,
376 ))
377 }
378 }
379 };
380}
381
382impl_try_from_num_range!(i8);
383impl_try_from_num_range!(i16);
384impl_try_from_num_range!(i32);
385impl_try_from_num_range!(i64);
386impl_try_from_num_range!(isize);
387impl_try_from_num_range!(u8);
388impl_try_from_num_range!(u16);
389impl_try_from_num_range!(u32);
390impl_try_from_num_range!(u64);
391impl_try_from_num_range!(usize);
392
393impl From<RangeFull> for Sequence {
394 fn from(_: RangeFull) -> Self {
395 Self::from(MIN..)
396 }
397}
398
399impl From<RangeFrom<NonZeroU32>> for Sequence {
400 fn from(range: RangeFrom<NonZeroU32>) -> Self {
401 Self::Range(SeqOrUid::from(range.start), SeqOrUid::Asterisk)
402 }
403}
404
405impl TryFrom<RangeTo<NonZeroU32>> for Sequence {
406 type Error = ValidationError;
407
408 fn try_from(range: RangeTo<NonZeroU32>) -> Result<Self, Self::Error> {
409 Self::try_from(MIN..range.end)
410 }
411}
412
413impl From<RangeToInclusive<NonZeroU32>> for Sequence {
414 fn from(range: RangeToInclusive<NonZeroU32>) -> Self {
415 Self::from(MIN..=range.end)
416 }
417}
418
419impl TryFrom<Range<NonZeroU32>> for Sequence {
420 type Error = ValidationError;
421
422 fn try_from(range: Range<NonZeroU32>) -> Result<Self, Self::Error> {
423 Ok(Self::Range(
424 SeqOrUid::from(MIN),
425 SeqOrUid::try_from(range.end.get().saturating_sub(1))?,
426 ))
427 }
428}
429
430impl From<RangeInclusive<NonZeroU32>> for Sequence {
431 fn from(range: RangeInclusive<NonZeroU32>) -> Self {
432 Self::Range(SeqOrUid::from(*range.start()), SeqOrUid::from(*range.end()))
433 }
434}
435
436impl<'a> SequenceSet {
439 pub fn iter(&'a self, strategy: Strategy) -> impl Iterator<Item = NonZeroU32> + 'a {
440 match strategy {
441 Strategy::Naive { largest } => SequenceSetIterNaive {
442 iter: self.0.as_ref().iter(),
443 active_range: None,
444 largest,
445 },
446 }
447 }
448}
449
450impl SeqOrUid {
451 pub fn expand(&self, largest: NonZeroU32) -> NonZeroU32 {
452 match self {
453 SeqOrUid::Value(value) => *value,
454 SeqOrUid::Asterisk => largest,
455 }
456 }
457}
458
459#[derive(Debug)]
462#[non_exhaustive]
463pub enum Strategy {
464 Naive { largest: NonZeroU32 },
465}
466
467#[derive(Debug)]
468pub struct SequenceSetIterNaive<'a> {
469 iter: core::slice::Iter<'a, Sequence>,
470 active_range: Option<RangeInclusive<u32>>,
471 largest: NonZeroU32,
472}
473
474impl<'a> Iterator for SequenceSetIterNaive<'a> {
475 type Item = NonZeroU32;
476
477 fn next(&mut self) -> Option<Self::Item> {
478 loop {
479 if let Some(ref mut range) = self.active_range {
480 if let Some(seq_or_uid) = range.next() {
481 return Some(NonZeroU32::try_from(seq_or_uid).unwrap());
482 } else {
483 self.active_range = None;
484 }
485 }
486
487 match self.iter.next() {
488 Some(seq) => match seq {
489 Sequence::Single(seq_no) => {
490 return Some(seq_no.expand(self.largest));
491 }
492 Sequence::Range(from, to) => {
493 let from = from.expand(self.largest);
494 let to = to.expand(self.largest);
495 self.active_range = Some(u32::from(from)..=u32::from(to));
496 }
497 },
498 None => return None,
499 }
500 }
501 }
502}
503
504#[cfg(test)]
505mod tests {
506 use std::num::NonZeroU32;
507
508 use super::*;
509 use crate::core::NonEmptyVec;
510
511 #[test]
512 fn test_creation_of_sequence_from_u32() {
513 assert_eq!(
514 SequenceSet::try_from(1),
515 Ok(SequenceSet(NonEmptyVec::from(Sequence::Single(
516 SeqOrUid::Value(NonZeroU32::new(1).unwrap())
517 ))))
518 );
519 assert_eq!(
520 SequenceSet::try_from(0),
521 Err(ValidationError::new(ValidationErrorKind::Invalid))
522 );
523 }
524
525 #[test]
526 fn test_creation_of_sequence_from_range() {
527 let range = ..;
529 let seq = Sequence::from(range);
530 assert_eq!(
531 seq,
532 Sequence::Range(
533 SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
534 SeqOrUid::Asterisk
535 )
536 );
537
538 let range = 1..;
540 let seq = Sequence::try_from(range).unwrap();
541 assert_eq!(
542 seq,
543 Sequence::Range(
544 SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
545 SeqOrUid::Asterisk
546 )
547 );
548
549 let range = 1337..;
551 let seq = Sequence::try_from(range).unwrap();
552 assert_eq!(
553 seq,
554 Sequence::Range(
555 SeqOrUid::Value(NonZeroU32::new(1337).unwrap()),
556 SeqOrUid::Asterisk
557 )
558 );
559
560 let range = 1..1337;
562 let seq = Sequence::try_from(range).unwrap();
563 assert_eq!(
564 seq,
565 Sequence::Range(
566 SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
567 SeqOrUid::Value(NonZeroU32::new(1336).unwrap())
568 )
569 );
570
571 let range = 1..=1337;
573 let seq = Sequence::try_from(range).unwrap();
574 assert_eq!(
575 seq,
576 Sequence::Range(
577 SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
578 SeqOrUid::Value(NonZeroU32::new(1337).unwrap())
579 )
580 );
581
582 let range = ..1337;
584 let seq = Sequence::try_from(range).unwrap();
585 assert_eq!(
586 seq,
587 Sequence::Range(
588 SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
589 SeqOrUid::Value(NonZeroU32::new(1336).unwrap())
590 )
591 );
592
593 let range = ..=1337;
595 let seq = Sequence::try_from(range).unwrap();
596 assert_eq!(
597 seq,
598 Sequence::Range(
599 SeqOrUid::Value(NonZeroU32::new(1).unwrap()),
600 SeqOrUid::Value(NonZeroU32::new(1337).unwrap())
601 )
602 );
603 }
604
605 #[test]
606 fn test_creation_of_sequence_set_from_str_positive() {
607 let tests = &[
608 (
609 "1",
610 SequenceSet(
611 vec![Sequence::Single(SeqOrUid::Value(1.try_into().unwrap()))]
612 .try_into()
613 .unwrap(),
614 ),
615 ),
616 (
617 "1,2,3",
618 SequenceSet(
619 vec![
620 Sequence::Single(SeqOrUid::Value(1.try_into().unwrap())),
621 Sequence::Single(SeqOrUid::Value(2.try_into().unwrap())),
622 Sequence::Single(SeqOrUid::Value(3.try_into().unwrap())),
623 ]
624 .try_into()
625 .unwrap(),
626 ),
627 ),
628 (
629 "*",
630 SequenceSet(
631 vec![Sequence::Single(SeqOrUid::Asterisk)]
632 .try_into()
633 .unwrap(),
634 ),
635 ),
636 (
637 "1:2",
638 SequenceSet(
639 vec![Sequence::Range(
640 SeqOrUid::Value(1.try_into().unwrap()),
641 SeqOrUid::Value(2.try_into().unwrap()),
642 )]
643 .try_into()
644 .unwrap(),
645 ),
646 ),
647 (
648 "1:2,3",
649 SequenceSet(
650 vec![
651 Sequence::Range(
652 SeqOrUid::Value(1.try_into().unwrap()),
653 SeqOrUid::Value(2.try_into().unwrap()),
654 ),
655 Sequence::Single(SeqOrUid::Value(3.try_into().unwrap())),
656 ]
657 .try_into()
658 .unwrap(),
659 ),
660 ),
661 (
662 "1:2,3,*",
663 SequenceSet(
664 vec![
665 Sequence::Range(
666 SeqOrUid::Value(1.try_into().unwrap()),
667 SeqOrUid::Value(2.try_into().unwrap()),
668 ),
669 Sequence::Single(SeqOrUid::Value(3.try_into().unwrap())),
670 Sequence::Single(SeqOrUid::Asterisk),
671 ]
672 .try_into()
673 .unwrap(),
674 ),
675 ),
676 ];
677
678 for (test, expected) in tests.iter() {
679 let got = SequenceSet::try_from(*test).unwrap();
680 assert_eq!(*expected, got);
681 }
682 }
683
684 #[test]
685 fn test_creation_of_sequence_set_from_str_negative() {
686 let tests = &[
687 "", "* ", " *", " * ", "1 ", " 1", " 1 ", "01", " 01", "01 ", " 01 ", "*1", ":", ":*",
688 "*:", "*: ", "1:2:3",
689 ];
690
691 for test in tests {
692 let got = SequenceSet::try_from(*test);
693 print!("\"{}\" | {:?} | ", test, got.clone().unwrap_err());
694 println!("{}", got.unwrap_err());
695 }
696 }
697
698 #[test]
699 fn test_iteration_over_some_sequence_sets() {
700 let tests = vec![
701 ("*", vec![3]),
702 ("1:*", vec![1, 2, 3]),
703 ("5,1:*,2:*", vec![5, 1, 2, 3, 2, 3]),
704 ("*:2", vec![]),
705 ("*:*", vec![3]),
706 ("4:6,*", vec![4, 5, 6, 3]),
707 ]
708 .into_iter()
709 .map(|(raw, vec)| {
710 (
711 raw,
712 vec.into_iter()
713 .map(|num| num.try_into().unwrap())
714 .collect::<Vec<NonZeroU32>>(),
715 )
716 })
717 .collect::<Vec<(&str, Vec<NonZeroU32>)>>();
718
719 for (test, expected) in tests {
720 let seq_set = SequenceSet::try_from(test).unwrap();
721 let got: Vec<NonZeroU32> = seq_set
722 .iter(Strategy::Naive {
723 largest: 3.try_into().unwrap(),
724 })
725 .collect();
726 assert_eq!(*expected, got);
727 }
728 }
729}