baseunits_rs/intervals/
interval_limit.rs1use std::cmp::Ordering;
2use crate::intervals::LimitValue;
3
4#[derive(Debug, Clone)]
5pub struct IntervalLimit<T> {
6 pub(crate) closed: bool,
7 pub(crate) lower: bool,
8 pub(crate) value: LimitValue<T>,
9}
10
11impl<T: Default + Clone + PartialOrd> Default for IntervalLimit<T> {
12 fn default() -> Self {
13 IntervalLimit::new(false, false, LimitValue::default())
14 }
15}
16
17impl<T: Default + Clone + PartialEq + PartialOrd> PartialOrd for IntervalLimit<T> {
18 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
19 match (&self.value, &other.value) {
20 (LimitValue::<T>::Limitless, LimitValue::<T>::Limitless) => {
21 if self.lower == other.lower {
22 Some(Ordering::Equal)
23 } else {
24 Some(self.lower_to_ordering(Ordering::Less, Ordering::Greater))
25 }
26 }
27 (LimitValue::<T>::Limitless, _) => {
28 Some(self.lower_to_ordering(Ordering::Less, Ordering::Greater))
29 }
30 (_, LimitValue::<T>::Limitless) => {
31 Some(other.lower_to_ordering(Ordering::Greater, Ordering::Less))
32 }
33 (LimitValue::<T>::Limit(ref lv), LimitValue::<T>::Limit(ref other_lv)) if lv == other_lv => {
34 match (self.lower, other.lower) {
35 (l, other_l) if l == other_l => {
36 if self.closed ^ other.closed {
37 Some(self.closed_to_ordering(Ordering::Greater, Ordering::Less))
38 } else {
39 Some(Ordering::Equal)
40 }
41 }
42 (l, other_l) if !l == !other_l => {
43 if self.closed ^ other.closed {
44 Some(self.closed_to_ordering(Ordering::Less, Ordering::Greater))
45 } else {
46 Some(Ordering::Equal)
47 }
48 }
49 _ => self.value.partial_cmp(&other.value),
50 }
51 }
52 _ => self.value.partial_cmp(&other.value),
53 }
54 }
55}
56
57impl<T: Default + Clone + PartialOrd> PartialEq for IntervalLimit<T> {
58 fn eq(&self, other: &Self) -> bool {
59 self.partial_cmp(other).unwrap() == Ordering::Equal
60 }
61}
62
63impl<T: Default + Clone + PartialEq + PartialOrd> IntervalLimit<T> {
64 pub fn new(closed: bool, lower: bool, value: LimitValue<T>) -> Self {
65 Self {
66 closed,
67 lower,
68 value,
69 }
70 }
71
72 pub fn lower(closed: bool, value: LimitValue<T>) -> Self {
73 Self::new(closed, true, value)
74 }
75
76 pub fn upper(closed: bool, value: LimitValue<T>) -> Self {
77 Self::new(closed, false, value)
78 }
79
80 fn lower_to_ordering<A>(&self, t: A, f: A) -> A {
81 if self.lower {
82 t
83 } else {
84 f
85 }
86 }
87
88 fn closed_to_ordering<A>(&self, t: A, f: A) -> A {
89 if self.closed {
90 t
91 } else {
92 f
93 }
94 }
95
96 pub fn infinity(&self) -> bool {
97 match self.value {
98 LimitValue::<T>::Limitless => true,
99 LimitValue::<T>::Limit(_) => false,
100 }
101 }
102
103 pub fn is_open(&self) -> bool {
104 !self.closed
105 }
106
107 pub fn is_upper(&self) -> bool {
108 !self.lower
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115 use crate::intervals::LimitValue;
116
117 #[test]
118 fn test_lower() {
119 assert_eq!(
120 IntervalLimit::lower(false, LimitValue::Limit(10)),
121 IntervalLimit::lower(false, LimitValue::Limit(10))
122 );
123 assert_ne!(
124 IntervalLimit::lower(false, LimitValue::Limit(10)),
125 IntervalLimit::lower(true, LimitValue::Limit(10))
126 );
127 assert_ne!(
128 IntervalLimit::lower(true, LimitValue::Limit(10)),
129 IntervalLimit::lower(false, LimitValue::Limit(10))
130 );
131 assert_eq!(
132 IntervalLimit::lower(true, LimitValue::Limit(10)),
133 IntervalLimit::lower(true, LimitValue::Limit(10))
134 );
135 }
136
137 #[test]
138 fn test_upper() {
139 assert_eq!(
140 IntervalLimit::upper(false, LimitValue::Limit(10)),
141 IntervalLimit::upper(false, LimitValue::Limit(10))
142 );
143 assert_ne!(
144 IntervalLimit::upper(false, LimitValue::Limit(10)),
145 IntervalLimit::upper(true, LimitValue::Limit(10))
146 );
147 assert_ne!(
148 IntervalLimit::upper(true, LimitValue::Limit(10)),
149 IntervalLimit::upper(false, LimitValue::Limit(10))
150 );
151 assert_eq!(
152 IntervalLimit::upper(true, LimitValue::Limit(10)),
153 IntervalLimit::upper(true, LimitValue::Limit(10))
154 );
155 }
156}