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
69958
    fn index(&self) -> Self::Target {
43
69958
        self.index
44
69958
    }
45
}
46

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

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

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

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

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

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

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

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

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

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

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

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

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

            
127
impl<T: fmt::Display, Tag> fmt::Display for TagIndex<T, Tag> {
128
651347
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129
651347
        self.index.fmt(f)
130
651347
    }
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
276590
    fn index(&self, index: TagIndex<T, Tag>) -> &Self::Output {
138
276590
        &self[index.value()]
139
276590
    }
140
}
141

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

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

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

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

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

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