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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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