1#![doc = include_str!("../README.md")]
2
3use core::fmt::Debug;
4use core::ops::{Add, Bound, RangeBounds, RangeInclusive, Sub};
5
6pub trait Integer
7where
8 Self: Copy + PartialOrd + Ord + Add<Output = Self> + Sub<Output = Self>,
9{
10 const ZERO: Self;
11 const ONE: Self;
12 const MAX: Self;
13 const MIN: Self;
14}
15
16macro_rules! impl_integers {
17 ($($ident: ident),*) => {
18 $(
19 impl Integer for $ident {
20 const ZERO: Self = 0;
21 const ONE: Self = 1;
22 const MAX: Self = $ident::MAX;
23 const MIN: Self = $ident::MIN;
24 }
25 )*
26 };
27}
28
29impl_integers!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
30
31#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
32pub enum Error {
33 EmptyRange,
34 SelfDoNotContainOtherRange,
35}
36
37impl core::fmt::Display for Error {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 let s = match self {
40 Error::EmptyRange => "empty range",
41 Error::SelfDoNotContainOtherRange => "self do not contain the other range",
42 };
43 f.write_str(s)
44 }
45}
46
47impl core::error::Error for Error {}
48
49#[allow(unused)]
50pub trait IntRangeExt<T: Integer>
51where
52 Self: RangeBounds<T>,
53{
54 fn is_empty(&self) -> bool;
61
62 fn to_inclusive(&self) -> Result<RangeInclusive<T>, Error>;
71
72 fn contains_subrange<Other: RangeBounds<T>>(&self, other: &Other) -> Result<bool, Error>;
82
83 fn equal<Other: RangeBounds<T>>(&self, other: &Other) -> bool;
89
90 #[allow(clippy::type_complexity)]
100 fn substract<Other: RangeBounds<T>>(
101 &self,
102 other: &Other,
103 ) -> Result<(Option<RangeInclusive<T>>, Option<RangeInclusive<T>>), Error>;
104
105 fn intersect<Other: RangeBounds<T>>(&self, other: &Other) -> Result<bool, Error>;
116}
117
118impl<T: Integer, U: RangeBounds<T>> IntRangeExt<T> for U {
119 fn is_empty(&self) -> bool {
120 match self.start_bound() {
121 Bound::Included(s) => {
122 match self.end_bound() {
123 Bound::Included(e) => {
124 s > e
126 }
127 Bound::Excluded(e) => {
128 s >= e
130 }
131 Bound::Unbounded => {
132 false
134 }
135 }
136 }
137 Bound::Excluded(s) => {
138 match self.end_bound() {
139 Bound::Included(e) => {
140 s >= e
142 }
143 Bound::Excluded(e) => {
144 !(s < e && *s + T::ONE < *e)
146 }
147 Bound::Unbounded => {
148 *s >= T::MAX
150 }
151 }
152 }
153 Bound::Unbounded => {
154 match self.end_bound() {
155 Bound::Included(e) => {
156 T::MIN > *e
158 }
159 Bound::Excluded(e) => {
160 T::MIN >= *e
162 }
163 Bound::Unbounded => {
164 false
166 }
167 }
168 }
169 }
170 }
171
172 fn to_inclusive(&self) -> Result<RangeInclusive<T>, Error> {
173 if self.is_empty() {
174 return Err(Error::EmptyRange);
175 }
176
177 let s = match self.start_bound() {
178 Bound::Included(n) => *n,
179 Bound::Excluded(n) => *n + T::ONE,
180 Bound::Unbounded => T::MIN,
181 };
182
183 let e = match self.end_bound() {
184 Bound::Included(n) => *n,
185 Bound::Excluded(n) => *n - T::ONE,
186 Bound::Unbounded => T::MAX,
187 };
188
189 Ok(s..=e)
190 }
191
192 fn contains_subrange<Other: RangeBounds<T>>(&self, other: &Other) -> Result<bool, Error> {
193 if self.is_empty() || other.is_empty() {
194 return Err(Error::EmptyRange);
195 }
196
197 match other.start_bound() {
198 Bound::Included(n) => {
199 if !self.contains(n) {
201 return Ok(false);
202 }
203 }
204 Bound::Excluded(n) => {
205 match self.start_bound() {
207 Bound::Included(x) => {
208 if x > n && *x > *n + T::ONE {
211 return Ok(false);
212 }
213 }
214 Bound::Excluded(x) => {
215 if x > n {
218 return Ok(false);
219 }
220 }
221 Bound::Unbounded => {
222 }
225 }
226 }
227 Bound::Unbounded => match self.start_bound() {
228 Bound::Included(n) => {
229 if *n != T::MIN {
230 return Ok(false);
231 }
232 }
233 Bound::Excluded(_) => {
234 return Ok(false);
235 }
236 Bound::Unbounded => {}
237 },
238 }
239 match other.end_bound() {
240 Bound::Included(n) => {
241 if !self.contains(n) {
243 return Ok(false);
244 }
245 }
246 Bound::Excluded(n) => {
247 match self.end_bound() {
249 Bound::Included(x) => {
250 if x < n && *x + T::ONE < *n {
253 return Ok(false);
254 }
255 }
256 Bound::Excluded(x) => {
257 if x < n {
260 return Ok(false);
261 }
262 }
263 Bound::Unbounded => {}
264 }
265 }
266 Bound::Unbounded => {
267 match self.end_bound() {
269 Bound::Included(n) => {
270 if *n != T::MAX {
271 return Ok(false);
272 }
273 }
274 Bound::Excluded(_) => {
275 return Ok(false);
276 }
277 Bound::Unbounded => {}
278 }
279 }
280 }
281
282 Ok(true)
283 }
284
285 fn equal<Other: RangeBounds<T>>(&self, other: &Other) -> bool {
286 self.contains_subrange(other).unwrap_or(false)
287 && other.contains_subrange(self).unwrap_or(false)
288 }
289
290 fn substract<Other: RangeBounds<T>>(
291 &self,
292 other: &Other,
293 ) -> Result<(Option<RangeInclusive<T>>, Option<RangeInclusive<T>>), Error> {
294 if !self.contains_subrange(other).unwrap_or(false) {
295 return Err(Error::SelfDoNotContainOtherRange);
296 }
297
298 let r1 = match self.start_bound() {
300 Bound::Included(s) => {
301 match other.start_bound() {
302 Bound::Included(e) => {
303 if s < e {
304 *s..=*e - T::ONE
305 } else {
306 T::ONE..=T::ZERO
307 }
308 }
309 Bound::Excluded(e) => {
310 *s..=*e
313 }
314 Bound::Unbounded => T::ONE..=T::ZERO,
315 }
316 }
317 Bound::Excluded(s) => {
318 match other.start_bound() {
320 Bound::Included(e) => {
321 *s + T::ONE..=*e - T::ONE
324 }
325 Bound::Excluded(e) => {
326 *s + T::ONE..=*e
329 }
330 Bound::Unbounded => T::ONE..=T::ZERO,
331 }
332 }
333 Bound::Unbounded => match other.start_bound() {
334 Bound::Included(e) => {
335 if T::MIN < *e {
336 T::MIN..=*e - T::ONE
337 } else {
338 T::ONE..=T::ZERO
339 }
340 }
341 Bound::Excluded(e) => T::MIN..=*e,
342 Bound::Unbounded => T::ONE..=T::ZERO,
343 },
344 };
345
346 let r2 = match other.end_bound() {
348 Bound::Included(s) => {
349 if *s == T::MAX {
350 T::ONE..=T::ZERO
351 } else {
352 match self.end_bound() {
353 Bound::Included(e) => *s + T::ONE..=*e,
354 Bound::Excluded(e) => *s + T::ONE..=*e - T::ONE,
355 Bound::Unbounded => *s + T::ONE..=T::MAX,
356 }
357 }
358 }
359 Bound::Excluded(s) => match self.end_bound() {
360 Bound::Included(e) => *s..=*e,
361 Bound::Excluded(e) => *s..=*e - T::ONE,
362 Bound::Unbounded => *s..=T::MAX,
363 },
364 Bound::Unbounded => T::ONE..=T::ZERO,
365 };
366
367 let r1 = if r1.is_empty() { None } else { Some(r1) };
368
369 let r2 = if r2.is_empty() { None } else { Some(r2) };
370
371 Ok((r1, r2))
372 }
373
374 fn intersect<Other: RangeBounds<T>>(&self, other: &Other) -> Result<bool, Error> {
375 if self.is_empty() || other.is_empty() {
376 return Err(Error::EmptyRange);
377 }
378 if self.contains_subrange(other).unwrap_or(false)
379 || other.contains_subrange(self).unwrap_or(false)
380 {
381 return Ok(true);
382 }
383
384 let s = match self.start_bound() {
387 Bound::Included(n) => *n,
388 Bound::Excluded(n) => *n + T::ONE,
389 Bound::Unbounded => T::MIN,
390 };
391 let e = match self.end_bound() {
392 Bound::Included(n) => *n,
393 Bound::Excluded(n) => *n - T::ONE,
394 Bound::Unbounded => T::MAX,
395 };
396
397 Ok(other.contains(&s) || other.contains(&e))
398 }
399}
400
401#[cfg(test)]
451mod tests {
452 use super::*;
453
454 #[test]
455 fn empty() {
456 let r = 0..0;
457 assert_eq!(r.is_empty(), true);
458
459 let r = 0..=0;
460 assert_eq!(r.is_empty(), false);
461
462 let r = u8::MAX..u8::MAX;
463 assert_eq!(r.is_empty(), true);
464
465 let r = u8::MIN..u8::MIN;
466 assert_eq!(r.is_empty(), true);
467
468 let r = u8::MAX..u8::MIN;
469 assert_eq!(r.is_empty(), true);
470
471 let r = u8::MIN..u8::MAX;
472 assert_eq!(r.is_empty(), false);
473
474 assert_eq!((1..0).is_empty(), true);
475 assert_eq!((1..=0).is_empty(), true);
476
477 assert_eq!((..u8::MIN).is_empty(), true);
478 assert_eq!((u8::MAX..).is_empty(), false);
479 }
480
481 #[test]
482 fn to_inclusive() {
483 assert_eq!((..).to_inclusive(), Ok(u8::MIN..=u8::MAX));
484 assert_eq!((u8::MIN..).to_inclusive(), Ok(u8::MIN..=u8::MAX));
485 assert_eq!((..u8::MAX).to_inclusive(), Ok(u8::MIN..=u8::MAX - 1));
486 assert_eq!((..=u8::MAX).to_inclusive(), Ok(u8::MIN..=u8::MAX));
487 assert_eq!((10..20).to_inclusive(), Ok(10..=19));
488 assert_eq!((0..0).to_inclusive(), Err(Error::EmptyRange));
489 }
490
491 #[test]
492 fn contains_subrange() {
493 assert_eq!(
494 (u8::MIN..=u8::MAX).contains_subrange(&(..=u8::MAX)),
495 Ok(true)
496 );
497 assert_eq!(
498 (..=u8::MAX).contains_subrange(&(u8::MIN..=u8::MAX)),
499 Ok(true)
500 );
501 assert_eq!((u8::MIN..=u8::MAX).contains_subrange(&(..)), Ok(true));
502 assert_eq!((..).contains_subrange(&(u8::MIN..u8::MAX)), Ok(true));
503 assert_eq!((..).contains_subrange(&(u8::MIN..=u8::MAX)), Ok(true));
504
505 assert_eq!((..).contains_subrange(&(0..)), Ok(true));
506 assert_eq!((..).contains_subrange(&(..42)), Ok(true));
507 assert_eq!((..).contains_subrange(&(0..42)), Ok(true));
508 assert_eq!((..).contains_subrange(&(0..=42)), Ok(true));
509
510 assert_eq!((2..42).contains_subrange(&(2..42)), Ok(true));
511 assert_eq!((2..42).contains_subrange(&(3..42)), Ok(true));
512 assert_eq!((2..42).contains_subrange(&(3..41)), Ok(true));
513
514 assert_eq!((2..42).contains_subrange(&(2..=42)), Ok(false));
515 assert_eq!((2..42).contains_subrange(&(2..43)), Ok(false));
516 assert_eq!((2..42).contains_subrange(&(1..42)), Ok(false));
517 assert_eq!((2..42).contains_subrange(&(1..44)), Ok(false));
518
519 assert_eq!((2..u8::MAX).contains_subrange(&(2..u8::MAX)), Ok(true));
520 assert_eq!((2..u8::MAX).contains_subrange(&(2..=u8::MAX)), Ok(false));
521 assert_eq!((2..u8::MAX).contains_subrange(&(3..u8::MAX)), Ok(true));
522
523 assert_eq!((2..u8::MAX).contains_subrange(&(1..u8::MAX)), Ok(false));
524 assert_eq!((2..u8::MAX).contains_subrange(&(2..u8::MAX - 1)), Ok(true));
525 assert_eq!((2..u8::MAX).contains_subrange(&(2..=u8::MAX - 1)), Ok(true));
526
527 assert_eq!((2..=u8::MAX).contains_subrange(&(2..u8::MAX)), Ok(true));
528 assert_eq!((2..=u8::MAX).contains_subrange(&(2..=u8::MAX)), Ok(true));
529
530 assert_eq!((2..=u8::MAX - 1).contains_subrange(&(2..u8::MAX)), Ok(true));
531 assert_eq!(
532 (2..=u8::MAX - 1).contains_subrange(&(2..=u8::MAX)),
533 Ok(false)
534 );
535
536 assert_eq!((0..10).contains_subrange(&(0..0)), Err(Error::EmptyRange));
537 assert_eq!((0..0).contains_subrange(&(0..10)), Err(Error::EmptyRange));
538 assert_eq!((0..0).contains_subrange(&(0..0)), Err(Error::EmptyRange));
539 }
540
541 #[test]
542 fn equal() {
543 assert_eq!((0..100).equal(&(0..=99)), true);
544 assert_eq!((0u8..).equal(&(0..=u8::MAX)), true);
545 assert_eq!((..).equal(&(0..=u8::MAX)), true);
546 assert_eq!((..).equal(&(u8::MIN..=u8::MAX)), true);
547 assert_eq!((..).equal(&(u8::MIN..u8::MAX)), false);
548 assert_eq!((0..=u8::MAX).equal(&(..)), true);
549 }
550
551 #[test]
552 fn sub() {
553 assert_eq!((..).substract(&(u8::MIN..=u8::MAX)), Ok((None, None)));
554 assert_eq!((u8::MIN..=u8::MAX).substract(&(..)), Ok((None, None)));
555 assert_eq!(
556 (..).substract(&(u8::MIN..u8::MAX)),
557 Ok((None, Some(255..=255u8)))
558 );
559 assert_eq!(
560 (..=u8::MAX).substract(&(u8::MIN..u8::MAX)),
561 Ok((None, Some(255..=255u8)))
562 );
563 assert_eq!(
564 (..=u8::MAX).substract(&(..u8::MAX)),
565 Ok((None, Some(255..=255u8)))
566 );
567 assert_eq!(
568 (..=u8::MAX).substract(&(1..u8::MAX)),
569 Ok((Some(0..=0), Some(255..=255u8)))
570 );
571
572 assert_eq!(
573 (0..100).substract(&(30..50)),
574 Ok((Some(0..=29), Some(50..=99)))
575 );
576 assert_eq!((0..100).substract(&(30..100)), Ok((Some(0..=29), None)));
577 assert_eq!((0..100).substract(&(0..50)), Ok((None, Some(50..=99))));
578
579 assert_eq!(
580 (20..40).substract(&(30..50)),
581 Err(Error::SelfDoNotContainOtherRange)
582 );
583 }
584
585 #[test]
586 fn intersect() {
587 assert_eq!((0..50).intersect(&(50..100)), Ok(false));
588 assert_eq!((0..=50).intersect(&(50..100)), Ok(true));
589 }
590
591 }