1use core::fmt;
22use std::error::Error;
23
24use into_owned_trait::IntoOwned;
25
26use crate::{JsonCodeMap, JsonValue, array::JsonArrayExt, code_map::JsonMapped};
27
28impl JsonValue {
29 pub fn locate_fragment(
48 &self,
49 code_map: &JsonCodeMap,
50 path: &JsonFragmentPath,
51 ) -> Option<usize> {
52 self.locate_fragment_at(code_map, path, 0)
53 }
54
55 fn locate_fragment_at(
56 &self,
57 code_map: &JsonCodeMap,
58 path: &JsonFragmentPath,
59 offset: usize,
60 ) -> Option<usize> {
61 match path.split_first() {
62 Some((segment, rest)) => match segment {
63 JsonFragmentPathSegment::ArrayItem(i) => {
64 let array = self.as_array()?;
65 for (j, JsonMapped(item, item_offset)) in
66 array.iter_mapped(code_map, offset).enumerate()
67 {
68 if j == *i {
69 return item.locate_fragment_at(code_map, rest, item_offset);
70 }
71 }
72
73 None
74 }
75 JsonFragmentPathSegment::ObjectEntry(k, occurrence, part) => {
76 let object = self.as_object()?;
77 let mut occ_count = 0usize;
78 for JsonMapped(
79 (JsonMapped(key, key_offset), JsonMapped(value, value_offset)),
80 entry_offset,
81 ) in object.iter_mapped(code_map, offset)
82 {
83 if k.as_str() == key.as_str() {
84 if occ_count == *occurrence {
85 return match *part {
86 JsonObjectEntryPart::All => {
87 if rest.is_empty() {
88 Some(entry_offset)
89 } else {
90 None
91 }
92 }
93 JsonObjectEntryPart::Key => {
94 if rest.is_empty() {
95 Some(key_offset)
96 } else {
97 None
98 }
99 }
100 JsonObjectEntryPart::Value => {
101 value.locate_fragment_at(code_map, rest, value_offset)
102 }
103 };
104 }
105
106 occ_count += 1;
107 }
108 }
109
110 None
111 }
112 },
113 None => Some(offset),
114 }
115 }
116}
117
118impl JsonValue {
119 pub fn find_duplicate_key_recursive(&self) -> Option<(JsonFragmentPathBuf, &str)> {
136 let (mut path, key) = self.find_duplicate_key_recursive_reversed()?;
137 path.reverse();
138 Some((path, key))
139 }
140
141 fn find_duplicate_key_recursive_reversed(&self) -> Option<(JsonFragmentPathBuf, &str)> {
148 match self {
149 Self::Array(items) => {
150 for (i, item) in items.iter().enumerate() {
151 if let Some((mut path, key)) = item.find_duplicate_key_recursive_reversed() {
152 path.push(JsonFragmentPathSegment::ArrayItem(i));
153 return Some((path, key));
154 }
155 }
156
157 None
158 }
159 Self::Object(object) => {
160 if let Some(key) = object.find_duplicate_key() {
163 return Some((Vec::new(), key));
164 }
165
166 for (key, value) in object.iter() {
170 if let Some((mut path, duplicate_key)) =
171 value.find_duplicate_key_recursive_reversed()
172 {
173 path.push(JsonFragmentPathSegment::ObjectEntry(
174 key.to_string(),
175 0,
176 JsonObjectEntryPart::Value,
177 ));
178 return Some((path, duplicate_key));
179 }
180 }
181
182 None
183 }
184 _ => None,
185 }
186 }
187}
188
189pub type JsonBacktraceBuf<T> = Vec<JsonBacktraceFrame<T>>;
205
206pub type JsonBacktrace<T> = [JsonBacktraceFrame<T>];
208
209#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
212pub struct JsonBacktraceFrame<T> {
213 pub file: T,
215
216 pub fragment: JsonFragmentPathBuf,
218}
219
220impl<T> JsonBacktraceFrame<T> {
221 pub fn new(file: T) -> Self {
223 Self {
224 file,
225 fragment: Vec::new(),
226 }
227 }
228}
229
230#[derive(Debug)]
237pub enum JsonBacktraceBuilder<'a, T: IntoOwned, O = <T as IntoOwned>::Owned> {
238 Root,
240
241 File(&'a Self, T),
243
244 Item(&'a Self, JsonFragmentPathItemRef<'a>),
246
247 Path(&'a Self, &'a JsonFragmentPathBuf),
250
251 Backtrace(&'a Self, &'a JsonBacktrace<O>),
253}
254
255impl<T: IntoOwned + Clone> Clone for JsonBacktraceBuilder<'_, T> {
256 fn clone(&self) -> Self {
257 match *self {
258 Self::Root => Self::Root,
259 Self::File(parent, ref file) => Self::File(parent, file.clone()),
260 Self::Item(parent, item) => Self::Item(parent, item),
261 Self::Path(parent, path) => Self::Path(parent, path),
262 Self::Backtrace(parent, b) => Self::Backtrace(parent, b),
263 }
264 }
265}
266
267impl<T: IntoOwned + Copy> Copy for JsonBacktraceBuilder<'_, T> {}
268
269impl<T: IntoOwned> JsonBacktraceBuilder<'_, T> {
270 pub fn new() -> &'static Self {
272 &Self::Root
273 }
274
275 pub fn file<'a>(&'a self, file: T) -> JsonBacktraceBuilder<'a, T> {
277 JsonBacktraceBuilder::File(self, file)
278 }
279
280 pub fn push<'a>(&'a self, item: JsonFragmentPathItemRef<'a>) -> JsonBacktraceBuilder<'a, T> {
282 JsonBacktraceBuilder::Item(self, item)
283 }
284
285 pub fn push_path<'a>(&'a self, path: &'a JsonFragmentPathBuf) -> JsonBacktraceBuilder<'a, T> {
290 JsonBacktraceBuilder::Path(self, path)
291 }
292
293 pub fn push_backtrace<'a>(
300 &'a self,
301 backtrace: &'a JsonBacktrace<T::Owned>,
302 ) -> JsonBacktraceBuilder<'a, T> {
303 JsonBacktraceBuilder::Backtrace(self, backtrace)
304 }
305
306 pub fn array_index(&self, index: usize) -> JsonBacktraceBuilder<'_, T> {
308 self.push(JsonFragmentPathItemRef::ArrayItem(index))
309 }
310
311 pub fn object_entry<'b>(&'b self, key: impl Into<&'b str>) -> JsonBacktraceBuilder<'b, T> {
316 self.push(JsonFragmentPathItemRef::ObjectEntry(
317 key.into(),
318 0,
319 JsonObjectEntryPart::All,
320 ))
321 }
322
323 pub fn object_entry_at<'b>(
327 &'b self,
328 key: impl Into<&'b str>,
329 occurrence: usize,
330 ) -> JsonBacktraceBuilder<'b, T> {
331 self.push(JsonFragmentPathItemRef::ObjectEntry(
332 key.into(),
333 occurrence,
334 JsonObjectEntryPart::All,
335 ))
336 }
337
338 pub fn object_key<'b>(&'b self, key: impl Into<&'b str>) -> JsonBacktraceBuilder<'b, T> {
343 self.push(JsonFragmentPathItemRef::ObjectEntry(
344 key.into(),
345 0,
346 JsonObjectEntryPart::Key,
347 ))
348 }
349
350 pub fn object_key_at<'b>(
354 &'b self,
355 key: impl Into<&'b str>,
356 occurrence: usize,
357 ) -> JsonBacktraceBuilder<'b, T> {
358 self.push(JsonFragmentPathItemRef::ObjectEntry(
359 key.into(),
360 occurrence,
361 JsonObjectEntryPart::Key,
362 ))
363 }
364
365 pub fn object_value<'b>(&'b self, key: impl Into<&'b str>) -> JsonBacktraceBuilder<'b, T> {
370 self.push(JsonFragmentPathItemRef::ObjectEntry(
371 key.into(),
372 0,
373 JsonObjectEntryPart::Value,
374 ))
375 }
376
377 pub fn object_value_at<'b>(
381 &'b self,
382 key: impl Into<&'b str>,
383 occurrence: usize,
384 ) -> JsonBacktraceBuilder<'b, T> {
385 self.push(JsonFragmentPathItemRef::ObjectEntry(
386 key.into(),
387 occurrence,
388 JsonObjectEntryPart::Value,
389 ))
390 }
391
392 pub fn build(self) -> JsonBacktraceBuf<T::Owned>
395 where
396 T: Clone,
397 T::Owned: Clone,
398 {
399 match self {
400 Self::Root => JsonBacktraceBuf::new(),
401 Self::File(parent, file) => {
402 let mut backtrace = parent.clone().build();
403 backtrace.push(JsonBacktraceFrame::new(file.into_owned()));
404 backtrace
405 }
406 Self::Item(parent, item) => {
407 let mut backtrace = parent.clone().build();
408
409 if let Some(last) = backtrace.last_mut() {
410 last.fragment.push(item.into_owned());
411 }
412
413 backtrace
414 }
415 Self::Path(parent, path) => {
416 let mut backtrace = parent.clone().build();
417
418 if let Some(last) = backtrace.last_mut() {
419 last.fragment.extend(path.iter().cloned());
420 }
421
422 backtrace
423 }
424 Self::Backtrace(parent, b) => {
425 let mut backtrace = parent.clone().build();
426 backtrace.extend(b.iter().cloned());
427 backtrace
428 }
429 }
430 }
431}
432
433impl<T: Clone + IntoOwned> From<JsonBacktraceBuilder<'_, T>> for JsonBacktraceBuf<T::Owned>
434where
435 T::Owned: Clone,
436{
437 fn from(value: JsonBacktraceBuilder<'_, T>) -> Self {
438 value.build()
439 }
440}
441
442#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
444pub struct JsonLocated<T, F> {
445 pub value: T,
447
448 pub location: JsonBacktraceBuf<F>,
450}
451
452impl<T, F> JsonLocated<T, F> {
453 pub fn new(value: T, location: JsonBacktraceBuf<F>) -> Self {
455 Self { value, location }
456 }
457
458 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> JsonLocated<U, F> {
460 JsonLocated {
461 value: f(self.value),
462 location: self.location,
463 }
464 }
465
466 pub fn cast<U>(self) -> JsonLocated<U, F>
469 where
470 T: Into<U>,
471 {
472 self.map(Into::into)
473 }
474}
475
476impl<T: fmt::Display, F> fmt::Display for JsonLocated<T, F> {
477 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478 self.value.fmt(f)
479 }
480}
481
482impl<T: 'static + Error, F: fmt::Debug> Error for JsonLocated<T, F> {
483 fn source(&self) -> Option<&(dyn Error + 'static)> {
484 Some(&self.value)
485 }
486}
487
488#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
491pub enum JsonFragmentPathSegment {
492 ArrayItem(usize),
494
495 ObjectEntry(String, usize, JsonObjectEntryPart),
498}
499
500#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
503pub enum JsonObjectEntryPart {
504 All,
506
507 Key,
509
510 Value,
512}
513
514#[derive(Debug, Clone, Copy)]
518pub enum JsonFragmentPathItemRef<'a> {
519 ArrayItem(usize),
521
522 ObjectEntry(&'a str, usize, JsonObjectEntryPart),
524}
525
526impl JsonFragmentPathItemRef<'_> {
527 pub fn into_owned(self) -> JsonFragmentPathSegment {
530 match self {
531 Self::ArrayItem(i) => JsonFragmentPathSegment::ArrayItem(i),
532 Self::ObjectEntry(k, n, part) => {
533 JsonFragmentPathSegment::ObjectEntry(k.to_owned(), n, part)
534 }
535 }
536 }
537}
538
539pub type JsonFragmentPathBuf = Vec<JsonFragmentPathSegment>;
541
542pub type JsonFragmentPath = [JsonFragmentPathSegment];
544
545pub trait JsonAt: Sized {
547 fn json_at<F>(self, location: impl Into<JsonBacktraceBuf<F>>) -> JsonLocated<Self, F>;
549}
550
551impl<T> JsonAt for T {
552 fn json_at<F>(self, location: impl Into<JsonBacktraceBuf<F>>) -> JsonLocated<Self, F> {
553 JsonLocated::new(self, location.into())
554 }
555}
556
557pub trait JsonErrorAt<T, E> {
559 fn json_err_at<F>(
561 self,
562 location: impl Into<JsonBacktraceBuf<F>>,
563 ) -> Result<T, JsonLocated<E, F>>;
564}
565
566impl<T, E> JsonErrorAt<T, E> for Result<T, E> {
567 fn json_err_at<F>(
568 self,
569 location: impl Into<JsonBacktraceBuf<F>>,
570 ) -> Result<T, JsonLocated<E, F>> {
571 self.map_err(|e| e.json_at(location))
572 }
573}
574
575#[cfg(test)]
576mod tests {
577 use crate::{JsonParse, JsonValue};
578
579 use super::*;
580
581 #[test]
582 fn locate_01() {
583 let (value, code_map) = JsonValue::parse_str(r#"{ "a": 0, "b": [1, 2] }"#).unwrap();
594
595 assert_eq!(value.locate_fragment(&code_map, &[]), Some(0));
597
598 assert_eq!(
600 value.locate_fragment(
601 &code_map,
602 &[JsonFragmentPathSegment::ObjectEntry(
603 "a".into(),
604 0,
605 JsonObjectEntryPart::All
606 )]
607 ),
608 Some(1)
609 );
610 assert_eq!(
611 value.locate_fragment(
612 &code_map,
613 &[JsonFragmentPathSegment::ObjectEntry(
614 "b".into(),
615 0,
616 JsonObjectEntryPart::All
617 )]
618 ),
619 Some(4)
620 );
621
622 assert_eq!(
624 value.locate_fragment(
625 &code_map,
626 &[JsonFragmentPathSegment::ObjectEntry(
627 "a".into(),
628 0,
629 JsonObjectEntryPart::Key
630 )]
631 ),
632 Some(2)
633 );
634 assert_eq!(
635 value.locate_fragment(
636 &code_map,
637 &[JsonFragmentPathSegment::ObjectEntry(
638 "b".into(),
639 0,
640 JsonObjectEntryPart::Key
641 )]
642 ),
643 Some(5)
644 );
645
646 assert_eq!(
648 value.locate_fragment(
649 &code_map,
650 &[JsonFragmentPathSegment::ObjectEntry(
651 "a".into(),
652 0,
653 JsonObjectEntryPart::Value
654 )]
655 ),
656 Some(3)
657 );
658 assert_eq!(
659 value.locate_fragment(
660 &code_map,
661 &[JsonFragmentPathSegment::ObjectEntry(
662 "b".into(),
663 0,
664 JsonObjectEntryPart::Value
665 )]
666 ),
667 Some(6)
668 );
669
670 assert_eq!(
672 value.locate_fragment(
673 &code_map,
674 &[
675 JsonFragmentPathSegment::ObjectEntry("b".into(), 0, JsonObjectEntryPart::Value),
676 JsonFragmentPathSegment::ArrayItem(0),
677 ]
678 ),
679 Some(7)
680 );
681 assert_eq!(
682 value.locate_fragment(
683 &code_map,
684 &[
685 JsonFragmentPathSegment::ObjectEntry("b".into(), 0, JsonObjectEntryPart::Value),
686 JsonFragmentPathSegment::ArrayItem(1),
687 ]
688 ),
689 Some(8)
690 );
691
692 assert_eq!(
694 value.locate_fragment(
695 &code_map,
696 &[JsonFragmentPathSegment::ObjectEntry(
697 "z".into(),
698 0,
699 JsonObjectEntryPart::Value
700 )]
701 ),
702 None
703 );
704
705 assert_eq!(
707 value.locate_fragment(
708 &code_map,
709 &[
710 JsonFragmentPathSegment::ObjectEntry("b".into(), 0, JsonObjectEntryPart::Value),
711 JsonFragmentPathSegment::ArrayItem(2),
712 ]
713 ),
714 None
715 );
716
717 assert_eq!(
719 value.locate_fragment(
720 &code_map,
721 &[
722 JsonFragmentPathSegment::ObjectEntry("b".into(), 0, JsonObjectEntryPart::All),
723 JsonFragmentPathSegment::ArrayItem(0),
724 ]
725 ),
726 None
727 );
728 assert_eq!(
729 value.locate_fragment(
730 &code_map,
731 &[
732 JsonFragmentPathSegment::ObjectEntry("b".into(), 0, JsonObjectEntryPart::Key),
733 JsonFragmentPathSegment::ArrayItem(0),
734 ]
735 ),
736 None
737 );
738 }
739
740 #[test]
741 fn locate_duplicate_keys() {
742 let (value, code_map) = JsonValue::parse_str(r#"{ "a": 1, "a": 2 }"#).unwrap();
751
752 assert_eq!(
754 value.locate_fragment(
755 &code_map,
756 &[JsonFragmentPathSegment::ObjectEntry(
757 "a".into(),
758 0,
759 JsonObjectEntryPart::All
760 )]
761 ),
762 Some(1)
763 );
764 assert_eq!(
765 value.locate_fragment(
766 &code_map,
767 &[JsonFragmentPathSegment::ObjectEntry(
768 "a".into(),
769 0,
770 JsonObjectEntryPart::Key
771 )]
772 ),
773 Some(2)
774 );
775 assert_eq!(
776 value.locate_fragment(
777 &code_map,
778 &[JsonFragmentPathSegment::ObjectEntry(
779 "a".into(),
780 0,
781 JsonObjectEntryPart::Value
782 )]
783 ),
784 Some(3)
785 );
786
787 assert_eq!(
789 value.locate_fragment(
790 &code_map,
791 &[JsonFragmentPathSegment::ObjectEntry(
792 "a".into(),
793 1,
794 JsonObjectEntryPart::All
795 )]
796 ),
797 Some(4)
798 );
799 assert_eq!(
800 value.locate_fragment(
801 &code_map,
802 &[JsonFragmentPathSegment::ObjectEntry(
803 "a".into(),
804 1,
805 JsonObjectEntryPart::Key
806 )]
807 ),
808 Some(5)
809 );
810 assert_eq!(
811 value.locate_fragment(
812 &code_map,
813 &[JsonFragmentPathSegment::ObjectEntry(
814 "a".into(),
815 1,
816 JsonObjectEntryPart::Value
817 )]
818 ),
819 Some(6)
820 );
821
822 assert_eq!(
824 value.locate_fragment(
825 &code_map,
826 &[JsonFragmentPathSegment::ObjectEntry(
827 "a".into(),
828 2,
829 JsonObjectEntryPart::Value
830 )]
831 ),
832 None
833 );
834 }
835}