1#![forbid(unsafe_code)]
44
45use core::fmt::Debug;
46use core::ops::{Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
47use std::cmp::Ordering;
48use std::ops::RangeBounds;
49
50#[derive(Clone, PartialEq, Eq, Hash)]
60pub enum AnyRange<T: Clone + PartialOrd + PartialEq> {
61 Range(Range<T>),
62 RangeFrom(RangeFrom<T>),
63 RangeFull(RangeFull),
64 RangeInclusive(RangeInclusive<T>),
65 RangeTo(RangeTo<T>),
66 RangeToInclusive(RangeToInclusive<T>),
67}
68impl<T: Clone + PartialOrd + PartialEq> AnyRange<T> {
69 #[must_use]
77 pub fn bounds(&self) -> (Bound<T>, Bound<T>) {
78 (self.start_bound().cloned(), self.end_bound().cloned())
79 }
80 pub fn contains(&self, value: &T) -> bool {
82 RangeBounds::contains(self, value)
83 }
84 pub fn start_bound(&self) -> Bound<&T> {
86 RangeBounds::start_bound(self)
87 }
88 pub fn end_bound(&self) -> Bound<&T> {
90 RangeBounds::end_bound(self)
91 }
92 fn order(&self) -> u8 {
93 match self {
94 Self::Range(_) => 0,
95 Self::RangeFrom(_) => 1,
96 Self::RangeFull(_) => 2,
97 Self::RangeInclusive(_) => 3,
98 Self::RangeTo(_) => 4,
99 Self::RangeToInclusive(_) => 5,
100 }
101 }
102}
103impl<T: Clone + PartialOrd + PartialEq> RangeBounds<T> for AnyRange<T> {
104 fn start_bound(&self) -> Bound<&T> {
105 match self {
106 Self::Range(r) => r.start_bound(),
107 Self::RangeFrom(r) => r.start_bound(),
108 Self::RangeFull(r) => r.start_bound(),
109 Self::RangeInclusive(r) => r.start_bound(),
110 Self::RangeTo(r) => r.start_bound(),
111 Self::RangeToInclusive(r) => r.start_bound(),
112 }
113 }
114 fn end_bound(&self) -> Bound<&T> {
115 match self {
116 Self::Range(r) => r.end_bound(),
117 Self::RangeFrom(r) => r.end_bound(),
118 Self::RangeFull(r) => r.end_bound(),
119 Self::RangeInclusive(r) => r.end_bound(),
120 Self::RangeTo(r) => r.end_bound(),
121 Self::RangeToInclusive(r) => r.end_bound(),
122 }
123 }
124}
125impl<T: Clone + PartialOrd + PartialEq> From<Range<T>> for AnyRange<T> {
126 fn from(r: Range<T>) -> Self {
127 Self::Range(r)
128 }
129}
130impl<T: Clone + PartialOrd + PartialEq> From<RangeFrom<T>> for AnyRange<T> {
131 fn from(r: RangeFrom<T>) -> Self {
132 Self::RangeFrom(r)
133 }
134}
135impl<T: Clone + PartialOrd + PartialEq> From<RangeFull> for AnyRange<T> {
136 fn from(r: RangeFull) -> Self {
137 Self::RangeFull(r)
138 }
139}
140impl<T: Clone + PartialOrd + PartialEq> From<RangeInclusive<T>> for AnyRange<T> {
141 fn from(r: RangeInclusive<T>) -> Self {
142 Self::RangeInclusive(r)
143 }
144}
145impl<T: Clone + PartialOrd + PartialEq> From<RangeTo<T>> for AnyRange<T> {
146 fn from(r: RangeTo<T>) -> Self {
147 Self::RangeTo(r)
148 }
149}
150impl<T: Clone + PartialOrd + PartialEq> From<RangeToInclusive<T>> for AnyRange<T> {
151 fn from(r: RangeToInclusive<T>) -> Self {
152 Self::RangeToInclusive(r)
153 }
154}
155impl<T: Clone + PartialOrd + PartialEq + Debug> Debug for AnyRange<T> {
156 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
157 match self {
158 AnyRange::Range(r) => write!(f, "AnyRange({r:?})"),
159 AnyRange::RangeFrom(r) => write!(f, "AnyRange({r:?})"),
160 AnyRange::RangeFull(r) => write!(f, "AnyRange({r:?})"),
161 AnyRange::RangeInclusive(r) => write!(f, "AnyRange({r:?})"),
162 AnyRange::RangeTo(r) => write!(f, "AnyRange({r:?})"),
163 AnyRange::RangeToInclusive(r) => write!(f, "AnyRange({r:?})"),
164 }
165 }
166}
167impl<T: Clone + PartialOrd + PartialEq + Debug> PartialOrd for AnyRange<T> {
168 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
169 match (self, other) {
170 (AnyRange::Range(a), AnyRange::Range(b)) if a.start == b.start => {
171 a.end.partial_cmp(&b.end)
172 }
173 (AnyRange::Range(a), AnyRange::Range(b)) => a.start.partial_cmp(&b.start),
174 (AnyRange::RangeFrom(a), AnyRange::RangeFrom(b)) => a.start.partial_cmp(&b.start),
175 (AnyRange::RangeFull(_), AnyRange::RangeFull(_)) => Some(Ordering::Equal),
176 (AnyRange::RangeInclusive(a), AnyRange::RangeInclusive(b))
177 if a.start() == b.start() =>
178 {
179 a.end().partial_cmp(b.end())
180 }
181 (AnyRange::RangeInclusive(a), AnyRange::RangeInclusive(b)) => {
182 a.start().partial_cmp(b.start())
183 }
184 (AnyRange::RangeTo(a), AnyRange::RangeTo(b)) => a.end.partial_cmp(&b.end),
185 (AnyRange::RangeToInclusive(a), AnyRange::RangeToInclusive(b)) => {
186 a.end.partial_cmp(&b.end)
187 }
188 (a, b) => a.order().partial_cmp(&b.order()),
189 }
190 }
191}
192impl<T: Clone + PartialOrd + PartialEq + Eq + Debug> Ord for AnyRange<T> {
193 fn cmp(&self, other: &Self) -> Ordering {
194 PartialOrd::partial_cmp(self, other).unwrap()
195 }
196}