Skip to main content

aoc/util/
integer.rs

1//! Combines common [operators](https://doc.rust-lang.org/book/appendix-02-operators.html)
2//! and constants `0`, `1` and `10` to enable generic methods on integer types.
3use std::ops::*;
4
5pub trait Integer:
6    Copy
7    + From<u8>
8    + PartialOrd
9    + Add<Output = Self>
10    + BitAnd<Output = Self>
11    + BitXor<Output = Self>
12    + Div<Output = Self>
13    + Mul<Output = Self>
14    + Rem<Output = Self>
15    + Shl<u32, Output = Self>
16    + Shr<u32, Output = Self>
17{
18    const ZERO: Self;
19    const ONE: Self;
20    const TEN: Self;
21
22    #[must_use]
23    fn lowest_one(self) -> Option<u32>;
24    #[must_use]
25    fn minmax(self, rhs: Self) -> (Self, Self);
26}
27
28pub trait Unsigned: Integer {}
29
30pub trait Signed: Integer + Neg<Output = Self> {}
31
32macro_rules! integer {
33    ($($t:ty)*) => {
34        $(impl Integer for $t {
35            const ZERO: Self = 0;
36            const ONE: Self = 1;
37            const TEN: Self = 10;
38
39            #[inline]
40            fn lowest_one(self) -> Option<u32> {
41                self.lowest_one()
42            }
43
44            #[inline]
45            fn minmax(self, rhs: Self) -> (Self, Self) {
46                if self < rhs { (self, rhs) } else { (rhs, self) }
47            }
48        })*
49    };
50}
51
52macro_rules! marker_trait {
53    ($name:ident for $($t:ty)*) => {
54        $(impl $name for $t {})*
55    };
56}
57
58integer!(u8 u16 u32 u64 u128 usize i16 i32 i64 i128 isize);
59marker_trait!(Unsigned for u8 u16 u32 u64 u128 usize);
60marker_trait!(Signed for i16 i32 i64 i128 isize);