1#[cfg(test)]
2#[path = "./table_tests.rs"]
3mod tests;
4
5use crate::Span;
6use crate::item::{
7 FLAG_DOTTED, FLAG_FROZEN, FLAG_HEADER, FLAG_TABLE, Item, ItemMetadata, Key, MaybeItem, NONE,
8 TAG_TABLE, TableStyle,
9};
10use crate::parser::KeyRef;
11use std::mem::size_of;
12use std::ptr::NonNull;
13
14use crate::arena::Arena;
15
16pub(crate) type TableIndex<'de> = foldhash::HashMap<KeyRef<'de>, usize>;
17
18type TableEntry<'de> = (Key<'de>, Item<'de>);
19
20const MIN_CAP: u32 = 2;
21
22#[repr(C, align(8))]
24pub(crate) struct InnerTable<'de> {
25 pub(super) len: u32,
26 pub(super) cap: u32,
27 pub(super) ptr: NonNull<TableEntry<'de>>,
28}
29
30impl<'de> InnerTable<'de> {
31 #[inline]
33 pub fn new() -> Self {
34 Self {
35 len: 0,
36 cap: 0,
37 ptr: NonNull::dangling(),
38 }
39 }
40
41 pub(crate) fn with_capacity(cap: u32, arena: &'de Arena) -> Self {
42 let mut table = Self::new();
43 if cap > 0 {
44 table.grow_to(cap, arena);
45 }
46 table
47 }
48
49 pub fn insert_unique(
51 &mut self,
52 key: Key<'de>,
53 item: Item<'de>,
54 arena: &'de Arena,
55 ) -> &mut TableEntry<'de> {
56 let len = self.len;
57 if self.len == self.cap {
58 self.grow(arena);
59 }
60 unsafe {
63 let ptr = self.ptr.as_ptr().add(len as usize);
64 ptr.write((key, item));
65 self.len = len + 1;
66 &mut (*ptr)
67 }
68 }
69
70 #[inline]
72 pub fn len(&self) -> usize {
73 self.len as usize
74 }
75
76 #[inline]
78 pub fn is_empty(&self) -> bool {
79 self.len == 0
80 }
81 #[cfg(feature = "to-toml")]
87 pub(crate) fn get_entry_with_index(
88 &self,
89 key: &str,
90 index: &TableIndex<'_>,
91 ) -> Option<&TableEntry<'de>> {
92 if self.len() > crate::parser::INDEXED_TABLE_THRESHOLD {
93 let first_key_span = unsafe { self.first_key_span_start_unchecked() };
95 let i = *index.get(&KeyRef::new(key, first_key_span))?;
96 self.entries().get(i)
97 } else {
98 for entry in self.entries() {
99 if entry.0.name == key {
100 return Some(entry);
101 }
102 }
103 None
104 }
105 }
106
107 pub(crate) fn get_entry_with_maybe_index(
108 &self,
109 key: &str,
110 index: Option<&TableIndex<'_>>,
111 ) -> Option<&TableEntry<'de>> {
112 if self.len() > crate::parser::INDEXED_TABLE_THRESHOLD {
113 if let Some(index) = index {
114 let first_key_span = unsafe { self.first_key_span_start_unchecked() };
116 let i = *index.get(&KeyRef::new(key, first_key_span))?;
117 return self.entries().get(i);
118 }
119 }
120 for entry in self.entries() {
121 if entry.0.name == key {
122 return Some(entry);
123 }
124 }
125 None
126 }
127 pub fn get_entry(&self, name: &str) -> Option<(&Key<'de>, &Item<'de>)> {
129 for (key, item) in self.entries() {
130 if key.name == name {
131 return Some((key, item));
132 }
133 }
134 None
135 }
136
137 pub fn get(&self, name: &str) -> Option<&Item<'de>> {
139 for (key, item) in self.entries() {
140 if key.name == name {
141 return Some(item);
142 }
143 }
144 None
145 }
146
147 pub fn get_mut(&mut self, name: &str) -> Option<&mut Item<'de>> {
149 for (key, item) in self.entries_mut() {
150 if key.name == name {
151 return Some(item);
152 }
153 }
154 None
155 }
156
157 #[inline]
159 pub fn contains_key(&self, name: &str) -> bool {
160 self.get(name).is_some()
161 }
162
163 pub fn remove_entry(&mut self, name: &str) -> Option<(Key<'de>, Item<'de>)> {
166 let idx = self.find_index(name)?;
167 Some(self.remove_at(idx))
168 }
169
170 #[inline]
177 pub(crate) unsafe fn first_key_span_start_unchecked(&self) -> u32 {
178 debug_assert!(self.len > 0);
179 unsafe { (*self.ptr.as_ptr()).0.span.start }
181 }
182
183 #[inline]
185 pub fn entries(&self) -> &[TableEntry<'de>] {
186 unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) }
190 }
191
192 #[inline]
193 pub fn entries_mut(&mut self) -> &mut [TableEntry<'de>] {
194 unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize) }
196 }
197
198 pub(crate) fn find_index(&self, name: &str) -> Option<usize> {
199 for (i, (key, _)) in self.entries().iter().enumerate() {
200 if key.name == name {
201 return Some(i);
202 }
203 }
204 None
205 }
206
207 fn remove_at(&mut self, idx: usize) -> (Key<'de>, Item<'de>) {
209 let last = self.len as usize - 1;
210 let ptr = unsafe { self.ptr.as_ptr().add(idx) };
213 let entry = unsafe { ptr.read() };
214 if idx != last {
215 unsafe {
217 ptr.write(self.ptr.as_ptr().add(last).read());
218 }
219 }
220 self.len -= 1;
221 entry
222 }
223
224 #[cold]
225 fn grow(&mut self, arena: &'de Arena) {
226 let new_cap = if self.cap == 0 {
227 MIN_CAP
228 } else {
229 self.cap.checked_mul(2).expect("capacity overflow")
230 };
231 self.grow_to(new_cap, arena);
232 }
233
234 fn grow_to(&mut self, new_cap: u32, arena: &'de Arena) {
235 #[cfg(target_pointer_width = "32")]
237 let new_size = (new_cap as usize)
238 .checked_mul(size_of::<TableEntry<'_>>())
239 .expect("capacity overflow");
240 #[cfg(not(target_pointer_width = "32"))]
241 let new_size = new_cap as usize * size_of::<TableEntry<'_>>();
242 if self.cap > 0 {
243 let old_size = self.cap as usize * size_of::<TableEntry<'_>>();
244 self.ptr = unsafe { arena.realloc(self.ptr.cast(), old_size, new_size).cast() };
246 } else {
247 self.ptr = arena.alloc(new_size).cast();
248 }
249 self.cap = new_cap;
250 }
251
252 pub(crate) fn clone_in(&self, arena: &'de Arena) -> Self {
255 let len = self.len as usize;
256 if len == 0 {
257 return Self::new();
258 }
259 let size = len * size_of::<TableEntry<'de>>();
260 let dst: NonNull<TableEntry<'de>> = arena.alloc(size).cast();
261 let src = self.ptr.as_ptr();
262 let dst_ptr = dst.as_ptr();
263
264 let mut run_start = 0;
265 for i in 0..len {
266 if unsafe { !(*src.add(i)).1.is_scalar() } {
268 if run_start < i {
269 unsafe {
273 std::ptr::copy_nonoverlapping(
274 src.add(run_start),
275 dst_ptr.add(run_start),
276 i - run_start,
277 );
278 }
279 }
280 unsafe {
283 let (key, item) = &*src.add(i);
284 dst_ptr.add(i).write((*key, item.clone_in(arena)));
285 }
286 run_start = i + 1;
287 }
288 }
289 if run_start < len {
290 unsafe {
291 std::ptr::copy_nonoverlapping(
292 src.add(run_start),
293 dst_ptr.add(run_start),
294 len - run_start,
295 );
296 }
297 }
298
299 Self {
300 len: self.len,
301 cap: self.len,
302 ptr: dst,
303 }
304 }
305}
306
307impl std::fmt::Debug for InnerTable<'_> {
308 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
309 let mut map = f.debug_map();
310 for (k, v) in self.entries() {
311 map.entry(k, v);
312 }
313 map.finish()
314 }
315}
316
317pub struct IntoIter<'de> {
319 table: InnerTable<'de>,
320 index: u32,
321}
322
323impl<'de> Iterator for IntoIter<'de> {
324 type Item = (Key<'de>, Item<'de>);
325
326 fn next(&mut self) -> Option<Self::Item> {
327 if self.index < self.table.len {
328 let entry = unsafe { self.table.ptr.as_ptr().add(self.index as usize).read() };
331 self.index += 1;
332 Some(entry)
333 } else {
334 None
335 }
336 }
337
338 fn size_hint(&self) -> (usize, Option<usize>) {
339 let remaining = (self.table.len - self.index) as usize;
340 (remaining, Some(remaining))
341 }
342}
343
344impl ExactSizeIterator for IntoIter<'_> {}
345
346#[repr(C)]
396pub struct Table<'de> {
397 pub(crate) value: InnerTable<'de>,
398 pub(crate) meta: ItemMetadata,
399}
400
401impl<'de> Table<'de> {
402 pub fn new() -> Table<'de> {
408 let mut meta = ItemMetadata::hints(TAG_TABLE, FLAG_TABLE);
409 meta.set_auto_style();
410 Table {
411 meta,
412 value: InnerTable::new(),
413 }
414 }
415
416 pub fn try_with_capacity(cap: usize, arena: &'de Arena) -> Option<Table<'de>> {
420 let cap: u32 = cap.try_into().ok()?;
421 let mut meta = ItemMetadata::hints(TAG_TABLE, FLAG_TABLE);
422 meta.set_auto_style();
423 Some(Table {
424 meta,
425 value: InnerTable::with_capacity(cap, arena),
426 })
427 }
428
429 pub(crate) fn new_spanned(span: Span) -> Table<'de> {
431 Table {
432 meta: ItemMetadata::spanned(TAG_TABLE, FLAG_TABLE, span.start, span.end),
433 value: InnerTable::new(),
434 }
435 }
436
437 pub fn span(&self) -> Span {
440 self.meta.span()
441 }
442}
443
444impl<'de> Default for Table<'de> {
445 fn default() -> Self {
446 Self::new()
447 }
448}
449
450impl std::fmt::Debug for Table<'_> {
451 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
452 self.value.fmt(f)
453 }
454}
455
456impl<'de> Table<'de> {
457 pub fn insert(&mut self, key: Key<'de>, value: Item<'de>, arena: &'de Arena) {
462 if let Some(existing) = self.get_mut(key.name) {
463 *existing = value;
464 return;
465 }
466 self.value.insert_unique(key, value, arena);
467 }
468
469 pub fn insert_unique(&mut self, key: Key<'de>, value: Item<'de>, arena: &'de Arena) {
474 self.value.insert_unique(key, value, arena);
475 }
476 #[inline]
478 pub fn len(&self) -> usize {
479 self.value.len()
480 }
481
482 #[inline]
484 pub fn is_empty(&self) -> bool {
485 self.value.is_empty()
486 }
487
488 pub fn get_key_value(&self, name: &str) -> Option<(&Key<'de>, &Item<'de>)> {
490 self.value.get_entry(name)
491 }
492
493 pub fn get(&self, name: &str) -> Option<&Item<'de>> {
495 self.value.get(name)
496 }
497
498 pub fn get_mut(&mut self, name: &str) -> Option<&mut Item<'de>> {
500 self.value.get_mut(name)
501 }
502
503 #[inline]
505 pub fn contains_key(&self, name: &str) -> bool {
506 self.value.contains_key(name)
507 }
508
509 pub fn remove_entry(&mut self, name: &str) -> Option<(Key<'de>, Item<'de>)> {
512 self.value.remove_entry(name)
513 }
514
515 #[inline]
517 pub fn entries(&self) -> &[TableEntry<'de>] {
518 self.value.entries()
519 }
520 #[inline]
522 pub fn entries_mut(&mut self) -> &mut [TableEntry<'de>] {
523 self.value.entries_mut()
524 }
525
526 #[inline]
528 pub fn iter(&self) -> std::slice::Iter<'_, TableEntry<'de>> {
529 self.entries().iter()
530 }
531
532 pub fn as_item(&self) -> &Item<'de> {
534 unsafe { &*(self as *const Table<'de>).cast::<Item<'de>>() }
542 }
543
544 pub fn into_item(self) -> Item<'de> {
546 unsafe { std::mem::transmute(self) }
550 }
551}
552
553impl<'a, 'de> IntoIterator for &'a mut Table<'de> {
554 type Item = &'a mut (Key<'de>, Item<'de>);
555 type IntoIter = std::slice::IterMut<'a, TableEntry<'de>>;
556
557 fn into_iter(self) -> Self::IntoIter {
558 self.value.entries_mut().iter_mut()
559 }
560}
561impl<'a, 'de> IntoIterator for &'a Table<'de> {
562 type Item = &'a (Key<'de>, Item<'de>);
563 type IntoIter = std::slice::Iter<'a, TableEntry<'de>>;
564
565 fn into_iter(self) -> Self::IntoIter {
566 self.value.entries().iter()
567 }
568}
569
570impl<'de> IntoIterator for Table<'de> {
571 type Item = (Key<'de>, Item<'de>);
572 type IntoIter = IntoIter<'de>;
573
574 fn into_iter(self) -> Self::IntoIter {
575 IntoIter {
576 table: self.value,
577 index: 0,
578 }
579 }
580}
581
582const _: () = assert!(std::mem::size_of::<Table<'_>>() == std::mem::size_of::<Item<'_>>());
583const _: () = assert!(std::mem::align_of::<Table<'_>>() == std::mem::align_of::<Item<'_>>());
584
585impl<'de> Table<'de> {
586 #[inline]
587 pub(crate) fn span_start(&self) -> u32 {
588 self.meta.span_start()
589 }
590
591 #[inline]
592 pub(crate) fn set_span_start(&mut self, v: u32) {
593 self.meta.set_span_start(v);
594 }
595
596 #[inline]
597 pub(crate) fn set_span_end(&mut self, v: u32) {
598 self.meta.set_span_end(v);
599 }
600
601 #[inline]
602 pub(crate) fn extend_span_end(&mut self, new_end: u32) {
603 self.meta.extend_span_end(new_end);
604 }
605
606 #[inline]
607 pub(crate) fn set_header_flag(&mut self) {
608 self.meta.set_flag(FLAG_HEADER);
609 }
610
611 #[inline]
612 pub(crate) fn set_dotted_flag(&mut self) {
613 self.meta.set_flag(FLAG_DOTTED);
614 }
615
616 #[inline]
618 pub fn style(&self) -> TableStyle {
619 match self.meta.flag() {
620 FLAG_DOTTED => TableStyle::Dotted,
621 FLAG_HEADER => TableStyle::Header,
622 FLAG_FROZEN => TableStyle::Inline,
623 _ => TableStyle::Implicit,
624 }
625 }
626
627 #[inline]
629 pub fn set_style(&mut self, kind: TableStyle) {
630 let flag = match kind {
631 TableStyle::Implicit => FLAG_TABLE,
632 TableStyle::Dotted => FLAG_DOTTED,
633 TableStyle::Header => FLAG_HEADER,
634 TableStyle::Inline => FLAG_FROZEN,
635 };
636 self.meta.set_flag(flag);
637 self.meta.clear_auto_style();
638 }
639
640 pub fn clone_in(&self, arena: &'de Arena) -> Table<'de> {
643 Table {
644 value: self.value.clone_in(arena),
645 meta: self.meta,
646 }
647 }
648}
649
650impl<'de> std::ops::Index<&str> for Table<'de> {
651 type Output = MaybeItem<'de>;
652
653 #[inline]
654 fn index(&self, index: &str) -> &Self::Output {
655 if let Some(item) = self.get(index) {
656 return MaybeItem::from_ref(item);
657 }
658 &NONE
659 }
660}