1use index_vec::{Idx, IndexVec};
2use rustc_hash::FxHashMap;
3use std::fmt;
4
5use crate::IndexedValue;
6
7#[derive(Clone)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize))]
12pub struct IndexedDomain<T: IndexedValue> {
13 domain: IndexVec<T::Index, T>,
14 #[cfg_attr(feature = "serde", serde(skip))]
15 reverse_map: FxHashMap<T, T::Index>,
16}
17
18#[cfg(feature = "serde")]
19impl<'de, T: IndexedValue + serde::Deserialize<'de>> serde::Deserialize<'de> for IndexedDomain<T> {
20 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
21 where
22 D: serde::Deserializer<'de>,
23 {
24 #[derive(serde::Deserialize)]
25 struct IndexedDomain2<T: IndexedValue> {
26 domain: IndexVec<T::Index, T>,
27 }
28 let domain = IndexedDomain2::<T>::deserialize(deserializer)?;
29 let reverse_map = domain
30 .domain
31 .iter_enumerated()
32 .map(|(idx, value)| (value.clone(), idx))
33 .collect();
34 Ok(IndexedDomain {
35 domain: domain.domain,
36 reverse_map,
37 })
38 }
39}
40
41impl<T: IndexedValue> IndexedDomain<T> {
42 #[must_use]
44 pub fn new() -> Self {
45 IndexedDomain {
46 domain: IndexVec::new(),
47 reverse_map: FxHashMap::default(),
48 }
49 }
50
51 pub fn value(&self, index: T::Index) -> &T {
55 &self.domain[index]
56 }
57
58 pub fn index(&self, value: &T) -> T::Index {
62 self.reverse_map[value]
63 }
64
65 pub fn contains_value(&self, value: &T) -> bool {
67 self.reverse_map.contains_key(value)
68 }
69
70 pub fn contains_index(&self, index: T::Index) -> bool {
72 index.index() < self.domain.len()
73 }
74
75 pub fn insert(&mut self, value: T) -> T::Index {
77 let idx = self.domain.push(value.clone());
78 self.reverse_map.insert(value, idx);
79 idx
80 }
81
82 #[must_use]
84 pub fn as_vec(&self) -> &IndexVec<T::Index, T> {
85 &self.domain
86 }
87
88 #[must_use]
90 pub fn len(&self) -> usize {
91 self.domain.len()
92 }
93
94 #[must_use]
96 pub fn is_empty(&self) -> bool {
97 self.len() == 0
98 }
99
100 pub fn ensure(&mut self, value: &T) -> T::Index {
103 if self.contains_value(value) {
104 self.index(value)
105 } else {
106 self.insert(value.clone())
107 }
108 }
109
110 #[must_use]
112 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &T> + ExactSizeIterator<Item = &T> {
113 self.domain.iter()
114 }
115
116 pub fn indices(
118 &self,
119 ) -> impl DoubleEndedIterator<Item = T::Index> + ExactSizeIterator<Item = T::Index> {
120 (0..self.domain.len()).map(T::Index::from_usize)
123 }
124
125 #[must_use]
127 pub fn iter_enumerated(
128 &self,
129 ) -> impl DoubleEndedIterator<Item = (T::Index, &T)> + ExactSizeIterator<Item = (T::Index, &T)>
130 {
131 self.domain.iter_enumerated()
132 }
133}
134
135impl<T: IndexedValue> Default for IndexedDomain<T> {
136 fn default() -> Self {
137 IndexedDomain::new()
138 }
139}
140
141impl<T: IndexedValue> From<IndexVec<T::Index, T>> for IndexedDomain<T> {
142 fn from(domain: IndexVec<T::Index, T>) -> Self {
147 let reverse_map = domain
148 .iter_enumerated()
149 .map(|(idx, value)| (value.clone(), idx))
150 .collect();
151 IndexedDomain {
152 domain,
153 reverse_map,
154 }
155 }
156}
157
158impl<T: IndexedValue> FromIterator<T> for IndexedDomain<T> {
159 fn from_iter<Iter: IntoIterator<Item = T>>(iter: Iter) -> Self {
160 let domain = iter.into_iter().collect::<IndexVec<T::Index, T>>();
161 IndexedDomain::from(domain)
162 }
163}
164
165impl<T: IndexedValue + fmt::Debug> fmt::Debug for IndexedDomain<T> {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 self.domain.fmt(f)
168 }
169}
170
171#[test]
172fn test_domain() {
173 fn mk(s: &str) -> String {
174 s.to_string()
175 }
176
177 let d = IndexedDomain::from_iter([mk("a"), mk("b")]);
178 let a = d.index(&mk("a"));
179 let b = d.index(&mk("b"));
180 assert_eq!(d.value(a), "a");
181 assert_eq!(d.value(b), "b");
182 assert!(d.contains_value(&mk("a")));
183 assert!(!d.contains_value(&mk("c")));
184 assert_eq!(d.len(), 2);
185
186 assert_eq!(d.iter().collect::<Vec<_>>(), vec!["a", "b"]);
187}