1#![allow(clippy::type_complexity)]
2
3use core::cell::{Cell, UnsafeCell};
4use core::fmt::{self, Write};
5use core::marker::PhantomData;
6use core::mem::take;
7use core::ops::Range;
8use core::slice;
9
10#[cfg(feature = "alloc")]
11use crate::alloc::System;
12use crate::alloc::{self, Allocator, String, Vec};
13use crate::Context;
14
15use super::{Access, ErrorMarker, Shared};
16
17pub struct DefaultContext<'a, A, M>
27where
28 A: 'a + ?Sized + Allocator,
29{
30 alloc: &'a A,
31 mark: Cell<usize>,
32 errors: UnsafeCell<Vec<'a, (Range<usize>, String<'a, A>), A>>,
33 path: UnsafeCell<Vec<'a, Step<'a, A>, A>>,
34 cap: Cell<usize>,
36 include_type: bool,
37 access: Access,
38 _marker: PhantomData<M>,
39}
40
41impl<'a, A, M> DefaultContext<'a, A, M> where A: ?Sized + Allocator {}
42
43#[cfg(feature = "alloc")]
44#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
45impl<M> DefaultContext<'static, System, M> {
46 #[inline]
48 pub(super) fn new() -> Self {
49 Self::with_alloc(&crate::alloc::SYSTEM)
50 }
51}
52
53#[cfg(feature = "alloc")]
54impl<M> Default for DefaultContext<'static, System, M> {
55 #[inline]
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl<'a, A, M> DefaultContext<'a, A, M>
62where
63 A: 'a + ?Sized + Allocator,
64{
65 pub(super) fn with_alloc(alloc: &'a A) -> Self {
68 let errors = Vec::new_in(alloc);
69 let path = Vec::new_in(alloc);
70
71 Self {
72 alloc,
73 mark: Cell::new(0),
74 errors: UnsafeCell::new(errors),
75 path: UnsafeCell::new(path),
76 cap: Cell::new(0),
77 include_type: false,
78 access: Access::new(),
79 _marker: PhantomData,
80 }
81 }
82
83 pub fn include_type(&mut self) -> &mut Self {
86 self.include_type = true;
87 self
88 }
89
90 pub fn report(&self) -> Report<'_, 'a, A> {
92 Report {
93 errors: self.errors(),
94 }
95 }
96
97 pub fn errors(&self) -> Errors<'_, 'a, A> {
99 let access = self.access.shared();
100
101 Errors {
102 path: unsafe { (*self.path.get()).as_slice() },
103 errors: unsafe { (*self.errors.get()).as_slice().iter() },
104 cap: self.cap.get(),
105 _access: access,
106 }
107 }
108
109 fn push_error(&self, range: Range<usize>, error: String<'a, A>) {
111 let _access = self.access.exclusive();
112
113 unsafe {
115 _ = (*self.errors.get()).push((range, error));
116 }
117 }
118
119 fn push_path(&self, step: Step<'a, A>) {
121 let _access = self.access.exclusive();
122
123 let path = unsafe { &mut (*self.path.get()) };
125
126 if !path.push(step) {
127 self.cap.set(self.cap.get() + 1);
128 }
129 }
130
131 fn pop_path(&self) {
133 let cap = self.cap.get();
134
135 if cap > 0 {
136 self.cap.set(cap - 1);
137 return;
138 }
139
140 let _access = self.access.exclusive();
141
142 unsafe {
144 (*self.path.get()).pop();
145 }
146 }
147
148 fn format_string<T>(&self, value: T) -> Option<String<'a, A>>
149 where
150 T: fmt::Display,
151 {
152 let mut string = String::new_in(self.alloc);
153 write!(string, "{value}").ok()?;
154 Some(string)
155 }
156}
157
158impl<'a, A, M> Context for DefaultContext<'a, A, M>
159where
160 A: 'a + ?Sized + Allocator,
161 M: 'static,
162{
163 type Mode = M;
164 type Error = ErrorMarker;
165 type Mark = usize;
166 type Allocator = A;
167 type String<'this> = String<'this, A> where Self: 'this;
168
169 #[inline]
170 fn clear(&self) {
171 self.mark.set(0);
172 let _access = self.access.exclusive();
173
174 unsafe {
176 (*self.errors.get()).clear();
177 (*self.path.get()).clear();
178 }
179 }
180
181 #[inline]
182 fn alloc(&self) -> &Self::Allocator {
183 self.alloc
184 }
185
186 #[inline]
187 fn collect_string<T>(&self, value: &T) -> Result<Self::String<'_>, Self::Error>
188 where
189 T: ?Sized + fmt::Display,
190 {
191 alloc::collect_string(self, value)
192 }
193
194 #[inline]
195 fn custom<T>(&self, message: T) -> Self::Error
196 where
197 T: 'static + Send + Sync + fmt::Display + fmt::Debug,
198 {
199 if let Some(string) = self.format_string(message) {
200 self.push_error(self.mark.get()..self.mark.get(), string);
201 }
202
203 ErrorMarker
204 }
205
206 #[inline]
207 fn message<T>(&self, message: T) -> Self::Error
208 where
209 T: fmt::Display,
210 {
211 if let Some(string) = self.format_string(message) {
212 self.push_error(self.mark.get()..self.mark.get(), string);
213 }
214
215 ErrorMarker
216 }
217
218 #[inline]
219 fn marked_message<T>(&self, mark: Self::Mark, message: T) -> Self::Error
220 where
221 T: fmt::Display,
222 {
223 if let Some(string) = self.format_string(message) {
224 self.push_error(mark..self.mark.get(), string);
225 }
226
227 ErrorMarker
228 }
229
230 #[inline]
231 fn marked_custom<T>(&self, mark: Self::Mark, message: T) -> Self::Error
232 where
233 T: 'static + Send + Sync + fmt::Display + fmt::Debug,
234 {
235 if let Some(string) = self.format_string(message) {
236 self.push_error(mark..self.mark.get(), string);
237 }
238
239 ErrorMarker
240 }
241
242 #[inline]
243 fn mark(&self) -> Self::Mark {
244 self.mark.get()
245 }
246
247 #[inline]
248 fn advance(&self, n: usize) {
249 self.mark.set(self.mark.get().wrapping_add(n));
250 }
251
252 #[inline]
253 fn enter_named_field<T>(&self, name: &'static str, _: &T)
254 where
255 T: ?Sized + fmt::Display,
256 {
257 self.push_path(Step::Named(name));
258 }
259
260 #[inline]
261 fn enter_unnamed_field<T>(&self, index: u32, _: &T)
262 where
263 T: ?Sized + fmt::Display,
264 {
265 self.push_path(Step::Unnamed(index));
266 }
267
268 #[inline]
269 fn leave_field(&self) {
270 self.pop_path();
271 }
272
273 #[inline]
274 fn enter_struct(&self, name: &'static str) {
275 if self.include_type {
276 self.push_path(Step::Struct(name));
277 }
278 }
279
280 #[inline]
281 fn leave_struct(&self) {
282 if self.include_type {
283 self.pop_path();
284 }
285 }
286
287 #[inline]
288 fn enter_enum(&self, name: &'static str) {
289 if self.include_type {
290 self.push_path(Step::Enum(name));
291 }
292 }
293
294 #[inline]
295 fn leave_enum(&self) {
296 if self.include_type {
297 self.pop_path();
298 }
299 }
300
301 #[inline]
302 fn enter_variant<T>(&self, name: &'static str, _: T) {
303 self.push_path(Step::Variant(name));
304 }
305
306 #[inline]
307 fn leave_variant(&self) {
308 self.pop_path();
309 }
310
311 #[inline]
312 fn enter_sequence_index(&self, index: usize) {
313 self.push_path(Step::Index(index));
314 }
315
316 #[inline]
317 fn leave_sequence_index(&self) {
318 self.pop_path();
319 }
320
321 #[inline]
322 fn enter_map_key<T>(&self, field: T)
323 where
324 T: fmt::Display,
325 {
326 if let Some(string) = self.format_string(field) {
327 self.push_path(Step::Key(string));
328 }
329 }
330
331 #[inline]
332 fn leave_map_key(&self) {
333 self.pop_path();
334 }
335}
336
337pub struct Report<'b, 'a, A>
339where
340 A: 'a + ?Sized + Allocator,
341{
342 errors: Errors<'b, 'a, A>,
343}
344
345impl<'b, 'a, A> fmt::Display for Report<'b, 'a, A>
346where
347 A: 'a + ?Sized + Allocator,
348{
349 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350 for error in self.errors.clone() {
351 writeln!(f, "{error}")?;
352 }
353
354 Ok(())
355 }
356}
357
358pub struct Errors<'b, 'a, A>
362where
363 A: 'a + ?Sized + Allocator,
364{
365 path: &'b [Step<'a, A>],
366 cap: usize,
367 errors: slice::Iter<'b, (Range<usize>, String<'a, A>)>,
368 _access: Shared<'b>,
369}
370
371impl<'b, 'a, A> Iterator for Errors<'b, 'a, A>
372where
373 A: 'a + ?Sized + Allocator,
374{
375 type Item = Error<'b, 'a, A>;
376
377 #[inline]
378 fn next(&mut self) -> Option<Self::Item> {
379 let (range, error) = self.errors.next()?;
380 Some(Error::new(self.path, self.cap, range.clone(), error))
381 }
382}
383
384impl<'b, 'a, A> Clone for Errors<'b, 'a, A>
385where
386 A: ?Sized + Allocator,
387{
388 fn clone(&self) -> Self {
389 Self {
390 path: self.path,
391 cap: self.cap,
392 errors: self.errors.clone(),
393 _access: self._access.clone(),
394 }
395 }
396}
397
398pub struct Error<'b, 'a, A>
400where
401 A: 'a + ?Sized + Allocator,
402{
403 path: &'b [Step<'a, A>],
404 cap: usize,
405 range: Range<usize>,
406 error: &'b str,
407}
408
409impl<'b, 'a, A> Error<'b, 'a, A>
410where
411 A: 'a + ?Sized + Allocator,
412{
413 fn new(path: &'b [Step<'a, A>], cap: usize, range: Range<usize>, error: &'b str) -> Self {
414 Self {
415 path,
416 cap,
417 range,
418 error,
419 }
420 }
421}
422
423impl<'a, A> fmt::Display for Error<'_, 'a, A>
424where
425 A: 'a + ?Sized + Allocator,
426{
427 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428 let path = FormatPath::new(self.path, self.cap);
429
430 if self.range.start != 0 || self.range.end != 0 {
431 if self.range.start == self.range.end {
432 write!(f, "{path}: {} (at byte {})", self.error, self.range.start)?;
433 } else {
434 write!(
435 f,
436 "{path}: {} (at bytes {}-{})",
437 self.error, self.range.start, self.range.end
438 )?;
439 }
440 } else {
441 write!(f, "{path}: {}", self.error)?;
442 }
443
444 Ok(())
445 }
446}
447
448#[derive(Debug)]
450pub(crate) enum Step<'a, A>
451where
452 A: 'a + ?Sized + Allocator,
453{
454 Struct(&'static str),
455 Enum(&'static str),
456 Variant(&'static str),
457 Named(&'static str),
458 Unnamed(u32),
459 Index(usize),
460 Key(String<'a, A>),
461}
462
463struct FormatPath<'b, 'a, A>
464where
465 A: 'a + ?Sized + Allocator,
466{
467 path: &'b [Step<'a, A>],
468 cap: usize,
469}
470
471impl<'b, 'a, A> FormatPath<'b, 'a, A>
472where
473 A: 'a + ?Sized + Allocator,
474{
475 pub(crate) fn new(path: &'b [Step<'a, A>], cap: usize) -> Self {
476 Self { path, cap }
477 }
478}
479
480impl<'a, A> fmt::Display for FormatPath<'_, 'a, A>
481where
482 A: 'a + ?Sized + Allocator,
483{
484 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
485 let mut has_type = false;
486 let mut has_field = false;
487 let mut level = 0;
488
489 for step in self.path {
490 match step {
491 Step::Struct(name) => {
492 if take(&mut has_field) {
493 write!(f, " = ")?;
494 }
495
496 write!(f, "{name}")?;
497 has_type = true;
498 }
499 Step::Enum(name) => {
500 if take(&mut has_field) {
501 write!(f, " = ")?;
502 }
503
504 write!(f, "{name}::")?;
505 }
506 Step::Variant(name) => {
507 if take(&mut has_field) {
508 write!(f, " = ")?;
509 }
510
511 write!(f, "{name}")?;
512 has_type = true;
513 }
514 Step::Named(name) => {
515 if take(&mut has_type) {
516 write!(f, " {{ ")?;
517 level += 1;
518 }
519
520 write!(f, ".{name}")?;
521 has_field = true;
522 }
523 Step::Unnamed(index) => {
524 if take(&mut has_type) {
525 write!(f, " {{ ")?;
526 level += 1;
527 }
528
529 write!(f, ".{index}")?;
530 has_field = true;
531 }
532 Step::Index(index) => {
533 if take(&mut has_type) {
534 write!(f, " {{ ")?;
535 level += 1;
536 }
537
538 write!(f, "[{index}]")?;
539 has_field = true;
540 }
541 Step::Key(key) => {
542 if take(&mut has_type) {
543 write!(f, " {{ ")?;
544 level += 1;
545 }
546
547 write!(f, "[{}]", key)?;
548 has_field = true;
549 }
550 }
551 }
552
553 for _ in 0..level {
554 write!(f, " }}")?;
555 }
556
557 match self.cap {
558 0 => {}
559 1 => write!(f, " .. *one capped step*")?,
560 n => write!(f, " .. *{n} capped steps*")?,
561 }
562
563 Ok(())
564 }
565}