Skip to main content

allen_intervals/interval/
interval.rs

1use core::ops::{Range, RangeInclusive};
2
3use crate::{
4    Contains, Equals, Finishes, IntervalFrom, IntervalFull, IntervalTo, Meets, NonEmpty, Overlaps,
5    Precedes, Starts,
6};
7
8/// A (half-open) interval bounded inclusively below
9/// and either exclusively or inclusively above.
10///
11/// - exclusively above (`start..end`) in discrete domains.
12/// - inclusively above (`start..=end`) in continuous domains.
13///
14/// The interval `Interval { start, end }` contains all values with `start <= x < end`,
15/// if `T` is a discrete domain, or `start <= x <= end`, if `T` is a continuous domain.
16///
17/// It is empty if `start >= end`, if `T` is a discrete domain,
18/// or `start > end` if `T` is a continuous domain.
19#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
20pub struct Interval<T> {
21    /// The lower bound of the interval (inclusive).
22    pub start: T,
23    /// The upper bound of the interval (exclusive, or inclusive).
24    pub end: T,
25}
26
27impl<T> From<Range<T>> for Interval<T> {
28    fn from(value: Range<T>) -> Self {
29        let Range { start, end } = value;
30        Self { start, end }
31    }
32}
33
34impl<T> From<Interval<T>> for Range<T> {
35    fn from(value: Interval<T>) -> Self {
36        (value.start)..(value.end)
37    }
38}
39
40impl<T> From<RangeInclusive<T>> for Interval<T>
41where
42    T: Copy,
43{
44    fn from(value: RangeInclusive<T>) -> Self {
45        let start = *value.start();
46        let end = *value.end();
47        Self { start, end }
48    }
49}
50
51impl<T> From<Interval<T>> for RangeInclusive<T>
52where
53    T: Copy,
54{
55    fn from(value: Interval<T>) -> Self {
56        (value.start)..=(value.end)
57    }
58}
59
60// Interval<T> vs. IntervalFull
61
62impl<T> Precedes<NonEmpty<IntervalFull>> for NonEmpty<Interval<T>> {}
63
64impl<T> Meets<NonEmpty<IntervalFull>> for NonEmpty<Interval<T>> {}
65
66impl<T> Overlaps<NonEmpty<IntervalFull>> for NonEmpty<Interval<T>> {}
67
68impl<T> Starts<NonEmpty<IntervalFull>> for NonEmpty<Interval<T>> {}
69
70impl<T> Contains<NonEmpty<IntervalFull>> for NonEmpty<Interval<T>> {}
71
72impl<T> Finishes<NonEmpty<IntervalFull>> for NonEmpty<Interval<T>> {}
73
74impl<T> Equals<NonEmpty<IntervalFull>> for NonEmpty<Interval<T>> {}
75
76// Interval<T> vs. IntervalTo
77
78impl<T> Precedes<NonEmpty<IntervalTo<T>>> for NonEmpty<Interval<T>> {}
79
80impl<T> Meets<NonEmpty<IntervalTo<T>>> for NonEmpty<Interval<T>> {}
81
82impl<T> Overlaps<NonEmpty<IntervalTo<T>>> for NonEmpty<Interval<T>> {}
83
84impl<T> Starts<NonEmpty<IntervalTo<T>>> for NonEmpty<Interval<T>>
85where
86    T: PartialOrd,
87{
88    #[inline]
89    fn starts(&self, other: &NonEmpty<IntervalTo<T>>) -> bool {
90        self.0.end < other.0.end
91    }
92}
93
94impl<T> Contains<NonEmpty<IntervalTo<T>>> for NonEmpty<Interval<T>> {}
95
96impl<T> Finishes<NonEmpty<IntervalTo<T>>> for NonEmpty<Interval<T>>
97where
98    T: PartialOrd,
99{
100    #[inline]
101    fn finishes(&self, other: &NonEmpty<IntervalTo<T>>) -> bool {
102        self.0.end == other.0.end
103    }
104}
105
106impl<T> Equals<NonEmpty<IntervalTo<T>>> for NonEmpty<Interval<T>> {}
107
108// Interval<T> vs. IntervalFrom
109
110impl<T> Precedes<NonEmpty<IntervalFrom<T>>> for NonEmpty<Interval<T>>
111where
112    T: PartialOrd,
113{
114    #[inline]
115    fn precedes(&self, other: &NonEmpty<IntervalFrom<T>>) -> bool {
116        self.0.end < other.0.start
117    }
118}
119
120impl<T> Meets<NonEmpty<IntervalFrom<T>>> for NonEmpty<Interval<T>>
121where
122    T: PartialOrd,
123{
124    #[inline]
125    fn meets(&self, other: &NonEmpty<IntervalFrom<T>>) -> bool {
126        self.0.end == other.0.start
127    }
128}
129
130impl<T> Overlaps<NonEmpty<IntervalFrom<T>>> for NonEmpty<Interval<T>>
131where
132    T: PartialOrd,
133{
134    #[inline]
135    fn overlaps(&self, other: &NonEmpty<IntervalFrom<T>>) -> bool {
136        (self.0.start < other.0.start) && (other.0.start < self.0.end)
137    }
138}
139
140impl<T> Starts<NonEmpty<IntervalFrom<T>>> for NonEmpty<Interval<T>>
141where
142    T: PartialOrd,
143{
144    #[inline]
145    fn starts(&self, other: &NonEmpty<IntervalFrom<T>>) -> bool {
146        self.0.start == other.0.start
147    }
148}
149
150impl<T> Contains<NonEmpty<IntervalFrom<T>>> for NonEmpty<Interval<T>> {}
151
152impl<T> Finishes<NonEmpty<IntervalFrom<T>>> for NonEmpty<Interval<T>>
153where
154    T: PartialOrd,
155{
156    #[inline]
157    fn finishes(&self, other: &NonEmpty<IntervalFrom<T>>) -> bool {
158        self.0.start > other.0.start
159    }
160}
161
162impl<T> Equals<NonEmpty<IntervalFrom<T>>> for NonEmpty<Interval<T>> {}
163
164// Interval<T> vs. Interval
165
166impl<T> Precedes<NonEmpty<Interval<T>>> for NonEmpty<Interval<T>>
167where
168    T: PartialOrd,
169{
170    #[inline]
171    fn precedes(&self, other: &NonEmpty<Interval<T>>) -> bool {
172        self.0.end < other.0.start
173    }
174}
175
176impl<T> Meets<NonEmpty<Interval<T>>> for NonEmpty<Interval<T>>
177where
178    T: PartialOrd,
179{
180    #[inline]
181    fn meets(&self, other: &NonEmpty<Interval<T>>) -> bool {
182        self.0.end == other.0.start
183    }
184}
185
186impl<T> Overlaps<NonEmpty<Interval<T>>> for NonEmpty<Interval<T>>
187where
188    T: PartialOrd,
189{
190    #[inline]
191    fn overlaps(&self, other: &NonEmpty<Interval<T>>) -> bool {
192        (self.0.start < other.0.start) && (other.0.start < self.0.end) && (self.0.end < other.0.end)
193    }
194}
195
196impl<T> Starts<NonEmpty<Interval<T>>> for NonEmpty<Interval<T>>
197where
198    T: PartialOrd,
199{
200    #[inline]
201    fn starts(&self, other: &NonEmpty<Interval<T>>) -> bool {
202        (self.0.start == other.0.start) && (self.0.end < other.0.end)
203    }
204}
205
206impl<T> Contains<NonEmpty<Interval<T>>> for NonEmpty<Interval<T>>
207where
208    T: PartialOrd,
209{
210    #[inline]
211    fn contains(&self, other: &NonEmpty<Interval<T>>) -> bool {
212        (self.0.start < other.0.start) && (self.0.end > other.0.end)
213    }
214}
215
216impl<T> Finishes<NonEmpty<Interval<T>>> for NonEmpty<Interval<T>>
217where
218    T: PartialOrd,
219{
220    #[inline]
221    fn finishes(&self, other: &NonEmpty<Interval<T>>) -> bool {
222        (self.0.start > other.0.start) && (self.0.end == other.0.end)
223    }
224}
225
226impl<T> Equals<NonEmpty<Interval<T>>> for NonEmpty<Interval<T>>
227where
228    T: PartialOrd,
229{
230    #[inline]
231    fn equals(&self, other: &NonEmpty<Interval<T>>) -> bool {
232        (self.0.start == other.0.start) && (self.0.end == other.0.end)
233    }
234}