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    fn lowest_one(self) -> Option<u32>;
23    fn minmax(self, rhs: Self) -> (Self, Self);
24}
25
26pub trait Unsigned: Integer {}
27
28pub trait Signed: Integer + Neg<Output = Self> {}
29
30macro_rules! integer {
31    ($($t:ty)*) => ($(
32        impl Integer for $t {
33            const ZERO: Self = 0;
34            const ONE: Self = 1;
35            const TEN: Self = 10;
36
37            #[inline]
38            fn lowest_one(self) -> Option<u32> {
39                self.lowest_one()
40            }
41
42            #[inline]
43            fn minmax(self, rhs: Self) -> (Self, Self) {
44                if self < rhs { (self, rhs) } else { (rhs, self) }
45            }
46        }
47    )*)
48}
49
50macro_rules! marker_trait {
51    ($name:ident for $($t:ty)*) => ($(
52        impl $name for $t {}
53    )*)
54}
55
56integer!(u8 u16 u32 u64 u128 usize i16 i32 i64 i128 isize);
57marker_trait!(Unsigned for u8 u16 u32 u64 u128 usize);
58marker_trait!(Signed for i16 i32 i64 i128 isize);