1#![allow(clippy::type_complexity)]
2
3use core::cell::{Cell, UnsafeCell};
4use core::fmt;
5use core::mem::take;
6use core::ops::Range;
7use core::slice;
8
9use crate::alloc::{Allocator, String, Vec};
10
11use super::{Access, Shared};
12
13mod sealed {
14 use crate::alloc::Allocator;
15
16 pub trait Sealed {}
17 impl<A> Sealed for super::WithTraceImpl<A> where A: Allocator {}
18 impl Sealed for super::NoTraceImpl {}
19 impl Sealed for super::Trace {}
20 impl Sealed for super::NoTrace {}
21}
22
23pub trait TraceMode: self::sealed::Sealed {
25 #[doc(hidden)]
26 type Impl<A>: TraceImpl<A>
27 where
28 A: Allocator;
29
30 #[doc(hidden)]
31 fn new_in<A>(alloc: A) -> Self::Impl<A>
32 where
33 A: Allocator;
34}
35
36pub trait TraceImpl<A>: self::sealed::Sealed {
40 #[doc(hidden)]
41 type Mark;
42
43 #[doc(hidden)]
44 fn clear(&self);
45
46 #[doc(hidden)]
47 fn advance(&self, n: usize);
48
49 #[doc(hidden)]
50 fn mark(&self) -> Self::Mark;
51
52 #[doc(hidden)]
53 fn restore(&self, mark: &Self::Mark);
54
55 #[doc(hidden)]
56 fn custom<T>(&self, alloc: A, message: &T)
57 where
58 T: 'static + Send + Sync + fmt::Display + fmt::Debug;
59
60 #[doc(hidden)]
61 fn message<T>(&self, alloc: A, message: &T)
62 where
63 T: fmt::Display;
64
65 #[doc(hidden)]
66 fn message_at<T>(&self, alloc: A, mark: &Self::Mark, message: &T)
67 where
68 T: fmt::Display;
69
70 #[doc(hidden)]
71 fn custom_at<T>(&self, alloc: A, mark: &Self::Mark, message: &T)
72 where
73 T: 'static + Send + Sync + fmt::Display + fmt::Debug;
74
75 #[doc(hidden)]
76 fn enter_named_field<T>(&self, name: &'static str, field: &T)
77 where
78 T: fmt::Display;
79
80 #[doc(hidden)]
81 fn enter_unnamed_field<T>(&self, index: u32, name: &T)
82 where
83 T: fmt::Display;
84
85 #[doc(hidden)]
86 fn leave_field(&self);
87
88 #[doc(hidden)]
89 fn enter_struct(&self, name: &'static str);
90
91 #[doc(hidden)]
92 fn leave_struct(&self);
93
94 #[doc(hidden)]
95 fn enter_enum(&self, name: &'static str);
96
97 #[doc(hidden)]
98 fn leave_enum(&self);
99
100 #[doc(hidden)]
101 fn enter_variant<T>(&self, name: &'static str, _: &T)
102 where
103 T: fmt::Display;
104
105 #[doc(hidden)]
106 fn leave_variant(&self);
107
108 #[doc(hidden)]
109 fn enter_sequence_index(&self, index: usize);
110
111 #[doc(hidden)]
112 fn leave_sequence_index(&self);
113
114 #[doc(hidden)]
115 fn enter_map_key<T>(&self, alloc: A, field: &T)
116 where
117 T: fmt::Display;
118
119 #[doc(hidden)]
120 fn leave_map_key(&self);
121}
122
123#[non_exhaustive]
129pub struct Trace;
130
131impl TraceMode for Trace {
132 type Impl<A>
133 = WithTraceImpl<A>
134 where
135 A: Allocator;
136
137 #[inline]
138 fn new_in<A>(alloc: A) -> Self::Impl<A>
139 where
140 A: Allocator,
141 {
142 WithTraceImpl::new_in(alloc)
143 }
144}
145
146pub struct WithTraceImpl<A>
149where
150 A: Allocator,
151{
152 mark: Cell<usize>,
153 errors: UnsafeCell<Vec<(Range<usize>, String<A>), A>>,
154 path: UnsafeCell<Vec<Step<A>, A>>,
155 cap: Cell<usize>,
157 include_type: bool,
158 access: Access,
159}
160
161impl<A> WithTraceImpl<A>
162where
163 A: Allocator,
164{
165 #[inline]
167 pub(super) fn new_in(alloc: A) -> Self {
168 let errors = Vec::new_in(alloc);
169 let path = Vec::new_in(alloc);
170
171 Self {
172 mark: Cell::new(0),
173 errors: UnsafeCell::new(errors),
174 path: UnsafeCell::new(path),
175 cap: Cell::new(0),
176 include_type: false,
177 access: Access::new(),
178 }
179 }
180
181 #[inline]
182 pub(super) fn include_type(&mut self) {
183 self.include_type = true;
184 }
185
186 #[inline]
188 pub fn report(&self) -> Report<'_, A> {
189 Report {
190 errors: self.errors(),
191 }
192 }
193
194 #[inline]
195 pub(super) fn errors(&self) -> Errors<'_, A> {
196 let access = self.access.shared();
197
198 Errors {
199 path: unsafe { (*self.path.get()).as_slice() },
200 errors: unsafe { (*self.errors.get()).as_slice().iter() },
201 cap: self.cap.get(),
202 _access: access,
203 }
204 }
205
206 #[inline]
208 fn push_path(&self, step: Step<A>) {
209 let _access = self.access.exclusive();
210
211 let path = unsafe { &mut (*self.path.get()) };
213
214 if path.push(step).is_err() {
215 self.cap.set(&self.cap.get() + 1);
216 }
217 }
218
219 #[inline]
221 fn pop_path(&self) {
222 let cap = self.cap.get();
223
224 if cap > 0 {
225 self.cap.set(cap - 1);
226 return;
227 }
228
229 let _access = self.access.exclusive();
230
231 unsafe {
233 (*self.path.get()).pop();
234 }
235 }
236
237 #[inline]
238 fn format_string<T>(&self, alloc: A, value: T) -> Option<String<A>>
239 where
240 T: fmt::Display,
241 {
242 use core::fmt::Write;
243
244 let mut string = String::new_in(alloc);
245 write!(string, "{value}").ok()?;
246 Some(string)
247 }
248
249 #[inline]
251 fn push_error(&self, range: Range<usize>, error: String<A>) {
252 let _access = self.access.exclusive();
253
254 unsafe {
256 _ = (*self.errors.get()).push((range, error));
257 }
258 }
259}
260
261impl<A> TraceImpl<A> for WithTraceImpl<A>
262where
263 A: Allocator,
264{
265 type Mark = usize;
266
267 #[inline]
268 fn clear(&self) {
269 self.mark.set(0);
270 let _access = self.access.exclusive();
271
272 unsafe {
274 (*self.errors.get()).clear();
275 (*self.path.get()).clear();
276 }
277 }
278
279 #[inline]
280 fn advance(&self, n: usize) {
281 self.mark.set(self.mark.get().wrapping_add(n));
282 }
283
284 #[inline]
285 fn mark(&self) -> Self::Mark {
286 self.mark.get()
287 }
288
289 #[inline]
290 fn restore(&self, mark: &Self::Mark) {
291 self.mark.set(*mark);
292 }
293
294 #[inline]
295 fn custom<T>(&self, alloc: A, message: &T)
296 where
297 T: 'static + Send + Sync + fmt::Display + fmt::Debug,
298 {
299 if let Some(string) = self.format_string(alloc, message) {
300 self.push_error(self.mark.get()..self.mark.get(), string);
301 }
302 }
303
304 #[inline]
305 fn message<T>(&self, alloc: A, message: &T)
306 where
307 T: fmt::Display,
308 {
309 if let Some(string) = self.format_string(alloc, message) {
310 self.push_error(self.mark.get()..self.mark.get(), string);
311 }
312 }
313
314 #[inline]
315 fn message_at<T>(&self, alloc: A, mark: &Self::Mark, message: &T)
316 where
317 T: fmt::Display,
318 {
319 if let Some(string) = self.format_string(alloc, message) {
320 self.push_error(*mark..self.mark.get(), string);
321 }
322 }
323
324 #[inline]
325 fn custom_at<T>(&self, alloc: A, mark: &Self::Mark, message: &T)
326 where
327 T: 'static + Send + Sync + fmt::Display + fmt::Debug,
328 {
329 if let Some(string) = self.format_string(alloc, message) {
330 self.push_error(*mark..self.mark.get(), string);
331 }
332 }
333
334 #[inline]
335 fn enter_named_field<T>(&self, name: &'static str, _: &T)
336 where
337 T: fmt::Display,
338 {
339 self.push_path(Step::Named(name));
340 }
341
342 #[inline]
343 fn enter_unnamed_field<T>(&self, index: u32, _: &T)
344 where
345 T: fmt::Display,
346 {
347 self.push_path(Step::Unnamed(index));
348 }
349
350 #[inline]
351 fn leave_field(&self) {
352 self.pop_path();
353 }
354
355 #[inline]
356 fn enter_struct(&self, name: &'static str) {
357 if self.include_type {
358 self.push_path(Step::Struct(name));
359 }
360 }
361
362 #[inline]
363 fn leave_struct(&self) {
364 if self.include_type {
365 self.pop_path();
366 }
367 }
368
369 #[inline]
370 fn enter_enum(&self, name: &'static str) {
371 if self.include_type {
372 self.push_path(Step::Enum(name));
373 }
374 }
375
376 #[inline]
377 fn leave_enum(&self) {
378 if self.include_type {
379 self.pop_path();
380 }
381 }
382
383 #[inline]
384 fn enter_variant<T>(&self, name: &'static str, _: &T) {
385 self.push_path(Step::Variant(name));
386 }
387
388 #[inline]
389 fn leave_variant(&self) {
390 self.pop_path();
391 }
392
393 #[inline]
394 fn enter_sequence_index(&self, index: usize) {
395 self.push_path(Step::Index(index));
396 }
397
398 #[inline]
399 fn leave_sequence_index(&self) {
400 self.pop_path();
401 }
402
403 #[inline]
404 fn enter_map_key<T>(&self, alloc: A, field: &T)
405 where
406 T: fmt::Display,
407 {
408 if let Some(string) = self.format_string(alloc, field) {
409 self.push_path(Step::Key(string));
410 }
411 }
412
413 #[inline]
414 fn leave_map_key(&self) {
415 self.pop_path();
416 }
417}
418
419#[non_exhaustive]
420pub struct NoTraceImpl;
421
422#[non_exhaustive]
429pub struct NoTrace;
430
431impl TraceMode for NoTrace {
432 type Impl<A>
433 = NoTraceImpl
434 where
435 A: Allocator;
436
437 #[inline]
438 fn new_in<A>(_: A) -> Self::Impl<A>
439 where
440 A: Allocator,
441 {
442 NoTraceImpl
443 }
444}
445
446impl<A> TraceImpl<A> for NoTraceImpl
447where
448 A: Allocator,
449{
450 type Mark = ();
451
452 #[inline]
453 fn clear(&self) {}
454
455 #[inline]
456 fn mark(&self) -> Self::Mark {}
457
458 #[inline]
459 fn restore(&self, mark: &Self::Mark) -> Self::Mark {
460 _ = mark;
461 }
462
463 #[inline]
464 fn advance(&self, n: usize) {
465 _ = n;
466 }
467
468 #[inline]
469 fn custom<T>(&self, alloc: A, message: &T)
470 where
471 T: 'static + Send + Sync + fmt::Display + fmt::Debug,
472 {
473 _ = alloc;
474 _ = message;
475 }
476
477 #[inline]
478 fn message<T>(&self, alloc: A, message: &T)
479 where
480 T: fmt::Display,
481 {
482 _ = alloc;
483 _ = message;
484 }
485
486 #[inline]
487 fn message_at<T>(&self, alloc: A, mark: &Self::Mark, message: &T)
488 where
489 T: fmt::Display,
490 {
491 _ = alloc;
492 _ = mark;
493 _ = message;
494 }
495
496 #[inline]
497 fn custom_at<T>(&self, alloc: A, mark: &Self::Mark, message: &T)
498 where
499 T: 'static + Send + Sync + fmt::Display + fmt::Debug,
500 {
501 _ = alloc;
502 _ = mark;
503 _ = message;
504 }
505
506 #[inline]
507 fn enter_named_field<T>(&self, name: &'static str, field: &T)
508 where
509 T: fmt::Display,
510 {
511 _ = name;
512 _ = field;
513 }
514
515 #[inline]
516 fn enter_unnamed_field<T>(&self, index: u32, field: &T)
517 where
518 T: fmt::Display,
519 {
520 _ = index;
521 _ = field;
522 }
523
524 #[inline]
525 fn leave_field(&self) {}
526
527 #[inline]
528 fn enter_struct(&self, name: &'static str) {
529 _ = name;
530 }
531
532 #[inline]
533 fn leave_struct(&self) {}
534
535 #[inline]
536 fn enter_enum(&self, name: &'static str) {
537 _ = name;
538 }
539
540 #[inline]
541 fn leave_enum(&self) {}
542
543 #[inline]
544 fn enter_variant<T>(&self, name: &'static str, variant: &T)
545 where
546 T: fmt::Display,
547 {
548 _ = name;
549 _ = variant;
550 }
551
552 #[inline]
553 fn leave_variant(&self) {}
554
555 #[inline]
556 fn enter_sequence_index(&self, index: usize) {
557 _ = index;
558 }
559
560 #[inline]
561 fn leave_sequence_index(&self) {}
562
563 #[inline]
564 fn enter_map_key<T>(&self, alloc: A, field: &T)
565 where
566 T: fmt::Display,
567 {
568 _ = alloc;
569 _ = field;
570 }
571
572 #[inline]
573 fn leave_map_key(&self) {}
574}
575
576pub struct Report<'a, A>
582where
583 A: Allocator,
584{
585 errors: Errors<'a, A>,
586}
587
588impl<A> fmt::Display for Report<'_, A>
589where
590 A: Allocator,
591{
592 #[inline]
593 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
594 for error in self.errors.clone() {
595 writeln!(f, "{error}")?;
596 }
597
598 Ok(())
599 }
600}
601
602pub struct Errors<'a, A>
608where
609 A: Allocator,
610{
611 path: &'a [Step<A>],
612 cap: usize,
613 errors: slice::Iter<'a, (Range<usize>, String<A>)>,
614 _access: Shared<'a>,
615}
616
617impl<'a, A> Iterator for Errors<'a, A>
618where
619 A: Allocator,
620{
621 type Item = Error<'a, A>;
622
623 #[inline]
624 fn next(&mut self) -> Option<Self::Item> {
625 let (range, error) = self.errors.next()?;
626 Some(Error::new(self.path, self.cap, range.clone(), error))
627 }
628}
629
630impl<A> Clone for Errors<'_, A>
631where
632 A: Allocator,
633{
634 #[inline]
635 fn clone(&self) -> Self {
636 Self {
637 path: self.path,
638 cap: self.cap,
639 errors: self.errors.clone(),
640 _access: self._access.clone(),
641 }
642 }
643}
644
645pub struct Error<'a, A>
647where
648 A: Allocator,
649{
650 path: &'a [Step<A>],
651 cap: usize,
652 range: Range<usize>,
653 error: &'a str,
654}
655
656impl<'a, A> Error<'a, A>
657where
658 A: Allocator,
659{
660 #[inline]
661 fn new(path: &'a [Step<A>], cap: usize, range: Range<usize>, error: &'a str) -> Self {
662 Self {
663 path,
664 cap,
665 range,
666 error,
667 }
668 }
669}
670
671impl<A> fmt::Display for Error<'_, A>
672where
673 A: Allocator,
674{
675 #[inline]
676 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
677 let path = FormatPath::new(self.path, self.cap);
678
679 if self.range.start != 0 || self.range.end != 0 {
680 if self.range.start == self.range.end {
681 write!(f, "{path}: {} (at byte {})", self.error, self.range.start)?;
682 } else {
683 write!(
684 f,
685 "{path}: {} (at bytes {}-{})",
686 self.error, self.range.start, self.range.end
687 )?;
688 }
689 } else {
690 write!(f, "{path}: {}", self.error)?;
691 }
692
693 Ok(())
694 }
695}
696
697#[derive(Debug)]
699enum Step<A>
700where
701 A: Allocator,
702{
703 Struct(&'static str),
704 Enum(&'static str),
705 Variant(&'static str),
706 Named(&'static str),
707 Unnamed(u32),
708 Index(usize),
709 Key(String<A>),
710}
711
712struct FormatPath<'a, A>
713where
714 A: Allocator,
715{
716 path: &'a [Step<A>],
717 cap: usize,
718}
719
720impl<'a, A> FormatPath<'a, A>
721where
722 A: Allocator,
723{
724 #[inline]
725 fn new(path: &'a [Step<A>], cap: usize) -> Self {
726 Self { path, cap }
727 }
728}
729
730impl<A> fmt::Display for FormatPath<'_, A>
731where
732 A: Allocator,
733{
734 #[inline]
735 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
736 let mut has_type = false;
737 let mut has_field = false;
738 let mut level = 0;
739
740 for step in self.path {
741 match step {
742 Step::Struct(name) => {
743 if take(&mut has_field) {
744 write!(f, " = ")?;
745 }
746
747 write!(f, "{name}")?;
748 has_type = true;
749 }
750 Step::Enum(name) => {
751 if take(&mut has_field) {
752 write!(f, " = ")?;
753 }
754
755 write!(f, "{name}::")?;
756 }
757 Step::Variant(name) => {
758 if take(&mut has_field) {
759 write!(f, " = ")?;
760 }
761
762 write!(f, "{name}")?;
763 has_type = true;
764 }
765 Step::Named(name) => {
766 if take(&mut has_type) {
767 write!(f, " {{ ")?;
768 level += 1;
769 }
770
771 write!(f, ".{name}")?;
772 has_field = true;
773 }
774 Step::Unnamed(index) => {
775 if take(&mut has_type) {
776 write!(f, " {{ ")?;
777 level += 1;
778 }
779
780 write!(f, ".{index}")?;
781 has_field = true;
782 }
783 Step::Index(index) => {
784 if take(&mut has_type) {
785 write!(f, " {{ ")?;
786 level += 1;
787 }
788
789 write!(f, "[{index}]")?;
790 has_field = true;
791 }
792 Step::Key(key) => {
793 if take(&mut has_type) {
794 write!(f, " {{ ")?;
795 level += 1;
796 }
797
798 write!(f, "[{}]", key)?;
799 has_field = true;
800 }
801 }
802 }
803
804 for _ in 0..level {
805 write!(f, " }}")?;
806 }
807
808 match self.cap {
809 0 => {}
810 1 => write!(f, " .. *one capped step*")?,
811 n => write!(f, " .. *{n} capped steps*")?,
812 }
813
814 Ok(())
815 }
816}