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
/// An index is an index that can only be compared with equivalent tags. Note that the constructor does
10
/// not requires us to provide a tag, and as such anyone can make a tagged index. It is not a proof of a
11
/// valid index. This could be extended in the future.
12
///
13
/// Implement all the traits that are typically used for indices, e.g. PartialEq, Eq, PartialOrd, Ord and Hash.
14
///
15
/// Does not implement operations such as addition and subtraction since there are not natural. However, we do implement
16
/// Index for various containers for ease of usage. Otherwise, `value()` can be used to obtain the underlying `T`.
17
pub struct TagIndex<T, Tag> {
18
    index: T,
19

            
20
    /// Ensures that the Tag is used by the struct
21
    marker: PhantomData<fn() -> Tag>,
22
}
23

            
24
impl<T: Default, Tag> Default for TagIndex<T, Tag> {
25
    fn default() -> Self {
26
        Self {
27
            index: T::default(),
28
            marker: PhantomData,
29
        }
30
    }
31
}
32

            
33
impl<T: PartialEq, Tag> Eq for TagIndex<T, Tag> {}
34

            
35
impl<T: PartialEq, Tag> PartialEq for TagIndex<T, Tag> {
36
6948241
    fn eq(&self, other: &Self) -> bool {
37
6948241
        self.index == other.index
38
6948241
    }
39
}
40

            
41
impl<T: Ord, Tag> Ord for TagIndex<T, Tag> {
42
327098
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
43
327098
        self.index.cmp(&other.index)
44
327098
    }
45
}
46

            
47
impl<T: PartialOrd, Tag> PartialOrd for TagIndex<T, Tag> {
48
14225488
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
49
14225488
        self.index.partial_cmp(&other.index)
50
14225488
    }
51
}
52

            
53
impl<T: Hash, Tag> Hash for TagIndex<T, Tag> {
54
1761983
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
55
1761983
        self.index.hash(state);
56
1761983
    }
57
}
58

            
59
impl<T: Clone, Tag> Clone for TagIndex<T, Tag> {
60
11495551
    fn clone(&self) -> Self {
61
11495551
        Self {
62
11495551
            index: self.index.clone(),
63
11495551
            marker: self.marker,
64
11495551
        }
65
11495551
    }
66
}
67

            
68
impl<T: PartialEq, Tag> PartialEq<T> for TagIndex<T, Tag> {
69
7682513
    fn eq(&self, other: &T) -> bool {
70
7682513
        self.index.eq(other)
71
7682513
    }
72
}
73

            
74
impl<T: PartialOrd, Tag> PartialOrd<T> for TagIndex<T, Tag> {
75
38580
    fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
76
38580
        self.index.partial_cmp(other)
77
38580
    }
78
}
79

            
80
impl<T: Copy, Tag> Copy for TagIndex<T, Tag> {}
81

            
82
impl<T, Tag> TagIndex<T, Tag> {
83
28626278
    pub fn new(index: T) -> Self {
84
28626278
        Self {
85
28626278
            index,
86
28626278
            marker: PhantomData,
87
28626278
        }
88
28626278
    }
89
}
90

            
91
impl<T: Copy, Tag> TagIndex<T, Tag> {
92
    /// Returns the underlying value of the safe index, mostly used for indexing.
93
47055152
    pub fn value(&self) -> T {
94
47055152
        self.index
95
47055152
    }
96
}
97

            
98
impl<T: fmt::Debug, Tag> fmt::Debug for TagIndex<T, Tag> {
99
120
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100
120
        self.index.fmt(f)
101
120
    }
102
}
103

            
104
impl<T: fmt::Display, Tag> fmt::Display for TagIndex<T, Tag> {
105
292056
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106
292056
        self.index.fmt(f)
107
292056
    }
108
}
109

            
110
// Convenient traits for using the `SafeIndex`.
111
impl<T: Copy + SliceIndex<[U], Output = U>, U, Tag> Index<TagIndex<T, Tag>> for Vec<U> {
112
    type Output = U;
113

            
114
3526948
    fn index(&self, index: TagIndex<T, Tag>) -> &Self::Output {
115
3526948
        &self[index.value()]
116
3526948
    }
117
}
118

            
119
impl<T: Copy + SliceIndex<[U], Output = U>, U, Tag> Index<TagIndex<T, Tag>> for [U] {
120
    type Output = U;
121

            
122
139475
    fn index(&self, index: TagIndex<T, Tag>) -> &Self::Output {
123
139475
        &self[index.value()]
124
139475
    }
125
}
126

            
127
impl<T: Copy + SliceIndex<[U], Output = U>, U, Tag> IndexMut<TagIndex<T, Tag>> for Vec<U> {
128
3096859
    fn index_mut(&mut self, index: TagIndex<T, Tag>) -> &mut Self::Output {
129
3096859
        &mut self[index.value()]
130
3096859
    }
131
}
132

            
133
impl<T: Copy + SliceIndex<[U], Output = U>, U, Tag> IndexMut<TagIndex<T, Tag>> for [U] {
134
20046
    fn index_mut(&mut self, index: TagIndex<T, Tag>) -> &mut Self::Output {
135
20046
        &mut self[index.value()]
136
20046
    }
137
}
138

            
139
impl<T, Tag> Deref for TagIndex<T, Tag> {
140
    type Target = T;
141

            
142
13640973
    fn deref(&self) -> &Self::Target {
143
13640973
        &self.index
144
13640973
    }
145
}