1#![no_std]
6#![allow(clippy::arithmetic_side_effects)]
7
8extern crate alloc;
9
10#[doc = include_str!("../README.md")]
11use alloc::{collections::BTreeMap, vec, vec::Vec};
12use core::{fmt::Debug, marker::PhantomData, ops};
13
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16use thiserror::Error;
17
18#[derive(Debug, Clone, PartialEq, Eq, Error)]
20pub enum IndexedVecError {
21 #[error("IndexedVec contains maximum number of items")]
23 TooManyItems,
24}
25
26pub trait Idx: Copy + Eq + Ord + Debug + From<u32> + Into<u32> {
28 #[inline]
30 fn to_usize(self) -> usize {
31 self.into() as usize
32 }
33}
34
35#[macro_export]
37macro_rules! newtype_id {
38 ($name:ident) => {
39 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
40 #[repr(transparent)]
41 pub struct $name(u32);
42
43 impl core::fmt::Debug for $name {
44 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
45 write!(f, "{}({})", stringify!($name), self.0)
46 }
47 }
48 impl From<u32> for $name {
49 fn from(v: u32) -> Self {
50 Self(v)
51 }
52 }
53 impl From<$name> for u32 {
54 fn from(v: $name) -> Self {
55 v.0
56 }
57 }
58 impl $crate::Idx for $name {}
59 };
60}
61
62#[derive(Clone, Debug, PartialEq, Eq)]
66#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
67pub struct IndexVec<I: Idx, T> {
68 raw: Vec<T>,
69 _m: PhantomData<I>,
70}
71
72impl<I: Idx, T> Default for IndexVec<I, T> {
73 fn default() -> Self {
74 Self { raw: Vec::new(), _m: PhantomData }
75 }
76}
77
78impl<I: Idx, T> IndexVec<I, T> {
79 #[inline]
81 pub fn new() -> Self {
82 Self { raw: Vec::new(), _m: PhantomData }
83 }
84
85 #[inline]
87 pub fn with_capacity(n: usize) -> Self {
88 Self {
89 raw: Vec::with_capacity(n),
90 _m: PhantomData,
91 }
92 }
93
94 #[inline]
96 pub fn len(&self) -> usize {
97 self.raw.len()
98 }
99
100 #[inline]
102 pub fn is_empty(&self) -> bool {
103 self.raw.is_empty()
104 }
105
106 #[inline]
110 pub fn push(&mut self, v: T) -> Result<I, IndexedVecError> {
111 if self.raw.len() >= u32::MAX as usize {
112 return Err(IndexedVecError::TooManyItems);
113 }
114 let id = I::from(self.raw.len() as u32);
115 self.raw.push(v);
116 Ok(id)
117 }
118
119 #[inline]
127 pub(crate) fn insert_at(&mut self, idx: I, v: T) {
128 self.raw[idx.to_usize()] = v;
129 }
130
131 #[inline]
133 pub fn get(&self, idx: I) -> Option<&T> {
134 self.raw.get(idx.to_usize())
135 }
136
137 #[inline]
139 pub fn as_slice(&self) -> &[T] {
140 &self.raw
141 }
142
143 #[inline]
145 pub fn into_inner(self) -> Vec<T> {
146 self.raw
147 }
148
149 pub fn swap_remove(&mut self, index: usize) -> T {
151 self.raw.swap_remove(index)
152 }
153
154 pub fn contains(&self, item: &T) -> bool
156 where
157 T: PartialEq,
158 {
159 self.raw.contains(item)
160 }
161
162 pub fn iter(&self) -> core::slice::Iter<'_, T> {
164 self.raw.iter()
165 }
166
167 pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
169 self.raw.iter_mut()
170 }
171}
172
173impl<I: Idx, T> ops::Index<I> for IndexVec<I, T> {
174 type Output = T;
175 #[inline]
176 fn index(&self, index: I) -> &Self::Output {
177 &self.raw[index.to_usize()]
178 }
179}
180
181impl<I: Idx, T> ops::IndexMut<I> for IndexVec<I, T> {
182 #[inline]
183 fn index_mut(&mut self, index: I) -> &mut Self::Output {
184 &mut self.raw[index.to_usize()]
185 }
186}
187
188#[derive(Clone)]
193pub struct DenseIdMap<From: Idx, To: Idx> {
194 inner: IndexVec<From, Option<To>>,
195}
196
197impl<From: Idx, To: Idx> DenseIdMap<From, To> {
198 #[inline]
200 pub fn with_len(length: usize) -> Self {
201 Self {
202 inner: IndexVec { raw: vec![None; length], _m: PhantomData },
203 }
204 }
205
206 #[inline]
214 pub fn insert(&mut self, k: From, v: To) {
215 let idx = k.to_usize();
216 let len = self.len();
217
218 assert!(idx < len, "source ID {idx} exceeds DenseIdMap length {len}");
219 self.inner.insert_at(k, Some(v));
220 }
221
222 #[inline]
224 pub fn get(&self, k: From) -> Option<To> {
225 *self.inner.get(k)?
226 }
227
228 #[inline]
230 pub fn len(&self) -> usize {
231 self.inner.len()
232 }
233
234 #[inline]
236 pub fn is_empty(&self) -> bool {
237 self.inner.is_empty()
238 }
239}
240
241pub trait LookupByIdx<ID, V>
243where
244 ID: Idx,
245{
246 fn get(&self, id: ID) -> Option<&V>;
248}
249
250pub trait LookupByKey<K, V> {
252 fn get(&self, key: &K) -> Option<&V>;
254}
255
256impl<I, T> LookupByIdx<I, T> for IndexVec<I, T>
257where
258 I: Idx,
259{
260 fn get(&self, id: I) -> Option<&T> {
261 IndexVec::get(self, id)
262 }
263}
264
265impl<K, V> LookupByKey<K, V> for BTreeMap<K, V>
266where
267 K: Ord,
268{
269 fn get(&self, key: &K) -> Option<&V> {
270 BTreeMap::get(self, key)
271 }
272}
273
274impl<K, V> LookupByIdx<K, V> for BTreeMap<K, V>
275where
276 K: Idx,
277{
278 fn get(&self, id: K) -> Option<&V> {
279 BTreeMap::get(self, &id)
280 }
281}
282
283impl<I: Idx, T> IntoIterator for IndexVec<I, T> {
284 type Item = T;
285 type IntoIter = alloc::vec::IntoIter<T>;
286
287 fn into_iter(self) -> Self::IntoIter {
288 self.raw.into_iter()
289 }
290}
291
292impl<'a, I: Idx, T> IntoIterator for &'a IndexVec<I, T> {
293 type Item = &'a T;
294 type IntoIter = core::slice::Iter<'a, T>;
295
296 fn into_iter(self) -> Self::IntoIter {
297 self.iter()
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use alloc::string::{String, ToString};
304
305 use super::*;
306
307 newtype_id!(TestId);
309 newtype_id!(TestId2);
310
311 #[test]
312 fn test_indexvec_basic() {
313 let mut vec = IndexVec::<TestId, String>::new();
314 let id1 = vec.push("hello".to_string()).unwrap();
315 let id2 = vec.push("world".to_string()).unwrap();
316
317 assert_eq!(vec.len(), 2);
318 assert_eq!(&vec[id1], "hello");
319 assert_eq!(&vec[id2], "world");
320 assert_eq!(vec.get(TestId::from(0)), Some(&"hello".to_string()));
321 assert_eq!(vec.get(TestId::from(2)), None);
322 }
323
324 #[test]
325 fn test_dense_id_map() {
326 let mut map = DenseIdMap::<TestId, TestId2>::with_len(2);
327 map.insert(TestId::from(0), TestId2::from(10));
328 map.insert(TestId::from(1), TestId2::from(11));
329
330 assert_eq!(map.len(), 2);
331 assert_eq!(map.get(TestId::from(0)), Some(TestId2::from(10)));
332 assert_eq!(map.get(TestId::from(1)), Some(TestId2::from(11)));
333 assert_eq!(map.get(TestId::from(2)), None);
334 }
335}