1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use core::ops::{Range, RangeInclusive};

use crate::cmp::{CmpWrapper, ConstCmp, IsAConstCmp, IsStdKind};

macro_rules! shared_range_impls {
    ($type:ty, $eq_fn_name:ident) => {
        impl ConstCmp for $type {
            type Kind = IsStdKind;
        }
        impl CmpWrapper<$type> {
            /// Compares `self` and `other` for equality.
            #[inline(always)]
            pub const fn const_eq(&self, other: &$type) -> bool {
                $eq_fn_name(&self.0, other)
            }
        }
    };
}

macro_rules! declare_range_cmp_fns {
    (
        ($type:ty, ($eq_fn_name:ident))

        docs( $docs_eq:expr, $docs_cmp:expr,)
    ) => {
        shared_range_impls! {$type, $eq_fn_name}

        impl<T> IsAConstCmp<IsStdKind, $type, T> {
            ///
            #[inline(always)]
            pub const fn coerce(self, range: &$type) -> CmpWrapper<$type> {
                CmpWrapper(Range {
                    start: range.start,
                    end: range.end,
                })
            }
        }

        __delegate_const_eq! {
            skip_coerce;
            for['a,]

            #[doc = $docs_eq]
            pub const fn $eq_fn_name(ref left: &'a $type, right: &'a $type) -> bool {
                left.start == right.start && left.end == right.end
            }
        }
    };
}

__declare_fns_with_docs! {
    (Range<u8>,    (eq_range_u8))
    (Range<u16>,   (eq_range_u16))
    (Range<u32>,   (eq_range_u32))
    (Range<u64>,   (eq_range_u64))
    (Range<u128>,  (eq_range_u128))
    (Range<usize>, (eq_range_usize))

    (Range<char>, (eq_range_char))

    docs(default)

    macro = declare_range_cmp_fns!(),
}

macro_rules! declare_rangeinclusive_cmp_fns {
    (
        ($type:ty, ($eq_fn_name:ident))

        docs( $docs_eq:expr, $docs_cmp:expr,)
    ) => {
        shared_range_impls! {$type, $eq_fn_name}

        impl<T> IsAConstCmp<IsStdKind, $type, T> {
            ///
            #[inline(always)]
            pub const fn coerce(self, range: &$type) -> CmpWrapper<$type> {
                CmpWrapper(RangeInclusive::new(*range.start(), *range.end()))
            }
        }

        #[doc = $docs_eq]
        pub const fn $eq_fn_name(left: &$type, right: &$type) -> bool {
            *left.start() == *right.start() && *left.end() == *right.end()
        }
    };
}

__declare_fns_with_docs! {
    (RangeInclusive<u8>,    (eq_rangeinc_u8,))
    (RangeInclusive<u16>,   (eq_rangeinc_u16))
    (RangeInclusive<u32>,   (eq_rangeinc_u32))
    (RangeInclusive<u64>,   (eq_rangeinc_u64))
    (RangeInclusive<u128>,  (eq_rangeinc_u128))
    (RangeInclusive<usize>, (eq_rangeinc_usize))

    (RangeInclusive<char>, (eq_rangeinc_char))

    docs(default)

    macro = declare_rangeinclusive_cmp_fns!(),
}