1use std::{fmt, marker::PhantomData};
2
3type Index = u32;
10
11pub struct Token<T> {
13 index: Index,
14 marker: PhantomData<T>,
15}
16
17impl<T> Clone for Token<T> {
18 fn clone(&self) -> Self {
19 *self
20 }
21}
22impl<T> Copy for Token<T> {}
23impl<T> PartialEq for Token<T> {
24 fn eq(&self, other: &Self) -> bool {
25 self.index == other.index
26 }
27}
28impl<T> Eq for Token<T> {}
29impl<T> fmt::Debug for Token<T> {
30 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
31 write!(formatter, "Token({})", self.index)
32 }
33}
34
35impl<T> Token<T> {
36 #[cfg(test)]
37 pub const DUMMY: Self = Token {
38 index: !0,
39 marker: PhantomData,
40 };
41
42 pub(in crate::sr) fn new(index: Index) -> Self {
43 Token {
44 index,
45 marker: PhantomData,
46 }
47 }
48
49 pub fn index(&self) -> Index {
50 self.index
51 }
52}
53
54#[derive(Debug, Default)]
57pub struct Storage<T> {
58 data: Vec<T>,
60}
61
62impl<T> Storage<T> {
63 pub fn new() -> Self {
64 Storage { data: Vec::new() }
65 }
66
67 pub fn append(&mut self, value: T) -> Token<T> {
71 let index = self.data.len() as Index;
72 self.data.push(value);
73 Token::new(index)
74 }
75
76 pub fn fetch_or_append(&mut self, value: T) -> Token<T>
80 where
81 T: PartialEq,
82 {
83 if let Some(index) = self.data.iter().position(|d| d == &value) {
84 Token::new(index as Index)
85 } else {
86 self.append(value)
87 }
88 }
89}
90
91impl<T> std::ops::Index<Token<T>> for Storage<T> {
92 type Output = T;
93 fn index(&self, token: Token<T>) -> &T {
94 &self.data[token.index as usize]
95 }
96}
97
98#[cfg(test)]
99#[allow(clippy::float_cmp)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn append_non_unique() {
105 let mut storage: Storage<f64> = Storage::new();
106 let t1 = storage.append(0.0);
107 let t2 = storage.append(0.0);
108 assert!(t1 != t2);
109 assert!(storage[t1] == storage[t2]);
110 }
111
112 #[test]
113 fn append_unique() {
114 let mut storage: Storage<f64> = Storage::new();
115 let t1 = storage.append(std::f64::NAN);
116 let t2 = storage.append(std::f64::NAN);
117 assert!(t1 != t2);
118 assert!(storage[t1] != storage[t2]);
119 }
120
121 #[test]
122 fn fetch_or_append_non_unique() {
123 let mut storage: Storage<f64> = Storage::new();
124 let t1 = storage.fetch_or_append(0.0);
125 let t2 = storage.fetch_or_append(0.0);
126 assert!(t1 == t2);
127 assert!(storage[t1] == storage[t2])
128 }
129
130 #[test]
131 fn fetch_or_append_unique() {
132 let mut storage: Storage<f64> = Storage::new();
133 let t1 = storage.fetch_or_append(std::f64::NAN);
134 let t2 = storage.fetch_or_append(std::f64::NAN);
135 assert!(t1 != t2);
136 assert!(storage[t1] != storage[t2]);
137 }
138}