1#![cfg_attr(not(feature = "std"), no_std)]
80#![forbid(unsafe_code)]
81#![warn(missing_docs)]
82
83extern crate alloc;
84
85#[cfg(feature = "canonical")]
86mod canonical;
87mod decode;
88mod encode;
89mod error;
90#[cfg(feature = "validate")]
91mod form;
92mod limits;
93mod number;
94mod parse;
95#[cfg(feature = "primitives")]
96mod primitives;
97mod value;
98mod write;
99
100#[cfg(feature = "canonical")]
101pub use canonical::{to_canonical_string, to_canonical_vec};
102pub use decode::{from_json_str, JsonDecode};
103pub use encode::{to_json_string, to_json_vec, JsonEncode};
104pub use error::{
105 JsonDecodeError, JsonDecodeErrorKind, JsonError, JsonErrorKind, JsonFromStrError,
106 JsonLimitKind, JsonNumberError, JsonPath, JsonPathSegment,
107};
108#[cfg(feature = "validate")]
109pub use form::JsonForm;
110pub use limits::JsonLimits;
111pub use number::JsonNumber;
112pub use parse::{parse, parse_str, parse_with_limits};
113#[cfg(feature = "primitives")]
114pub use primitives::{JsonExtractError, JsonExtractErrorKind};
115pub use value::{JsonMember, JsonObject, JsonValue};
116pub use write::{to_compact_string, to_compact_vec};
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121 use alloc::string::{String, ToString};
122
123 fn parse_ok(input: &str) -> JsonValue {
124 parse_str(input).expect("should parse")
125 }
126
127 fn kind(input: &str) -> JsonErrorKind {
128 parse_str(input).expect_err("should fail").kind().clone()
129 }
130
131 #[test]
134 fn parses_scalars() {
135 assert_eq!(parse_ok("null"), JsonValue::Null);
136 assert_eq!(parse_ok("true"), JsonValue::Bool(true));
137 assert_eq!(parse_ok("false"), JsonValue::Bool(false));
138 assert_eq!(parse_ok("\"hi\"").as_str(), Some("hi"));
139 assert_eq!(parse_ok("42").as_number().unwrap().to_i64().unwrap(), 42);
140 }
141
142 #[test]
143 fn whitespace_is_allowed_around_values() {
144 assert_eq!(parse_ok(" \t\r\n 7 \n").as_number().unwrap().as_str(), "7");
145 }
146
147 #[test]
148 fn only_json_whitespace_is_accepted() {
149 assert_eq!(kind("\u{0B}1"), JsonErrorKind::UnexpectedByte);
151 }
152
153 #[test]
156 fn parses_object_and_array() {
157 let value = parse_ok(r#"{"a":[1,2,3],"b":{"c":null}}"#);
158 let obj = value.as_object().unwrap();
159 assert_eq!(obj.len(), 2);
160 assert_eq!(obj.get("a").unwrap().as_array().unwrap().len(), 3);
161 assert!(obj
162 .get("b")
163 .unwrap()
164 .as_object()
165 .unwrap()
166 .get("c")
167 .unwrap()
168 .is_null());
169 }
170
171 #[test]
172 fn empty_containers() {
173 assert_eq!(parse_ok("[]").as_array().unwrap().len(), 0);
174 assert_eq!(parse_ok("{}").as_object().unwrap().len(), 0);
175 }
176
177 #[test]
180 fn rejects_trailing_data() {
181 assert_eq!(kind("1 2"), JsonErrorKind::TrailingData);
182 assert_eq!(kind("{} x"), JsonErrorKind::TrailingData);
183 }
184
185 #[test]
186 fn rejects_comments_and_trailing_commas() {
187 assert_eq!(kind("1 // c"), JsonErrorKind::TrailingData);
188 assert_eq!(kind("[1,]"), JsonErrorKind::UnexpectedByte);
189 assert_eq!(kind(r#"{"a":1,}"#), JsonErrorKind::UnexpectedByte);
190 }
191
192 #[test]
193 fn rejects_bad_numbers() {
194 for bad in ["01", "1.", "-", "1e", "1e+", "00", "1.2.3"] {
195 assert_eq!(kind(bad), JsonErrorKind::InvalidNumber, "input {bad:?}");
196 }
197 assert_eq!(kind(".5"), JsonErrorKind::UnexpectedByte);
200 assert_eq!(kind("+1"), JsonErrorKind::UnexpectedByte);
201 assert_eq!(kind("0x1"), JsonErrorKind::TrailingData);
202 }
203
204 #[test]
205 fn rejects_nan_and_infinity() {
206 assert_eq!(kind("NaN"), JsonErrorKind::UnexpectedByte);
207 assert_eq!(kind("Infinity"), JsonErrorKind::UnexpectedByte);
208 assert_eq!(kind("-Infinity"), JsonErrorKind::InvalidNumber);
209 }
210
211 #[test]
212 fn rejects_unescaped_control_and_bad_escapes() {
213 assert_eq!(kind("\"\u{01}\""), JsonErrorKind::UnescapedControlCharacter);
214 assert_eq!(kind(r#""\x""#), JsonErrorKind::InvalidEscape);
215 assert_eq!(kind(r#""\u00""#), JsonErrorKind::InvalidUnicodeEscape);
216 }
217
218 #[test]
219 fn rejects_lone_surrogates() {
220 assert_eq!(kind(r#""\uD800""#), JsonErrorKind::LoneSurrogate);
221 assert_eq!(kind(r#""\uDC00""#), JsonErrorKind::LoneSurrogate);
222 assert_eq!(kind(r#""\uD800a""#), JsonErrorKind::LoneSurrogate);
223 }
224
225 #[test]
226 fn accepts_valid_surrogate_pair() {
227 assert_eq!(parse_ok(r#""𝄞""#).as_str(), Some("\u{1D11E}"));
228 }
229
230 #[test]
231 fn rejects_invalid_utf8_and_bom() {
232 assert_eq!(
233 parse(&[0xff]).unwrap_err().kind().clone(),
234 JsonErrorKind::InvalidUtf8
235 );
236 assert_eq!(
237 parse(&[0xEF, 0xBB, 0xBF, b'1']).unwrap_err().kind().clone(),
238 JsonErrorKind::InvalidUtf8
239 );
240 }
241
242 #[test]
245 fn escape_and_literal_decode_equally() {
246 assert_eq!(parse_ok(r#""a""#), parse_ok(r#""a""#));
247 }
248
249 #[test]
250 fn decodes_named_escapes() {
251 assert_eq!(
252 parse_ok(r#""\n\t\r\b\f\"\\\/""#).as_str(),
253 Some("\n\t\r\u{08}\u{0C}\"\\/")
254 );
255 }
256
257 #[test]
260 fn rejects_duplicate_keys() {
261 assert_eq!(kind(r#"{"a":1,"a":2}"#), JsonErrorKind::DuplicateKey);
262 }
263
264 #[test]
265 fn duplicate_detection_is_after_escape_decoding() {
266 assert_eq!(
267 kind(r#"{"role":"user","role":"admin"}"#),
268 JsonErrorKind::DuplicateKey
269 );
270 }
271
272 #[test]
275 fn enforces_depth_limit() {
276 let limits = JsonLimits::new().with_max_depth(3);
277 assert!(parse_with_limits(b"[[[1]]]", limits).is_ok());
278 assert_eq!(
279 parse_with_limits(b"[[[[1]]]]", limits)
280 .unwrap_err()
281 .kind()
282 .clone(),
283 JsonErrorKind::LimitExceeded(JsonLimitKind::Depth)
284 );
285 }
286
287 #[test]
288 fn enforces_count_limits() {
289 let limits = JsonLimits::new();
290 let limits = limits
291 .with_max_array_items(2)
292 .with_max_object_members(2)
293 .with_max_total_nodes(100);
294 assert_eq!(
295 parse_with_limits(b"[1,2,3]", limits)
296 .unwrap_err()
297 .kind()
298 .clone(),
299 JsonErrorKind::LimitExceeded(JsonLimitKind::ArrayItems)
300 );
301 assert_eq!(
302 parse_with_limits(br#"{"a":1,"b":2,"c":3}"#, limits)
303 .unwrap_err()
304 .kind()
305 .clone(),
306 JsonErrorKind::LimitExceeded(JsonLimitKind::ObjectMembers)
307 );
308 }
309
310 #[test]
311 fn enforces_total_nodes_and_input_bytes() {
312 let nodes = JsonLimits::new().with_max_total_nodes(2);
313 assert_eq!(
314 parse_with_limits(b"[1,2]", nodes)
315 .unwrap_err()
316 .kind()
317 .clone(),
318 JsonErrorKind::LimitExceeded(JsonLimitKind::TotalNodes)
319 );
320 let bytes = JsonLimits::new().with_max_input_bytes(2);
321 assert_eq!(
322 parse_with_limits(b"[1]", bytes).unwrap_err().kind().clone(),
323 JsonErrorKind::LimitExceeded(JsonLimitKind::InputBytes)
324 );
325 }
326
327 #[test]
328 fn enforces_string_and_number_byte_limits() {
329 let s = JsonLimits::new().with_max_string_bytes(3);
330 assert_eq!(
331 parse_with_limits(br#""abcd""#, s)
332 .unwrap_err()
333 .kind()
334 .clone(),
335 JsonErrorKind::LimitExceeded(JsonLimitKind::StringBytes)
336 );
337 let n = JsonLimits::new().with_max_number_bytes(2);
338 assert_eq!(
339 parse_with_limits(b"12345", n).unwrap_err().kind().clone(),
340 JsonErrorKind::LimitExceeded(JsonLimitKind::NumberBytes)
341 );
342 }
343
344 #[test]
347 fn number_conversions() {
348 assert_eq!(parse_ok("-7").as_number().unwrap().to_i64().unwrap(), -7);
349 assert_eq!(parse_ok("7").as_number().unwrap().to_u64().unwrap(), 7);
350 assert!((parse_ok("1.5").as_number().unwrap().to_f64().unwrap() - 1.5).abs() < 1e-12);
351 assert_eq!(
352 parse_ok("1.5").as_number().unwrap().to_i64(),
353 Err(JsonNumberError::NotAnInteger)
354 );
355 assert_eq!(
356 parse_ok("99999999999999999999999")
357 .as_number()
358 .unwrap()
359 .to_i64(),
360 Err(JsonNumberError::OutOfRange)
361 );
362 assert_eq!(
363 parse_ok("1e400").as_number().unwrap().to_f64(),
364 Err(JsonNumberError::NotFinite)
365 );
366 }
367
368 #[test]
369 fn number_preserves_representation() {
370 assert_eq!(parse_ok("1.0").as_number().unwrap().as_str(), "1.0");
371 assert_ne!(parse_ok("1.0"), parse_ok("1")); }
373
374 #[test]
375 fn json_number_from_f64() {
376 assert_eq!(JsonNumber::try_from_f64(1.5).unwrap().as_str(), "1.5");
377 assert_eq!(
378 JsonNumber::try_from_f64(f64::NAN),
379 Err(JsonNumberError::NotFinite)
380 );
381 assert_eq!(
382 JsonNumber::try_from_f64(f64::INFINITY),
383 Err(JsonNumberError::NotFinite)
384 );
385 assert_eq!(JsonNumber::new("01"), Err(JsonNumberError::InvalidNumber));
386 }
387
388 #[test]
391 fn error_reports_location_and_path() {
392 let err = parse_str(" @").unwrap_err();
393 assert_eq!(err.kind().clone(), JsonErrorKind::UnexpectedByte);
394 assert_eq!(err.offset(), 2);
395 assert_eq!(err.line(), 1);
396 assert_eq!(err.column(), 3);
397
398 let err = parse_str(r#"{"users":[{"name":1},{"name":}]}"#).unwrap_err();
399 let path = err.path().unwrap().to_string();
400 assert_eq!(path, "$.users[1].name");
401 }
402
403 #[test]
406 fn compact_roundtrip_and_golden_bytes() {
407 let value = parse_ok(r#"{"a":1,"b":true,"c":[null,"x"]}"#);
408 assert_eq!(
409 to_compact_vec(&value),
410 br#"{"a":1,"b":true,"c":[null,"x"]}"#
411 );
412 let again = parse_str(&to_compact_string(&value)).unwrap();
414 assert_eq!(value, again);
415 }
416
417 #[test]
418 fn writer_escapes_control_and_special_characters() {
419 let mut object = JsonObject::new();
420 object.insert(
421 String::from("k"),
422 JsonValue::String(String::from("a\nb\"c\\\u{01}")),
423 );
424 let value = JsonValue::Object(object);
425 assert_eq!(to_compact_string(&value), r#"{"k":"a\nb\"c\\\u0001"}"#);
426 }
427
428 #[test]
429 fn object_insert_replaces_in_place() {
430 let mut object = JsonObject::new();
431 assert!(object
432 .insert(String::from("a"), JsonValue::Bool(true))
433 .is_none());
434 let old = object.insert(String::from("a"), JsonValue::Bool(false));
435 assert_eq!(old, Some(JsonValue::Bool(true)));
436 assert_eq!(object.len(), 1);
437 }
438
439 #[test]
440 fn deeply_nested_within_limits_does_not_overflow() {
441 let depth = 64;
443 let mut s = String::new();
444 for _ in 0..depth {
445 s.push('[');
446 }
447 s.push('1');
448 for _ in 0..depth {
449 s.push(']');
450 }
451 let _ = parse_str(&s); assert!(parse_with_limits(s.as_bytes(), JsonLimits::new().with_max_depth(64)).is_ok());
454 }
455
456 #[test]
457 fn arbitrary_bytes_never_panic() {
458 for input in [
460 &b""[..],
461 b" ",
462 b"{",
463 b"[",
464 b"\"",
465 b"\"\\",
466 b"\"\\u",
467 b"tru",
468 b"-",
469 b"[,]",
470 b"{,}",
471 b"\xff\xfe",
472 b"[[[",
473 b"}}}",
474 b"\"\\uD800\"",
475 b"1e",
476 b"{\"a\"}",
477 ] {
478 let _ = parse(input);
479 }
480 }
481
482 #[test]
483 fn json_test_suite_conformance() {
484 let must_accept: &[&[u8]] = &[
487 b"[]",
488 b"{}",
489 b"[1]",
490 b"[1,2,3]",
491 b"{\"a\":1}",
492 b"{\"a\":1,\"b\":2}",
493 b"[null,true,false]",
494 b"\"\\u0061\"",
495 b"\"\\uD834\\uDD1E\"", b"0",
497 b"-0",
498 b"123",
499 b"-123",
500 b"1.5",
501 b"1E10",
502 b"1e-10",
503 b"-1.2e+3",
504 b" 7 ",
505 b"\"abc\"",
506 b"true",
507 b"[[[[1]]]]",
508 b"{\"a\":{\"b\":[1,{\"c\":null}]}}",
509 ];
510 let must_reject: &[&[u8]] = &[
511 b"",
512 b"[1,]",
513 b"{\"a\":1,}",
514 b"[1 2]",
515 b"{\"a\" 1}",
516 b"{\"a\":1 \"b\":2}",
517 b"[1,,2]",
518 b"01",
519 b"1.",
520 b".1",
521 b"+1",
522 b"1e",
523 b"1e+",
524 b"0x1",
525 b"--1",
526 b"NaN",
527 b"Infinity",
528 b"[",
529 b"]",
530 b"{",
531 b"}",
532 b"\"",
533 b"\"\\x\"",
534 b"\"\\uZZZZ\"",
535 b"\"\x01\"", b"'single'",
537 b"1 1", b"tru",
539 b"nul",
540 b"\xEF\xBB\xBF1", b"\xff\xfe", b"\"\\uD800\"", b"/* comment */ 1",
544 b"{1:2}", ];
546 for input in must_accept {
547 assert!(parse(input).is_ok(), "should accept {input:?}");
548 }
549 for input in must_reject {
550 assert!(parse(input).is_err(), "should reject {input:?}");
551 }
552 }
553
554 #[test]
555 fn fuzz_parse_is_panic_free_and_roundtrips() {
556 let mut state: u64 = 0xD1B5_4A32_D192_ED03;
559 let mut next = || {
560 state ^= state << 13;
561 state ^= state >> 7;
562 state ^= state << 17;
563 state
564 };
565 let alphabet = b"{}[]\":,0123456789-+.eEtruefalsn \t\n\\/u";
567 let mut buf: Vec<u8> = Vec::new();
568 for _ in 0..40_000 {
569 buf.clear();
570 let len = (next() % 40) as usize;
571 for _ in 0..len {
572 let r = next();
573 let byte = if r & 7 == 0 {
574 (r >> 8) as u8 } else {
576 alphabet[((r >> 8) as usize) % alphabet.len()]
577 };
578 buf.push(byte);
579 }
580 if let Ok(value) = parse(&buf) {
581 let compact = to_compact_string(&value);
582 let reparsed = parse_str(&compact).expect("compact output must reparse");
583 assert_eq!(reparsed, value);
584 assert_eq!(to_compact_string(&reparsed), compact);
585
586 #[cfg(feature = "canonical")]
588 if let Ok(canonical) = to_canonical_string(&value) {
589 let again = parse_str(&canonical).expect("canonical output must reparse");
590 assert_eq!(to_canonical_string(&again).unwrap(), canonical);
591 }
592 }
593 }
594 }
595
596 #[test]
597 fn value_accessors_return_inner_or_none() {
598 let v = parse_ok(r#"{"b":true,"n":7,"s":"x","a":[1],"nil":null}"#);
599 let o = v.as_object().expect("object");
600 assert!(o.get("nil").unwrap().is_null());
601 assert_eq!(o.get("b").unwrap().as_bool(), Some(true));
602 assert_eq!(o.get("s").unwrap().as_str(), Some("x"));
603 assert_eq!(o.get("n").unwrap().as_number().unwrap().as_str(), "7");
604 assert_eq!(o.get("a").unwrap().as_array().unwrap().len(), 1);
605
606 let b = JsonValue::Bool(true);
608 assert!(!b.is_null());
609 assert_eq!(b.as_str(), None);
610 assert_eq!(b.as_number(), None);
611 assert_eq!(b.as_array(), None);
612 assert!(b.as_object().is_none());
613 assert_eq!(JsonValue::Null.as_bool(), None);
614 }
615
616 #[test]
617 fn object_insert_get_iter_and_len() {
618 let mut obj = JsonObject::new();
619 assert!(obj.is_empty());
620 assert_eq!(obj.len(), 0);
621 assert!(!obj.contains_key("k"));
622
623 assert_eq!(obj.insert("k".to_string(), JsonValue::Bool(false)), None);
624 assert!(obj.contains_key("k"));
625 assert_eq!(obj.len(), 1);
626
627 let old = obj.insert("k".to_string(), JsonValue::Bool(true));
629 assert_eq!(old, Some(JsonValue::Bool(false)));
630 assert_eq!(obj.len(), 1);
631 assert_eq!(obj.get("k"), Some(&JsonValue::Bool(true)));
632 assert_eq!(obj.get("missing"), None);
633
634 obj.insert("k2".to_string(), JsonValue::Null);
635 let members: Vec<&str> = obj.iter().map(|m| m.key()).collect();
636 assert_eq!(members, ["k", "k2"]);
637 assert_eq!(obj.iter().next().unwrap().value(), &JsonValue::Bool(true));
638
639 assert_eq!(JsonObject::default().len(), 0);
640 }
641
642 #[test]
643 fn number_conversions_cover_each_error() {
644 let int = JsonNumber::new("42").unwrap();
645 assert!(int.is_integer());
646 assert_eq!(int.to_i64(), Ok(42));
647 assert_eq!(int.to_u64(), Ok(42));
648 assert_eq!(int.to_f64(), Ok(42.0));
649
650 let neg = JsonNumber::new("-1").unwrap();
651 assert_eq!(neg.to_u64(), Err(JsonNumberError::OutOfRange));
652
653 let frac = JsonNumber::new("1.5").unwrap();
654 assert!(!frac.is_integer());
655 assert_eq!(frac.to_i64(), Err(JsonNumberError::NotAnInteger));
656 assert_eq!(frac.to_u64(), Err(JsonNumberError::NotAnInteger));
657 assert_eq!(frac.to_f64(), Ok(1.5));
658
659 let huge = JsonNumber::new("99999999999999999999").unwrap();
660 assert_eq!(huge.to_i64(), Err(JsonNumberError::OutOfRange));
661
662 let overflow = JsonNumber::new("1e400").unwrap();
663 assert_eq!(overflow.to_f64(), Err(JsonNumberError::NotFinite));
664
665 assert_eq!(JsonNumber::new("+1"), Err(JsonNumberError::InvalidNumber));
666 assert_eq!(JsonNumber::try_from_f64(2.5).unwrap().to_f64(), Ok(2.5));
667 assert_eq!(
668 JsonNumber::try_from_f64(f64::NAN),
669 Err(JsonNumberError::NotFinite)
670 );
671 assert_eq!(
672 JsonNumber::try_from_f64(f64::INFINITY),
673 Err(JsonNumberError::NotFinite)
674 );
675 }
676
677 #[test]
678 fn limits_profiles_and_builders() {
679 assert_eq!(JsonLimits::default(), JsonLimits::new());
680 assert!(JsonLimits::conservative().max_input_bytes() < JsonLimits::new().max_input_bytes());
681 assert!(JsonLimits::permissive().max_input_bytes() > JsonLimits::new().max_input_bytes());
682
683 let tuned = JsonLimits::new()
684 .with_max_depth(8)
685 .with_max_input_bytes(1024)
686 .with_max_string_bytes(16)
687 .with_max_key_bytes(12)
688 .with_max_number_bytes(6)
689 .with_max_array_items(20)
690 .with_max_object_members(24)
691 .with_max_total_nodes(32)
692 .with_max_total_decoded_string_bytes(2048);
693 assert_eq!(tuned.max_depth(), 8);
694 assert_eq!(tuned.max_input_bytes(), 1024);
695 assert_eq!(tuned.max_string_bytes(), 16);
696 assert_eq!(tuned.max_key_bytes(), 12);
697 assert_eq!(tuned.max_number_bytes(), 6);
698 assert_eq!(tuned.max_array_items(), 20);
699 assert_eq!(tuned.max_object_members(), 24);
700 assert_eq!(tuned.max_total_nodes(), 32);
701 assert_eq!(tuned.max_total_decoded_string_bytes(), 2048);
702 }
703
704 #[test]
705 fn error_display_covers_each_kind() {
706 let cases: &[(&str, &str)] = &[
708 ("", "unexpected end of input"),
709 ("@", "unexpected byte"),
710 ("\"a\\xb\"", "invalid escape sequence"),
711 ("\"\\uZZZZ\"", "invalid unicode escape"),
712 ("\"\\uD800\"", "unpaired UTF-16 surrogate"),
713 ("01", "invalid number"),
714 ("{\"a\":1,\"a\":2}", "duplicate object key"),
715 ("true false", "trailing data after JSON value"),
716 ];
717 for (input, expected) in cases {
718 let err = parse_str(input).unwrap_err();
719 assert!(
720 err.to_string().contains(expected),
721 "input {input:?} -> {err} (expected to contain {expected:?})"
722 );
723 }
724
725 let ctrl = parse(b"\"\x01\"").unwrap_err();
727 assert!(ctrl.to_string().contains("unescaped control character"));
728
729 let utf8 = parse(b"\xff").unwrap_err();
731 assert!(utf8.to_string().contains("invalid UTF-8"));
732 }
733
734 #[test]
735 fn error_accessors_and_limit_display_with_path() {
736 let limits = JsonLimits::new().with_max_depth(1);
737 let err = parse_with_limits(b"[[1]]", limits).unwrap_err();
738 assert_eq!(
739 err.kind(),
740 &JsonErrorKind::LimitExceeded(JsonLimitKind::Depth)
741 );
742 assert!(err.offset() >= 1);
743 assert_eq!(err.line(), 1);
744 assert!(err.column() >= 1);
745 let shown = err.to_string();
746 assert!(shown.contains("limit exceeded: nesting depth"));
747 assert!(shown.contains("path: $"));
748 assert_eq!(JsonLimitKind::Depth.as_str(), "nesting depth");
749 }
750
751 #[test]
752 fn path_display_formats_keys_and_indices() {
753 let path = JsonPath::from_segments(vec![
754 JsonPathSegment::Key("users".to_string()),
755 JsonPathSegment::Index(3),
756 JsonPathSegment::Key("email".to_string()),
757 ]);
758 assert_eq!(path.to_string(), "$.users[3].email");
759 assert_eq!(path.segments().len(), 3);
760 assert_eq!(JsonPath::default().to_string(), "$");
761 }
762
763 #[test]
764 fn number_error_display_is_distinct() {
765 assert_eq!(
766 JsonNumberError::OutOfRange.to_string(),
767 "number out of range for target type"
768 );
769 assert_eq!(
770 JsonNumberError::NotAnInteger.to_string(),
771 "number is not an integer"
772 );
773 assert_eq!(
774 JsonNumberError::NotFinite.to_string(),
775 "number is not finite"
776 );
777 assert_eq!(
778 JsonNumberError::InvalidNumber.to_string(),
779 "not a valid JSON number"
780 );
781 }
782
783 #[test]
784 fn writer_serializes_all_branches() {
785 let mut obj = JsonObject::new();
786 obj.insert("off".to_string(), JsonValue::Bool(false));
787 obj.insert(
788 "esc".to_string(),
789 JsonValue::String("\u{08}\u{0C}\n\r\t\u{1F}".to_string()),
791 );
792 obj.insert(
793 "arr".to_string(),
794 JsonValue::Array(vec![JsonValue::Null, JsonValue::Bool(true)]),
795 );
796 let value = JsonValue::Object(obj);
797
798 let s = to_compact_string(&value);
799 assert_eq!(parse_str(&s).unwrap(), value);
802 assert_eq!(to_compact_vec(&value), s.clone().into_bytes());
803 assert!(s.starts_with("{\"off\":false,"));
804 assert!(s.ends_with(",\"arr\":[null,true]}"));
805 }
806
807 #[cfg(feature = "std")]
808 #[test]
809 fn errors_implement_std_error() {
810 fn assert_error<E: std::error::Error>(_: &E) {}
811 let parse_err = parse_str("").unwrap_err();
812 assert_error(&parse_err);
813 let num_err = JsonNumber::new("1.5").unwrap().to_i64().unwrap_err();
814 assert_error(&num_err);
815 }
816}