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_len = capacity.div_ceil(64);
66 let bitset = arena.alloc(bitset_len).cast::<u64>();
67 for offset in 0..bitset_len {
68 unsafe {
69 bitset.add(offset).write(0);
70 }
71 }
72 let slice = unsafe { std::slice::from_raw_parts_mut(bitset.as_ptr(), bitset_len) };
73 unsafe { &mut *(slice as *mut [u64] as *mut FixedBitset) }
74 }
75
76 pub fn insert(&mut self, index: usize) -> bool {
77 let offset = index >> 6;
78 let bit = 1 << (index & 63);
79 let old = self.0[offset];
80 self.0[offset] |= bit;
81 old & bit == 0
82 }
83
84 pub fn get(&self, index: usize) -> bool {
85 let offset = index >> 6;
86 let bit = 1 << (index & 63);
87 self.0[offset] & bit != 0
88 }
89}
90
91pub struct RemainingEntriesIter<'t, 'de> {
96 entries: &'t [(Key<'de>, Item<'de>)],
97 remaining_cells: std::slice::Iter<'de, u64>,
98 bits: u64,
99}
100impl RemainingEntriesIter<'_, '_> {
101 fn next_bucket(&mut self) -> bool {
102 if let Some(bucket) = self.remaining_cells.next() {
103 debug_assert!(self.entries.len() > 64);
104 if let Some(remaining) = self.entries.get(64..) {
105 self.entries = remaining;
106 } else {
107 return false;
109 }
110 self.bits = !*bucket;
111 true
112 } else {
113 false
114 }
115 }
116}
117
118impl<'t, 'de> Iterator for RemainingEntriesIter<'t, 'de> {
119 type Item = &'t (Key<'de>, Item<'de>);
120
121 fn next(&mut self) -> Option<Self::Item> {
122 loop {
123 if let Some(bits) = NonZeroU64::new(self.bits) {
124 let bit_index = bits.trailing_zeros() as usize;
125 self.bits &= self.bits - 1;
126 return self.entries.get(bit_index);
127 }
128 if !self.next_bucket() {
129 return None;
130 }
131 }
132 }
133}
134
135impl<'ctx, 't, 'de> TableHelper<'ctx, 't, 'de> {
136 pub fn new(ctx: &'ctx mut Context<'de>, table: &'t Table<'de>) -> Self {
141 let table_id = if table.len() > INDEXED_TABLE_THRESHOLD {
142 table.entries()[0].0.span.start as i32
144 } else {
145 -1
146 };
147 Self {
148 used: FixedBitset::new(table.len(), ctx.arena),
149 ctx,
150 table,
151 table_id,
152 used_count: 0,
153 }
154 }
155 pub fn get_entry(&self, key: &str) -> Option<&'t (Key<'de>, Item<'de>)> {
162 if self.table_id < 0 {
163 for entry in self.table.entries() {
164 if entry.0.name == key {
165 return Some(entry);
166 }
167 }
168 None
169 } else {
170 match self.ctx.index.get(&KeyRef::new(key, self.table_id as u32)) {
171 Some(index) => Some(&self.table.entries()[*index]),
172 None => None,
173 }
174 }
175 }
176
177 pub fn required_mapped<T>(
189 &mut self,
190 name: &'static str,
191 func: fn(&Item<'de>) -> Result<T, Error>,
192 ) -> Result<T, Failed> {
193 let Some((_, item)) = self.optional_entry(name) else {
194 return Err(self.report_missing_field(name));
195 };
196
197 func(item).map_err(|err| {
198 self.ctx.push_error(Error {
199 kind: ErrorKind::Custom(std::borrow::Cow::Owned(err.to_string())),
200 span: item.span(),
201 })
202 })
203 }
204
205 pub fn optional_mapped<T>(
212 &mut self,
213 name: &'static str,
214 func: fn(&Item<'de>) -> Result<T, Error>,
215 ) -> Option<T> {
216 let Some((_, item)) = self.optional_entry(name) else {
217 return None;
218 };
219
220 func(item)
221 .map_err(|err| {
222 self.ctx.push_error(Error {
223 kind: ErrorKind::Custom(std::borrow::Cow::Owned(err.to_string())),
224 span: item.span(),
225 })
226 })
227 .ok()
228 }
229
230 pub fn required_item(&mut self, name: &'static str) -> Result<&'t Item<'de>, Failed> {
241 self.required_entry(name).map(|(_, value)| value)
242 }
243
244 pub fn optional_item(&mut self, name: &'static str) -> Option<&'t Item<'de>> {
250 self.optional_entry(name).map(|(_, value)| value)
251 }
252
253 pub fn required_entry(
264 &mut self,
265 name: &'static str,
266 ) -> Result<&'t (Key<'de>, Item<'de>), Failed> {
267 match self.optional_entry(name) {
268 Some(entry) => Ok(entry),
269 None => Err(self.report_missing_field(name)),
270 }
271 }
272
273 pub fn optional_entry(&mut self, key: &str) -> Option<&'t (Key<'de>, Item<'de>)> {
279 let entry = self.get_entry(key)?;
280 let index = unsafe {
281 let ptr = entry as *const (Key<'de>, Item<'de>);
282 let base = self.table.entries().as_ptr();
283 ptr.offset_from(base) as usize
284 };
285 if self.used.insert(index) {
286 self.used_count += 1;
287 }
288 Some(entry)
289 }
290
291 #[cold]
292 fn report_missing_field(&mut self, name: &'static str) -> Failed {
293 self.ctx.errors.push(Error {
294 kind: ErrorKind::MissingField(name),
295 span: self.table.span(),
296 });
297 Failed
298 }
299
300 pub fn required<T: Deserialize<'de>>(&mut self, name: &'static str) -> Result<T, Failed> {
310 let Some((_, val)) = self.optional_entry(name) else {
311 return Err(self.report_missing_field(name));
312 };
313
314 T::deserialize(self.ctx, val)
315 }
316
317 pub fn optional<T: Deserialize<'de>>(&mut self, name: &str) -> Option<T> {
323 let Some((_, val)) = self.optional_entry(name) else {
324 return None;
325 };
326
327 #[allow(clippy::manual_ok_err)]
328 match T::deserialize(self.ctx, val) {
329 Ok(value) => Some(value),
330 Err(_) => None,
332 }
333 }
334
335 pub fn remaining_count(&self) -> usize {
337 self.table.len() - self.used_count as usize
338 }
339
340 pub fn into_remaining(self) -> RemainingEntriesIter<'t, 'de> {
342 let entries = self.table.entries();
343 let mut remaining_cells = self.used.0.iter();
344 RemainingEntriesIter {
345 bits: if let Some(value) = remaining_cells.next() {
346 !*value
347 } else {
348 0
349 },
350 entries,
351 remaining_cells,
352 }
353 }
354
355 #[inline(never)]
367 pub fn expect_empty(self) -> Result<(), Failed> {
368 if self.used_count as usize == self.table.len() {
369 return Ok(());
370 }
371
372 let mut keys = Vec::new();
373 for (i, (key, _)) in self.table.entries().iter().enumerate() {
374 if !self.used.get(i) {
375 keys.push((key.name.into(), key.span));
376 }
377 }
378
379 if keys.is_empty() {
380 return Ok(());
381 }
382
383 self.ctx.errors.push(Error::from((
384 ErrorKind::UnexpectedKeys { keys },
385 self.table.span(),
386 )));
387 Err(Failed)
388 }
389}
390
391pub struct Context<'de> {
400 pub arena: &'de Arena,
401 pub(crate) index: HashMap<KeyRef<'de>, usize>,
402 pub errors: Vec<Error>,
403}
404
405impl<'de> Context<'de> {
406 #[cold]
408 pub fn error_expected_but_found(&mut self, message: &'static str, found: &Item<'_>) -> Failed {
409 self.errors.push(Error {
410 kind: ErrorKind::Wanted {
411 expected: message,
412 found: found.type_str(),
413 },
414 span: found.span(),
415 });
416 Failed
417 }
418
419 #[cold]
421 pub fn error_message_at(&mut self, message: &'static str, at: Span) -> Failed {
422 self.errors.push(Error {
423 kind: ErrorKind::Custom(std::borrow::Cow::Borrowed(message)),
424 span: at,
425 });
426 Failed
427 }
428 #[cold]
430 pub fn push_error(&mut self, error: Error) -> Failed {
431 self.errors.push(error);
432 Failed
433 }
434
435 #[cold]
437 pub fn error_out_of_range(&mut self, name: &'static str, span: Span) -> Failed {
438 self.errors.push(Error {
439 kind: ErrorKind::OutOfRange(name),
440 span,
441 });
442 Failed
443 }
444}
445
446#[derive(Debug)]
454pub struct Failed;
455
456pub trait Deserialize<'de>: Sized {
484 fn deserialize(ctx: &mut Context<'de>, item: &Item<'de>) -> Result<Self, Failed>;
489}
490
491impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for [T; N] {
492 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
493 let boxed_slice = Box::<[T]>::deserialize(ctx, value)?;
494 match <Box<[T; N]>>::try_from(boxed_slice) {
495 Ok(array) => Ok(*array),
496 Err(res) => Err(ctx.push_error(Error {
497 kind: ErrorKind::Custom(std::borrow::Cow::Owned(format!(
498 "Expect Array Size: found {} but expected {}",
499 res.len(),
500 N
501 ))),
502 span: value.span(),
503 })),
504 }
505 }
506}
507
508impl<'de> Deserialize<'de> for String {
509 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
510 match value.as_str() {
511 Some(s) => Ok(s.to_string()),
512 None => Err(ctx.error_expected_but_found("a string", value)),
513 }
514 }
515}
516
517impl<'de, T: Deserialize<'de>> Deserialize<'de> for Box<T> {
518 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
519 match T::deserialize(ctx, value) {
520 Ok(v) => Ok(Box::new(v)),
521 Err(e) => Err(e),
522 }
523 }
524}
525impl<'de, T: Deserialize<'de>> Deserialize<'de> for Box<[T]> {
526 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
527 match Vec::<T>::deserialize(ctx, value) {
528 Ok(vec) => Ok(vec.into_boxed_slice()),
529 Err(e) => Err(e),
530 }
531 }
532}
533impl<'de> Deserialize<'de> for Box<str> {
534 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
535 match value.value() {
536 value::Value::String(&s) => Ok(s.into()),
537 _ => Err(ctx.error_expected_but_found("a string", value)),
538 }
539 }
540}
541impl<'de> Deserialize<'de> for &'de str {
542 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
543 match value.value() {
544 value::Value::String(s) => Ok(*s),
545 _ => Err(ctx.error_expected_but_found("a string", value)),
546 }
547 }
548}
549
550impl<'de> Deserialize<'de> for std::borrow::Cow<'de, str> {
551 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
552 match value.value() {
553 value::Value::String(s) => Ok(std::borrow::Cow::Borrowed(*s)),
554 _ => Err(ctx.error_expected_but_found("a string", value)),
555 }
556 }
557}
558
559impl<'de> Deserialize<'de> for bool {
560 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
561 match value.as_bool() {
562 Some(b) => Ok(b),
563 None => Err(ctx.error_expected_but_found("a bool", value)),
564 }
565 }
566}
567
568fn deser_integer_ctx(
569 ctx: &mut Context<'_>,
570 value: &Item<'_>,
571 min: i64,
572 max: i64,
573 name: &'static str,
574) -> Result<i64, Failed> {
575 let span = value.span();
576 match value.as_i64() {
577 Some(i) if i >= min && i <= max => Ok(i),
578 Some(_) => Err(ctx.error_out_of_range(name, span)),
579 None => Err(ctx.error_expected_but_found("an integer", value)),
580 }
581}
582
583macro_rules! integer_new {
584 ($($num:ty),+) => {$(
585 impl<'de> Deserialize<'de> for $num {
586 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
587 match deser_integer_ctx(ctx, value, <$num>::MIN as i64, <$num>::MAX as i64, stringify!($num)) {
588 Ok(i) => Ok(i as $num),
589 Err(e) => Err(e),
590 }
591 }
592 }
593 )+};
594}
595
596integer_new!(i8, i16, i32, isize, u8, u16, u32);
597
598impl<'de> Deserialize<'de> for i64 {
599 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
600 deser_integer_ctx(ctx, value, i64::MIN, i64::MAX, "i64")
601 }
602}
603
604impl<'de> Deserialize<'de> for u64 {
605 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
606 match deser_integer_ctx(ctx, value, 0, i64::MAX, "u64") {
607 Ok(i) => Ok(i as u64),
608 Err(e) => Err(e),
609 }
610 }
611}
612
613impl<'de> Deserialize<'de> for usize {
614 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
615 const MAX: i64 = if usize::BITS < 64 {
616 usize::MAX as i64
617 } else {
618 i64::MAX
619 };
620 match deser_integer_ctx(ctx, value, 0, MAX, "usize") {
621 Ok(i) => Ok(i as usize),
622 Err(e) => Err(e),
623 }
624 }
625}
626
627impl<'de> Deserialize<'de> for f32 {
628 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
629 match value.as_f64() {
630 Some(f) => Ok(f as f32),
631 None => Err(ctx.error_expected_but_found("a float", value)),
632 }
633 }
634}
635
636impl<'de> Deserialize<'de> for f64 {
637 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
638 match value.as_f64() {
639 Some(f) => Ok(f),
640 None => Err(ctx.error_expected_but_found("a float", value)),
641 }
642 }
643}
644
645impl<'de, T> Deserialize<'de> for Vec<T>
646where
647 T: Deserialize<'de>,
648{
649 fn deserialize(ctx: &mut Context<'de>, value: &Item<'de>) -> Result<Self, Failed> {
650 let arr = value.expect_array(ctx)?;
651 let mut result = Vec::with_capacity(arr.len());
652 let mut had_error = false;
653 for item in arr {
654 match T::deserialize(ctx, item) {
655 Ok(v) => result.push(v),
656 Err(_) => had_error = true,
657 }
658 }
659 if had_error { Err(Failed) } else { Ok(result) }
660 }
661}
662
663impl<'de> Item<'de> {
664 pub fn expect_custom_string(
670 &self,
671 ctx: &mut Context<'de>,
672 expected: &'static str,
673 ) -> Result<&'de str, Failed> {
674 match self.value() {
675 value::Value::String(s) => Ok(*s),
676 _ => Err(ctx.error_expected_but_found(expected, self)),
677 }
678 }
679 pub fn expect_string(&self, ctx: &mut Context<'de>) -> Result<&'de str, Failed> {
681 match self.value() {
682 value::Value::String(s) => Ok(*s),
683 _ => Err(ctx.error_expected_but_found("a string", self)),
684 }
685 }
686
687 pub fn expect_array(&self, ctx: &mut Context<'de>) -> Result<&crate::Array<'de>, Failed> {
689 match self.as_array() {
690 Some(arr) => Ok(arr),
691 None => Err(ctx.error_expected_but_found("an array", self)),
692 }
693 }
694
695 pub fn expect_table(&self, ctx: &mut Context<'de>) -> Result<&crate::Table<'de>, Failed> {
697 match self.as_table() {
698 Some(table) => Ok(table),
699 None => Err(ctx.error_expected_but_found("a table", self)),
700 }
701 }
702
703 pub fn table_helper<'ctx, 'item>(
707 &'item self,
708 ctx: &'ctx mut Context<'de>,
709 ) -> Result<TableHelper<'ctx, 'item, 'de>, Failed> {
710 let Some(table) = self.as_table() else {
711 return Err(ctx.error_expected_but_found("a table", self));
712 };
713 Ok(TableHelper::new(ctx, table))
714 }
715}