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
103
use std::fmt::Debug;
use std::iter::Sum;
use std::ops::{Range, RangeInclusive};
use std::sync::atomic::Ordering;

use atoi::FromRadix10;
use atomic::Atomic;

pub trait Idx:
    Copy
    + std::ops::Add<Output = Self>
    + std::ops::AddAssign
    + std::ops::Sub<Output = Self>
    + std::ops::Div<Output = Self>
    + std::ops::Mul<Output = Self>
    + Ord
    + Debug
    + Send
    + Sum
    + Sync
    + Sized
    + 'static
{
    fn new(idx: usize) -> Self;

    fn zero() -> Self;

    fn index(self) -> usize;

    type RangeIter: Iterator<Item = Self>;

    fn range(self, end: Self) -> Self::RangeIter;

    type RangeInclusiveIter: Iterator<Item = Self>;

    fn range_inclusive(self, end: Self) -> Self::RangeInclusiveIter;

    fn parse(bytes: &[u8]) -> (Self, usize);

    fn get_and_increment(this: &Atomic<Self>, order: Ordering) -> Self {
        Self::fetch_add(this, Self::new(1), order)
    }

    fn fetch_add(this: &Atomic<Self>, val: Self, order: Ordering) -> Self;
}

macro_rules! impl_idx {
    ($TYPE:ty) => {
        impl Idx for $TYPE {
            #[inline]
            fn new(idx: usize) -> Self {
                assert!(idx <= <$TYPE>::MAX as usize);
                idx as $TYPE
            }

            #[inline]
            fn zero() -> Self {
                0
            }

            #[inline]
            fn index(self) -> usize {
                self as usize
            }

            type RangeIter = Range<Self>;

            #[inline]
            fn range(self, end: Self) -> Self::RangeIter {
                self..end
            }

            type RangeInclusiveIter = RangeInclusive<Self>;

            #[inline]
            fn range_inclusive(self, end: Self) -> Self::RangeInclusiveIter {
                self..=end
            }

            #[inline]
            fn parse(bytes: &[u8]) -> (Self, usize) {
                FromRadix10::from_radix_10(bytes)
            }

            #[inline]
            fn fetch_add(this: &Atomic<$TYPE>, val: $TYPE, order: Ordering) -> $TYPE {
                this.fetch_add(val, order)
            }
        }
    };
}

impl_idx!(u8);
impl_idx!(u16);
impl_idx!(u32);
impl_idx!(u64);
impl_idx!(usize);

impl_idx!(i8);
impl_idx!(i16);
impl_idx!(i32);
impl_idx!(i64);
impl_idx!(isize);