1use core::cmp::Ordering;
8use core::fmt::Debug;
9use core::ops::Deref;
10use ord_subset_trait::*;
11
12#[derive(PartialEq, PartialOrd, Clone, Copy, Debug, Hash)]
19pub struct OrdVar<T: PartialOrd + PartialEq>(T);
20
21impl<T: PartialOrd + PartialEq> OrdVar<T> {
22 #[inline]
28 pub fn new(data: T) -> OrdVar<T>
29 where
30 T: Debug + OrdSubset,
31 {
32 if data.is_outside_order() {
33 panic!(
34 "Attempted saving data outside of total order into OrdVar: {:?}",
35 data
36 )
37 };
38 OrdVar(data)
39 }
40
41 #[inline]
43 pub fn new_checked(data: T) -> Option<OrdVar<T>>
44 where
45 T: OrdSubset,
46 {
47 match data.is_outside_order() {
48 true => None,
49 false => Some(OrdVar(data)),
50 }
51 }
52
53 #[inline(always)]
56 pub fn new_unchecked(data: T) -> OrdVar<T> {
57 OrdVar(data)
58 }
59
60 #[inline(always)]
61 pub fn into_inner(self) -> T {
62 self.0
63 }
64}
65
66impl<T: PartialOrd + PartialEq> Eq for OrdVar<T> {}
67
68#[cfg_attr(clippy, allow(clippy::derive_ord_xor_partial_ord))]
69impl<T: PartialOrd + PartialEq> Ord for OrdVar<T> {
70 #[inline]
71 fn cmp(&self, other: &Self) -> Ordering {
72 self.partial_cmp(other)
73 .expect("OrdVar contains value outside total order")
74 }
75}
76
77impl<T: PartialOrd + PartialEq> Deref for OrdVar<T> {
78 type Target = T;
79
80 #[inline(always)]
81 fn deref(&self) -> &Self::Target {
82 &self.0
83 }
84}
85
86impl<T: PartialOrd + PartialEq> AsRef<T> for OrdVar<T> {
87 #[inline(always)]
88 fn as_ref(&self) -> &T {
89 &self.0
90 }
91}
92
93impl<T: Default + OrdSubset + Debug> Default for OrdVar<T> {
94 #[inline(always)]
95 fn default() -> Self {
96 OrdVar::new(T::default())
97 }
98}
99
100#[cfg(feature = "ops")]
101mod ops {
102 #[cfg_attr(rustfmt, rustfmt_skip)]
104 use core::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Shl, Shr, Neg, Not,
105 AddAssign, SubAssign, MulAssign, DivAssign, RemAssign, BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign,};
106 use super::OrdVar;
107 use core::fmt::Debug;
108 use ord_subset_trait::*;
109
110 #[inline(always)]
111 fn construct<T: OrdSubset + Debug>(t: T) -> OrdVar<T> {
112 match cfg!(feature = "unchecked_ops") {
113 true => OrdVar::new_unchecked(t),
114 false => OrdVar::new(t),
115 }
116 }
117
118 impl<T, RHS> Add<RHS> for OrdVar<T>
121 where
122 T: PartialOrd + PartialEq + Add<RHS>,
123 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
124 {
125 type Output = OrdVar<T::Output>;
126 fn add(self, rhs: RHS) -> Self::Output {
127 construct(self.into_inner().add(rhs))
128 }
129 }
130
131 impl<T, RHS> Sub<RHS> for OrdVar<T>
132 where
133 T: PartialOrd + PartialEq + Sub<RHS>,
134 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
135 {
136 type Output = OrdVar<T::Output>;
137 fn sub(self, rhs: RHS) -> Self::Output {
138 construct(self.into_inner().sub(rhs))
139 }
140 }
141
142 impl<T, RHS> Mul<RHS> for OrdVar<T>
143 where
144 T: PartialOrd + PartialEq + Mul<RHS>,
145 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
146 {
147 type Output = OrdVar<T::Output>;
148 fn mul(self, rhs: RHS) -> Self::Output {
149 construct(self.into_inner().mul(rhs))
150 }
151 }
152
153 impl<T, RHS> Div<RHS> for OrdVar<T>
154 where
155 T: PartialOrd + PartialEq + Div<RHS>,
156 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
157 {
158 type Output = OrdVar<T::Output>;
159 fn div(self, rhs: RHS) -> Self::Output {
160 construct(self.into_inner().div(rhs))
161 }
162 }
163
164 impl<T, RHS> Rem<RHS> for OrdVar<T>
165 where
166 T: PartialOrd + PartialEq + Rem<RHS>,
167 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
168 {
169 type Output = OrdVar<T::Output>;
170 fn rem(self, rhs: RHS) -> Self::Output {
171 construct(self.into_inner().rem(rhs))
172 }
173 }
174
175 impl<T, RHS> BitAnd<RHS> for OrdVar<T>
176 where
177 T: PartialOrd + PartialEq + BitAnd<RHS>,
178 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
179 {
180 type Output = OrdVar<T::Output>;
181 fn bitand(self, rhs: RHS) -> Self::Output {
182 construct(self.into_inner().bitand(rhs))
183 }
184 }
185
186 impl<T, RHS> BitOr<RHS> for OrdVar<T>
187 where
188 T: PartialOrd + PartialEq + BitOr<RHS>,
189 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
190 {
191 type Output = OrdVar<T::Output>;
192 fn bitor(self, rhs: RHS) -> Self::Output {
193 construct(self.into_inner().bitor(rhs))
194 }
195 }
196
197 impl<T, RHS> BitXor<RHS> for OrdVar<T>
198 where
199 T: PartialOrd + PartialEq + BitXor<RHS>,
200 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
201 {
202 type Output = OrdVar<T::Output>;
203 fn bitxor(self, rhs: RHS) -> Self::Output {
204 construct(self.into_inner().bitxor(rhs))
205 }
206 }
207
208 impl<T, RHS> Shl<RHS> for OrdVar<T>
209 where
210 T: PartialOrd + PartialEq + Shl<RHS>,
211 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
212 {
213 type Output = OrdVar<T::Output>;
214 fn shl(self, rhs: RHS) -> Self::Output {
215 construct(self.into_inner().shl(rhs))
216 }
217 }
218
219 impl<T, RHS> Shr<RHS> for OrdVar<T>
220 where
221 T: PartialOrd + PartialEq + Shr<RHS>,
222 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
223 {
224 type Output = OrdVar<T::Output>;
225 fn shr(self, rhs: RHS) -> Self::Output {
226 construct(self.into_inner().shr(rhs))
227 }
228 }
229
230 impl<T, RHS> AddAssign<RHS> for OrdVar<T>
233 where
234 T: PartialOrd + PartialEq + AddAssign<RHS> + OrdSubset,
235 {
236 fn add_assign(&mut self, rhs: RHS) {
237 self.0.add_assign(rhs);
238 if !cfg!(feature = "unchecked_ops") {
239 assert!(
240 !self.0.is_outside_order(),
241 "Result of {}= operation is outside order",
242 "+"
243 );
244 }
245 }
246 }
247
248 impl<T, RHS> SubAssign<RHS> for OrdVar<T>
249 where
250 T: PartialOrd + PartialEq + SubAssign<RHS> + OrdSubset,
251 {
252 fn sub_assign(&mut self, rhs: RHS) {
253 self.0.sub_assign(rhs);
254 if !cfg!(feature = "unchecked_ops") {
255 assert!(
256 !self.0.is_outside_order(),
257 "Result of {}= operation is outside order",
258 "-"
259 );
260 }
261 }
262 }
263
264 impl<T, RHS> MulAssign<RHS> for OrdVar<T>
265 where
266 T: PartialOrd + PartialEq + MulAssign<RHS> + OrdSubset,
267 {
268 fn mul_assign(&mut self, rhs: RHS) {
269 self.0.mul_assign(rhs);
270 if !cfg!(feature = "unchecked_ops") {
271 assert!(
272 !self.0.is_outside_order(),
273 "Result of {}= operation is outside order",
274 "*"
275 );
276 }
277 }
278 }
279
280 impl<T, RHS> DivAssign<RHS> for OrdVar<T>
281 where
282 T: PartialOrd + PartialEq + DivAssign<RHS> + OrdSubset,
283 {
284 fn div_assign(&mut self, rhs: RHS) {
285 self.0.div_assign(rhs);
286 if !cfg!(feature = "unchecked_ops") {
287 assert!(
288 !self.0.is_outside_order(),
289 "Result of {}= operation is outside order",
290 "/"
291 );
292 }
293 }
294 }
295
296 impl<T, RHS> RemAssign<RHS> for OrdVar<T>
297 where
298 T: PartialOrd + PartialEq + RemAssign<RHS> + OrdSubset,
299 {
300 fn rem_assign(&mut self, rhs: RHS) {
301 self.0.rem_assign(rhs);
302 if !cfg!(feature = "unchecked_ops") {
303 assert!(
304 !self.0.is_outside_order(),
305 "Result of {}= operation is outside order",
306 "%"
307 );
308 }
309 }
310 }
311
312 impl<T, RHS> BitAndAssign<RHS> for OrdVar<T>
313 where
314 T: PartialOrd + PartialEq + BitAndAssign<RHS> + OrdSubset,
315 {
316 fn bitand_assign(&mut self, rhs: RHS) {
317 self.0.bitand_assign(rhs);
318 if !cfg!(feature = "unchecked_ops") {
319 assert!(
320 !self.0.is_outside_order(),
321 "Result of {}= operation is outside order",
322 "&"
323 );
324 }
325 }
326 }
327
328 impl<T, RHS> BitOrAssign<RHS> for OrdVar<T>
329 where
330 T: PartialOrd + PartialEq + BitOrAssign<RHS> + OrdSubset,
331 {
332 fn bitor_assign(&mut self, rhs: RHS) {
333 self.0.bitor_assign(rhs);
334 if !cfg!(feature = "unchecked_ops") {
335 assert!(
336 !self.0.is_outside_order(),
337 "Result of {}= operation is outside order",
338 "|"
339 );
340 }
341 }
342 }
343
344 impl<T, RHS> BitXorAssign<RHS> for OrdVar<T>
345 where
346 T: PartialOrd + PartialEq + BitXorAssign<RHS> + OrdSubset,
347 {
348 fn bitxor_assign(&mut self, rhs: RHS) {
349 self.0.bitxor_assign(rhs);
350 if !cfg!(feature = "unchecked_ops") {
351 assert!(
352 !self.0.is_outside_order(),
353 "Result of {}= operation is outside order",
354 "^"
355 );
356 }
357 }
358 }
359
360 impl<T, RHS> ShlAssign<RHS> for OrdVar<T>
361 where
362 T: PartialOrd + PartialEq + ShlAssign<RHS> + OrdSubset,
363 {
364 fn shl_assign(&mut self, rhs: RHS) {
365 self.0.shl_assign(rhs);
366 if !cfg!(feature = "unchecked_ops") {
367 assert!(
368 !self.0.is_outside_order(),
369 "Result of {}= operation is outside order",
370 "<<"
371 );
372 }
373 }
374 }
375
376 impl<T, RHS> ShrAssign<RHS> for OrdVar<T>
377 where
378 T: PartialOrd + PartialEq + ShrAssign<RHS> + OrdSubset,
379 {
380 fn shr_assign(&mut self, rhs: RHS) {
381 self.0.shr_assign(rhs);
382 if !cfg!(feature = "unchecked_ops") {
383 assert!(
384 !self.0.is_outside_order(),
385 "Result of {}= operation is outside order",
386 ">>"
387 );
388 }
389 }
390 }
391
392 impl<T> Neg for OrdVar<T>
394 where
395 T: PartialOrd + PartialEq + Neg,
396 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
397 {
398 type Output = OrdVar<T::Output>;
399 fn neg(self) -> Self::Output {
400 construct(self.into_inner().neg())
401 }
402 }
403
404 impl<T> Not for OrdVar<T>
405 where
406 T: PartialOrd + PartialEq + Not,
407 T::Output: PartialOrd + PartialEq + Debug + OrdSubset,
408 {
409 type Output = OrdVar<T::Output>;
410 fn not(self) -> Self::Output {
411 construct(self.into_inner().not())
412 }
413 }
414}