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 + PartialEq, Tag> MercIndex for TagIndex<T, Tag> {
40
    type Target = T;
41

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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