1use core::{
2 cmp::{max, min, Eq, Ord, Ordering, PartialEq, PartialOrd},
3 fmt::{Debug, Display},
4 ops::{Range, RangeInclusive},
5};
6use num_traits::{CheckedAdd, One};
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Copy, Clone)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub struct Interval<T: Ord> {
13 pub start: T,
14 pub end: T,
15}
16
17impl<T: Ord> Interval<T> {
18 pub fn new(start: T, end: T) -> Self {
19 Interval { start, end }
20 }
21
22 pub fn is_valid(&self) -> bool {
23 self.start < self.end
24 }
25}
26
27impl<T: Ord + Clone> Interval<T> {
28 pub fn intersect(&self, other: &Self) -> Option<Self> {
29 let result = Interval::new(
30 max(self.start.clone(), other.start.clone()),
31 min(self.end.clone(), other.end.clone()),
32 );
33 if result.is_valid() {
34 Some(result)
35 } else {
36 None
37 }
38 }
39}
40
41impl<T: Ord> PartialEq for Interval<T> {
42 fn eq(&self, other: &Self) -> bool {
43 self.start == other.start && self.end == other.end
44 }
45}
46
47impl<T: Ord> Eq for Interval<T> {}
48
49impl<T: Ord> PartialOrd for Interval<T> {
50 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
51 Some(match self.start.cmp(&other.start) {
52 Ordering::Equal => self.end.cmp(&other.end),
53 ord => ord,
54 })
55 }
56}
57
58impl<T: Ord> Ord for Interval<T> {
59 fn cmp(&self, other: &Self) -> Ordering {
60 self.partial_cmp(other).unwrap()
61 }
62}
63
64impl<T: Ord + Display> Display for Interval<T> {
65 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66 write!(f, "{}..{}", self.start, self.end)
67 }
68}
69
70impl<T: Ord + Clone> From<Range<T>> for Interval<T> {
71 fn from(range: Range<T>) -> Self {
72 Interval::new(range.start.clone(), range.end.clone())
73 }
74}
75
76impl<T: Ord + Clone> From<&Range<T>> for Interval<T> {
77 fn from(range: &Range<T>) -> Self {
78 Interval::new(range.start.clone(), range.end.clone())
79 }
80}
81
82impl<T: Ord + Clone + CheckedAdd + One> From<RangeInclusive<T>> for Interval<T> {
83 fn from(range: RangeInclusive<T>) -> Self {
84 Interval::new(range.start().clone(), range.end().clone() + T::one())
85 }
86}
87
88impl<T: Ord + Clone + CheckedAdd + One> From<&RangeInclusive<T>> for Interval<T> {
89 fn from(range: &RangeInclusive<T>) -> Self {
90 Interval::new(range.start().clone(), range.end().clone() + T::one())
91 }
92}