1use std::{
2 borrow::Borrow,
3 cmp::Ordering,
4 fmt,
5 ops::{self, Bound},
6};
7
8use crate::RangesRelation;
9
10#[allow(clippy::derive_partial_eq_without_eq)]
11#[derive(Clone, Hash, PartialEq)]
12pub enum ContinuousRange<Idx> {
13 Empty,
17
18 Single(Idx),
22
23 Inclusive(Idx, Idx),
27
28 Exclusive(Idx, Idx),
32
33 StartExclusive(Idx, Idx),
37
38 EndExclusive(Idx, Idx),
42
43 From(Idx),
47
48 FromExclusive(Idx),
52
53 To(Idx),
57
58 ToExclusive(Idx),
62
63 Full,
65}
66
67#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
68enum BoundSide {
69 Start,
70 End,
71}
72
73fn partial_cmp_bounds<Idx: PartialOrd>(
74 this: &Bound<&Idx>,
75 this_side: BoundSide,
76 other: &Bound<&Idx>,
77 other_side: BoundSide,
78) -> Option<Ordering> {
79 match this {
80 Bound::Included(this_value) => match other {
81 Bound::Included(other_value) => this_value.partial_cmp(other_value),
82 Bound::Excluded(other_value) => match this_value.partial_cmp(other_value) {
83 Some(Ordering::Equal) => match (this_side, other_side) {
84 (BoundSide::Start, BoundSide::Start) => Some(Ordering::Less),
85 (BoundSide::End, BoundSide::End) => Some(Ordering::Greater),
86 (BoundSide::Start, BoundSide::End) => Some(Ordering::Greater),
87 (BoundSide::End, BoundSide::Start) => Some(Ordering::Less),
88 },
89 other => other,
90 },
91 Bound::Unbounded => match other_side {
92 BoundSide::Start => Some(Ordering::Greater), BoundSide::End => Some(Ordering::Less), },
95 },
96 Bound::Excluded(this_value) => match other {
97 Bound::Included(other_value) => match this_value.partial_cmp(other_value) {
98 Some(Ordering::Equal) => match (this_side, other_side) {
99 (BoundSide::Start, BoundSide::Start) => Some(Ordering::Greater),
100 (BoundSide::End, BoundSide::End) => Some(Ordering::Less),
101 (BoundSide::Start, BoundSide::End) => Some(Ordering::Greater),
102 (BoundSide::End, BoundSide::Start) => Some(Ordering::Less),
103 },
104 other => other,
105 },
106 Bound::Excluded(other_value) => match this_value.partial_cmp(other_value) {
107 Some(Ordering::Equal) => match (this_side, other_side) {
108 (BoundSide::Start, BoundSide::Start) => Some(Ordering::Equal),
109 (BoundSide::End, BoundSide::End) => Some(Ordering::Equal),
110 (BoundSide::Start, BoundSide::End) => Some(Ordering::Greater),
111 (BoundSide::End, BoundSide::Start) => Some(Ordering::Less),
112 },
113 other => other,
114 },
115 Bound::Unbounded => match other_side {
116 BoundSide::Start => Some(Ordering::Greater), BoundSide::End => Some(Ordering::Less), },
119 },
120 Bound::Unbounded => match other {
121 Bound::Included(_) | Bound::Excluded(_) => match this_side {
122 BoundSide::Start => Some(Ordering::Less), BoundSide::End => Some(Ordering::Greater), },
125 Bound::Unbounded => match (this_side, other_side) {
126 (BoundSide::Start, BoundSide::Start) => Some(Ordering::Equal),
127 (BoundSide::End, BoundSide::End) => Some(Ordering::Equal),
128 (BoundSide::Start, BoundSide::End) => Some(Ordering::Less),
129 (BoundSide::End, BoundSide::Start) => Some(Ordering::Greater),
130 },
131 },
132 }
133}
134
135fn expect_bound<'a, Idx>(bound: Option<Bound<&'a Idx>>, msg: &'static str) -> &'a Idx {
137 match bound.expect(msg) {
138 Bound::Included(x) => x,
139 Bound::Excluded(x) => x,
140 Bound::Unbounded => panic!("{}", msg),
141 }
142}
143
144fn reverse_bound<Idx>(bound: Bound<&Idx>) -> Bound<&Idx> {
148 match bound {
149 Bound::Included(x) => Bound::Excluded(x),
150 Bound::Excluded(x) => Bound::Included(x),
151 Bound::Unbounded => Bound::Unbounded,
152 }
153}
154
155impl<Idx: PartialOrd + Clone> ContinuousRange<Idx> {
156 #[must_use]
160 pub fn empty() -> ContinuousRange<Idx> {
161 ContinuousRange::Empty
162 }
163
164 #[must_use]
168 pub fn single(value: Idx) -> ContinuousRange<Idx> {
169 ContinuousRange::Single(value)
170 }
171
172 #[must_use]
176 pub fn inclusive(start: Idx, end: Idx) -> ContinuousRange<Idx>
177 where
178 Idx: PartialOrd,
179 {
180 if start == end {
181 ContinuousRange::Single(start)
182 } else if start > end {
183 ContinuousRange::Empty
184 } else {
185 ContinuousRange::Inclusive(start, end)
186 }
187 }
188
189 #[must_use]
193 pub fn exclusive(start: Idx, end: Idx) -> ContinuousRange<Idx>
194 where
195 Idx: PartialOrd,
196 {
197 if start >= end {
198 ContinuousRange::Empty
199 } else {
200 ContinuousRange::Exclusive(start, end)
201 }
202 }
203
204 #[must_use]
208 pub fn start_exclusive(start: Idx, end: Idx) -> ContinuousRange<Idx>
209 where
210 Idx: PartialOrd,
211 {
212 if start >= end {
213 ContinuousRange::Empty
214 } else {
215 ContinuousRange::StartExclusive(start, end)
216 }
217 }
218
219 #[must_use]
223 pub fn end_exclusive(start: Idx, end: Idx) -> ContinuousRange<Idx>
224 where
225 Idx: PartialOrd,
226 {
227 if start >= end {
228 ContinuousRange::Empty
229 } else {
230 ContinuousRange::EndExclusive(start, end)
231 }
232 }
233
234 #[must_use]
238 pub fn from(start: Idx) -> ContinuousRange<Idx> {
239 ContinuousRange::From(start)
240 }
241
242 #[must_use]
246 pub fn from_exclusive(start: Idx) -> ContinuousRange<Idx> {
247 ContinuousRange::FromExclusive(start)
248 }
249
250 #[must_use]
254 pub fn to(end: Idx) -> ContinuousRange<Idx> {
255 ContinuousRange::To(end)
256 }
257
258 #[must_use]
262 pub fn to_exclusive(end: Idx) -> ContinuousRange<Idx> {
263 ContinuousRange::ToExclusive(end)
264 }
265
266 #[must_use]
268 pub fn full() -> ContinuousRange<Idx> {
269 ContinuousRange::Full
270 }
271
272 #[must_use]
274 pub fn from_bounds(bounds: (Bound<&Idx>, Bound<&Idx>)) -> Self {
275 match bounds {
276 (Bound::Unbounded, Bound::Unbounded) => Self::full(),
277 (Bound::Included(start), Bound::Included(end)) => {
278 Self::inclusive(start.clone(), end.clone())
279 }
280 (Bound::Included(start), Bound::Excluded(end)) => {
281 Self::end_exclusive(start.clone(), end.clone())
282 }
283 (Bound::Included(start), Bound::Unbounded) => Self::from(start.clone()),
284 (Bound::Excluded(start), Bound::Included(end)) => {
285 Self::start_exclusive(start.clone(), end.clone())
286 }
287 (Bound::Excluded(start), Bound::Excluded(end)) => {
288 Self::exclusive(start.clone(), end.clone())
289 }
290 (Bound::Excluded(start), Bound::Unbounded) => Self::from_exclusive(start.clone()),
291 (Bound::Unbounded, Bound::Included(end)) => Self::to(end.clone()),
292 (Bound::Unbounded, Bound::Excluded(end)) => Self::to_exclusive(end.clone()),
293 }
294 }
295
296 #[must_use]
298 pub fn range_bounds(&self) -> Option<(Bound<&Idx>, Bound<&Idx>)> {
299 match self {
300 Self::Empty => {
301 None
306 }
307 Self::Single(value) => Some((Bound::Included(value), Bound::Included(value))),
308 Self::Inclusive(start, end) => Some((Bound::Included(start), Bound::Included(end))),
309 Self::Exclusive(start, end) => Some((Bound::Excluded(start), Bound::Excluded(end))),
310 Self::StartExclusive(start, end) => {
311 Some((Bound::Excluded(start), Bound::Included(end)))
312 }
313 Self::EndExclusive(start, end) => Some((Bound::Included(start), Bound::Excluded(end))),
314 Self::From(start) => Some((Bound::Included(start), Bound::Unbounded)),
315 Self::FromExclusive(start) => Some((Bound::Excluded(start), Bound::Unbounded)),
316 Self::To(end) => Some((Bound::Unbounded, Bound::Included(end))),
317 Self::ToExclusive(end) => Some((Bound::Unbounded, Bound::Excluded(end))),
318 Self::Full => Some((Bound::Unbounded, Bound::Unbounded)),
319 }
320 }
321
322 #[must_use]
323 pub fn start(&self) -> Option<Bound<&Idx>> {
324 match self {
325 Self::Empty => None,
326 Self::Single(value) => Some(Bound::Included(value)),
327 Self::Inclusive(start, _) => Some(Bound::Included(start)),
328 Self::Exclusive(start, _) => Some(Bound::Excluded(start)),
329 Self::StartExclusive(start, _) => Some(Bound::Excluded(start)),
330 Self::EndExclusive(start, _) => Some(Bound::Included(start)),
331 Self::From(start) => Some(Bound::Included(start)),
332 Self::FromExclusive(start) => Some(Bound::Excluded(start)),
333 Self::To(_) | Self::ToExclusive(_) | Self::Full => Some(Bound::Unbounded),
334 }
335 }
336
337 #[must_use]
338 pub fn end(&self) -> Option<Bound<&Idx>> {
339 match self {
340 Self::Empty => None,
341 Self::Single(value) => Some(Bound::Included(value)),
342 Self::Inclusive(_, end) => Some(Bound::Included(end)),
343 Self::Exclusive(_, end) => Some(Bound::Excluded(end)),
344 Self::StartExclusive(_, end) => Some(Bound::Included(end)),
345 Self::EndExclusive(_, end) => Some(Bound::Excluded(end)),
346 Self::To(end) => Some(Bound::Included(end)),
347 Self::ToExclusive(end) => Some(Bound::Excluded(end)),
348 Self::From(_) | Self::FromExclusive(_) | Self::Full => Some(Bound::Unbounded),
349 }
350 }
351
352 #[must_use]
354 pub fn contains(&self, value: impl Borrow<Idx>) -> bool
355 where
356 Idx: PartialOrd + PartialEq,
357 {
358 match self {
359 Self::Empty => false,
360 Self::Single(single_value) => single_value == value.borrow(),
361 Self::Inclusive(start, end) => {
362 let value = value.borrow();
363 value >= start && value <= end
364 }
365 Self::Exclusive(start, end) => {
366 let value = value.borrow();
367 value > start && value < end
368 }
369 Self::StartExclusive(start, end) => {
370 let value = value.borrow();
371 value > start && value <= end
372 }
373 Self::EndExclusive(start, end) => {
374 let value = value.borrow();
375 value >= start && value < end
376 }
377 Self::From(start) => value.borrow() >= start,
378 Self::FromExclusive(start) => value.borrow() > start,
379 Self::To(end) => value.borrow() <= end,
380 Self::ToExclusive(end) => value.borrow() < end,
381 Self::Full => true,
382 }
383 }
384
385 #[must_use]
386 pub fn contains_range(&self, other: &ContinuousRange<Idx>) -> bool
387 where
388 Idx: std::fmt::Debug,
389 {
390 self.compare(other).map_or(false, |r| r.contains())
391 }
392
393 #[must_use]
394 pub fn disjoint_from_range(&self, other: &ContinuousRange<Idx>) -> bool
395 where
396 Idx: std::fmt::Debug,
397 {
398 self.compare(other).map_or(true, |r| r.disjoint())
399 }
400
401 #[must_use]
402 #[allow(clippy::missing_panics_doc)]
403 pub fn union(&self, other: &ContinuousRange<Idx>) -> Option<ContinuousRange<Idx>>
404 where
405 Idx: PartialOrd + std::fmt::Debug,
406 {
407 match (self, other) {
408 (ContinuousRange::Empty, r) | (r, ContinuousRange::Empty) => Some(r.clone()),
409 (ContinuousRange::Full, _) | (_, ContinuousRange::Full) => Some(ContinuousRange::Full),
410 _ => match self.compare(other) {
411 Some(cmp) => match cmp {
412 RangesRelation::StrictlyBefore => None,
413 RangesRelation::StrictlyAfter => None,
414 RangesRelation::Meets => {
415 let start = self.start().expect("Self meets without bounds");
416 let end = other.end().expect("Other meets without bounds");
417 Some(ContinuousRange::from_bounds((start, end)))
418 }
419 RangesRelation::IsMet => {
420 let end = self.end().expect("Self meets without bounds");
421 let start = other.start().expect("Other meets without bounds");
422 Some(ContinuousRange::from_bounds((start, end)))
423 }
424 RangesRelation::Overlaps => {
425 let start = self.start().expect("Self meets without bounds");
426 let end = other.end().expect("Other meets without bounds");
427 Some(ContinuousRange::from_bounds((start, end)))
428 }
429 RangesRelation::IsOverlapped => {
430 let end = self.end().expect("Self meets without bounds");
431 let start = other.start().expect("Other meets without bounds");
432 Some(ContinuousRange::from_bounds((start, end)))
433 }
434 RangesRelation::Starts => Some(other.clone()),
435 RangesRelation::IsStarted => Some(self.clone()),
436 RangesRelation::StrictlyContains => Some(self.clone()),
437 RangesRelation::IsStrictlyContained => Some(other.clone()),
438 RangesRelation::Finishes => Some(other.clone()),
439 RangesRelation::IsFinished => Some(self.clone()),
440 RangesRelation::Equal => Some(self.clone()),
441 },
442 None => None,
443 },
444 }
445 }
446
447 #[must_use]
448 #[allow(clippy::missing_panics_doc)]
449 pub fn intersection(&self, other: &ContinuousRange<Idx>) -> ContinuousRange<Idx>
450 where
451 Idx: PartialOrd + std::fmt::Debug,
452 {
453 match (self, other) {
454 (ContinuousRange::Empty, _) | (_, ContinuousRange::Empty) => ContinuousRange::Empty,
455 (ContinuousRange::Full, r) | (r, ContinuousRange::Full) => r.clone(),
456 _ => match self.compare(other) {
457 Some(cmp) => match cmp {
458 RangesRelation::StrictlyBefore => ContinuousRange::Empty,
459 RangesRelation::StrictlyAfter => ContinuousRange::Empty,
460 RangesRelation::Meets => {
461 let end = expect_bound(self.end(), "Self meets without end bound");
462 ContinuousRange::single(end.clone())
463 }
464 RangesRelation::IsMet => {
465 let start = expect_bound(self.start(), "Self is met without start bound");
466 ContinuousRange::single(start.clone())
467 }
468 RangesRelation::Overlaps => {
469 let (_, end) = self.range_bounds().expect("Self overlaps without bounds");
470 let (start, _) = other
471 .range_bounds()
472 .expect("Other is overlapped without bounds");
473 ContinuousRange::from_bounds((start, end))
474 }
475 RangesRelation::IsOverlapped => {
476 let (start, _) = self
477 .range_bounds()
478 .expect("Self is overlapped without bounds");
479 let (_, end) = other.range_bounds().expect("Other overlaps without bounds");
480 ContinuousRange::from_bounds((start, end))
481 }
482 RangesRelation::Starts => self.clone(),
483 RangesRelation::IsStarted => other.clone(),
484
485 RangesRelation::StrictlyContains => other.clone(),
486 RangesRelation::IsStrictlyContained => self.clone(),
487 RangesRelation::Finishes => self.clone(),
488 RangesRelation::IsFinished => other.clone(),
489 RangesRelation::Equal => self.clone(),
490 },
491 None => ContinuousRange::Empty,
492 },
493 }
494 }
495
496 #[must_use]
497 #[allow(clippy::missing_panics_doc)]
498 pub fn difference(&self, other: &ContinuousRange<Idx>) -> Option<ContinuousRange<Idx>>
499 where
500 Idx: PartialOrd + std::fmt::Debug,
501 {
502 match (self, other) {
503 (ContinuousRange::Empty, r) => Some(r.clone()),
504 (_, ContinuousRange::Empty) => Some(ContinuousRange::Empty),
505 _ => match self.compare(other) {
506 Some(cmp) => match cmp {
507 RangesRelation::StrictlyBefore => Some(self.clone()),
508 RangesRelation::StrictlyAfter => Some(self.clone()),
509 RangesRelation::Equal => Some(ContinuousRange::Empty),
510 RangesRelation::IsStrictlyContained => Some(ContinuousRange::Empty),
511 RangesRelation::StrictlyContains => None,
512
513 RangesRelation::Meets => {
514 let (start, end) = self.range_bounds().expect("Self meets without bounds");
515 let end = reverse_bound(end);
516 Some(ContinuousRange::from_bounds((start, end)))
517 }
518 RangesRelation::IsMet => {
519 let (start, end) = self.range_bounds().expect("Self is met without bounds");
520 let start = reverse_bound(start);
521 Some(ContinuousRange::from_bounds((start, end)))
522 }
523 RangesRelation::Overlaps => {
524 let start = self.start().expect("Self overlaps without bounds");
525 let end = other.start().expect("Other is overlapped without bounds");
526 let end = reverse_bound(end);
527 Some(ContinuousRange::from_bounds((start, end)))
528 }
529 RangesRelation::IsOverlapped => {
530 let end = self.end().expect("Self is overlapped without bounds");
531 let start = other.end().expect("Other overlaps without bounds");
532 let start = reverse_bound(start);
533 Some(ContinuousRange::from_bounds((start, end)))
534 }
535 RangesRelation::Starts => Some(ContinuousRange::Empty),
536 RangesRelation::IsStarted => {
537 let end = self.end().expect("Self is overlapped without bounds");
538 let start = other.end().expect("Other overlaps without bounds");
539 let start = reverse_bound(start);
540 Some(ContinuousRange::from_bounds((start, end)))
541 }
542 RangesRelation::Finishes => Some(ContinuousRange::Empty),
543 RangesRelation::IsFinished => {
544 let start = self.start().expect("Self overlaps without bounds");
545 let end = other.start().expect("Other is overlapped without bounds");
546 let end = reverse_bound(end);
547 Some(ContinuousRange::from_bounds((start, end)))
548 }
549 },
550 None => None,
551 },
552 }
553 }
554
555 #[must_use]
556 pub fn intersects(&self, other: &ContinuousRange<Idx>) -> bool
557 where
558 Idx: std::fmt::Debug,
559 {
560 if self.is_empty() && other.is_empty() {
562 false
563 } else {
564 match self.compare(other) {
565 Some(relation) => relation.intersects(),
566 None => false,
567 }
568 }
569 }
570
571 #[must_use]
572 pub fn compare(&self, other: &ContinuousRange<Idx>) -> Option<RangesRelation>
579 where
580 Idx: std::fmt::Debug,
581 {
582 if self.is_empty() {
587 return if other.is_empty() {
588 Some(RangesRelation::Equal)
589 } else {
590 None
591 };
592 } else if other.is_empty() {
593 return None;
594 }
595
596 let (self_start, self_end) = self
597 .range_bounds()
598 .expect("Non-empty self should have bounds");
599 let (other_start, other_end) = other
600 .range_bounds()
601 .expect("Non-empty other should have bounds");
602
603 let cmp_end_start =
604 partial_cmp_bounds(&self_end, BoundSide::End, &other_start, BoundSide::Start)?;
605
606 if cmp_end_start == Ordering::Less {
607 return Some(RangesRelation::StrictlyBefore);
608 }
609
610 let cmp_start_end =
611 partial_cmp_bounds(&self_start, BoundSide::Start, &other_end, BoundSide::End)?;
612
613 if cmp_start_end == Ordering::Greater {
614 return Some(RangesRelation::StrictlyAfter);
615 }
616
617 let self_cmp =
618 partial_cmp_bounds(&self_start, BoundSide::Start, &self_end, BoundSide::End)?;
619
620 let other_cmp =
621 partial_cmp_bounds(&other_start, BoundSide::Start, &other_end, BoundSide::End)?;
622
623 if cmp_end_start == Ordering::Equal
624 && self_cmp != Ordering::Equal
625 && other_cmp != Ordering::Equal
626 {
627 return Some(RangesRelation::Meets);
628 }
629 if cmp_start_end == Ordering::Equal
630 && self_cmp != Ordering::Equal
631 && other_cmp != Ordering::Equal
632 {
633 return Some(RangesRelation::IsMet);
634 }
635
636 let cmp_start_start = partial_cmp_bounds(
637 &self_start,
638 BoundSide::Start,
639 &other_start,
640 BoundSide::Start,
641 )?;
642
643 let cmp_end_end =
644 partial_cmp_bounds(&self_end, BoundSide::End, &other_end, BoundSide::End)?;
645
646 if cmp_start_start == Ordering::Less
647 && cmp_end_start == Ordering::Greater
648 && cmp_end_end == Ordering::Less
649 {
650 return Some(RangesRelation::Overlaps);
651 }
652 if cmp_start_start == Ordering::Greater
653 && cmp_start_end == Ordering::Less
654 && cmp_end_end == Ordering::Greater
655 {
656 return Some(RangesRelation::IsOverlapped);
657 }
658 if cmp_start_start == Ordering::Equal && cmp_end_end == Ordering::Less {
659 return Some(RangesRelation::Starts);
660 }
661 if cmp_start_start == Ordering::Equal && cmp_end_end == Ordering::Greater {
662 return Some(RangesRelation::IsStarted);
663 }
664 if cmp_start_start == Ordering::Greater && cmp_end_end == Ordering::Equal {
665 return Some(RangesRelation::Finishes);
666 }
667 if cmp_start_start == Ordering::Less && cmp_end_end == Ordering::Equal {
668 return Some(RangesRelation::IsFinished);
669 }
670 if cmp_start_start == Ordering::Less && cmp_end_end == Ordering::Greater {
671 return Some(RangesRelation::StrictlyContains);
672 }
673 if cmp_start_start == Ordering::Greater && cmp_end_end == Ordering::Less {
674 return Some(RangesRelation::IsStrictlyContained);
675 }
676 if cmp_start_start == Ordering::Equal && cmp_end_end == Ordering::Equal {
677 return Some(RangesRelation::Equal);
678 }
679
680 panic!(
682 r"PartialOrd contract isn't correctly implemented.
683No ordering can be found between {self:?} and {other:?}",
684 self = &self,
685 other = &other
686 );
687 }
688
689 pub fn simplify_mut(&mut self)
690 where
691 Idx: PartialOrd,
692 {
693 match self {
694 ContinuousRange::Inclusive(start, end) => {
695 if start == end {
696 *self = ContinuousRange::Single(start.clone());
697 } else if start > end {
698 *self = ContinuousRange::Empty;
699 }
700 }
701 ContinuousRange::Exclusive(start, end)
702 | ContinuousRange::StartExclusive(start, end)
703 | ContinuousRange::EndExclusive(start, end) => {
704 if start >= end {
705 *self = ContinuousRange::Empty;
706 }
707 }
708 ContinuousRange::Empty
709 | ContinuousRange::Single(_)
710 | ContinuousRange::From(_)
711 | ContinuousRange::FromExclusive(_)
712 | ContinuousRange::To(_)
713 | ContinuousRange::ToExclusive(_)
714 | ContinuousRange::Full => {}
715 }
716 }
717
718 #[must_use]
719 pub fn simplify(&self) -> Self
720 where
721 Idx: PartialOrd,
722 {
723 let mut clone = (*self).clone();
724 clone.simplify_mut();
725 clone
726 }
727
728 #[must_use]
729 pub fn is_empty(&self) -> bool {
730 match self {
731 Self::Empty => true,
732
733 Self::Inclusive(start, end) => start > end,
735 Self::Exclusive(start, end)
736 | Self::StartExclusive(start, end)
737 | Self::EndExclusive(start, end) => start >= end,
738
739 Self::Single(_)
740
741 | Self::From(_)
743 | Self::FromExclusive(_)
744 | Self::To(_)
745 | Self::ToExclusive(_)
746 | Self::Full => false,
747 }
748 }
749
750 #[must_use]
751 pub fn is_full(&self) -> bool {
752 match self {
753 Self::Full => true,
754 _ => false,
755 }
756 }
757}
758
759impl<Idx: PartialOrd + Clone> From<()> for ContinuousRange<Idx> {
760 fn from(_: ()) -> Self {
761 Self::empty()
762 }
763}
764
765impl<Idx: PartialOrd + Clone> From<ops::RangeFull> for ContinuousRange<Idx> {
766 fn from(_: ops::RangeFull) -> Self {
767 Self::full()
768 }
769}
770
771impl<Idx: PartialOrd + Clone> From<ops::Range<Idx>> for ContinuousRange<Idx> {
772 fn from(r: ops::Range<Idx>) -> Self {
773 Self::end_exclusive(r.start, r.end)
774 }
775}
776
777impl<Idx: PartialOrd + Clone> From<ops::RangeInclusive<Idx>> for ContinuousRange<Idx> {
778 fn from(r: ops::RangeInclusive<Idx>) -> Self {
779 let (start, end) = r.into_inner();
780 Self::inclusive(start, end)
781 }
782}
783
784impl<Idx: PartialOrd + Clone> From<ops::RangeFrom<Idx>> for ContinuousRange<Idx> {
785 fn from(r: ops::RangeFrom<Idx>) -> Self {
786 Self::from(r.start)
787 }
788}
789
790impl<Idx: PartialOrd + Clone> From<ops::RangeToInclusive<Idx>> for ContinuousRange<Idx> {
791 fn from(r: ops::RangeToInclusive<Idx>) -> Self {
792 Self::to(r.end)
793 }
794}
795
796impl<Idx: PartialOrd + Clone> From<ops::RangeTo<Idx>> for ContinuousRange<Idx> {
797 fn from(r: ops::RangeTo<Idx>) -> Self {
798 Self::to_exclusive(r.end)
799 }
800}
801
802impl<Idx: fmt::Debug> fmt::Debug for ContinuousRange<Idx> {
803 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
804 match self {
805 ContinuousRange::Empty => write!(fmt, "[]")?,
806 ContinuousRange::Single(value) => value.fmt(fmt)?,
807 ContinuousRange::Full => write!(fmt, "(..)")?,
808 ContinuousRange::Inclusive(start, end) => {
809 write!(fmt, "[")?;
810 start.fmt(fmt)?;
811 write!(fmt, "..")?;
812 end.fmt(fmt)?;
813 write!(fmt, "]")?;
814 }
815 ContinuousRange::Exclusive(start, end) => {
816 write!(fmt, "(")?;
817 start.fmt(fmt)?;
818 write!(fmt, "..")?;
819 end.fmt(fmt)?;
820 write!(fmt, ")")?;
821 }
822 ContinuousRange::StartExclusive(start, end) => {
823 write!(fmt, "(")?;
824 start.fmt(fmt)?;
825 write!(fmt, "..")?;
826 end.fmt(fmt)?;
827 write!(fmt, "]")?;
828 }
829 ContinuousRange::EndExclusive(start, end) => {
830 write!(fmt, "[")?;
831 start.fmt(fmt)?;
832 write!(fmt, "..")?;
833 end.fmt(fmt)?;
834 write!(fmt, ")")?;
835 }
836 ContinuousRange::From(start) => {
837 write!(fmt, "[")?;
838 start.fmt(fmt)?;
839 write!(fmt, "..")?;
840 write!(fmt, ")")?;
841 }
842 ContinuousRange::FromExclusive(start) => {
843 write!(fmt, "(")?;
844 start.fmt(fmt)?;
845 write!(fmt, "..")?;
846 write!(fmt, ")")?;
847 }
848 ContinuousRange::To(end) => {
849 write!(fmt, "(")?;
850 write!(fmt, "..")?;
851 end.fmt(fmt)?;
852 write!(fmt, "]")?;
853 }
854 ContinuousRange::ToExclusive(end) => {
855 write!(fmt, "(")?;
856 write!(fmt, "..")?;
857 end.fmt(fmt)?;
858 write!(fmt, ")")?;
859 }
860 }
861 Ok(())
862 }
863}
864
865impl<Idx> Default for ContinuousRange<Idx> {
866 fn default() -> Self {
867 Self::Empty
868 }
869}