space_time/
index_range.rs

1//
2// Copyright 2020, Gobsmacked Labs, LLC.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Contains trait `IndexRange` and concrete structs `CoveredRange` and
17//! `OverlappingRange`. `IndexRange` has `Ord` so is sortable.
18
19use core::cmp::{Ord, Ordering};
20
21/// Sortable Range trait.
22pub trait IndexRange: core::fmt::Debug {
23    /// The lower index.
24    fn lower(&self) -> u64;
25
26    /// The upper index.
27    fn upper(&self) -> u64;
28
29    /// Contained.
30    fn contained(&self) -> bool;
31
32    /// Returns all three (lower, upper, contained) as a tuple.
33    fn tuple(&self) -> (u64, u64, bool) {
34        (
35            <Self as IndexRange>::lower(self),
36            <Self as IndexRange>::upper(self),
37            self.contained(),
38        )
39    }
40}
41
42impl Ord for dyn IndexRange {
43    fn cmp(&self, other: &Self) -> Ordering {
44        let l_cmp = self.lower().cmp(&other.lower());
45        if l_cmp != Ordering::Equal {
46            return l_cmp;
47        }
48        let u_cmp = self.upper().cmp(&other.upper());
49        if u_cmp != Ordering::Equal {
50            return u_cmp;
51        }
52        Ordering::Equal
53    }
54}
55
56impl PartialOrd for dyn IndexRange {
57    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
58        Some(self.cmp(other))
59    }
60}
61
62impl PartialEq for dyn IndexRange {
63    fn eq(&self, other: &Self) -> bool {
64        self.lower() == other.lower() && self.upper() == other.upper()
65    }
66}
67
68impl Eq for dyn IndexRange {}
69
70/// A covered range.
71#[derive(Debug, PartialEq, Eq)]
72pub struct CoveredRange {
73    upper: u64,
74    lower: u64,
75}
76
77impl CoveredRange {
78    /// Constructor.
79    #[must_use]
80    pub fn new(lower: u64, upper: u64) -> Self {
81        CoveredRange { upper, lower }
82    }
83}
84
85impl IndexRange for CoveredRange {
86    fn upper(&self) -> u64 {
87        self.upper
88    }
89
90    fn lower(&self) -> u64 {
91        self.lower
92    }
93
94    fn contained(&self) -> bool {
95        true
96    }
97}
98
99/// An overlapping range.
100#[derive(Debug, PartialEq, Eq)]
101pub struct OverlappingRange {
102    upper: u64,
103    lower: u64,
104}
105
106impl OverlappingRange {
107    /// Constructor.
108    #[must_use]
109    pub fn new(lower: u64, upper: u64) -> Self {
110        OverlappingRange { upper, lower }
111    }
112}
113
114impl IndexRange for OverlappingRange {
115    fn upper(&self) -> u64 {
116        self.upper
117    }
118
119    fn lower(&self) -> u64 {
120        self.lower
121    }
122
123    fn contained(&self) -> bool {
124        false
125    }
126}