1#[cfg(test)]
2#[path = "./table_tests.rs"]
3mod tests;
4
5use crate::Span;
6use crate::value::{
7 FLAG_HEADER, FLAG_MASK, FLAG_SHIFT, FLAG_TABLE, Item, Key, MaybeItem, NONE, TAG_MASK,
8 TAG_SHIFT, TAG_TABLE,
9};
10use std::mem::size_of;
11use std::ptr::NonNull;
12
13use crate::arena::Arena;
14
15type TableEntry<'de> = (Key<'de>, Item<'de>);
16
17const MIN_CAP: u32 = 2;
18
19#[repr(C, align(8))]
21pub(crate) struct InnerTable<'de> {
22 len: u32,
23 cap: u32,
24 ptr: NonNull<TableEntry<'de>>,
25}
26
27impl<'de> InnerTable<'de> {
28 #[inline]
30 pub fn new() -> Self {
31 Self {
32 len: 0,
33 cap: 0,
34 ptr: NonNull::dangling(),
35 }
36 }
37
38 pub fn insert(
40 &mut self,
41 key: Key<'de>,
42 item: Item<'de>,
43 arena: &'de Arena,
44 ) -> &mut TableEntry<'de> {
45 let len = self.len;
46 if self.len == self.cap {
47 self.grow(arena);
48 }
49 unsafe {
52 let ptr = self.ptr.as_ptr().add(len as usize);
53 ptr.write((key, item));
54 self.len = len + 1;
55 &mut (*ptr)
56 }
57 }
58
59 #[inline]
61 pub fn len(&self) -> usize {
62 self.len as usize
63 }
64
65 #[inline]
67 pub fn is_empty(&self) -> bool {
68 self.len == 0
69 }
70
71 pub fn get_entry(&self, name: &str) -> Option<(&Key<'de>, &Item<'de>)> {
73 for entry in self.entries() {
74 if entry.0.name == name {
75 return Some((&entry.0, &entry.1));
76 }
77 }
78 None
79 }
80
81 pub fn get(&self, name: &str) -> Option<&Item<'de>> {
83 for entry in self.entries() {
84 if entry.0.name == name {
85 return Some(&entry.1);
86 }
87 }
88 None
89 }
90
91 pub fn get_mut(&mut self, name: &str) -> Option<&mut Item<'de>> {
93 for entry in self.entries_mut() {
94 if entry.0.name == name {
95 return Some(&mut entry.1);
96 }
97 }
98 None
99 }
100
101 #[inline]
103 pub fn contains_key(&self, name: &str) -> bool {
104 self.get(name).is_some()
105 }
106
107 pub fn remove_entry(&mut self, name: &str) -> Option<(Key<'de>, Item<'de>)> {
110 let idx = self.find_index(name)?;
111 Some(self.remove_at(idx))
112 }
113
114 #[inline]
121 pub(crate) unsafe fn first_key_span_start_unchecked(&self) -> u32 {
122 debug_assert!(self.len > 0);
123 unsafe { (*self.ptr.as_ptr()).0.span.start }
125 }
126
127 #[inline]
129 pub fn entries(&self) -> &[TableEntry<'de>] {
130 unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) }
134 }
135
136 #[inline]
137 pub(crate) fn entries_mut(&mut self) -> &mut [TableEntry<'de>] {
138 unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize) }
140 }
141
142 pub(crate) fn find_index(&self, name: &str) -> Option<usize> {
143 for (i, entry) in self.entries().iter().enumerate() {
144 if entry.0.name == name {
145 return Some(i);
146 }
147 }
148 None
149 }
150
151 fn remove_at(&mut self, idx: usize) -> (Key<'de>, Item<'de>) {
153 let last = self.len as usize - 1;
154 let ptr = unsafe { self.ptr.as_ptr().add(idx) };
157 let entry = unsafe { ptr.read() };
158 if idx != last {
159 unsafe {
161 ptr.write(self.ptr.as_ptr().add(last).read());
162 }
163 }
164 self.len -= 1;
165 entry
166 }
167
168 #[cold]
169 fn grow(&mut self, arena: &'de Arena) {
170 let new_cap = if self.cap == 0 {
171 MIN_CAP
172 } else {
173 self.cap.checked_mul(2).expect("capacity overflow")
174 };
175 self.grow_to(new_cap, arena);
176 }
177
178 fn grow_to(&mut self, new_cap: u32, arena: &'de Arena) {
179 #[cfg(target_pointer_width = "32")]
181 let new_size = (new_cap as usize)
182 .checked_mul(size_of::<TableEntry<'_>>())
183 .expect("capacity overflow");
184 #[cfg(not(target_pointer_width = "32"))]
185 let new_size = new_cap as usize * size_of::<TableEntry<'_>>();
186 if self.cap > 0 {
187 let old_size = self.cap as usize * size_of::<TableEntry<'_>>();
188 self.ptr = unsafe { arena.realloc(self.ptr.cast(), old_size, new_size).cast() };
190 } else {
191 self.ptr = arena.alloc(new_size).cast();
192 }
193 self.cap = new_cap;
194 }
195}
196
197impl std::fmt::Debug for InnerTable<'_> {
198 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199 let mut map = f.debug_map();
200 for (k, v) in self.entries() {
201 map.entry(k, v);
202 }
203 map.finish()
204 }
205}
206
207pub struct IntoIter<'de> {
209 table: InnerTable<'de>,
210 index: u32,
211}
212
213impl<'de> Iterator for IntoIter<'de> {
214 type Item = (Key<'de>, Item<'de>);
215
216 fn next(&mut self) -> Option<Self::Item> {
217 if self.index < self.table.len {
218 let entry = unsafe { self.table.ptr.as_ptr().add(self.index as usize).read() };
221 self.index += 1;
222 Some(entry)
223 } else {
224 None
225 }
226 }
227
228 fn size_hint(&self) -> (usize, Option<usize>) {
229 let remaining = (self.table.len - self.index) as usize;
230 (remaining, Some(remaining))
231 }
232}
233
234impl ExactSizeIterator for IntoIter<'_> {}
235
236#[repr(C)]
279pub struct Table<'de> {
280 pub(crate) value: InnerTable<'de>,
281 start_and_tag: u32,
283 end_and_flag: u32,
285}
286
287impl<'de> Table<'de> {
288 pub fn new(span: Span) -> Table<'de> {
290 Table {
291 start_and_tag: span.start << TAG_SHIFT | TAG_TABLE,
292 end_and_flag: (span.end << FLAG_SHIFT) | FLAG_TABLE,
293 value: InnerTable::new(),
294 }
295 }
296 pub fn span(&self) -> Span {
298 Span {
299 start: self.start_and_tag >> TAG_SHIFT,
300 end: self.end_and_flag >> FLAG_SHIFT,
301 }
302 }
303}
304
305impl<'de> Default for Table<'de> {
306 fn default() -> Self {
307 Self::new(Span::default())
308 }
309}
310
311impl std::fmt::Debug for Table<'_> {
312 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
313 self.value.fmt(f)
314 }
315}
316
317impl<'de> Table<'de> {
318 pub fn insert(&mut self, key: Key<'de>, value: Item<'de>, arena: &'de Arena) {
320 self.value.insert(key, value, arena);
321 }
322
323 #[inline]
325 pub fn len(&self) -> usize {
326 self.value.len()
327 }
328
329 #[inline]
331 pub fn is_empty(&self) -> bool {
332 self.value.is_empty()
333 }
334
335 pub fn get_key_value(&self, name: &str) -> Option<(&Key<'de>, &Item<'de>)> {
337 self.value.get_entry(name)
338 }
339
340 pub fn get(&self, name: &str) -> Option<&Item<'de>> {
342 self.value.get(name)
343 }
344
345 pub fn get_mut(&mut self, name: &str) -> Option<&mut Item<'de>> {
347 self.value.get_mut(name)
348 }
349
350 #[inline]
352 pub fn contains_key(&self, name: &str) -> bool {
353 self.value.contains_key(name)
354 }
355
356 pub fn remove_entry(&mut self, name: &str) -> Option<(Key<'de>, Item<'de>)> {
359 self.value.remove_entry(name)
360 }
361
362 #[inline]
364 pub fn entries(&self) -> &[TableEntry<'de>] {
365 self.value.entries()
366 }
367
368 pub fn as_item(&self) -> &Item<'de> {
370 unsafe {
371 &*(self as *const Table<'de>).cast::<Item<'de>>()
374 }
375 }
376
377 pub fn into_item(self) -> Item<'de> {
379 let span = self.span();
380 Item::table(self.value, span)
381 }
382}
383
384impl<'a, 'de> IntoIterator for &'a mut Table<'de> {
385 type Item = &'a mut (Key<'de>, Item<'de>);
386 type IntoIter = std::slice::IterMut<'a, TableEntry<'de>>;
387
388 fn into_iter(self) -> Self::IntoIter {
389 self.value.entries_mut().iter_mut()
390 }
391}
392impl<'a, 'de> IntoIterator for &'a Table<'de> {
393 type Item = &'a (Key<'de>, Item<'de>);
394 type IntoIter = std::slice::Iter<'a, TableEntry<'de>>;
395
396 fn into_iter(self) -> Self::IntoIter {
397 self.value.entries().iter()
398 }
399}
400
401impl<'de> IntoIterator for Table<'de> {
402 type Item = (Key<'de>, Item<'de>);
403 type IntoIter = IntoIter<'de>;
404
405 fn into_iter(self) -> Self::IntoIter {
406 IntoIter {
407 table: self.value,
408 index: 0,
409 }
410 }
411}
412
413const _: () = assert!(std::mem::size_of::<Table<'_>>() == std::mem::size_of::<Item<'_>>());
414const _: () = assert!(std::mem::align_of::<Table<'_>>() == std::mem::align_of::<Item<'_>>());
415
416impl<'de> Table<'de> {
417 #[inline]
418 pub(crate) fn span_start(&self) -> u32 {
419 self.start_and_tag >> TAG_SHIFT
420 }
421
422 #[inline]
423 pub(crate) fn set_span_start(&mut self, v: u32) {
424 self.start_and_tag = (v << TAG_SHIFT) | (self.start_and_tag & TAG_MASK);
425 }
426
427 #[inline]
428 pub(crate) fn set_span_end(&mut self, v: u32) {
429 self.end_and_flag = (v << FLAG_SHIFT) | (self.end_and_flag & FLAG_MASK);
430 }
431
432 #[inline]
433 pub(crate) fn extend_span_end(&mut self, new_end: u32) {
434 let old = self.end_and_flag;
435 let current = old >> FLAG_SHIFT;
436 self.end_and_flag = (current.max(new_end) << FLAG_SHIFT) | (old & FLAG_MASK);
437 }
438
439 #[inline]
440 pub(crate) fn set_header_flag(&mut self) {
441 self.end_and_flag = (self.end_and_flag & !FLAG_MASK) | FLAG_HEADER;
442 }
443}
444
445impl<'de> std::ops::Index<&str> for Table<'de> {
446 type Output = MaybeItem<'de>;
447
448 #[inline]
449 fn index(&self, index: &str) -> &Self::Output {
450 if let Some(item) = self.get(index) {
451 return MaybeItem::from_ref(item);
452 }
453 &NONE
454 }
455}