1#[cfg(test)]
2#[path = "./de_tests.rs"]
3mod tests;
4
5use std::num::NonZeroU64;
6
7use foldhash::HashMap;
8
9use crate::{
10 Arena, Error, ErrorKind, Key, Span, Table,
11 parser::{INDEXED_TABLE_THRESHOLD, KeyRef},
12 value::{self, Item},
13};
14
15pub struct TableHelper<'ctx, 'table, 'de> {
50 pub ctx: &'ctx mut Context<'de>,
51 pub table: &'table Table<'de>,
52 table_id: i32,
54 used_count: u32,
56 used: &'de mut FixedBitset,
57}
58
59#[repr(transparent)]
60struct FixedBitset([u64]);
61
62impl FixedBitset {
63 #[allow(clippy::mut_from_ref)]
64 pub fn new(capacity: usize, arena: &Arena) -> &mut FixedBitset {
65 let bitset_bucket_count = capacity.div_ceil(64);
66 let bitset = arena
67 .alloc(bitset_bucket_count * std::mem::size_of::<u64>())
68 .cast::<u64>();
69 for offset in 0..bitset_bucket_count {
70 unsafe {
73 bitset.add(offset).write(0);
74 }
75 }
76 let slice = unsafe { std::slice::from_raw_parts_mut(bitset.as_ptr(), bitset_bucket_count) };
78 unsafe { &mut *(slice as *mut [u64] as *mut FixedBitset) }
80 }
81
82 pub fn insert(&mut self, index: usize) -> bool {
83 let offset = index >> 6;
84 let bit = 1 << (index & 63);
85 let old = self.0[offset];
86 self.0[offset] |= bit;
87 old & bit == 0
88 }
89
90 pub fn get(&self, index: usize) -> bool {
91 let offset = index >> 6;
92 let bit = 1 << (index & 63);
93 self.0[offset] & bit != 0
94 }
95}
96
97pub struct RemainingEntriesIter<'t, 'de> {
102 entries: &'t [(Key<'de>, Item<'de>)],
103 remaining_cells: std::slice::Iter<'de, u64>,
104 bits: u64,
105}
106impl RemainingEntriesIter<'_, '_> {
107 fn next_bucket(&mut self) -> bool {
108 if let Some(bucket) = self.remaining_cells.next() {
109 debug_assert!(self.entries.len() > 64);
110 if let Some(remaining) = self.entries.get(64..) {
111 self.entries = remaining;
112 } else {
113 return false;
115 }
116 self.bits = !*bucket;
117 true
118 } else {
119 false
120 }
121 }
122}
123
124impl<'t, 'de> Iterator for RemainingEntriesIter<'t, 'de> {
125 type Item = &'t (Key<'de>, Item<'de>);
126
127 fn next(&mut self) -> Option<Self::Item> {
128 loop {
129 if let Some(bits) = NonZeroU64::new(self.bits) {
130 let bit_index = bits.trailing_zeros() as usize;
131 self.bits &= self.bits - 1;
132 return self.entries.get(bit_index);
133 }
134 if !self.next_bucket() {
135 return None;
136 }
137 }
138 }
139}
140
141impl<'ctx, 't, 'de> TableHelper<'ctx, 't, 'de> {
142 pub fn new(ctx: &'ctx mut Context<'de>, table: &'t Table<'de>) -> Self {
147 let table_id = if table.len() > INDEXED_TABLE_THRESHOLD {
148 table.entries()[0].0.span.start as i32
150 } else {
151 -1
152 };
153 Self {
154 used: FixedBitset::new(table.len(), ctx.arena),
155 ctx,
156 table,
157 table_id,
158 used_count: 0,
159 }
160 }
161 pub fn get_entry(&self, key: &str) -> Option<&'t (Key<'de>, Item<'de>)> {
168 if self.table_id < 0 {
169 for entry in self.table.entries() {
170 if entry.0.name == key {
171 return Some(entry);
172 }
173 }
174 None
175 } else {
176 match self.ctx.index.get(&KeyRef::new(key, self.table_id as u32)) {
177 Some(index) => Some(&self.table.entries()[*index]),
178 None => None,
179 }
180 }
181 }
182
183 pub fn required_mapped<T>(
195 &mut self,
196 name: &'static str,
197 func: fn(&Item<'de>) -> Result<T, Error>,
198 ) -> Result<T, Failed> {
199 let Some((_, item)) = self.optional_entry(name) else {
200 return Err(self.report_missing_field(name));
201 };
202
203 func(item).map_err(|err| {
204 self.ctx.push_error(Error {
205 kind: ErrorKind::Custom(std::borrow::Cow::Owned(err.to_string())),
206 span: item.span(),
207 })
208 })
209 }
210
211 pub fn optional_mapped<T>(
218 &mut self,
219 name: &'static str,
220 func: fn(&Item<'de>) -> Result<T, Error>,
221 ) -> Option<T> {
222 let Some((_, item)) = self.optional_entry(name) else {
223 return None;
224 };
225
226 func(item)
227 .map_err(|err| {
228 self.ctx.push_error(Error {
229 kind: ErrorKind::Custom(std::borrow::Cow::Owned(err.to_string())),
230 span: item.span(),
231 })
232 })
233 .ok()
234 }
235
236 pub fn required_item(&mut self, name: &'static str) -> Result<&'t Item<'de>, Failed> {
247 self.required_entry(name).map(|(_, value)| value)
248 }
249
250 pub fn optional_item(&mut self, name: &'static str) -> Option<&'t Item<'de>> {
256 self.optional_entry(name).map(|(_, value)| value)
257 }
258
259 pub fn required_entry(
270 &mut self,
271 name: &'static str,
272 ) -> Result<&'t (Key<'de>, Item<'de>), Failed> {
273 match self.optional_entry(name) {
274 Some(entry) => Ok(entry),
275 None => Err(self.report_missing_field(name)),
276 }
277 }
278
279 pub fn optional_entry(&mut self, key: &str) -> Option<&'t (Key<'de>, Item<'de>)> {
285 let entry = self.get_entry(key)?;
286 let index = unsafe {
287 let ptr = entry as *const (Key<'de>, Item<'de>);
288 let base = self.table.entries().as_ptr();
289 ptr.offset_from(base) as usize
290 };
291 if self.used.insert(index) {
292 self.used_count += 1;
293 }
294 Some(entry)
295 }
296
297 #[cold]
298 fn report_missing_field(&mut self, name: &'static str) -> Failed {
299 self.ctx.errors.push(Error {
300 kind: ErrorKind::MissingField(name),
301 span: self.table.span(),
302 });
303 Failed
304 }
305
306 pub fn required<T: Deserialize<'de>>(&mut self, name: &'static str) -> Result<T, Failed> {
316 let Some((_, val)) = self.optional_entry(name) else {
317 return Err(self.report_missing_field(name));
318 };
319
320 T::deserialize(self.ctx, val)
321 }
322
323 pub fn optional<T: Deserialize<'de>>(&mut self, name: &str) -> Option<T> {
329 let Some((_, val)) = self.optional_entry(name) else {
330 return None;
331 };
332
333 #[allow(clippy::manual_ok_err)]
334 match T::deserialize(self.ctx, val) {
335 Ok(value) => Some(value),
336 Err(_) => None,
338 }
339 }
340
341 pub fn remaining_count(&self) -> usize {
343 self.table.len() - self.used_count as usize
344 }
345
346 pub fn into_remaining(self) -> RemainingEntriesIter<'t, 'de> {
348 let entries = self.table.entries();
349 let mut remaining_cells = self.used.0.iter();
350 RemainingEntriesIter {
351 bits: if let Some(value) = remaining_cells.next() {
352 !*value
353 } else {
354 0
355 },
356 entries,
357 remaining_cells,
358 }
359 }
360
361 #[inline(never)]
373 pub fn expect_empty(self) -> Result<(), Failed> {
374 if self.used_count as usize == self.table.len() {
375 return Ok(());
376 }
377
378 let mut keys = Vec::new();
379 for (i, (key, _)) in self.table.entries().iter().enumerate() {
380 if !self.used.get(i) {
381 keys.push((key.name.into(), key.span));
382 }
383 }
384
385 if keys.is_empty() {
386 return Ok(());
387 }
388
389 self.ctx.errors.push(Error::from((
390 ErrorKind::UnexpectedKeys { keys },
391 self.table.span(),
392 )));
393 Err(Failed)
394 }
395}
396
397pub struct Context<'de> {
406 pub arena: &'de Arena,
407 pub(crate) index: HashMap<KeyRef<'de>, usize>,
408 pub errors: Vec<Error>,
409}
410
411impl<'de> Context<'de> {
412 #[cold]
414 pub fn error_expected_but_found(&mut self, message: &'static str, found: &Item<'_>) -> Failed {
415 self.errors.push(Error {
416 kind: ErrorKind::Wanted {
417 expected: message,
418 found: found.type_str(),
419 },
420 span: found.span(),
421 });
422 Failed
423 }
424
425 #[cold]
427 pub fn error_message_at(&mut self, message: &'static str, at: Span) -> Failed {
428 self.errors.push(Error {
429 kind: ErrorKind::Custom(std::borrow::Cow::Borrowed(message)),
430 span: at,
431 });
432 Failed
433 }
434 #[cold]
436 pub fn push_error(&mut self, error: Error) -> Failed {
437 self.errors.push(error);
438 Failed
439 }
440
441 #[cold]
443 pub fn error_out_of_range(&mut self, name: &'static str, span: Span) -> Failed {
444 self.errors.push(Error {
445 kind: ErrorKind::OutOfRange(name),
446 span,
447 });
448 Failed
449 }
450}
451
452#[derive(Debug)]
460pub struct Failed;
461
462pub trait Deserialize<'de>: Sized {
490 fn deserialize(ctx: &mut Context<'de>, item: &Item<'de>) -> Result<Self, Failed>;
495}
496
497impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for [T; N] {
498 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
499 let boxed_slice = Box::<[T]>::deserialize(ctx, value)?;
500 match <Box<[T; N]>>::try_from(boxed_slice) {
501 Ok(array) => Ok(*array),
502 Err(res) => Err(ctx.push_error(Error {
503 kind: ErrorKind::Custom(std::borrow::Cow::Owned(format!(
504 "Expect Array Size: found {} but expected {}",
505 res.len(),
506 N
507 ))),
508 span: value.span(),
509 })),
510 }
511 }
512}
513
514impl<'de> Deserialize<'de> for String {
515 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
516 match value.as_str() {
517 Some(s) => Ok(s.to_string()),
518 None => Err(ctx.error_expected_but_found("a string", value)),
519 }
520 }
521}
522
523impl<'de, T: Deserialize<'de>> Deserialize<'de> for Box<T> {
524 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
525 match T::deserialize(ctx, value) {
526 Ok(v) => Ok(Box::new(v)),
527 Err(e) => Err(e),
528 }
529 }
530}
531impl<'de, T: Deserialize<'de>> Deserialize<'de> for Box<[T]> {
532 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
533 match Vec::<T>::deserialize(ctx, value) {
534 Ok(vec) => Ok(vec.into_boxed_slice()),
535 Err(e) => Err(e),
536 }
537 }
538}
539impl<'de> Deserialize<'de> for Box<str> {
540 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
541 match value.value() {
542 value::Value::String(&s) => Ok(s.into()),
543 _ => Err(ctx.error_expected_but_found("a string", value)),
544 }
545 }
546}
547impl<'de> Deserialize<'de> for &'de str {
548 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
549 match value.value() {
550 value::Value::String(s) => Ok(*s),
551 _ => Err(ctx.error_expected_but_found("a string", value)),
552 }
553 }
554}
555
556impl<'de> Deserialize<'de> for std::borrow::Cow<'de, str> {
557 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
558 match value.value() {
559 value::Value::String(s) => Ok(std::borrow::Cow::Borrowed(*s)),
560 _ => Err(ctx.error_expected_but_found("a string", value)),
561 }
562 }
563}
564
565impl<'de> Deserialize<'de> for bool {
566 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
567 match value.as_bool() {
568 Some(b) => Ok(b),
569 None => Err(ctx.error_expected_but_found("a bool", value)),
570 }
571 }
572}
573
574fn deser_integer_ctx(
575 ctx: &mut Context<'_>,
576 value: &Item<'_>,
577 min: i64,
578 max: i64,
579 name: &'static str,
580) -> Result<i64, Failed> {
581 let span = value.span();
582 match value.as_i64() {
583 Some(i) if i >= min && i <= max => Ok(i),
584 Some(_) => Err(ctx.error_out_of_range(name, span)),
585 None => Err(ctx.error_expected_but_found("an integer", value)),
586 }
587}
588
589macro_rules! integer_new {
590 ($($num:ty),+) => {$(
591 impl<'de> Deserialize<'de> for $num {
592 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
593 match deser_integer_ctx(ctx, value, <$num>::MIN as i64, <$num>::MAX as i64, stringify!($num)) {
594 Ok(i) => Ok(i as $num),
595 Err(e) => Err(e),
596 }
597 }
598 }
599 )+};
600}
601
602integer_new!(i8, i16, i32, isize, u8, u16, u32);
603
604impl<'de> Deserialize<'de> for i64 {
605 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
606 deser_integer_ctx(ctx, value, i64::MIN, i64::MAX, "i64")
607 }
608}
609
610impl<'de> Deserialize<'de> for u64 {
611 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
612 match deser_integer_ctx(ctx, value, 0, i64::MAX, "u64") {
613 Ok(i) => Ok(i as u64),
614 Err(e) => Err(e),
615 }
616 }
617}
618
619impl<'de> Deserialize<'de> for usize {
620 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
621 const MAX: i64 = if usize::BITS < 64 {
622 usize::MAX as i64
623 } else {
624 i64::MAX
625 };
626 match deser_integer_ctx(ctx, value, 0, MAX, "usize") {
627 Ok(i) => Ok(i as usize),
628 Err(e) => Err(e),
629 }
630 }
631}
632
633impl<'de> Deserialize<'de> for f32 {
634 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
635 match value.as_f64() {
636 Some(f) => Ok(f as f32),
637 None => Err(ctx.error_expected_but_found("a float", value)),
638 }
639 }
640}
641
642impl<'de> Deserialize<'de> for f64 {
643 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
644 match value.as_f64() {
645 Some(f) => Ok(f),
646 None => Err(ctx.error_expected_but_found("a float", value)),
647 }
648 }
649}
650
651impl<'de, T> Deserialize<'de> for Vec<T>
652where
653 T: Deserialize<'de>,
654{
655 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
656 let arr = value.expect_array(ctx)?;
657 let mut result = Vec::with_capacity(arr.len());
658 let mut had_error = false;
659 for item in arr {
660 match T::deserialize(ctx, item) {
661 Ok(v) => result.push(v),
662 Err(_) => had_error = true,
663 }
664 }
665 if had_error { Err(Failed) } else { Ok(result) }
666 }
667}
668
669impl<'de> Item<'de> {
670 pub fn expect_custom_string(
676 &self,
677 ctx: &mut Context<'de>,
678 expected: &'static str,
679 ) -> Result<&'de str, Failed> {
680 match self.value() {
681 value::Value::String(s) => Ok(*s),
682 _ => Err(ctx.error_expected_but_found(expected, self)),
683 }
684 }
685 pub fn expect_string(&self, ctx: &mut Context<'de>) -> Result<&'de str, Failed> {
687 match self.value() {
688 value::Value::String(s) => Ok(*s),
689 _ => Err(ctx.error_expected_but_found("a string", self)),
690 }
691 }
692
693 pub fn expect_array(&self, ctx: &mut Context<'de>) -> Result<&crate::Array<'de>, Failed> {
695 match self.as_array() {
696 Some(arr) => Ok(arr),
697 None => Err(ctx.error_expected_but_found("an array", self)),
698 }
699 }
700
701 pub fn expect_table(&self, ctx: &mut Context<'de>) -> Result<&crate::Table<'de>, Failed> {
703 match self.as_table() {
704 Some(table) => Ok(table),
705 None => Err(ctx.error_expected_but_found("a table", self)),
706 }
707 }
708
709 pub fn table_helper<'ctx, 'item>(
713 &'item self,
714 ctx: &'ctx mut Context<'de>,
715 ) -> Result<TableHelper<'ctx, 'item, 'de>, Failed> {
716 let Some(table) = self.as_table() else {
717 return Err(ctx.error_expected_but_found("a table", self));
718 };
719 Ok(TableHelper::new(ctx, table))
720 }
721}