1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
13pub struct Id<K> {
14 index: u32,
15 generation: u32,
16 _kind: std::marker::PhantomData<K>,
17}
18
19impl<K> Id<K> {
20 pub fn index(self) -> usize {
21 self.index as usize
22 }
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct DocumentKind;
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub struct ViewKind;
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct PaneKind;
32
33pub type DocumentId = Id<DocumentKind>;
34pub type ViewId = Id<ViewKind>;
35pub type PaneId = Id<PaneKind>;
36
37pub struct Arena<K, T> {
40 slots: Vec<Slot<T>>,
41 free: Vec<u32>,
42 _kind: std::marker::PhantomData<K>,
43}
44
45#[derive(Debug)]
46struct Slot<T> {
47 generation: u32,
48 value: Option<T>,
49}
50
51impl<K, T> Default for Arena<K, T> {
52 fn default() -> Self {
53 Self {
54 slots: Vec::new(),
55 free: Vec::new(),
56 _kind: std::marker::PhantomData,
57 }
58 }
59}
60
61impl<K, T> Arena<K, T> {
62 pub fn insert(&mut self, value: T) -> Id<K> {
63 if let Some(index) = self.free.pop() {
64 let slot = &mut self.slots[index as usize];
65 slot.generation += 1;
66 slot.value = Some(value);
67 return Id {
68 index,
69 generation: slot.generation,
70 _kind: std::marker::PhantomData,
71 };
72 }
73 let index = self.slots.len() as u32;
74 self.slots.push(Slot {
75 generation: 0,
76 value: Some(value),
77 });
78 Id {
79 index,
80 generation: 0,
81 _kind: std::marker::PhantomData,
82 }
83 }
84
85 pub fn get(&self, id: Id<K>) -> Option<&T> {
87 self.slots
88 .get(id.index as usize)
89 .filter(|s| s.generation == id.generation)
90 .and_then(|s| s.value.as_ref())
91 }
92
93 pub fn get_mut(&mut self, id: Id<K>) -> Option<&mut T> {
94 self.slots
95 .get_mut(id.index as usize)
96 .filter(|s| s.generation == id.generation)
97 .and_then(|s| s.value.as_mut())
98 }
99
100 pub fn remove(&mut self, id: Id<K>) -> Option<T> {
102 let slot = self.slots.get_mut(id.index as usize)?;
103 if slot.generation != id.generation {
104 return None;
105 }
106 let value = slot.value.take()?;
107 self.free.push(id.index);
108 Some(value)
109 }
110
111 pub fn iter(&self) -> impl Iterator<Item = (Id<K>, &T)> {
112 self.slots.iter().enumerate().filter_map(|(i, s)| {
113 s.value.as_ref().map(|v| {
114 (
115 Id {
116 index: i as u32,
117 generation: s.generation,
118 _kind: std::marker::PhantomData,
119 },
120 v,
121 )
122 })
123 })
124 }
125
126 pub fn len(&self) -> usize {
127 self.slots.iter().filter(|s| s.value.is_some()).count()
128 }
129
130 pub fn clear(&mut self) {
132 let live: Vec<u32> = self
133 .slots
134 .iter()
135 .enumerate()
136 .filter(|(_, s)| s.value.is_some())
137 .map(|(i, _)| i as u32)
138 .collect();
139 for s in &mut self.slots {
140 s.value = None;
141 }
142 self.free.extend(live);
143 }
144 pub fn is_empty(&self) -> bool {
145 self.len() == 0
146 }
147}
148
149pub type ByteOffset = usize;
151pub type LineIndex = usize;
153
154#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn stale_ids_fail_lookup() {
166 let mut a: Arena<DocumentKind, String> = Arena::default();
167 let one = a.insert("one".into());
168 let two = a.insert("two".into());
169 assert_eq!(a.get(one).map(String::as_str), Some("one"));
170 a.remove(one);
171 assert_eq!(a.get(one), None, "removed");
172 let three = a.insert("three".into()); assert_eq!(a.get(one), None, "stale generation must not resolve");
174 assert_eq!(a.get(three).map(String::as_str), Some("three"));
175 assert_eq!(a.get(two).map(String::as_str), Some("two"));
176 assert_eq!(a.len(), 2);
177 }
178}