Skip to main content

thedes_entity/
monotonic.rs

1use std::{collections::HashMap, fmt};
2
3use serde::{Deserialize, Serialize};
4use thiserror::Error;
5
6#[derive(Debug, Clone, Copy, Error)]
7#[error("Invalid identifier {0}")]
8pub struct InvalidId(pub Id);
9
10#[derive(Debug, Clone, Copy, Error)]
11#[error("Invalid index {index} out of length {len}")]
12pub struct InvalidIndex {
13    pub index: usize,
14    pub len: usize,
15}
16
17#[derive(
18    Debug,
19    Clone,
20    Copy,
21    PartialEq,
22    Eq,
23    PartialOrd,
24    Ord,
25    Hash,
26    Default,
27    Serialize,
28    Deserialize,
29)]
30#[serde(transparent)]
31pub struct Id(u64);
32
33impl fmt::Display for Id {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        write!(f, "{}", self.0)
36    }
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct Registry<T> {
41    primary: Vec<(Id, T)>,
42    secondary_pos: HashMap<Id, usize>,
43    secondary_neg: Id,
44}
45
46impl<T> Registry<T> {
47    pub fn new() -> Self {
48        Self {
49            primary: Vec::new(),
50            secondary_pos: HashMap::new(),
51            secondary_neg: Id(0),
52        }
53    }
54
55    pub fn len(&self) -> usize {
56        self.primary.len()
57    }
58
59    pub fn create(&mut self, data: T) -> Id {
60        let id = self.secondary_neg;
61        self.secondary_neg.0 += 1;
62        let index = self.primary.len();
63        self.primary.push((id, data));
64        self.secondary_pos.insert(id, index);
65        id
66    }
67
68    pub fn remove(&mut self, id: Id) -> Option<T> {
69        let index = self.secondary_pos.get(&id).copied()?;
70        let new_index = self.primary.len() - 1;
71        if index != new_index {
72            self.primary.swap(index, new_index);
73            let (id, _) = self.primary[index];
74            self.secondary_pos.insert(id, index);
75        }
76        let (_, item) = self.primary.pop().expect("inconsistent tables");
77        Some(item)
78    }
79
80    pub fn id_to_index(&self, id: Id) -> Result<usize, InvalidId> {
81        self.secondary_pos.get(&id).copied().ok_or(InvalidId(id))
82    }
83
84    pub fn get_by_id(&self, id: Id) -> Result<&T, InvalidId> {
85        let index = self.id_to_index(id)?;
86        Ok(&self.primary[index].1)
87    }
88
89    pub fn get_by_id_mut(&mut self, id: Id) -> Result<&mut T, InvalidId> {
90        let index = self.id_to_index(id)?;
91        Ok(&mut self.primary[index].1)
92    }
93
94    pub fn get_by_index(&self, index: usize) -> Result<(Id, &T), InvalidIndex> {
95        let error = InvalidIndex { index, len: self.primary.len() };
96        let (id, value) = self.primary.get(index).ok_or(error)?;
97        Ok((*id, value))
98    }
99
100    pub fn get_by_index_mut(
101        &mut self,
102        index: usize,
103    ) -> Result<(Id, &mut T), InvalidIndex> {
104        let error = InvalidIndex { index, len: self.primary.len() };
105        let (id, value) = self.primary.get_mut(index).ok_or(error)?;
106        Ok((*id, value))
107    }
108
109    pub fn iter<'a>(
110        &'a self,
111    ) -> impl DoubleEndedIterator<Item = (Id, &'a T)> + 'a + Send + Sync
112    where
113        T: Send + Sync,
114    {
115        self.primary.iter().map(|(id, elem)| (*id, elem))
116    }
117
118    pub fn iter_mut<'a>(
119        &'a mut self,
120    ) -> impl DoubleEndedIterator<Item = (Id, &'a mut T)> + 'a + Send + Sync
121    where
122        T: Send + Sync,
123    {
124        self.primary.iter_mut().map(|(id, elem)| (*id, elem))
125    }
126
127    pub fn into_iter<'a>(
128        self,
129    ) -> impl DoubleEndedIterator<Item = (Id, T)> + 'a + Send + Sync
130    where
131        T: Send + Sync + 'a,
132    {
133        self.primary.into_iter().map(|(id, elem)| (id, elem))
134    }
135}