Skip to main content

jsonc_parser/
serde.rs

1use std::borrow::Cow;
2use std::cell::Cell;
3
4use ::serde::de::DeserializeSeed;
5use ::serde::de::EnumAccess;
6use ::serde::de::IntoDeserializer;
7use ::serde::de::MapAccess;
8use ::serde::de::SeqAccess;
9use ::serde::de::VariantAccess;
10use ::serde::de::Visitor;
11use ::serde::forward_to_deserialize_any;
12
13use super::ParseOptions;
14use super::common::Range;
15use super::errors::ParseError;
16use super::errors::ParseErrorKind;
17use super::tokens::Token;
18use crate::parser::JsoncParser;
19
20/// Parses a string containing JSONC to a `serde_json::Value` or any
21/// type that implements `serde::Deserialize`.
22///
23/// Requires the "serde" cargo feature:
24///
25/// ```toml
26/// jsonc-parser = { version = "...", features = ["serde"] }
27/// ```
28///
29/// # Example
30///
31/// Parsing to a `serde_json::Value`:
32///
33/// ```rs
34/// use jsonc_parser::parse_to_serde_value;
35///
36/// let json_value: serde_json::Value = parse_to_serde_value(
37///   r#"{ "test": 5 } // test"#,
38///   &Default::default(),
39/// ).unwrap();
40/// ```
41///
42/// Or to a concrete type:
43///
44/// ```rs
45/// use jsonc_parser::parse_to_serde_value;
46///
47/// #[derive(serde::Deserialize)]
48/// struct Config {
49///   test: u32,
50/// }
51///
52/// let config: Config = parse_to_serde_value(
53///   r#"{ "test": 5 } // test"#,
54///   &Default::default(),
55/// ).unwrap();
56/// ```
57///
58/// Empty or whitespace-only input deserializes as `null`, which means
59/// `Option<T>` will produce `None` while other types will return a
60/// type-mismatch error.
61pub fn parse_to_serde_value<T: ::serde::de::DeserializeOwned>(
62  text: &str,
63  parse_options: &ParseOptions,
64) -> Result<T, ParseError> {
65  let mut parser = JsoncParser::new(text, parse_options);
66
67  let token = parser.scan()?;
68  match token {
69    Some(token) => parser.put_back(token),
70    None => parser.put_back(Token::Null),
71  }
72
73  let value = T::deserialize(&mut parser)?;
74  if parser.scan()?.is_some() {
75    return Err(
76      parser
77        .scanner
78        .create_error_for_current_token(ParseErrorKind::MultipleRootJsonValues),
79    );
80  }
81  Ok(value)
82}
83
84impl ::serde::de::Error for ParseError {
85  fn custom<T: std::fmt::Display>(msg: T) -> Self {
86    ParseError::custom_err(msg.to_string())
87  }
88}
89
90impl<'de> ::serde::Deserializer<'de> for &mut JsoncParser<'de> {
91  type Error = ParseError;
92
93  fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
94    match self.scan()? {
95      None => Err(ParseError::custom_err("unexpected end of input".to_string())),
96      Some(token) => deserialize_token(self, token, visitor),
97    }
98  }
99
100  fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
101    match self.scan()? {
102      Some(Token::Null) => visitor.visit_none(),
103      Some(token) => {
104        self.put_back(token);
105        visitor.visit_some(self)
106      }
107      None => visitor.visit_none(),
108    }
109  }
110
111  fn deserialize_enum<V: Visitor<'de>>(
112    self,
113    _name: &'static str,
114    _variants: &'static [&'static str],
115    visitor: V,
116  ) -> Result<V::Value, Self::Error> {
117    let token = self.scan()?;
118    let token_range = Range::new(self.scanner.token_start(), self.scanner.token_end());
119    let text = self.text;
120    let result = match token {
121      Some(Token::String(s)) => {
122        let variant: String = s.into_owned();
123        visitor.visit_enum(variant.into_deserializer())
124      }
125      Some(Token::OpenBrace) => {
126        // expect exactly one property: { "Variant": data }
127        let key = match self.scan()? {
128          Some(Token::String(s)) => s.into_owned(),
129          _ => {
130            return Err(ParseError::new(
131              token_range,
132              ParseErrorKind::Custom("expected a string key for enum variant".to_string()),
133              text,
134            ));
135          }
136        };
137
138        // expect colon
139        self.scan_object_colon()?;
140
141        let result = visitor.visit_enum(ObjectEnumAccess {
142          parser: self,
143          variant: key,
144        });
145        result.and_then(|v| {
146          // expect close brace
147          match self.scan()? {
148            Some(Token::CloseBrace) => Ok(v),
149            _ => Err(
150              self
151                .scanner
152                .create_error_for_current_token(ParseErrorKind::UnterminatedObject),
153            ),
154          }
155        })
156      }
157      _ => {
158        return Err(ParseError::new(
159          token_range,
160          ParseErrorKind::Custom("expected a string or object for enum".to_string()),
161          text,
162        ));
163      }
164    };
165    result.map_err(|e| e.with_position(token_range, text))
166  }
167
168  fn deserialize_newtype_struct<V: Visitor<'de>>(
169    self,
170    _name: &'static str,
171    visitor: V,
172  ) -> Result<V::Value, Self::Error> {
173    visitor.visit_newtype_struct(self)
174  }
175
176  forward_to_deserialize_any! {
177    bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64
178    char str string bytes byte_buf unit unit_struct
179    seq tuple tuple_struct map struct identifier ignored_any
180  }
181}
182
183fn deserialize_token<'de, V: Visitor<'de>>(
184  parser: &mut JsoncParser<'de>,
185  token: Token<'de>,
186  visitor: V,
187) -> Result<V::Value, ParseError> {
188  let token_range = Range::new(parser.scanner.token_start(), parser.scanner.token_end());
189  let text = parser.text;
190  let result = match token {
191    Token::Null => visitor.visit_unit(),
192    Token::Boolean(b) => visitor.visit_bool(b),
193    Token::Number(n) => visit_number(n, visitor),
194    Token::String(s) => match s {
195      Cow::Borrowed(b) => visitor.visit_borrowed_str(b),
196      Cow::Owned(o) => visitor.visit_string(o),
197    },
198    Token::OpenBracket => {
199      parser.enter_container()?;
200      let finished = Cell::new(false);
201      let result = visitor.visit_seq(ScannerSeqAccess {
202        parser,
203        first: true,
204        finished: &finished,
205      });
206      if result.is_ok() && !finished.get() {
207        if let Err(e) = drain_array(parser) {
208          parser.exit_container();
209          return Err(e);
210        }
211      }
212      parser.exit_container();
213      result
214    }
215    Token::OpenBrace => {
216      parser.enter_container()?;
217      let result = visitor.visit_map(ScannerMapAccess { parser, first: true });
218      parser.exit_container();
219      result
220    }
221    other => return Err(parser.unexpected_token_error(&other)),
222  };
223  result.map_err(|e| e.with_position(token_range, text))
224}
225
226// number handling
227
228fn visit_number<'de, V: Visitor<'de>>(raw: &str, visitor: V) -> Result<V::Value, ParseError> {
229  // handle hexadecimal
230  let trimmed = raw.trim_start_matches(['-', '+']);
231  if trimmed.len() > 2 && (trimmed.starts_with("0x") || trimmed.starts_with("0X")) {
232    let hex_part = &trimmed[2..];
233    let negative = raw.starts_with('-');
234    if let Ok(val) = i64::from_str_radix(hex_part, 16) {
235      return visitor.visit_i64(if negative { -val } else { val });
236    }
237    // fall back to an i128 for the values that don't fit in an i64, which
238    // are the ones that fit in a u64 and `i64::MIN`
239    return match i128::from_str_radix(hex_part, 16) {
240      Ok(val) => {
241        let val = if negative { -val } else { val };
242        if let Ok(val) = i64::try_from(val) {
243          visitor.visit_i64(val)
244        } else if let Ok(val) = u64::try_from(val) {
245          visitor.visit_u64(val)
246        } else {
247          Err(number_out_of_range_error())
248        }
249      }
250      Err(_) => Err(number_out_of_range_error()),
251    };
252  }
253
254  // strip unary plus
255  let num_str = raw.trim_start_matches('+');
256
257  if let Ok(v) = num_str.parse::<i64>() {
258    return visitor.visit_i64(v);
259  }
260  if let Ok(v) = num_str.parse::<u64>() {
261    return visitor.visit_u64(v);
262  }
263  match num_str.parse::<f64>() {
264    Ok(v) if v.is_finite() => visitor.visit_f64(v),
265    // `parse` resolves to infinity instead of erroring for numbers that are
266    // too large and the scanner only ever provides numbers an f64 can parse
267    _ => Err(number_out_of_range_error()),
268  }
269}
270
271/// Errors instead of silently changing the value's JSON type, which is what
272/// visiting a non-finite float would do (ex. `serde_json::Value` turns those
273/// into `null`).
274fn number_out_of_range_error() -> ParseError {
275  ParseError::custom_err("Number is out of range".to_string())
276}
277
278// array handling
279
280/// Consumes remaining array elements and the closing `]` when a visitor
281/// (e.g. for a tuple) stops reading before the end of the array.
282fn drain_array(parser: &mut JsoncParser) -> Result<(), ParseError> {
283  loop {
284    match parser.scan_array_comma()? {
285      Some(Token::CloseBracket) => return Ok(()),
286      Some(token) => {
287        parser.put_back(token);
288        <::serde::de::IgnoredAny as ::serde::Deserialize>::deserialize(&mut *parser)?;
289      }
290      None => {
291        return Err(
292          parser
293            .scanner
294            .create_error_for_current_token(ParseErrorKind::UnterminatedArray),
295        );
296      }
297    }
298  }
299}
300
301struct ScannerSeqAccess<'a, 'b> {
302  parser: &'b mut JsoncParser<'a>,
303  first: bool,
304  finished: &'b Cell<bool>,
305}
306
307impl<'de, 'b> SeqAccess<'de> for ScannerSeqAccess<'de, 'b> {
308  type Error = ParseError;
309
310  fn next_element_seed<T: DeserializeSeed<'de>>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> {
311    let token = if self.first {
312      self.first = false;
313      self.parser.scan()?
314    } else {
315      self.parser.scan_array_comma()?
316    };
317
318    match token {
319      Some(Token::CloseBracket) => {
320        self.finished.set(true);
321        Ok(None)
322      }
323      Some(token) => {
324        self.parser.put_back(token);
325        seed.deserialize(&mut *self.parser).map(Some)
326      }
327      None => Err(
328        self
329          .parser
330          .scanner
331          .create_error_for_current_token(ParseErrorKind::UnterminatedArray),
332      ),
333    }
334  }
335}
336
337// object handling
338
339struct ScannerMapAccess<'a, 'b> {
340  parser: &'b mut JsoncParser<'a>,
341  first: bool,
342}
343
344impl<'de, 'b> MapAccess<'de> for ScannerMapAccess<'de, 'b> {
345  type Error = ParseError;
346
347  fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> {
348    let key = self.parser.scan_object_entry(self.first)?;
349    self.first = false;
350
351    match key {
352      None => Ok(None),
353      Some(key) => {
354        // borrow the key from the source when it's clean, only allocating for
355        // owned (escaped) keys — mirrors the value path's `Cow` keys
356        seed
357          .deserialize(<Cow<'de, str> as IntoDeserializer<Self::Error>>::into_deserializer(
358            key.into_cow(),
359          ))
360          .map(Some)
361      }
362    }
363  }
364
365  fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> Result<V::Value, Self::Error> {
366    self.parser.scan_object_colon()?;
367    seed.deserialize(&mut *self.parser)
368  }
369}
370
371// enum handling
372
373struct ObjectEnumAccess<'a, 'b> {
374  parser: &'b mut JsoncParser<'a>,
375  variant: String,
376}
377
378impl<'de, 'b> EnumAccess<'de> for ObjectEnumAccess<'de, 'b> {
379  type Error = ParseError;
380  type Variant = ObjectVariantAccess<'de, 'b>;
381
382  fn variant_seed<V: DeserializeSeed<'de>>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> {
383    let variant = seed.deserialize(<String as IntoDeserializer<Self::Error>>::into_deserializer(
384      self.variant,
385    ))?;
386    Ok((variant, ObjectVariantAccess { parser: self.parser }))
387  }
388}
389
390struct ObjectVariantAccess<'a, 'b> {
391  parser: &'b mut JsoncParser<'a>,
392}
393
394impl<'de, 'b> VariantAccess<'de> for ObjectVariantAccess<'de, 'b> {
395  type Error = ParseError;
396
397  fn unit_variant(self) -> Result<(), Self::Error> {
398    ::serde::Deserialize::deserialize(&mut *self.parser)
399  }
400
401  fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, seed: T) -> Result<T::Value, Self::Error> {
402    seed.deserialize(&mut *self.parser)
403  }
404
405  fn tuple_variant<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error> {
406    match self.parser.scan()? {
407      Some(Token::OpenBracket) => {
408        self.parser.enter_container()?;
409        let finished = Cell::new(false);
410        let result = visitor.visit_seq(ScannerSeqAccess {
411          parser: self.parser,
412          first: true,
413          finished: &finished,
414        });
415        if result.is_ok() && !finished.get() {
416          if let Err(e) = drain_array(self.parser) {
417            self.parser.exit_container();
418            return Err(e);
419          }
420        }
421        self.parser.exit_container();
422        result
423      }
424      _ => Err(ParseError::custom_err(
425        "expected an array for tuple variant".to_string(),
426      )),
427    }
428  }
429
430  fn struct_variant<V: Visitor<'de>>(
431    self,
432    _fields: &'static [&'static str],
433    visitor: V,
434  ) -> Result<V::Value, Self::Error> {
435    match self.parser.scan()? {
436      Some(Token::OpenBrace) => {
437        self.parser.enter_container()?;
438        let result = visitor.visit_map(ScannerMapAccess {
439          parser: self.parser,
440          first: true,
441        });
442        self.parser.exit_container();
443        result
444      }
445      _ => Err(ParseError::custom_err(
446        "expected an object for struct variant".to_string(),
447      )),
448    }
449  }
450}
451
452#[cfg(test)]
453mod tests {
454  use pretty_assertions::assert_eq;
455  use serde_json::Value as SerdeValue;
456  use std::str::FromStr;
457
458  use super::*;
459
460  #[test]
461  fn it_should_error_when_has_error() {
462    assert_has_error(
463      "[][]",
464      "Text cannot contain more than one JSON value on line 1 column 3",
465    );
466  }
467
468  fn assert_has_error(text: &str, message: &str) {
469    let result = parse_to_serde_value::<SerdeValue>(text, &Default::default());
470    match result {
471      Ok(_) => panic!("Expected error, but did not find one."),
472      Err(err) => assert_eq!(err.to_string(), message),
473    }
474  }
475
476  #[test]
477  fn it_should_parse_to_serde_value() {
478    let result = parse_to_serde_value::<SerdeValue>(
479      r#"{ "a": { "a1": 5 }, "b": [0.3e+025], "c": "c1", "d": true, "e": false, "f": null }"#,
480      &Default::default(),
481    )
482    .unwrap();
483
484    let mut expected_value = serde_json::map::Map::new();
485    expected_value.insert("a".to_string(), {
486      let mut inner_obj = serde_json::map::Map::new();
487      inner_obj.insert(
488        "a1".to_string(),
489        SerdeValue::Number(serde_json::Number::from_str("5").unwrap()),
490      );
491      SerdeValue::Object(inner_obj)
492    });
493    expected_value.insert("b".to_string(), {
494      let mut inner_array = Vec::new();
495      inner_array.push(SerdeValue::Number(serde_json::Number::from_str("0.3e+025").unwrap()));
496      SerdeValue::Array(inner_array)
497    });
498    expected_value.insert("c".to_string(), SerdeValue::String("c1".to_string()));
499    expected_value.insert("d".to_string(), SerdeValue::Bool(true));
500    expected_value.insert("e".to_string(), SerdeValue::Bool(false));
501    expected_value.insert("f".to_string(), SerdeValue::Null);
502
503    assert_eq!(result, SerdeValue::Object(expected_value));
504  }
505
506  #[test]
507  fn it_should_parse_hexadecimal_numbers_to_decimal() {
508    let result = parse_to_serde_value::<SerdeValue>(
509      r#"{
510        "hex1": 0x7DF,
511        "hex2": 0xFF,
512        "hex3": 0x10
513      }"#,
514      &Default::default(),
515    )
516    .unwrap();
517
518    let mut expected_value = serde_json::map::Map::new();
519    expected_value.insert("hex1".to_string(), SerdeValue::Number(serde_json::Number::from(2015)));
520    expected_value.insert("hex2".to_string(), SerdeValue::Number(serde_json::Number::from(255)));
521    expected_value.insert("hex3".to_string(), SerdeValue::Number(serde_json::Number::from(16)));
522
523    assert_eq!(result, SerdeValue::Object(expected_value));
524  }
525
526  #[test]
527  fn it_should_parse_unary_plus_numbers() {
528    let result = parse_to_serde_value::<SerdeValue>(
529      r#"{
530        "pos1": +42,
531        "pos2": +0.5,
532        "pos3": +1e10
533      }"#,
534      &Default::default(),
535    )
536    .unwrap();
537
538    let mut expected_value = serde_json::map::Map::new();
539    expected_value.insert("pos1".to_string(), SerdeValue::Number(serde_json::Number::from(42)));
540    expected_value.insert(
541      "pos2".to_string(),
542      SerdeValue::Number(serde_json::Number::from_str("0.5").unwrap()),
543    );
544    expected_value.insert(
545      "pos3".to_string(),
546      SerdeValue::Number(serde_json::Number::from_str("1e10").unwrap()),
547    );
548
549    assert_eq!(result, SerdeValue::Object(expected_value));
550  }
551
552  #[test]
553  fn it_should_error_when_number_is_out_of_f64_range() {
554    assert_has_error(r#"{ "amount": 1e400 }"#, "Number is out of range on line 1 column 13");
555    assert_has_error("[-1e400]", "Number is out of range on line 1 column 2");
556    assert_has_error("1.7976931348623159e308", "Number is out of range on line 1 column 1");
557
558    // deserializing to a float should error as well instead of resolving to infinity
559    let err = parse_to_serde_value::<f64>("1e400", &Default::default()).unwrap_err();
560    assert_eq!(err.to_string(), "Number is out of range on line 1 column 1");
561
562    // the number being out of range still errors when the value is ignored
563    #[derive(::serde::Deserialize, Debug, PartialEq)]
564    #[serde(crate = "::serde")]
565    struct Amount {
566      amount: u32,
567    }
568    let err = parse_to_serde_value::<Amount>(r#"{ "amount": 1, "other": 1e400 }"#, &Default::default()).unwrap_err();
569    assert_eq!(err.to_string(), "Number is out of range on line 1 column 25");
570
571    // numbers that underflow are fine
572    let result = parse_to_serde_value::<f64>("1e-400", &Default::default()).unwrap();
573    assert_eq!(result, 0.0);
574    let result = parse_to_serde_value::<f64>("-1e-400", &Default::default()).unwrap();
575    assert_eq!(result, -0.0);
576    assert!(result.is_sign_negative());
577
578    // the largest finite f64 is fine
579    let result = parse_to_serde_value::<f64>("1.7976931348623157e308", &Default::default()).unwrap();
580    assert_eq!(result, f64::MAX);
581  }
582
583  #[test]
584  fn it_should_error_when_hexadecimal_number_is_out_of_range() {
585    assert_has_error(
586      r#"{ "value": 0xFFFFFFFFFFFFFFFFFF }"#,
587      "Number is out of range on line 1 column 12",
588    );
589    assert_has_error("-0x8000000000000001", "Number is out of range on line 1 column 1");
590
591    // hexadecimal numbers that don't fit in an i64, but fit in a u64
592    let result = parse_to_serde_value::<u64>("0x8000000000000000", &Default::default()).unwrap();
593    assert_eq!(result, 9223372036854775808);
594
595    // i64::MIN
596    let result = parse_to_serde_value::<i64>("-0x8000000000000000", &Default::default()).unwrap();
597    assert_eq!(result, i64::MIN);
598  }
599
600  #[test]
601  fn it_should_deserialize_to_struct() {
602    #[derive(::serde::Deserialize, Debug, PartialEq)]
603    #[serde(crate = "::serde")]
604    struct Config {
605      name: String,
606      value: u32,
607      enabled: bool,
608    }
609
610    let result: Config = parse_to_serde_value(
611      r#"{ "name": "test", "value": 42, "enabled": true }"#,
612      &Default::default(),
613    )
614    .unwrap();
615
616    assert_eq!(
617      result,
618      Config {
619        name: "test".to_string(),
620        value: 42,
621        enabled: true,
622      }
623    );
624  }
625
626  #[test]
627  fn it_should_report_position_on_type_error() {
628    #[derive(::serde::Deserialize, Debug)]
629    #[serde(crate = "::serde")]
630    #[allow(dead_code)]
631    struct Config {
632      name: String,
633    }
634
635    let text = r#"{
636  "name": true
637}"#;
638    let err = parse_to_serde_value::<Config>(text, &Default::default()).unwrap_err();
639    // the error should point at `true` (line 2, column 11)
640    assert_eq!(err.line_display(), 2);
641    assert_eq!(err.column_display(), 11);
642    assert!(err.to_string().contains("invalid type"), "got: {}", err);
643  }
644
645  #[test]
646  fn it_should_deserialize_option_fields() {
647    #[derive(::serde::Deserialize, Debug, PartialEq)]
648    #[serde(crate = "::serde")]
649    struct Config {
650      a: Option<u32>,
651      b: Option<u32>,
652    }
653
654    let result: Config = parse_to_serde_value(r#"{ "a": 5, "b": null }"#, &Default::default()).unwrap();
655
656    assert_eq!(result, Config { a: Some(5), b: None });
657  }
658
659  #[test]
660  fn it_should_deserialize_enum() {
661    #[derive(::serde::Deserialize, Debug, PartialEq)]
662    #[serde(crate = "::serde")]
663    enum Color {
664      Red,
665      Green,
666      Blue,
667    }
668
669    #[derive(::serde::Deserialize, Debug, PartialEq)]
670    #[serde(crate = "::serde")]
671    struct Config {
672      color: Color,
673    }
674
675    let result: Config = parse_to_serde_value(r#"{ "color": "Red" }"#, &Default::default()).unwrap();
676
677    assert_eq!(result, Config { color: Color::Red });
678  }
679
680  #[test]
681  fn it_should_deserialize_complex_enum() {
682    #[derive(::serde::Deserialize, Debug, PartialEq)]
683    #[serde(crate = "::serde")]
684    enum Shape {
685      Circle(f64),
686      Rectangle { width: f64, height: f64 },
687    }
688
689    let result: Shape = parse_to_serde_value(r#"{ "Circle": 5.0 }"#, &Default::default()).unwrap();
690    assert_eq!(result, Shape::Circle(5.0));
691
692    let result: Shape = parse_to_serde_value(
693      r#"{ "Rectangle": { "width": 3.0, "height": 4.0 } }"#,
694      &Default::default(),
695    )
696    .unwrap();
697    assert_eq!(
698      result,
699      Shape::Rectangle {
700        width: 3.0,
701        height: 4.0
702      }
703    );
704  }
705
706  #[test]
707  fn it_should_return_null_for_empty_input() {
708    let result = parse_to_serde_value::<SerdeValue>("", &Default::default()).unwrap();
709    assert_eq!(result, SerdeValue::Null);
710  }
711
712  #[test]
713  fn it_should_return_none_for_empty_input_with_option() {
714    let result: Option<SerdeValue> = parse_to_serde_value("", &Default::default()).unwrap();
715    assert_eq!(result, None);
716  }
717
718  #[test]
719  fn it_should_return_some_for_non_empty_input_with_option() {
720    let result: Option<SerdeValue> = parse_to_serde_value(r#"{ "a": 1 }"#, &Default::default()).unwrap();
721    assert!(result.is_some());
722  }
723
724  #[test]
725  fn it_should_return_none_for_empty_input_with_option_struct() {
726    #[derive(::serde::Deserialize, Debug, PartialEq)]
727    #[serde(crate = "::serde")]
728    struct Config {
729      value: u32,
730    }
731
732    let result: Option<Config> = parse_to_serde_value("", &Default::default()).unwrap();
733    assert_eq!(result, None);
734
735    let result: Option<Config> = parse_to_serde_value("  \n  ", &Default::default()).unwrap();
736    assert_eq!(result, None);
737  }
738
739  #[test]
740  fn it_should_deserialize_tuples() {
741    // 1-element
742    let result: (u8,) = parse_to_serde_value("[1]", &Default::default()).unwrap();
743    assert_eq!(result, (1,));
744
745    // 2-element with mixed types
746    let result: (u8, String) = parse_to_serde_value(r#"[1, "hello"]"#, &Default::default()).unwrap();
747    assert_eq!(result, (1, "hello".to_string()));
748
749    // 3-element in an object
750    #[derive(::serde::Deserialize, Debug, PartialEq)]
751    #[serde(crate = "::serde")]
752    struct Config {
753      version: (u8, u8, u8),
754    }
755    let result: Config = parse_to_serde_value(r#"{ "version": [0, 3, 0] }"#, &Default::default()).unwrap();
756    assert_eq!(result, Config { version: (0, 3, 0) });
757
758    // 6-element
759    let result: (u8, u8, u8, u8, u8, u8) = parse_to_serde_value("[1, 2, 3, 4, 5, 6]", &Default::default()).unwrap();
760    assert_eq!(result, (1, 2, 3, 4, 5, 6));
761
762    // 9-element
763    let result: (u8, u8, u8, u8, u8, u8, u8, u8, u8) =
764      parse_to_serde_value("[1, 2, 3, 4, 5, 6, 7, 8, 9]", &Default::default()).unwrap();
765    assert_eq!(result, (1, 2, 3, 4, 5, 6, 7, 8, 9));
766
767    // 12-element
768    let result: (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) =
769      parse_to_serde_value("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]", &Default::default()).unwrap();
770    assert_eq!(result, (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
771  }
772
773  #[test]
774  fn it_should_handle_comments_in_jsonc() {
775    #[derive(::serde::Deserialize, Debug, PartialEq)]
776    #[serde(crate = "::serde")]
777    struct Config {
778      value: u32,
779    }
780
781    let result: Config = parse_to_serde_value(
782      r#"{
783        // this is a comment
784        "value": 42 /* inline comment */
785      }"#,
786      &Default::default(),
787    )
788    .unwrap();
789
790    assert_eq!(result, Config { value: 42 });
791  }
792
793  #[test]
794  fn missing_comma_between_array_elements() {
795    let result = parse_to_serde_value::<SerdeValue>("[1 2]", &Default::default()).unwrap();
796    assert_eq!(result, serde_json::json!([1, 2]));
797
798    // but is strict when strict
799    assert_has_strict_error("[1 2]", "Expected comma on line 1 column 3");
800    assert_has_strict_error("[01]", "Expected comma on line 1 column 3");
801    assert_has_strict_error(r#"["a" "b"]"#, "Expected comma on line 1 column 5");
802    assert_has_strict_error("[true false]", "Expected comma on line 1 column 6");
803    assert_has_strict_error("[null null]", "Expected comma on line 1 column 6");
804    assert_has_strict_error("[[1] [2]]", "Expected comma on line 1 column 5");
805    assert_has_strict_error(r#"[{"a":1} {"b":2}]"#, "Expected comma on line 1 column 9");
806
807    for text in ["[]", "[1,2]", "[1 , 2]", "[[1],[2]]", r#"[{"a":1},{"b":2}]"#] {
808      parse_to_serde_value_strict::<SerdeValue>(text).unwrap();
809    }
810  }
811
812  #[test]
813  fn missing_comma_between_array_elements_when_draining() {
814    // a tuple stops reading before the end of the array, so the
815    // remaining elements are drained and should still be strict
816    assert_has_strict_drain_error::<(u32,)>("[1 2]", "Expected comma on line 1 column 3");
817    // the drained element here ends with a `}`
818    assert_has_strict_drain_error::<(u32, SerdeValue)>(r#"[1, {"a":2} 3]"#, "Expected comma on line 1 column 12");
819  }
820
821  #[test]
822  fn missing_comma_with_comment_between_array_elements() {
823    // when comments are allowed but missing commas are not,
824    // should still detect the missing comma after the comment is skipped
825    let result = parse_to_serde_value::<SerdeValue>(
826      r#"[
827  1 // comment here
828  2
829]"#,
830      &ParseOptions {
831        allow_comments: true,
832        allow_missing_commas: false,
833        ..Default::default()
834      },
835    );
836    match result {
837      Ok(_) => panic!("Expected error, but did not find one."),
838      Err(err) => assert_eq!(err.to_string(), "Expected comma on line 2 column 4"),
839    }
840  }
841
842  #[track_caller]
843  fn assert_has_strict_error(text: &str, message: &str) {
844    match parse_to_serde_value_strict::<SerdeValue>(text) {
845      Ok(_) => panic!("Expected error, but did not find one."),
846      Err(err) => assert_eq!(err.to_string(), message),
847    }
848  }
849
850  #[track_caller]
851  fn assert_has_strict_drain_error<T: ::serde::de::DeserializeOwned>(text: &str, message: &str) {
852    match parse_to_serde_value_strict::<T>(text) {
853      Ok(_) => panic!("Expected error, but did not find one."),
854      Err(err) => assert_eq!(err.to_string(), message),
855    }
856  }
857
858  fn parse_to_serde_value_strict<T: ::serde::de::DeserializeOwned>(text: &str) -> Result<T, ParseError> {
859    parse_to_serde_value(
860      text,
861      &ParseOptions {
862        allow_comments: false,
863        allow_loose_object_property_names: false,
864        allow_trailing_commas: false,
865        allow_missing_commas: false,
866        allow_single_quoted_strings: false,
867        allow_hexadecimal_numbers: false,
868        allow_unary_plus_numbers: false,
869      },
870    )
871  }
872}