1use std::cmp::Ordering;
2
3use crate::{
4 Bb, Be, Bounds, Eb, Ee, FromIntervals, Interval, IntervalBounds, IntervalError, IntervalFrom,
5 IntervalFull, IntervalTo, NonEmpty, TryFromIntervals,
6};
7
8mod contains;
9mod equals;
10mod finishes;
11mod meets;
12mod overlaps;
13mod precedes;
14mod starts;
15
16pub use self::{
17 contains::*, equals::*, finishes::*, meets::*, overlaps::*, precedes::*, starts::*,
18};
19
20#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
21enum RelationOrder {
22 Precedes,
23 Meets,
24 Overlaps,
25 IsFinishedBy,
26 Contains,
27 Starts,
28 Equals,
29 IsStartedBy,
30 IsContainedBy,
31 Finishes,
32 IsOverlappedBy,
33 IsMetBy,
34 IsPrecededBy,
35}
36
37#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
44pub enum Relation {
45 Precedes {
59 is_inverted: bool,
64 },
65 Meets {
79 is_inverted: bool,
84 },
85 Overlaps {
99 is_inverted: bool,
104 },
105 Finishes {
118 is_inverted: bool,
123 },
124 Contains {
138 is_inverted: bool,
143 },
144 Starts {
158 is_inverted: bool,
163 },
164 Equals,
171}
172
173impl Relation {
174 #[inline]
175 fn from_bounds<T>(s: &Bounds<T>, t: &Bounds<T>) -> Self
176 where
177 T: Ord,
178 {
179 let bb = Bb::from_bounds(&s.start, &t.start);
180 let be = Be::from_bounds(&s.start, &t.end);
181 let eb = Eb::from_bounds(&s.end, &t.start);
182 let ee = Ee::from_bounds(&s.end, &t.end);
183
184 Self::from_atomic_relations(bb, be, eb, ee)
185 }
186
187 #[inline]
188 fn try_from_bounds<T>(s: &Bounds<T>, t: &Bounds<T>) -> Result<Self, IntervalError>
189 where
190 T: PartialOrd,
191 {
192 let bb = Bb::try_from_bounds(&s.start, &t.start)?;
193 let be = Be::try_from_bounds(&s.start, &t.end)?;
194 let eb = Eb::try_from_bounds(&s.end, &t.start)?;
195 let ee = Ee::try_from_bounds(&s.end, &t.end)?;
196
197 Ok(Self::from_atomic_relations(bb, be, eb, ee))
198 }
199
200 #[inline]
211 fn from_atomic_relations(bb: Bb, be: Be, eb: Eb, ee: Ee) -> Self {
212 use Ordering::*;
213
214 match (bb.0, be.0, eb.0, ee.0) {
215 (_, _, Less, _) => Self::Precedes { is_inverted: false },
218 (_, Greater, _, _) => Self::Precedes { is_inverted: true },
222 (_, _, Equal, _) => Self::Meets { is_inverted: false },
225 (_, Equal, _, _) => Self::Meets { is_inverted: true },
228 (Greater, _, _, Equal) => Self::Finishes { is_inverted: false },
232 (Less, _, _, Equal) => Self::Finishes { is_inverted: true },
235 (Equal, _, _, Less) => Self::Starts { is_inverted: false },
238 (Equal, _, _, Greater) => Self::Starts { is_inverted: true },
242 (Less, _, _, Greater) => Self::Contains { is_inverted: false },
246 (Greater, _, _, Less) => Self::Contains { is_inverted: true },
250 (Equal, _, _, Equal) => Self::Equals,
253 (Less, _, Greater, Less) => Self::Overlaps { is_inverted: false },
257 (Greater, Less, _, Greater) => Self::Overlaps { is_inverted: true },
261 }
262 }
263
264 fn order(&self) -> RelationOrder {
265 match self {
266 Relation::Precedes { is_inverted: false } => RelationOrder::Precedes,
267 Relation::Precedes { is_inverted: true } => RelationOrder::IsPrecededBy,
268 Relation::Meets { is_inverted: false } => RelationOrder::Meets,
269 Relation::Meets { is_inverted: true } => RelationOrder::IsMetBy,
270 Relation::Overlaps { is_inverted: false } => RelationOrder::Overlaps,
271 Relation::Overlaps { is_inverted: true } => RelationOrder::IsOverlappedBy,
272 Relation::Finishes { is_inverted: false } => RelationOrder::Finishes,
273 Relation::Finishes { is_inverted: true } => RelationOrder::IsFinishedBy,
274 Relation::Contains { is_inverted: false } => RelationOrder::Contains,
275 Relation::Contains { is_inverted: true } => RelationOrder::IsContainedBy,
276 Relation::Starts { is_inverted: false } => RelationOrder::IsStartedBy,
277 Relation::Starts { is_inverted: true } => RelationOrder::Starts,
278 Relation::Equals => RelationOrder::Equals,
279 }
280 }
281
282 pub fn as_converse(&self) -> Self {
284 match self {
285 Self::Precedes { is_inverted } => Self::Precedes {
286 is_inverted: !is_inverted,
287 },
288 Self::Meets { is_inverted } => Self::Meets {
289 is_inverted: !is_inverted,
290 },
291 Self::Overlaps { is_inverted } => Self::Overlaps {
292 is_inverted: !is_inverted,
293 },
294 Self::Finishes { is_inverted } => Self::Finishes {
295 is_inverted: !is_inverted,
296 },
297 Self::Contains { is_inverted } => Self::Contains {
298 is_inverted: !is_inverted,
299 },
300 Self::Starts { is_inverted } => Self::Starts {
301 is_inverted: !is_inverted,
302 },
303 Self::Equals => Self::Equals,
304 }
305 }
306}
307
308impl Ord for Relation {
309 #[inline]
310 fn cmp(&self, other: &Self) -> Ordering {
311 self.order().cmp(&other.order())
312 }
313}
314
315impl PartialOrd for Relation {
316 #[inline]
317 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
318 Some(self.cmp(other))
319 }
320}
321
322impl FromIntervals<IntervalFull, IntervalFull> for Relation {
323 #[inline]
324 fn from_intervals(s: &NonEmpty<IntervalFull>, t: &NonEmpty<IntervalFull>) -> Self {
325 assert_eq!(s, t);
326
327 let bb = Bb(Ordering::Equal);
328 let be = Be(Ordering::Less);
329 let eb = Eb(Ordering::Greater);
330 let ee = Ee(Ordering::Equal);
331
332 Self::from_atomic_relations(bb, be, eb, ee)
333 }
334}
335
336impl TryFromIntervals<IntervalFull, IntervalFull> for Relation {
337 #[inline]
338 fn try_from_intervals(
339 s: &NonEmpty<IntervalFull>,
340 t: &NonEmpty<IntervalFull>,
341 ) -> Result<Self, IntervalError> {
342 assert_eq!(s, t);
343
344 let bb = Bb(Ordering::Equal);
345 let be = Be(Ordering::Less);
346 let eb = Eb(Ordering::Greater);
347 let ee = Ee(Ordering::Equal);
348
349 Ok(Self::from_atomic_relations(bb, be, eb, ee))
350 }
351}
352
353macro_rules! from_intervals_impl {
354 ($s:ty, $t:ty) => {
355 impl<T> FromIntervals<$s, $t> for Relation
356 where
357 T: Ord + Copy,
358 {
359 fn from_intervals(s: &NonEmpty<$s>, t: &NonEmpty<$t>) -> Self {
360 Self::from_bounds(&s.0.bounds(), &t.0.bounds())
361 }
362 }
363
364 impl<T> TryFromIntervals<$s, $t> for Relation
365 where
366 T: PartialOrd + Copy,
367 {
368 fn try_from_intervals(
369 s: &NonEmpty<$s>,
370 t: &NonEmpty<$t>,
371 ) -> Result<Self, IntervalError> {
372 Self::try_from_bounds(&s.0.bounds(), &t.0.bounds())
373 }
374 }
375 };
376}
377
378from_intervals_impl!(IntervalFull, IntervalTo<T>);
379from_intervals_impl!(IntervalFull, IntervalFrom<T>);
380from_intervals_impl!(IntervalFull, Interval<T>);
381
382from_intervals_impl!(IntervalTo<T>, IntervalFull);
383from_intervals_impl!(IntervalTo<T>, IntervalTo<T>);
384from_intervals_impl!(IntervalTo<T>, IntervalFrom<T>);
385from_intervals_impl!(IntervalTo<T>, Interval<T>);
386
387from_intervals_impl!(IntervalFrom<T>, IntervalFull);
388from_intervals_impl!(IntervalFrom<T>, IntervalTo<T>);
389from_intervals_impl!(IntervalFrom<T>, IntervalFrom<T>);
390from_intervals_impl!(IntervalFrom<T>, Interval<T>);
391
392from_intervals_impl!(Interval<T>, IntervalFull);
393from_intervals_impl!(Interval<T>, IntervalTo<T>);
394from_intervals_impl!(Interval<T>, IntervalFrom<T>);
395from_intervals_impl!(Interval<T>, Interval<T>);
396
397#[cfg(test)]
398mod tests;