1pub mod array;
5pub mod boolean;
7pub mod iterative;
9pub mod null;
11pub mod number;
13pub mod object;
15pub mod optimized;
16pub mod optimized_v2;
17pub mod optimized_v3;
18pub mod recursive;
20pub mod state;
22pub mod string;
24
25use self::boolean::{parse_false, parse_true};
26use self::null::parse_null;
27use self::number::parse_number_token;
28use self::string::parse_string_token;
29use crate::ast::{Number, Token, Value};
30use crate::error::repair::{EnhancedParseResult, ParsingTier, RepairAction};
31use crate::error::{Error, ErrorContext, ErrorRecoveryEngineV2, Result, Span};
32use crate::lexer::{FastLexer, JsonLexer, Lexer, LexerConfig, LexerMode};
33use crate::optimization::ValueBuilder;
34use crate::repair::JsonRepairer;
35pub use iterative::{parse_iterative, IterativeParser};
36pub use optimized::{
37 parse_optimized, parse_optimized_with_options, parse_with_stats, OptimizedParser,
38};
39pub use optimized_v2::{
40 parse_optimized_v2, parse_optimized_v2_with_options, parse_v2_with_stats, OptimizedParserV2,
41};
42pub use optimized_v3::{
43 parse_optimized_v3, parse_optimized_v3_with_options, parse_v3_with_stats, OptimizedParserV3,
44};
45pub use recursive::{parse_recursive, RecursiveDescentParser};
46use rustc_hash::FxHashMap;
47pub use state::ParserState;
48
49#[cfg(feature = "serde")]
50use serde::{Deserialize, Serialize};
51
52#[derive(Debug, Clone)]
57#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
58#[cfg_attr(feature = "serde", serde(default))]
59pub struct ParserOptions {
60 pub allow_comments: bool,
62 pub allow_trailing_commas: bool,
64 pub allow_unquoted_keys: bool,
66 pub allow_single_quotes: bool,
68 pub implicit_top_level: bool,
71 pub newline_as_comma: bool,
73 pub max_depth: usize,
75 pub enable_repair: bool,
77 pub max_repairs: usize,
79 pub fast_repair: bool,
81 pub report_repairs: bool,
83}
84
85impl Default for ParserOptions {
86 fn default() -> Self {
87 ParserOptions {
88 allow_comments: true,
89 allow_trailing_commas: true,
90 allow_unquoted_keys: true,
91 allow_single_quotes: true,
92 implicit_top_level: true,
93 newline_as_comma: true,
94 max_depth: 128,
95 enable_repair: true,
96 max_repairs: 100,
97 fast_repair: false,
98 report_repairs: true,
99 }
100 }
101}
102
103pub struct Parser<'a> {
108 pub(super) lexer: Box<dyn JsonLexer + 'a>,
109 pub(super) original_input: &'a str,
110 pub(super) options: ParserOptions,
111 pub(super) current_token: Option<(Token, Span)>,
112 pub(super) state: ParserState,
116 #[allow(dead_code)]
118 pub(super) value_builder: ValueBuilder,
119}
120
121impl<'a> Parser<'a> {
122 pub fn new(input: &'a str, options: ParserOptions) -> Self {
124 let needs_forgiving = options.allow_comments
126 || options.allow_trailing_commas
127 || options.allow_unquoted_keys
128 || options.allow_single_quotes
129 || options.implicit_top_level
130 || options.newline_as_comma;
131
132 let lexer: Box<dyn JsonLexer + 'a> = if needs_forgiving {
134 let config = LexerConfig {
136 mode: if options.allow_comments {
137 LexerMode::Forgiving
138 } else {
139 LexerMode::Strict
140 },
141 collect_stats: false,
142 buffer_size: 8192,
143 max_depth: options.max_depth,
144 track_positions: true,
145 };
146 Box::new(FastLexer::new(input, config))
147 } else {
148 Box::new(Lexer::new(input))
150 };
151
152 Parser {
153 lexer,
154 original_input: input,
155 options,
156 current_token: None, state: ParserState::new(),
158 value_builder: ValueBuilder::new(),
159 }
160 }
161
162 pub fn parse(&mut self) -> Result<Value> {
170 self.advance()?;
171 self.skip_comments()?;
172
173 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
175 return Ok(Value::Null);
176 }
177
178 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Newline)
189 && self.options.newline_as_comma
190 {
191 self.skip_comments_and_newlines()?;
192 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
193 return Ok(Value::Null);
194 }
195 }
196
197 if self.is_separator() && self.options.implicit_top_level {
199 let mut array = vec![Value::Null];
200 self.advance()?;
201
202 loop {
203 self.skip_comments_and_newlines()?;
204 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
205 break;
206 }
207
208 if self.is_separator() {
210 array.push(Value::Null);
211 self.advance()?;
212 continue;
213 }
214
215 array.push(self.parse_value()?);
216
217 self.skip_comments_and_newlines()?;
218 if self.is_separator() {
219 self.advance()?;
220 } else if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
221 break;
222 } else {
223 return Err(Error::Expected {
224 expected: ", or newline or end of input".to_string(),
225 found: format!("{:?}", self.current_token.as_ref().map(|(t, _)| t)),
226 position: self.lexer.position(),
227 });
228 }
229 }
230
231 return Ok(Value::Array(array));
232 }
233
234 let is_explicit_structure = matches!(
237 self.current_token.as_ref().map(|(t, _)| t),
238 Some(&Token::LeftBrace) | Some(&Token::LeftBracket)
239 );
240
241 let first_value = if self.options.implicit_top_level && !is_explicit_structure {
242 self.parse_value_or_implicit()?
243 } else {
244 self.parse_value()?
245 };
246
247 self.skip_comments()?;
249
250 match self.current_token.as_ref().map(|(t, _)| t) {
251 Some(&Token::Eof) => Ok(first_value),
252 _ if is_explicit_structure => {
253 if self.options.implicit_top_level
256 && matches!(
257 self.current_token.as_ref().map(|(t, _)| t),
258 Some(&Token::Comma)
259 )
260 {
261 let mut array = vec![first_value];
263 self.advance()?;
264
265 loop {
266 self.skip_comments_and_newlines()?;
267 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
268 break;
269 }
270
271 if self.is_separator() {
273 array.push(Value::Null);
274 self.advance()?;
275 continue;
276 }
277
278 array.push(self.parse_value()?);
279
280 self.skip_comments_and_newlines()?;
281 if self.is_separator() {
282 self.advance()?;
283 } else if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
284 break;
285 } else {
286 return Err(Error::Expected {
287 expected: ", or newline or end of input".to_string(),
288 found: format!("{:?}", self.current_token.as_ref().map(|(t, _)| t)),
289 position: self.lexer.position(),
290 });
291 }
292 }
293
294 Ok(Value::Array(array))
295 } else {
296 Err(Error::Expected {
298 expected: "end of input".to_string(),
299 found: format!("{:?}", self.current_token.as_ref().map(|(t, _)| t)),
300 position: self.lexer.position(),
301 })
302 }
303 }
304 Some(&Token::Comma) | Some(&Token::Newline)
305 if matches!(
306 self.current_token.as_ref().map(|(t, _)| t),
307 Some(&Token::Comma)
308 ) || (self.options.newline_as_comma
309 && matches!(
310 self.current_token.as_ref().map(|(t, _)| t),
311 Some(&Token::Newline)
312 )) =>
313 {
314 if self.options.newline_as_comma
316 && matches!(
317 self.current_token.as_ref().map(|(t, _)| t),
318 Some(&Token::Newline)
319 )
320 {
321 self.advance()?;
322 self.skip_comments_and_newlines()?;
323
324 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
326 return Ok(first_value);
327 } else {
328 let mut array = vec![first_value];
331 array.push(self.parse_value()?);
332
333 loop {
334 self.skip_comments_and_newlines()?;
335 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
336 break;
337 }
338
339 if self.is_separator() {
340 self.advance()?;
341 self.skip_comments_and_newlines()?;
342 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof)
343 {
344 break;
345 }
346 }
347
348 array.push(self.parse_value()?);
349 }
350
351 return Ok(Value::Array(array));
352 }
353 }
354
355 if self.options.implicit_top_level {
357 let mut array = vec![first_value];
358 self.advance()?;
359
360 loop {
361 self.skip_comments_and_newlines()?;
362 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
363 break;
364 }
365
366 if self.is_separator() {
368 array.push(Value::Null);
369 self.advance()?;
370 continue;
371 }
372
373 array.push(self.parse_value()?);
374
375 self.skip_comments_and_newlines()?;
376 if self.is_separator() {
377 self.advance()?;
378 } else if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
379 break;
380 } else {
381 return Err(Error::Expected {
382 expected: ", or newline or end of input".to_string(),
383 found: format!("{:?}", self.current_token.as_ref().map(|(t, _)| t)),
384 position: self.lexer.position(),
385 });
386 }
387 }
388
389 Ok(Value::Array(array))
390 } else {
391 Err(Error::Expected {
392 expected: "end of input".to_string(),
393 found: format!("{:?}", self.current_token.as_ref().map(|(t, _)| t)),
394 position: self.lexer.position(),
395 })
396 }
397 }
398 _ => {
399 if self.options.implicit_top_level && self.is_value_token() {
401 let mut array = vec![first_value];
403
404 loop {
406 if self.is_separator() {
408 array.push(Value::Null);
409 self.advance()?;
410 self.skip_comments_and_newlines()?;
411 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
412 break;
413 }
414 continue;
415 }
416
417 array.push(self.parse_value()?);
418 self.skip_comments()?;
419
420 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
421 break;
422 }
423
424 if self.is_separator() {
426 self.advance()?;
427 self.skip_comments_and_newlines()?;
428 if self.current_token.as_ref().map(|(t, _)| t) == Some(&Token::Eof) {
429 break;
430 }
431 } else if !self.is_value_token() {
432 return Err(Error::Expected {
433 expected: "value, separator, or end of input".to_string(),
434 found: format!("{:?}", self.current_token.as_ref().map(|(t, _)| t)),
435 position: self.lexer.position(),
436 });
437 }
438 }
439
440 Ok(Value::Array(array))
441 } else {
442 Err(Error::Expected {
443 expected: "end of input".to_string(),
444 found: format!("{:?}", self.current_token.as_ref().map(|(t, _)| t)),
445 position: self.lexer.position(),
446 })
447 }
448 }
449 }
450 }
451
452 pub(super) fn advance(&mut self) -> Result<()> {
453 loop {
454 let (token, span) = self.lexer.next_token()?;
455 self.state.span = span; self.current_token = Some((token, span));
457
458 match self.current_token.as_ref().map(|(t, _)| t) {
459 Some(&Token::SingleLineComment) | Some(&Token::MultiLineComment) => {
460 if self.options.allow_comments {
461 continue;
462 } else {
463 return Err(Error::Custom("Comments are not allowed".to_string()));
464 }
465 }
466 _ => break,
467 }
468 }
469 Ok(())
470 }
471
472 pub(super) fn skip_comments(&mut self) -> Result<()> {
473 while matches!(
474 self.current_token.as_ref().map(|(t, _)| t),
475 Some(&Token::SingleLineComment) | Some(&Token::MultiLineComment)
476 ) {
477 self.advance()?;
478 }
479 Ok(())
480 }
481
482 fn is_value_token(&self) -> bool {
484 matches!(
485 self.current_token.as_ref().map(|(t, _)| t),
486 Some(&Token::String)
487 | Some(&Token::UnquotedString)
488 | Some(&Token::Number)
489 | Some(&Token::LeftBrace)
490 | Some(&Token::LeftBracket)
491 | Some(&Token::True)
492 | Some(&Token::False)
493 | Some(&Token::Null)
494 )
495 }
496
497 pub(super) fn skip_comments_and_newlines(&mut self) -> Result<()> {
499 let mut just_had_single_line_comment = false;
500
501 loop {
502 match self.current_token.as_ref().map(|(t, _)| t) {
503 Some(&Token::SingleLineComment) => {
504 just_had_single_line_comment = true;
505 self.advance()?;
506 }
507 Some(&Token::MultiLineComment) => {
508 just_had_single_line_comment = false;
509 self.advance()?;
510 }
511 Some(&Token::Newline)
512 if self.options.newline_as_comma || just_had_single_line_comment =>
513 {
514 just_had_single_line_comment = false;
515 self.advance()?;
516 }
517 _ => break,
518 }
519 }
520 Ok(())
521 }
522
523 pub(super) fn is_separator(&self) -> bool {
525 matches!(
526 self.current_token.as_ref().map(|(t, _)| t),
527 Some(&Token::Comma)
528 ) || (self.options.newline_as_comma
529 && matches!(
530 self.current_token.as_ref().map(|(t, _)| t),
531 Some(&Token::Newline)
532 ))
533 }
534
535 #[allow(dead_code)]
537 fn is_only_whitespace_and_newlines(&mut self) -> bool {
538 let current_pos = self.lexer.position();
540 let remaining_input = &self.original_input[current_pos..];
541
542 let needs_forgiving = self.options.allow_comments
544 || self.options.allow_trailing_commas
545 || self.options.allow_unquoted_keys
546 || self.options.allow_single_quotes
547 || self.options.implicit_top_level
548 || self.options.newline_as_comma;
549
550 let mut temp_lexer: Box<dyn JsonLexer> = if needs_forgiving {
551 let config = LexerConfig {
552 mode: if self.options.allow_comments {
553 LexerMode::Forgiving
554 } else {
555 LexerMode::Strict
556 },
557 collect_stats: false,
558 buffer_size: 8192,
559 max_depth: self.options.max_depth,
560 track_positions: true,
561 };
562 Box::new(FastLexer::new(remaining_input, config))
563 } else {
564 Box::new(Lexer::new(remaining_input))
565 };
566
567 loop {
568 match temp_lexer.next_token() {
569 Ok((Token::Eof, _)) => return true,
570 Ok((Token::Newline, _)) => continue,
571 Ok((Token::SingleLineComment, _)) => continue,
572 Ok((Token::MultiLineComment, _)) => continue,
573 Ok((_, _)) => return false,
574 Err(_) => return false, }
576 }
577 }
578
579 fn parse_value_or_implicit(&mut self) -> Result<Value> {
580 self.skip_comments()?;
581
582 if self.options.implicit_top_level {
584 match self.current_token {
585 Some((Token::UnquotedString, _))
586 | Some((Token::String, _))
587 | Some((Token::Number, _)) => {
588 let potential_key = match self.current_token {
592 Some((Token::String, span)) => {
593 match parse_string_token(self.original_input, span, &self.options)? {
595 Value::String(s) => s,
596 _ => {
597 unreachable!("parse_string_token should always return a String")
598 }
599 }
600 }
601 Some((Token::UnquotedString, span)) => {
602 self.original_input[span.start..span.end].to_string()
604 }
605 Some((Token::Number, span)) => {
606 self.original_input[span.start..span.end].to_string()
608 }
609 _ => unreachable!(),
610 };
611
612 let key_token = self.current_token;
614
615 self.advance()?;
617 self.skip_comments_and_newlines()?;
618
619 if let Some((Token::Colon, _)) = self.current_token {
620 let mut object = FxHashMap::default();
622
623 self.advance()?; let value = self.parse_value()?;
626 object.insert(potential_key, value);
627
628 loop {
630 self.skip_comments_and_newlines()?;
631
632 if let Some((Token::Eof, _)) = self.current_token {
633 break;
634 }
635
636 if self.is_separator() {
637 self.advance()?;
638 self.skip_comments_and_newlines()?;
639
640 if let Some((Token::Eof, _)) = self.current_token {
641 break;
642 }
643 }
644
645 let key = match self.current_token {
647 Some((Token::String, span)) => {
648 let k = match parse_string_token(
650 self.original_input,
651 span,
652 &self.options,
653 )? {
654 Value::String(s) => s,
655 _ => unreachable!(
656 "parse_string_token should always return a String"
657 ),
658 };
659 self.advance()?;
660 k
661 }
662 Some((Token::UnquotedString, span)) => {
663 let k = self.original_input[span.start..span.end].to_string();
665 self.advance()?;
666 k
667 }
668 Some((Token::Number, span)) => {
669 let k = self.original_input[span.start..span.end].to_string();
671 self.advance()?;
672 k
673 }
674 _ => break,
675 };
676
677 self.skip_comments_and_newlines()?;
679 if !matches!(self.current_token, Some((Token::Colon, _))) {
680 return Err(Error::Expected {
681 expected: ":".to_string(),
682 found: format!("{:?}", self.current_token),
683 position: self.lexer.position(),
684 });
685 }
686 self.advance()?;
687
688 let value = self.parse_value()?;
690 object.insert(key, value);
691 }
692
693 return Ok(Value::Object(object));
694 } else {
695 let value = match key_token {
697 Some((Token::String, span)) => {
698 parse_string_token(self.original_input, span, &self.options)?
700 }
701 Some((Token::UnquotedString, span)) => {
702 let s = self.original_input[span.start..span.end].to_string();
704 Value::String(s)
705 }
706 Some((Token::Number, span)) => {
707 parse_number_token(self.original_input, span)?
709 }
710 _ => unreachable!(),
711 };
712
713 return Ok(value);
715 }
716 }
717 _ => {}
718 }
719 }
720
721 self.parse_value()
723 }
724
725 pub(super) fn parse_value(&mut self) -> Result<Value> {
726 self.skip_comments_and_newlines()?;
727
728 match self.current_token {
729 Some((Token::Null, _)) => {
730 self.advance()?;
731 parse_null()
732 }
733 Some((Token::True, _)) => {
734 self.advance()?;
735 parse_true()
736 }
737 Some((Token::False, _)) => {
738 self.advance()?;
739 parse_false()
740 }
741 Some((Token::String, span)) => {
742 let value = parse_string_token(self.original_input, span, &self.options)?;
743 self.advance()?;
744 Ok(value)
745 }
746 Some((Token::UnquotedString, span)) => {
747 let s = self.original_input[span.start..span.end].to_string();
749 self.advance()?;
750 Ok(Value::String(s))
751 }
752 Some((Token::Number, span)) => {
753 let value = parse_number_token(self.original_input, span)?;
754 self.advance()?;
755 Ok(value)
756 }
757 Some((Token::LeftBrace, _)) => self.parse_object(),
758 Some((Token::LeftBracket, _)) => self.parse_array(),
759 None => {
760 if self.options.allow_comments {
762 Ok(Value::Null)
763 } else {
764 Err(Error::Expected {
765 expected: "value".to_string(),
766 found: "EOF".to_string(),
767 position: self.lexer.position(),
768 })
769 }
770 }
771 Some((Token::Eof, _)) => {
772 if self.options.allow_comments {
774 Ok(Value::Null)
775 } else {
776 Err(Error::Expected {
777 expected: "value".to_string(),
778 found: "EOF".to_string(),
779 position: self.lexer.position(),
780 })
781 }
782 }
783 _ => Err(Error::Expected {
784 expected: "value".to_string(),
785 found: format!("{:?}", self.current_token),
786 position: self.lexer.position(),
787 }),
788 }
789 }
790
791 pub(super) fn check_depth(&self) -> Result<()> {
792 if self.state.depth >= self.options.max_depth {
793 Err(Error::DepthLimitExceeded(self.lexer.position()))
794 } else {
795 Ok(())
796 }
797 }
798}
799
800pub fn parse(input: &str) -> Result<Value> {
816 let mut parser = Parser::new(input, ParserOptions::default());
817 parser.parse()
818}
819
820pub fn parse_with_options(input: &str, options: ParserOptions) -> Result<Value> {
839 let mut parser = Parser::new(input, options);
840 parser.parse()
841}
842
843pub fn parse_with_fallback(input: &str, options: ParserOptions) -> EnhancedParseResult<Value> {
853 if let Ok(serde_value) = serde_json::from_str::<serde_json::Value>(input) {
855 let vexy_json_value = convert_serde_to_vexy_json(serde_value);
857 return EnhancedParseResult::success(vexy_json_value, ParsingTier::Fast);
858 }
859
860 match parse_with_options(input, options.clone()) {
862 Ok(value) => EnhancedParseResult::success(value, ParsingTier::Forgiving),
863 Err(error) => {
864 if options.enable_repair {
866 parse_with_repair(input, &options)
867 } else {
868 EnhancedParseResult::failure(Value::Null, vec![error], ParsingTier::Forgiving)
869 }
870 }
871 }
872}
873
874fn parse_with_repair(input: &str, options: &ParserOptions) -> EnhancedParseResult<Value> {
876 let mut repairer = if options.fast_repair {
878 JsonRepairer::new_without_cache(options.max_repairs)
879 } else {
880 JsonRepairer::new(options.max_repairs)
881 };
882
883 match repairer.repair(input) {
884 Ok((repaired_json, repairs)) => {
885 match parse_with_options(&repaired_json, options.clone()) {
887 Ok(value) => {
888 EnhancedParseResult::success_with_repairs(value, repairs, ParsingTier::Repair)
889 }
890 Err(error) => {
891 parse_with_advanced_recovery(input, options, error, repairs)
893 }
894 }
895 }
896 Err(_repair_error) => {
897 match parse_with_options(input, options.clone()) {
900 Ok(value) => {
901 EnhancedParseResult::success(value, ParsingTier::Repair)
903 }
904 Err(parse_error) => {
905 parse_with_advanced_recovery(input, options, parse_error, vec![])
906 }
907 }
908 }
909 }
910}
911
912fn parse_with_advanced_recovery(
914 input: &str,
915 options: &ParserOptions,
916 original_error: Error,
917 previous_repairs: Vec<RepairAction>,
918) -> EnhancedParseResult<Value> {
919 let mut recovery_engine = ErrorRecoveryEngineV2::new();
921
922 let error_context = ErrorContext {
924 error: original_error.clone(),
925 input: input.to_string(),
926 position: match &original_error {
927 Error::UnexpectedEof(pos) => *pos,
928 Error::UnterminatedString(pos) => *pos,
929 Error::Expected { position, .. } => *position,
930 Error::InvalidNumber(pos) => *pos,
931 Error::InvalidEscape(pos) => *pos,
932 Error::UnexpectedChar(_, pos) => *pos,
933 Error::DepthLimitExceeded(pos) => *pos,
934 _ => 0,
935 },
936 tokens_before: vec![], partial_ast: None,
938 parsing_context: "top_level".to_string(),
939 };
940
941 let suggestions = recovery_engine.suggest_recovery(&error_context);
943
944 let mut all_repairs = previous_repairs;
946
947 for suggestion in suggestions {
948 match parse_with_options(&suggestion.fixed_input, options.clone()) {
950 Ok(value) => {
951 let repair_action = RepairAction {
953 position: suggestion.fix_location.start,
954 action_type: suggestion.category.clone().into(),
955 original: input[suggestion.fix_location.start..suggestion.fix_location.end.min(input.len())].to_string(),
956 replacement: match suggestion.category {
957 crate::error::SuggestionCategory::MissingBracket => {
958 if suggestion.fixed_input.ends_with('}') {
959 "}".to_string()
960 } else if suggestion.fixed_input.ends_with(']') {
961 "]".to_string()
962 } else {
963 "".to_string()
964 }
965 }
966 crate::error::SuggestionCategory::UnmatchedQuote => "\"".to_string(),
967 crate::error::SuggestionCategory::MissingComma => ",".to_string(),
968 _ => "".to_string(),
969 },
970 description: suggestion.description.clone(),
971 };
972
973 all_repairs.push(repair_action);
974 return EnhancedParseResult::success_with_repairs(
975 value,
976 all_repairs,
977 ParsingTier::Repair,
978 );
979 }
980 Err(_) => {
981 continue;
983 }
984 }
985 }
986
987 EnhancedParseResult::failure_with_repairs(
989 Value::Null,
990 vec![original_error],
991 all_repairs,
992 ParsingTier::Repair,
993 )
994}
995
996fn convert_serde_to_vexy_json(serde_value: serde_json::Value) -> Value {
998 match serde_value {
999 serde_json::Value::Null => Value::Null,
1000 serde_json::Value::Bool(b) => Value::Bool(b),
1001 serde_json::Value::Number(n) => {
1002 if let Some(i) = n.as_i64() {
1003 Value::Number(Number::Integer(i))
1004 } else if let Some(f) = n.as_f64() {
1005 Value::Number(Number::Float(f))
1006 } else {
1007 Value::Number(Number::Float(0.0))
1008 }
1009 }
1010 serde_json::Value::String(s) => Value::String(s),
1011 serde_json::Value::Array(arr) => {
1012 let converted: Vec<Value> = arr.into_iter().map(convert_serde_to_vexy_json).collect();
1013 Value::Array(converted)
1014 }
1015 serde_json::Value::Object(obj) => {
1016 let converted: FxHashMap<String, Value> = obj
1017 .into_iter()
1018 .map(|(k, v)| (k, convert_serde_to_vexy_json(v)))
1019 .collect();
1020 Value::Object(converted)
1021 }
1022 }
1023}
1024
1025pub fn parse_with_detailed_repair_tracking(
1027 input: &str,
1028 options: ParserOptions,
1029) -> EnhancedParseResult<Value> {
1030 let mut repairer = JsonRepairer::new(options.max_repairs);
1031
1032 match repairer.repair_with_detailed_tracking(input) {
1033 Ok((repaired_json, repairs)) => match parse_with_options(&repaired_json, options) {
1034 Ok(value) => {
1035 EnhancedParseResult::success_with_repairs(value, repairs, ParsingTier::Repair)
1036 }
1037 Err(error) => EnhancedParseResult::failure_with_repairs(
1038 Value::Null,
1039 vec![error],
1040 repairs,
1041 ParsingTier::Repair,
1042 ),
1043 },
1044 Err(repair_error) => EnhancedParseResult::failure(
1045 Value::Null,
1046 vec![Error::RepairFailed(repair_error)],
1047 ParsingTier::Repair,
1048 ),
1049 }
1050}