1
use std::fmt;
2
use std::hash::Hash;
3
use std::marker::PhantomData;
4
use std::ops::Deref;
5
use std::ops::Index;
6
use std::ops::IndexMut;
7
use std::slice::SliceIndex;
8

            
9
/// A trait for index types.
10
pub trait MercIndex: Copy + PartialEq {
11
    /// The underlying target type.
12
    type Target;
13

            
14
    /// Returns the underlying index.
15
    fn index(&self) -> Self::Target;
16
}
17

            
18
impl MercIndex for () {
19
    type Target = ();
20

            
21
    fn index(&self) -> Self::Target {}
22
}
23

            
24
/// An index is an index that can only be compared with equivalent tags. Note that the constructor does
25
/// not requires us to provide a tag, and as such anyone can make a tagged index. It is not a proof of a
26
/// valid index. This could be extended in the future.
27
///
28
/// Implement all the traits that are typically used for indices, e.g. PartialEq, Eq, PartialOrd, Ord and Hash.
29
///
30
/// Does not implement operations such as addition and subtraction since there are not natural. However, we do implement
31
/// Index for various containers for ease of usage. Otherwise, `value()` can be used to obtain the underlying `T`.
32
pub struct TagIndex<T, Tag> {
33
    index: T,
34

            
35
    /// Ensures that the Tag is used by the struct
36
    marker: PhantomData<fn() -> Tag>,
37
}
38

            
39
impl<T: Copy + fmt::Display + PartialEq, Tag> MercIndex for TagIndex<T, Tag> {
40
    type Target = T;
41

            
42
10680008
    fn index(&self) -> Self::Target {
43
10680008
        self.index
44
10680008
    }
45
}
46

            
47
impl<T: Default, Tag> Default for TagIndex<T, Tag> {
48
5956
    fn default() -> Self {
49
5956
        Self {
50
5956
            index: T::default(),
51
5956
            marker: PhantomData,
52
5956
        }
53
5956
    }
54
}
55

            
56
impl<T: PartialEq, Tag> Eq for TagIndex<T, Tag> {}
57

            
58
impl<T: PartialEq, Tag> PartialEq for TagIndex<T, Tag> {
59
13811257429
    fn eq(&self, other: &Self) -> bool {
60
13811257429
        self.index == other.index
61
13811257429
    }
62
}
63

            
64
impl<T: Ord, Tag> Ord for TagIndex<T, Tag> {
65
68775
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
66
68775
        self.index.cmp(&other.index)
67
68775
    }
68
}
69

            
70
impl<T: PartialOrd, Tag> PartialOrd for TagIndex<T, Tag> {
71
575000471
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
72
575000471
        self.index.partial_cmp(&other.index)
73
575000471
    }
74
}
75

            
76
impl<T: Hash, Tag> Hash for TagIndex<T, Tag> {
77
52298492
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
78
52298492
        self.index.hash(state);
79
52298492
    }
80
}
81

            
82
impl<T: Clone, Tag> Clone for TagIndex<T, Tag> {
83
847906603
    fn clone(&self) -> Self {
84
847906603
        Self {
85
847906603
            index: self.index.clone(),
86
847906603
            marker: self.marker,
87
847906603
        }
88
847906603
    }
89
}
90

            
91
impl<T: PartialEq, Tag> PartialEq<T> for TagIndex<T, Tag> {
92
29125572687
    fn eq(&self, other: &T) -> bool {
93
29125572687
        self.index.eq(other)
94
29125572687
    }
95
}
96

            
97
impl<T: PartialOrd, Tag> PartialOrd<T> for TagIndex<T, Tag> {
98
2138595
    fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
99
2138595
        self.index.partial_cmp(other)
100
2138595
    }
101
}
102

            
103
impl<T: Copy, Tag> Copy for TagIndex<T, Tag> {}
104

            
105
impl<T, Tag> TagIndex<T, Tag> {
106
22842839577
    pub fn new(index: T) -> Self {
107
22842839577
        Self {
108
22842839577
            index,
109
22842839577
            marker: PhantomData,
110
22842839577
        }
111
22842839577
    }
112
}
113

            
114
impl<T: Copy, Tag> TagIndex<T, Tag> {
115
    /// Returns the underlying value of the safe index, mostly used for indexing.
116
34228737138
    pub fn value(&self) -> T {
117
34228737138
        self.index
118
34228737138
    }
119
}
120

            
121
impl<T: fmt::Debug, Tag> fmt::Debug for TagIndex<T, Tag> {
122
1200000
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123
1200000
        self.index.fmt(f)
124
1200000
    }
125
}
126

            
127
impl<T: fmt::Display, Tag> fmt::Display for TagIndex<T, Tag> {
128
700683
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129
700683
        self.index.fmt(f)
130
700683
    }
131
}
132

            
133
// Convenient traits for using the `SafeIndex`.
134
impl<T: Copy + SliceIndex<[U], Output = U>, U, Tag> Index<TagIndex<T, Tag>> for Vec<U> {
135
    type Output = U;
136

            
137
577241063
    fn index(&self, index: TagIndex<T, Tag>) -> &Self::Output {
138
577241063
        &self[index.value()]
139
577241063
    }
140
}
141

            
142
impl<T: Copy + SliceIndex<[U], Output = U>, U, Tag> Index<TagIndex<T, Tag>> for [U] {
143
    type Output = U;
144

            
145
13296060
    fn index(&self, index: TagIndex<T, Tag>) -> &Self::Output {
146
13296060
        &self[index.value()]
147
13296060
    }
148
}
149

            
150
impl<T: Copy + SliceIndex<[U], Output = U>, U, Tag> IndexMut<TagIndex<T, Tag>> for Vec<U> {
151
242155339
    fn index_mut(&mut self, index: TagIndex<T, Tag>) -> &mut Self::Output {
152
242155339
        &mut self[index.value()]
153
242155339
    }
154
}
155

            
156
impl<T: Copy + SliceIndex<[U], Output = U>, U, Tag> IndexMut<TagIndex<T, Tag>> for [U] {
157
5049293
    fn index_mut(&mut self, index: TagIndex<T, Tag>) -> &mut Self::Output {
158
5049293
        &mut self[index.value()]
159
5049293
    }
160
}
161

            
162
impl<T, Tag> Deref for TagIndex<T, Tag> {
163
    type Target = T;
164

            
165
19985136378
    fn deref(&self) -> &Self::Target {
166
19985136378
        &self.index
167
19985136378
    }
168
}