1use std::collections::BTreeSet;
13use std::fmt;
14use thiserror::Error;
15
16pub const AUTOSTEP_DISABLED: f64 = 1e100;
18
19#[derive(Debug, Error)]
24pub enum RangeSetError {
25 #[error("parse error: {msg} (in \"{part}\")")]
26 ParseError { part: String, msg: String },
27
28 #[error("padding mismatch: {msg} (in \"{part}\")")]
29 PaddingError { part: String, msg: String },
30}
31
32pub type Result<T> = std::result::Result<T, RangeSetError>;
33
34fn sort_key(s: &str) -> (i64, i64, String) {
42 if s.starts_with('-') {
43 let ival: i64 = s.parse().unwrap_or(0);
44 (-(s.len() as i64), ival, String::new())
45 } else {
46 (s.len() as i64, 0, s.to_string())
47 }
48}
49
50fn sorted_elements(elements: &BTreeSet<String>) -> Vec<String> {
51 let mut v: Vec<String> = elements.iter().cloned().collect();
52 v.sort_by(|a, b| sort_key(a).cmp(&sort_key(b)));
53 v
54}
55
56#[derive(Debug, Clone)]
61struct RangeSlice {
62 start: i64,
63 stop: i64, step: i64,
65 pad: usize,
66}
67
68#[derive(Debug, Clone)]
75pub struct RangeSet {
76 elements: BTreeSet<String>,
78 _autostep: f64,
81}
82
83impl RangeSet {
84 pub fn new() -> Self {
86 Self {
87 elements: BTreeSet::new(),
88 _autostep: AUTOSTEP_DISABLED,
89 }
90 }
91
92 pub fn parse(pattern: &str, autostep: Option<u32>) -> Result<Self> {
97 let mut rs = Self::new();
98 rs.set_autostep(autostep);
99 rs._parse(pattern)?;
100 Ok(rs)
101 }
102
103 fn _parse(&mut self, pattern: &str) -> Result<()> {
105 for subrange in pattern.split(',') {
106 let subrange = subrange.trim();
107
108 let (baserange, step) = if subrange.contains('/') {
109 let parts: Vec<&str> = subrange.splitn(2, '/').collect();
110 let step_str = parts[1];
111 let step: i64 = step_str.parse().map_err(|_| RangeSetError::ParseError {
112 part: subrange.to_string(),
113 msg: "cannot convert string to integer".to_string(),
114 })?;
115 (parts[0], step)
116 } else {
117 (subrange, 1i64)
118 };
119
120 let (begin_str, end_str, _begin_sign, _end_sign) =
122 self.parse_range_part(baserange, subrange, step)?;
123
124 let (start, stop, pad) = self.compute_padding(&begin_str, &end_str, subrange)?;
126
127 if stop > 1e100 as i64 || start > stop || step < 1 {
129 return Err(RangeSetError::ParseError {
130 part: subrange.to_string(),
131 msg: "invalid values in range".to_string(),
132 });
133 }
134
135 self.add_range(start, stop + 1, step, pad as u32);
136 }
137 Ok(())
138 }
139
140 fn parse_range_part<'a>(
142 &self,
143 baserange: &'a str,
144 subrange: &str,
145 step: i64,
146 ) -> Result<(String, String, i64, i64)> {
147 if !baserange.contains('-') {
148 if step != 1 {
150 return Err(RangeSetError::ParseError {
151 part: subrange.to_string(),
152 msg: "invalid step usage".to_string(),
153 });
154 }
155 return Ok((baserange.to_string(), baserange.to_string(), 1, 1));
156 }
157
158 let parts: Vec<&str> = baserange.split('-').collect();
160 match parts.len() {
161 2 => {
162 let begin = parts[0].trim().to_string();
164 let end = parts[1].trim().to_string();
165 if begin.is_empty() {
166 if end.is_empty() {
168 return Err(RangeSetError::ParseError {
169 part: subrange.to_string(),
170 msg: "cannot convert string to integer".to_string(),
171 });
172 }
173 return Ok((end.clone(), end, -1, -1));
174 }
175 Ok((begin, end, 1, 1))
176 }
177 3 => {
178 let begin = parts[1].trim().to_string();
180 let end = parts[2].trim().to_string();
181 Ok((begin, end, -1, 1))
182 }
183 4 => {
184 let begin = parts[1].trim().to_string();
186 let end = parts[3].trim().to_string();
187 Ok((begin, end, -1, -1))
188 }
189 _ => Err(RangeSetError::ParseError {
190 part: subrange.to_string(),
191 msg: "cannot convert string to integer".to_string(),
192 }),
193 }
194 }
195
196 fn compute_padding(&self, begin: &str, end: &str, subrange: &str) -> Result<(i64, i64, usize)> {
198 let mut pad: usize = 0;
199
200 let begin_int: i64 = begin.parse().map_err(|_| {
202 if subrange.is_empty() {
203 RangeSetError::ParseError {
204 part: subrange.to_string(),
205 msg: "empty range".to_string(),
206 }
207 } else {
208 RangeSetError::ParseError {
209 part: subrange.to_string(),
210 msg: "cannot convert string to integer".to_string(),
211 }
212 }
213 })?;
214
215 if begin_int != 0 {
216 let begins = begin.trim_start_matches('0');
217 if begin.len() - begins.len() > 0 {
218 pad = begin.len();
219 }
220 } else if begin.len() > 1 {
221 pad = begin.len();
222 }
223
224 let end_trimmed = if end.parse::<i64>().unwrap_or(1) != 0 {
226 end.trim_start_matches('0')
227 } else {
228 end
229 };
230
231 let mut endpad: usize = 0;
232 if end.len() - end_trimmed.len() > 0 {
233 endpad = end.len();
234 }
235
236 if (pad > 0 || endpad > 0) && begin.len() != end.len() {
238 return Err(RangeSetError::ParseError {
239 part: subrange.to_string(),
240 msg: "padding length mismatch".to_string(),
241 });
242 }
243
244 let end_int: i64 = end_trimmed.parse().map_err(|_| RangeSetError::ParseError {
245 part: subrange.to_string(),
246 msg: "cannot convert string to integer".to_string(),
247 })?;
248
249 Ok((begin_int, end_int, pad))
250 }
251
252 pub fn add_range(&mut self, start: i64, stop: i64, step: i64, pad: u32) {
254 assert!(start < stop, "please provide ordered node index ranges");
255 assert!(step > 0);
256 assert!(stop - start < 1_000_000_000, "range too large");
257
258 let mut i = start;
259 while i < stop {
260 if pad == 0 {
261 self.elements.insert(format!("{}", i));
262 } else {
263 self.elements
264 .insert(format!("{:0>width$}", i, width = pad as usize));
265 }
266 i += step;
267 }
268 }
269
270 pub fn len(&self) -> usize {
272 self.elements.len()
273 }
274
275 pub fn is_empty(&self) -> bool {
277 self.elements.is_empty()
278 }
279
280 pub fn add_str(&mut self, s: &str) {
282 self.elements.insert(s.to_string());
283 }
284
285 pub fn add_int(&mut self, value: i64, pad: u32) {
287 if pad == 0 {
288 self.elements.insert(format!("{}", value));
289 } else {
290 self.elements
291 .insert(format!("{:0>width$}", value, width = pad as usize));
292 }
293 }
294
295 pub fn remove_str(&mut self, s: &str) {
297 if !self.elements.remove(s) {
298 panic!("element '{}' not found in RangeSet", s);
299 }
300 }
301
302 pub fn discard_str(&mut self, s: &str) {
304 self.elements.remove(s);
305 }
306
307 pub fn contains_str(&self, s: &str) -> bool {
309 self.elements.contains(s)
310 }
311
312 pub fn contains_int(&self, value: i64) -> bool {
314 self.elements.contains(&format!("{}", value))
315 }
316
317 pub fn sorted(&self) -> Vec<String> {
319 sorted_elements(&self.elements)
320 }
321
322 pub fn striter(&self) -> impl Iterator<Item = String> {
324 sorted_elements(&self.elements).into_iter()
325 }
326
327 pub fn intiter(&self) -> impl Iterator<Item = i64> {
329 sorted_elements(&self.elements)
330 .into_iter()
331 .map(|s| s.parse::<i64>().unwrap_or(0))
332 }
333
334 pub fn union(&self, other: &RangeSet) -> RangeSet {
340 let mut result = self.clone();
341 result.update(other);
342 result
343 }
344
345 pub fn intersection(&self, other: &RangeSet) -> RangeSet {
347 let mut result = self.clone();
348 result.intersection_update(other);
349 result
350 }
351
352 pub fn difference(&self, other: &RangeSet) -> RangeSet {
354 let mut result = self.clone();
355 result.difference_update(other);
356 result
357 }
358
359 pub fn symmetric_difference(&self, other: &RangeSet) -> RangeSet {
361 let mut result = self.clone();
362 result.symmetric_difference_update(other);
363 result
364 }
365
366 pub fn update(&mut self, other: &RangeSet) {
368 for elem in &other.elements {
369 self.elements.insert(elem.clone());
370 }
371 }
372
373 pub fn intersection_update(&mut self, other: &RangeSet) {
375 self.elements = self
376 .elements
377 .intersection(&other.elements)
378 .cloned()
379 .collect();
380 }
381
382 pub fn difference_update(&mut self, other: &RangeSet) {
384 self.elements = self.elements.difference(&other.elements).cloned().collect();
385 }
386
387 pub fn symmetric_difference_update(&mut self, other: &RangeSet) {
389 self.elements = self
390 .elements
391 .symmetric_difference(&other.elements)
392 .cloned()
393 .collect();
394 }
395
396 pub fn autostep(&self) -> Option<u32> {
402 if self._autostep >= AUTOSTEP_DISABLED {
403 None
404 } else {
405 Some((self._autostep as u32) + 1)
406 }
407 }
408
409 pub fn set_autostep(&mut self, val: Option<u32>) {
411 match val {
412 None => self._autostep = AUTOSTEP_DISABLED,
413 Some(v) => self._autostep = (v as f64) - 1.0,
414 }
415 }
416
417 fn slices_padding(&self, autostep: f64) -> Vec<RangeSlice> {
424 let sorted = sorted_elements(&self.elements);
425 if sorted.is_empty() {
426 return Vec::new();
427 }
428
429 let mut result: Vec<RangeSlice> = Vec::new();
430
431 let mut cur_pad: usize = 0;
432 let mut cur_padded: bool = false;
433 let mut cur_start: Option<i64> = None;
434 let mut cur_step: Option<i64> = None;
435 let mut last_idx: i64 = 0;
436
437 for si in &sorted {
438 let idx: i64 = si.parse().unwrap_or(0);
439 let digitlen = si.len();
440 let padded = digitlen > 1 && si.starts_with('0');
441
442 if let Some(cs) = cur_start {
443 let padding_mismatch = if cur_padded {
445 digitlen != cur_pad
446 } else {
447 padded
448 };
449
450 let step_mismatch = if let Some(cstep) = cur_step {
452 cstep != idx - last_idx
453 } else {
454 false
455 };
456
457 if padding_mismatch || step_mismatch {
458 let (stepped, step) = if let Some(cstep) = cur_step {
459 let stepped =
460 (cstep == 1) || ((last_idx - cs) as f64 >= autostep * cstep as f64);
461 (stepped, cstep)
462 } else {
463 (true, 1i64)
464 };
465
466 if stepped {
467 result.push(RangeSlice {
468 start: cs,
469 stop: last_idx + 1,
470 step,
471 pad: if cur_padded { cur_pad } else { 0 },
472 });
473 cur_start = Some(idx);
474 cur_padded = padded;
475 cur_pad = digitlen;
476 } else {
477 if padding_mismatch {
478 let stop = last_idx + 1;
479 let mut j = cs;
480 while j < stop {
481 result.push(RangeSlice {
482 start: j,
483 stop: j + 1,
484 step: 1,
485 pad: if cur_padded { cur_pad } else { 0 },
486 });
487 j += step;
488 }
489 cur_start = Some(idx);
490 cur_padded = padded;
491 cur_pad = digitlen;
492 } else {
493 let stop = last_idx - step + 1;
494 let mut j = cs;
495 while j < stop {
496 result.push(RangeSlice {
497 start: j,
498 stop: j + 1,
499 step: 1,
500 pad: if cur_padded { cur_pad } else { 0 },
501 });
502 j += step;
503 }
504 cur_start = Some(last_idx);
505 }
506 }
507
508 cur_step = if step_mismatch {
509 Some(idx - last_idx)
510 } else {
511 None
512 };
513 last_idx = idx;
514 continue;
515 }
516 } else {
517 cur_padded = padded;
519 cur_pad = digitlen;
520 cur_start = Some(idx);
521 cur_step = None;
522 last_idx = idx;
523 continue;
524 }
525
526 cur_step = Some(idx - last_idx);
527 last_idx = idx;
528 }
529
530 if let Some(cs) = cur_start {
532 if let Some(cstep) = cur_step {
533 let stepped = (last_idx - cs) as f64 >= self._autostep * cstep as f64;
534 if stepped || cstep == 1 {
535 result.push(RangeSlice {
536 start: cs,
537 stop: last_idx + 1,
538 step: cstep,
539 pad: if cur_padded { cur_pad } else { 0 },
540 });
541 } else {
542 let mut j = cs;
543 while j <= last_idx {
544 result.push(RangeSlice {
545 start: j,
546 stop: j + 1,
547 step: 1,
548 pad: if cur_padded { cur_pad } else { 0 },
549 });
550 j += cstep;
551 }
552 }
553 } else {
554 result.push(RangeSlice {
556 start: cs,
557 stop: last_idx + 1,
558 step: 1,
559 pad: if cur_padded { cur_pad } else { 0 },
560 });
561 }
562 }
563
564 result
565 }
566
567 fn folded_slices(&self) -> Vec<RangeSlice> {
569 self.slices_padding(self._autostep)
570 }
571
572 fn strslices(&self) -> Vec<String> {
574 self.folded_slices()
575 .iter()
576 .map(|sli| {
577 if sli.start + 1 == sli.stop {
578 if sli.pad > 0 {
580 format!("{:0>width$}", sli.start, width = sli.pad)
581 } else {
582 format!("{}", sli.start)
583 }
584 } else if sli.step == 1 {
585 if sli.pad > 0 {
587 format!(
588 "{:0>width$}-{:0>width$}",
589 sli.start,
590 sli.stop - 1,
591 width = sli.pad
592 )
593 } else {
594 format!("{}-{}", sli.start, sli.stop - 1)
595 }
596 } else {
597 if sli.pad > 0 {
599 format!(
600 "{:0>width$}-{:0>width$}/{}",
601 sli.start,
602 sli.stop - 1,
603 sli.step,
604 width = sli.pad
605 )
606 } else {
607 format!("{}-{}/{}", sli.start, sli.stop - 1, sli.step)
608 }
609 }
610 })
611 .collect()
612 }
613
614 pub fn padding(&self) -> Option<usize> {
616 let mut result = None;
617 for si in sorted_elements(&self.elements) {
618 let digitlen = si.len();
619 if digitlen > 1 && si.starts_with('0') {
620 result = Some(digitlen);
621 }
622 }
623 result
624 }
625}
626
627impl Default for RangeSet {
628 fn default() -> Self {
629 Self::new()
630 }
631}
632
633impl fmt::Display for RangeSet {
634 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635 write!(f, "{}", self.strslices().join(","))
636 }
637}
638
639#[derive(Debug, Clone)]
645pub struct RangeSetND {
646 pub vecrangesets: Vec<Vec<RangeSet>>,
647 _autostep: f64,
648}
649
650impl RangeSetND {
651 pub fn new(autostep: Option<u32>) -> Self {
652 Self {
653 vecrangesets: Vec::new(),
654 _autostep: autostep.map(|v| v as f64).unwrap_or(AUTOSTEP_DISABLED),
655 }
656 }
657}
658
659#[cfg(test)]
664mod tests {
665 use super::*;
666
667 fn test_rs(input: &str, expected: &str, expected_len: usize) {
668 let rs = RangeSet::parse(input, Some(3)).unwrap();
669 assert_eq!(
670 rs.to_string(),
671 expected,
672 "parse '{}' display mismatch",
673 input
674 );
675 assert_eq!(rs.len(), expected_len, "parse '{}' len mismatch", input);
676 }
677
678 #[test]
679 fn test_simple() {
680 test_rs("0", "0", 1);
681 test_rs("1", "1", 1);
682 test_rs("0-2", "0-2", 3);
683 test_rs("1-3", "1-3", 3);
684 test_rs("1-3,4-6", "1-6", 6);
685 test_rs("1-3,4-6,7-10", "1-10", 10);
686 }
687
688 #[test]
689 fn test_step_simple() {
690 test_rs("0-4/2", "0-4/2", 3);
691 test_rs("1-4/2", "1,3", 2);
692 test_rs("1-4/3", "1,4", 2);
693 test_rs("1-4/4", "1", 1);
694 }
695
696 #[test]
697 fn test_step_advanced() {
698 test_rs("1-4/4,2-6/2", "1-2,4,6", 4);
699 test_rs("6-24/6,9-21/6", "6-24/3", 7);
700 test_rs("0-24/2,9-21/2", "0-8/2,9-22,24", 20);
701 test_rs("0-24/2,9-21/2,100", "0-8/2,9-22,24,100", 21);
702 test_rs("3-21/9,6-24/9,9-27/9", "3-27/3", 9);
703 test_rs("1-17/2,2-18/2", "1-18", 18);
704 test_rs("1-17/01", "1-17", 17);
705 test_rs("1-17/02", "1-17/2", 9);
706 test_rs("1-17/03", "1-16/3", 6);
707 }
708
709 #[test]
710 fn test_step_advanced_more() {
711 test_rs("0-24/2,9-21/2,100-101", "0-8/2,9-22,24,100-101", 22);
712 test_rs("101-121/4,1-225/112", "1,101-121/4,225", 8);
713 test_rs("1-32/3,13-28/9", "1-31/3", 11);
714 test_rs("1-32/3,13-22/9", "1-31/3", 11);
715 test_rs("1-32/3,13-31/9", "1-31/3", 11);
716 test_rs("1-32/3,13-40/9", "1-31/3,40", 12);
717 }
718
719 #[test]
720 fn test_step_more_complex() {
721 test_rs("1-16/3,13-28/6", "1-19/3,25", 8);
722 test_rs("1-16/3,1-16/6", "1-16/3", 6);
723 test_rs("1-16/6,1-16/3", "1-16/3", 6);
724 test_rs("1-17/2,33-41/2,2-18/2", "1-18,33-41/2", 23);
725 test_rs("1-17/2,33-41/2,2-20/2", "1-18,20,33-41/2", 24);
726 test_rs("1-17/2,33-41/2,2-19/2", "1-18,33-41/2", 23);
727 }
728
729 #[test]
730 fn test_bad_syntax() {
731 assert!(RangeSet::parse("", None).is_err());
732 assert!(RangeSet::parse("-", None).is_err());
733 assert!(RangeSet::parse("A", None).is_err());
734 assert!(RangeSet::parse("2-5/a", None).is_err());
735 assert!(RangeSet::parse("3/2", None).is_err());
736 assert!(RangeSet::parse("3-/2", None).is_err());
737 assert!(RangeSet::parse("-/2", None).is_err());
738 assert!(RangeSet::parse("4-a/2", None).is_err());
739 assert!(RangeSet::parse("4-3/2", None).is_err());
740 assert!(RangeSet::parse("4-5/-2", None).is_err());
741 assert!(RangeSet::parse("004-002", None).is_err());
742 }
743
744 #[test]
745 fn test_intersection() {
746 let mut r1 = RangeSet::parse("4-34", None).unwrap();
747 let r2 = RangeSet::parse("27-42", None).unwrap();
748 r1.intersection_update(&r2);
749 assert_eq!(r1.to_string(), "27-34");
750 assert_eq!(r1.len(), 8);
751 }
752
753 #[test]
754 fn test_intersection_complex() {
755 let mut r1 = RangeSet::parse("2-450,654-700,800", None).unwrap();
756 let r2 = RangeSet::parse("500-502,690-820,830-840,900", None).unwrap();
757 r1.intersection_update(&r2);
758 assert_eq!(r1.to_string(), "690-700,800");
759 assert_eq!(r1.len(), 12);
760 }
761
762 #[test]
763 fn test_intersection_step() {
764 let mut r1 = RangeSet::parse("4-34/2", None).unwrap();
765 let r2 = RangeSet::parse("28-42/2", None).unwrap();
766 r1.intersection_update(&r2);
767 assert_eq!(r1.to_string(), "28,30,32,34");
768 assert_eq!(r1.len(), 4);
769
770 let mut r1 = RangeSet::parse("4-34/2", None).unwrap();
771 let r2 = RangeSet::parse("27-42/2", None).unwrap();
772 r1.intersection_update(&r2);
773 assert_eq!(r1.to_string(), "");
774 assert_eq!(r1.len(), 0);
775
776 let mut r1 = RangeSet::parse("2-60/3", Some(3)).unwrap();
777 let r2 = RangeSet::parse("3-50/2", Some(3)).unwrap();
778 r1.intersection_update(&r2);
779 assert_eq!(r1.to_string(), "5-47/6");
780 assert_eq!(r1.len(), 8);
781 }
782
783 #[test]
784 fn test_difference() {
785 let mut r1 = RangeSet::parse("4,7-33", None).unwrap();
786 let r2 = RangeSet::parse("8-33", None).unwrap();
787 r1.difference_update(&r2);
788 assert_eq!(r1.to_string(), "4,7");
789 assert_eq!(r1.len(), 2);
790 }
791
792 #[test]
793 fn test_difference_bounds() {
794 let mut r1 = RangeSet::parse("1-10,39-41,50-60", None).unwrap();
795 let r2 = RangeSet::parse("1-10,38-39,50-60", None).unwrap();
796 r1.difference_update(&r2);
797 assert_eq!(r1.len(), 2);
798 assert_eq!(r1.to_string(), "40-41");
799 }
800
801 #[test]
802 fn test_symmetric_difference() {
803 let mut r1 = RangeSet::parse("4,7-33", None).unwrap();
804 let r2 = RangeSet::parse("8-34", None).unwrap();
805 r1.symmetric_difference_update(&r2);
806 assert_eq!(r1.to_string(), "4,7,34");
807 assert_eq!(r1.len(), 3);
808 }
809
810 #[test]
811 fn test_symmetric_difference_complex() {
812 let mut r1 = RangeSet::parse("5,7,10-12,33-50", None).unwrap();
813 let r2 = RangeSet::parse("8-34", None).unwrap();
814 r1.symmetric_difference_update(&r2);
815 assert_eq!(r1.to_string(), "5,7-9,13-32,35-50");
816 assert_eq!(r1.len(), 40);
817
818 let mut r1 = RangeSet::parse("8-30", None).unwrap();
819 let r2 = RangeSet::parse("31-40", None).unwrap();
820 r1.symmetric_difference_update(&r2);
821 assert_eq!(r1.to_string(), "8-40");
822 assert_eq!(r1.len(), 33);
823
824 let mut r1 = RangeSet::parse("8-30", None).unwrap();
825 let r2 = RangeSet::parse("8-30", None).unwrap();
826 r1.symmetric_difference_update(&r2);
827 assert_eq!(r1.to_string(), "");
828 assert_eq!(r1.len(), 0);
829 }
830
831 #[test]
832 fn test_union() {
833 let r1 = RangeSet::parse("1-10", None).unwrap();
834 let r2 = RangeSet::parse("8-20", None).unwrap();
835 let r3 = r1.union(&r2);
836 assert_eq!(r3.to_string(), "1-20");
837 assert_eq!(r3.len(), 20);
838 }
839
840 #[test]
841 fn test_contains() {
842 let r1 = RangeSet::parse("1-100,102,105-242,800", None).unwrap();
843 assert_eq!(r1.len(), 240);
844 assert!(r1.contains_str("99"));
845 assert!(!r1.contains_str("099"));
846 assert!(!r1.contains_str("101"));
847 }
848
849 #[test]
850 fn test_padding() {
851 let r1 = RangeSet::parse("001-010", None).unwrap();
852 assert_eq!(r1.len(), 10);
853 assert!(r1.contains_str("001"));
854 assert!(r1.contains_str("010"));
855 assert!(!r1.contains_str("1"));
856 assert!(!r1.contains_str("10"));
857
858 let r2 = RangeSet::parse("00-02", None).unwrap();
859 assert!(r2.contains_str("00"));
860 assert!(!r2.contains_str("0"));
861 assert!(r2.contains_str("01"));
862 assert!(!r2.contains_str("1"));
863
864 let r3 = RangeSet::parse("0003-0143,0360-1000", None).unwrap();
865 assert!(!r3.contains_str("360"));
866 assert!(r3.contains_str("0360"));
867 }
868
869 #[test]
870 fn test_padding_display() {
871 test_rs("001-010", "001-010", 10);
872 test_rs("00-02", "00-02", 3);
873 }
874
875 #[test]
876 fn test_empty() {
877 let rs = RangeSet::new();
878 assert!(rs.is_empty());
879 assert_eq!(rs.len(), 0);
880 assert_eq!(rs.to_string(), "");
881 }
882
883 #[test]
884 fn test_add_remove() {
885 let mut rs = RangeSet::new();
886 rs.add_int(5, 0);
887 rs.add_int(3, 0);
888 rs.add_int(1, 0);
889 assert_eq!(rs.len(), 3);
890 assert_eq!(rs.to_string(), "1,3,5");
891 rs.discard_str("3");
892 assert_eq!(rs.len(), 2);
893 assert_eq!(rs.to_string(), "1,5");
894 }
895
896 #[test]
897 fn test_intiter() {
898 let rs = RangeSet::parse("3,1,5,10", None).unwrap();
899 let vals: Vec<i64> = rs.intiter().collect();
900 assert_eq!(vals, vec![1, 3, 5, 10]);
901 }
902
903 #[test]
904 fn test_large_range() {
905 let rs = RangeSet::parse("1-1000", None).unwrap();
906 assert_eq!(rs.len(), 1000);
907 assert_eq!(rs.to_string(), "1-1000");
908 }
909
910 #[test]
911 fn test_diff_step() {
912 let mut r1 = RangeSet::parse("4-34/2", Some(3)).unwrap();
913 let r2 = RangeSet::parse("3-33/2", Some(3)).unwrap();
914 r1.difference_update(&r2);
915 assert_eq!(r1.to_string(), "4-34/2");
916 assert_eq!(r1.len(), 16);
917
918 let mut r1 = RangeSet::parse("4-34/2", Some(3)).unwrap();
919 let r2 = RangeSet::parse("2-14/2", Some(3)).unwrap();
920 r1.difference_update(&r2);
921 assert_eq!(r1.to_string(), "16-34/2");
922 assert_eq!(r1.len(), 10);
923
924 let mut r1 = RangeSet::parse("4-34/2", Some(3)).unwrap();
925 let r2 = RangeSet::parse("28-52/2", Some(3)).unwrap();
926 r1.difference_update(&r2);
927 assert_eq!(r1.to_string(), "4-26/2");
928 assert_eq!(r1.len(), 12);
929
930 let mut r1 = RangeSet::parse("4-34/2", Some(3)).unwrap();
931 let r2 = RangeSet::parse("12-18/2", Some(3)).unwrap();
932 r1.difference_update(&r2);
933 assert_eq!(r1.to_string(), "4-10/2,20-34/2");
934 assert_eq!(r1.len(), 12);
935 }
936
937 #[test]
938 fn test_diff_step_complex() {
939 let mut r1 = RangeSet::parse("1-100", Some(3)).unwrap();
940 let r2 = RangeSet::parse("2-98/2", Some(3)).unwrap();
941 r1.difference_update(&r2);
942 assert_eq!(r1.to_string(), "1-99/2,100");
943 assert_eq!(r1.len(), 51);
944
945 let mut r1 = RangeSet::parse("1-1000", Some(3)).unwrap();
946 let r2 = RangeSet::parse("2-999/2", Some(3)).unwrap();
947 r1.difference_update(&r2);
948 assert_eq!(r1.to_string(), "1-999/2,1000");
949 assert_eq!(r1.len(), 501);
950 }
951
952 #[test]
953 fn test_folding() {
954 let r1 = RangeSet::parse(
956 "112,114-117,119,121,130,132,134,136,138,139-141,144,147-148",
957 Some(6),
958 )
959 .unwrap();
960 assert_eq!(
961 r1.to_string(),
962 "112,114-117,119,121,130,132,134,136,138-141,144,147-148"
963 );
964
965 let r1 = RangeSet::parse(
966 "112,114-117,119,121,130,132,134,136,138,139-141,144,147-148",
967 Some(5),
968 )
969 .unwrap();
970 assert_eq!(
971 r1.to_string(),
972 "112,114-117,119,121,130-138/2,139-141,144,147-148"
973 );
974
975 let r1 = RangeSet::parse("1,3-4,6,8", None).unwrap();
976 assert_eq!(r1.to_string(), "1,3-4,6,8");
977
978 let r1 = RangeSet::parse("1,3-4,6,8", Some(4)).unwrap();
979 assert_eq!(r1.to_string(), "1,3-4,6,8");
980
981 let r1 = RangeSet::parse("1,3-4,6,8", Some(2)).unwrap();
982 assert_eq!(r1.to_string(), "1-3/2,4,6-8/2");
983
984 let r1 = RangeSet::parse("1,3-4,6,8", Some(3)).unwrap();
985 assert_eq!(r1.to_string(), "1,3-4,6,8");
986 }
987
988 #[test]
989 fn test_mixed_padding() {
990 let r0 = RangeSet::parse("030-031,032-100/2,101-489", Some(3)).unwrap();
992 assert_eq!(r0.to_string(), "030-032,034-100/2,101-489");
993
994 let r1 = RangeSet::parse("030-032,033-100/3,102", Some(3)).unwrap();
995 assert_eq!(r1.to_string(), "030-033,036-102/3");
996
997 let r2 = RangeSet::parse("030-032,033-100/3,101", Some(3)).unwrap();
998 assert_eq!(r2.to_string(), "030-033,036-099/3,101");
999
1000 let r3 = RangeSet::parse("030-032,033-100/3,100", Some(3)).unwrap();
1001 assert_eq!(r3.to_string(), "030-033,036-099/3,100");
1002 }
1003
1004 #[test]
1005 fn test_mixed_padding_with_different_widths() {
1006 let r5 = RangeSet::parse("030-032,033-100/3,99-105/3,0001", Some(3)).unwrap();
1008 assert_eq!(r5.to_string(), "99,030-033,036-105/3,0001");
1009 }
1010
1011 #[test]
1012 fn test_padding_mismatch_errors() {
1013 assert!(RangeSet::parse("1-044", None).is_err());
1015 assert!(RangeSet::parse("01-044", None).is_err());
1016 assert!(RangeSet::parse("001-44", None).is_err());
1017 assert!(RangeSet::parse("0-9,1-044", None).is_err());
1018 assert!(RangeSet::parse("0-9,01-044", None).is_err());
1019 assert!(RangeSet::parse("0-9,001-44", None).is_err());
1020 assert!(RangeSet::parse("030-032,033-99/3,100", None).is_err());
1021 }
1022
1023 #[test]
1024 fn test_update_complex() {
1025 let mut r1 = RangeSet::parse("1-100,102,105-242,800", None).unwrap();
1027 assert_eq!(r1.len(), 240);
1028 let r2 = RangeSet::parse("243-799,1924-1984", None).unwrap();
1029 assert_eq!(r2.len(), 618);
1030 r1.update(&r2);
1031 assert_eq!(r1.len(), 240 + 618);
1032 assert_eq!(r1.to_string(), "1-100,102,105-800,1924-1984");
1033 }
1034
1035 #[test]
1036 fn test_union_complex() {
1037 let r1 = RangeSet::parse("1-100,102,105-242,800", None).unwrap();
1039 let r2 = RangeSet::parse("243-799,1924-1984", None).unwrap();
1040 let r3 = r1.union(&r2);
1041 assert_eq!(r3.len(), 858);
1042 assert_eq!(r3.to_string(), "1-100,102,105-800,1924-1984");
1043
1044 let r2 = RangeSet::parse("200-799", None).unwrap();
1046 let r3 = r1.union(&r2);
1047 assert_eq!(r3.len(), 797);
1048 assert_eq!(r3.to_string(), "1-100,102,105-800");
1049 }
1050
1051 #[test]
1052 fn test_intersection_length() {
1053 let r1 = RangeSet::parse("115-117,130,166-170,4780-4999", None).unwrap();
1055 assert_eq!(r1.len(), 229);
1056 let r2 = RangeSet::parse("116-117,130,4781-4999", None).unwrap();
1057 assert_eq!(r2.len(), 222);
1058 let res = r1.intersection(&r2);
1059 assert_eq!(res.len(), 222);
1060
1061 let r1 = RangeSet::parse("115-200", None).unwrap();
1062 assert_eq!(r1.len(), 86);
1063 let r2 = RangeSet::parse("116-117,119,123-131,133,149,199", None).unwrap();
1064 assert_eq!(r2.len(), 15);
1065 let res = r1.intersection(&r2);
1066 assert_eq!(res.len(), 15);
1067
1068 let r1 = RangeSet::parse("115-117,130,166-170,4780-4999,5003", None).unwrap();
1070 assert_eq!(r1.len(), 230);
1071 let r2 = RangeSet::parse("116-117,130,4781-4999", None).unwrap();
1072 assert_eq!(r2.len(), 222);
1073 let res = r1.intersection(&r2);
1074 assert_eq!(res.len(), 222);
1075
1076 let r1 = RangeSet::parse("130,166-170,4780-4999", None).unwrap();
1078 assert_eq!(r1.len(), 226);
1079 let r2 = RangeSet::parse("116-117", None).unwrap();
1080 assert_eq!(r2.len(), 2);
1081 let res = r1.intersection(&r2);
1082 assert_eq!(res.len(), 0);
1083 }
1084
1085 #[test]
1086 fn test_ior() {
1087 let mut r1 = RangeSet::parse("1,3-9,14-21,30-39,42", None).unwrap();
1089 let r2 = RangeSet::parse("2-5,10-32,35,40-41", None).unwrap();
1090 r1.update(&r2);
1091 assert_eq!(r1.len(), 42);
1092 assert_eq!(r1.to_string(), "1-42");
1093 }
1094
1095 #[test]
1096 fn test_iand() {
1097 let mut r1 = RangeSet::parse("1,3-9,14-21,30-39,42", None).unwrap();
1099 let r2 = RangeSet::parse("2-5,10-32,35,40-41", None).unwrap();
1100 r1.intersection_update(&r2);
1101 assert_eq!(r1.len(), 15);
1102 assert_eq!(r1.to_string(), "3-5,14-21,30-32,35");
1103 }
1104
1105 #[test]
1106 fn test_ixor() {
1107 let mut r1 = RangeSet::parse("1,3-9,14-21,30-39,42", None).unwrap();
1109 let r2 = RangeSet::parse("2-5,10-32,35,40-41", None).unwrap();
1110 r1.symmetric_difference_update(&r2);
1111 assert_eq!(r1.len(), 27);
1112 assert_eq!(r1.to_string(), "1-2,6-13,22-29,33-34,36-42");
1113 }
1114
1115 #[test]
1116 fn test_isub() {
1117 let mut r1 = RangeSet::parse("1,3-9,14-21,30-39,42", None).unwrap();
1119 let r2 = RangeSet::parse("2-5,10-32,35,40-41", None).unwrap();
1120 r1.difference_update(&r2);
1121 assert_eq!(r1.len(), 12);
1122 assert_eq!(r1.to_string(), "1,6-9,33-34,36-39,42");
1123 }
1124
1125 #[test]
1126 fn test_add_range_api() {
1127 let mut r1 = RangeSet::new();
1129 r1.add_range(1, 100, 1, 0);
1130 assert_eq!(r1.len(), 99);
1131 assert_eq!(r1.to_string(), "1-99");
1132 r1.add_range(40, 101, 1, 0);
1133 assert_eq!(r1.len(), 100);
1134 assert_eq!(r1.to_string(), "1-100");
1135 r1.add_range(399, 423, 2, 0);
1136 assert_eq!(r1.len(), 112);
1137 assert_eq!(
1138 r1.to_string(),
1139 "1-100,399,401,403,405,407,409,411,413,415,417,419,421"
1140 );
1141
1142 let mut r1 = RangeSet::new();
1144 r1.set_autostep(Some(3));
1145 r1.add_range(1, 100, 1, 0);
1146 assert_eq!(r1.autostep(), Some(3));
1147 assert_eq!(r1.len(), 99);
1148 assert_eq!(r1.to_string(), "1-99");
1149 r1.add_range(40, 101, 1, 0);
1150 assert_eq!(r1.len(), 100);
1151 assert_eq!(r1.to_string(), "1-100");
1152 r1.add_range(399, 423, 2, 0);
1153 assert_eq!(r1.len(), 112);
1154 assert_eq!(r1.to_string(), "1-100,399-421/2");
1155 }
1156
1157 #[test]
1158 fn test_add_range_bounds() {
1159 let mut r1 = RangeSet::parse("1-30", Some(2)).unwrap();
1160 assert_eq!(r1.len(), 30);
1161 assert_eq!(r1.to_string(), "1-30");
1162 r1.add_range(32, 35, 1, 0);
1163 assert_eq!(r1.len(), 33);
1164 assert_eq!(r1.to_string(), "1-30,32-34");
1165 r1.add_range(31, 32, 1, 0);
1166 assert_eq!(r1.len(), 34);
1167 assert_eq!(r1.to_string(), "1-34");
1168
1169 let mut r1 = RangeSet::parse("1-30", Some(3)).unwrap();
1170 r1.add_range(40, 65, 10, 0);
1171 assert_eq!(r1.autostep(), Some(3));
1172 assert_eq!(r1.len(), 33);
1173 assert_eq!(r1.to_string(), "1-30,40-60/10");
1174
1175 r1.add_range(103, 104, 1, 0);
1177 assert_eq!(r1.len(), 34);
1178 assert_eq!(r1.to_string(), "1-30,40-60/10,103");
1179 }
1180
1181 #[test]
1182 fn test_autostep_property() {
1183 let mut rs = RangeSet::new();
1184 assert_eq!(rs.autostep(), None);
1185 rs.set_autostep(Some(3));
1186 assert_eq!(rs.autostep(), Some(3));
1187 rs.set_autostep(None);
1188 assert_eq!(rs.autostep(), None);
1189 }
1190
1191 #[test]
1192 fn test_padding_property() {
1193 let r1 = RangeSet::parse("001-010", None).unwrap();
1194 assert_eq!(r1.padding(), Some(3));
1195
1196 let r2 = RangeSet::parse("1-10", None).unwrap();
1197 assert_eq!(r2.padding(), None);
1198
1199 let r3 = RangeSet::parse("0003-0143,0360-1000", None).unwrap();
1200 assert_eq!(r3.padding(), Some(4));
1201 }
1202
1203 #[test]
1204 fn test_copy() {
1205 let rangeset = RangeSet::parse("115-117,130,166-170,4780-4999", None).unwrap();
1207 assert_eq!(rangeset.len(), 229);
1208 assert_eq!(rangeset.to_string(), "115-117,130,166-170,4780-4999");
1209 let mut r1 = rangeset.clone();
1210 let mut r2 = rangeset.clone();
1211 r1.remove_str("166");
1212 assert_eq!(rangeset.len(), r1.len() + 1);
1213 assert_eq!(rangeset.to_string(), "115-117,130,166-170,4780-4999");
1214 assert_eq!(r1.to_string(), "115-117,130,167-170,4780-4999");
1215 r2.update(&RangeSet::parse("118", None).unwrap());
1216 assert_eq!(rangeset.len() + 1, r2.len());
1217 assert_eq!(r2.to_string(), "115-118,130,166-170,4780-4999");
1218 }
1219
1220 #[test]
1221 fn test_remove_and_discard() {
1222 let mut r1 = RangeSet::parse("1-100,102,105-242,800", None).unwrap();
1224 assert_eq!(r1.len(), 240);
1225 r1.remove_str("100");
1226 assert_eq!(r1.len(), 239);
1227 assert_eq!(r1.to_string(), "1-99,102,105-242,800");
1228
1229 r1.discard_str("101"); r1.discard_str("105");
1231 assert_eq!(r1.len(), 238);
1232 assert_eq!(r1.to_string(), "1-99,102,106-242,800");
1233 }
1234
1235 #[test]
1236 #[should_panic(expected = "not found")]
1237 fn test_remove_missing_panics() {
1238 let mut r1 = RangeSet::parse("1-100", None).unwrap();
1239 r1.remove_str("101");
1240 }
1241}