1#![cfg_attr(not(feature = "std"), no_std)]
2
3#![allow(unsafe_code)]
104
105#[cfg(feature = "alloc")]
106extern crate alloc;
107
108mod de;
109mod error;
110mod event;
111#[cfg(feature = "alloc")]
112mod float;
113mod lexer;
114mod parser;
115mod ser;
116#[cfg(all(test, feature = "std"))]
117mod teju_gen;
118
119pub use de::{FromJson, parse, parse_str};
120#[cfg(feature = "alloc")]
121pub use de::{MapKey, key_to_cow};
122pub use error::{Error, ErrorKind, LineColumn, Position};
123pub use event::{Event, JsonNum, JsonStr, MAX_INPUT_LEN};
124pub use lexer::{Checkpoint, DEFAULT_MAX_DEPTH, Lexer, ValueKind};
125pub use parser::Parser;
126#[cfg(feature = "alloc")]
127pub use ser::{
128 ByteSink, FmtWriteSink, MapKeyOut, PrettyStringSink, StringSink, to_fmt, to_string,
129 to_string_pretty, to_vec,
130};
131#[cfg(feature = "std")]
132pub use ser::{IoWriteSink, to_writer};
133pub use ser::{JsonWrite, ToJson};
134
135mod macros;
136
137#[cfg(all(test, feature = "std"))]
138mod tests {
139 use super::*;
140
141 #[test]
149 fn object_first_key_then_next_event_for_value() {
150 let mut p: Parser<'_> = Parser::new(br#"{"flag":true}"#);
151 let start = p.next_event().unwrap().unwrap();
152 assert!(matches!(start, Event::StartObject));
153
154 let key = p.object_first_key().unwrap().unwrap();
156 assert_eq!(key, "flag");
157
158 let val = p.next_event().unwrap().unwrap();
160 assert_eq!(val, Event::Bool(true));
161
162 let close = p.next_event().unwrap().unwrap();
164 assert!(matches!(close, Event::EndObject));
165 assert!(p.next_event().unwrap().is_none());
166 }
167
168 #[test]
171 fn object_next_key_handoff_to_next_event() {
172 let mut p: Parser<'_> = Parser::new(br#"{"a":1,"b":true}"#);
173 let _ = p.next_event().unwrap().unwrap(); let k1 = p.object_first_key().unwrap().unwrap();
176 assert_eq!(k1, "a");
177 let v1 = p.parse_i64_value().unwrap();
178 assert_eq!(v1, 1);
179
180 let k2 = p.object_next_key().unwrap().unwrap();
181 assert_eq!(k2, "b");
182 let v2 = p.next_event().unwrap().unwrap();
183 assert_eq!(v2, Event::Bool(true));
184
185 assert!(p.object_next_key().unwrap().is_none());
186 assert!(p.next_event().unwrap().is_none());
187 }
188
189 #[test]
190 fn primitives_round_through_typed_parse() {
191 assert!(parse_str::<bool>("true").unwrap());
192 assert!(!parse_str::<bool>("false").unwrap());
193 assert_eq!(parse_str::<i32>("-7").unwrap(), -7);
194 assert_eq!(parse_str::<u64>("9999999999").unwrap(), 9_999_999_999);
195 let f: f64 = parse_str("1.5e2").unwrap();
196 assert!((f - 150.0).abs() < f64::EPSILON);
197 assert_eq!(parse_str::<&str>("\"hello\"").unwrap(), "hello");
198 }
199
200 #[test]
201 fn integer_overflow_is_rejected_at_parse_site() {
202 let r = parse_str::<u8>("256");
203 assert_eq!(r.unwrap_err().kind, ErrorKind::NumberOutOfRange);
204 }
205
206 #[test]
207 fn type_mismatch_is_rejected_at_parse_site() {
208 let r = parse_str::<u32>("\"five\"");
209 assert_eq!(r.unwrap_err().kind, ErrorKind::ExpectedNumber);
210 }
211
212 #[test]
213 fn option_handles_null_and_value() {
214 let none: Option<u32> = parse_str("null").unwrap();
215 assert_eq!(none, None);
216 let some: Option<u32> = parse_str("17").unwrap();
217 assert_eq!(some, Some(17));
218 }
219
220 #[test]
221 fn fixed_array_exact_length() {
222 let arr: [i32; 3] = parse_str("[1,2,3]").unwrap();
223 assert_eq!(arr, [1, 2, 3]);
224 }
225
226 #[test]
227 fn fixed_array_too_short_errors() {
228 let r = parse_str::<[i32; 3]>("[1,2]");
229 assert!(r.is_err());
230 }
231
232 #[test]
233 fn fixed_array_too_long_errors() {
234 let r = parse_str::<[i32; 3]>("[1,2,3,4]");
235 assert!(r.is_err());
236 }
237
238 #[test]
239 fn tuple_heterogeneous() {
240 let v: (i32, &str, bool) = parse_str(r#"[1, "hi", true]"#).unwrap();
241 assert_eq!(v, (1, "hi", true));
242 }
243
244 #[test]
245 fn borrowed_str_lifetime() {
246 let input = String::from(r#""borrowed""#);
247 let s: &str = parse_str(&input).unwrap();
248 assert_eq!(s, "borrowed");
249 }
250
251 #[test]
252 fn rejects_trailing_data_at_typed_layer() {
253 let r = parse_str::<u32>("1 2");
254 assert!(r.is_err());
255 }
256
257 #[cfg(feature = "std")]
263 #[test]
264 fn duration_round_trips_fractional_seconds() {
265 use std::time::Duration;
266 let d: Duration = parse_str("1.5").unwrap();
267 assert_eq!(d, Duration::new(1, 500_000_000));
268 let d: Duration = parse_str("0").unwrap();
269 assert_eq!(d, Duration::ZERO);
270 assert!(parse_str::<Duration>("-1").is_err());
272 }
273
274 #[cfg(feature = "std")]
275 #[test]
276 fn system_time_round_trips_around_epoch() {
277 use std::time::{Duration, SystemTime, UNIX_EPOCH};
278 let t: SystemTime = parse_str("0").unwrap();
280 assert_eq!(t, UNIX_EPOCH);
281 let t: SystemTime = parse_str("1.5").unwrap();
283 assert_eq!(t, UNIX_EPOCH + Duration::new(1, 500_000_000));
284 let t: SystemTime = parse_str("-2").unwrap();
287 assert_eq!(t, UNIX_EPOCH - Duration::from_secs(2));
288 let s = to_string(&(UNIX_EPOCH + Duration::from_secs(42))).unwrap();
290 let back: SystemTime = parse_str(&s).unwrap();
291 assert_eq!(back, UNIX_EPOCH + Duration::from_secs(42));
292 }
293
294 #[cfg(feature = "std")]
295 #[test]
296 fn ip_and_socket_addrs_parse_from_strings() {
297 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
298 let v4: Ipv4Addr = parse_str(r#""127.0.0.1""#).unwrap();
299 assert_eq!(v4, Ipv4Addr::LOCALHOST);
300 let v6: Ipv6Addr = parse_str(r#""::1""#).unwrap();
301 assert_eq!(v6, Ipv6Addr::LOCALHOST);
302 let ip: IpAddr = parse_str(r#""10.0.0.1""#).unwrap();
303 assert!(matches!(ip, IpAddr::V4(_)));
304 let sa: SocketAddr = parse_str(r#""127.0.0.1:8080""#).unwrap();
305 assert_eq!(sa.port(), 8080);
306 assert!(parse_str::<Ipv4Addr>(r#""not-an-ip""#).is_err());
308 }
309
310 #[cfg(feature = "std")]
311 #[test]
312 fn pathbuf_parses_from_string() {
313 use std::path::PathBuf;
314 let p: PathBuf = parse_str(r#""/etc/hosts""#).unwrap();
315 assert_eq!(p, PathBuf::from("/etc/hosts"));
316 }
317
318 #[cfg(feature = "std")]
319 #[test]
320 fn hashmap_string_key() {
321 use std::collections::HashMap;
322 let m: HashMap<String, i32> = parse_str(r#"{"a":1,"b":2}"#).unwrap();
323 assert_eq!(m.get("a"), Some(&1));
324 assert_eq!(m.get("b"), Some(&2));
325 assert_eq!(m.len(), 2);
326 }
327
328 #[cfg(feature = "std")]
329 #[test]
330 fn hashmap_borrowed_key_zero_copy() {
331 use std::collections::HashMap;
332 let input = String::from(r#"{"alpha":1,"beta":2}"#);
333 let m: HashMap<&str, i32> = parse_str(&input).unwrap();
334 let input_start = input.as_ptr() as usize;
336 let input_end = input_start + input.len();
337 for k in m.keys() {
338 let p = k.as_ptr() as usize;
339 assert!((input_start..input_end).contains(&p), "key was copied");
340 }
341 }
342
343 #[cfg(feature = "alloc")]
344 #[test]
345 fn btreemap_round_trips() {
346 use std::collections::BTreeMap;
347 let m: BTreeMap<String, Vec<i32>> = parse_str(r#"{"x":[1,2],"y":[3]}"#).unwrap();
348 assert_eq!(m["x"], vec![1, 2]);
349 assert_eq!(m["y"], vec![3]);
350 }
351
352 #[cfg(feature = "std")]
353 #[test]
354 fn map_rejects_duplicate_key() {
355 use std::collections::HashMap;
356 let r: Result<HashMap<String, i32>, _> = parse_str(r#"{"a":1,"a":2}"#);
357 assert_eq!(r.unwrap_err().kind, ErrorKind::DuplicateKey);
358 }
359
360 #[cfg(feature = "std")]
361 #[test]
362 fn map_rejects_non_object() {
363 use std::collections::HashMap;
364 let r: Result<HashMap<String, i32>, _> = parse_str("[1,2]");
365 assert!(r.is_err());
366 }
367
368 #[cfg(feature = "std")]
369 #[test]
370 fn hashset_round_trips() {
371 use std::collections::HashSet;
372 let s: HashSet<i32> = parse_str("[1,2,3,2,1]").unwrap();
373 assert_eq!(s.len(), 3);
374 assert!(s.contains(&1));
375 assert!(s.contains(&2));
376 assert!(s.contains(&3));
377 }
378
379 #[cfg(feature = "alloc")]
380 #[test]
381 fn btreeset_round_trips() {
382 use std::collections::BTreeSet;
383 let s: BTreeSet<i32> = parse_str("[3,1,2]").unwrap();
384 assert_eq!(s.into_iter().collect::<Vec<_>>(), vec![1, 2, 3]);
385 }
386
387 #[cfg(feature = "alloc")]
388 #[test]
389 fn box_rc_arc_are_transparent_wrappers() {
390 let b: Box<u32> = parse_str("42").unwrap();
391 assert_eq!(*b, 42);
392 let r: std::rc::Rc<&str> = parse_str(r#""hello""#).unwrap();
393 assert_eq!(*r, "hello");
394 let a: std::sync::Arc<Vec<i32>> = parse_str("[1,2,3]").unwrap();
395 assert_eq!(*a, vec![1, 2, 3]);
396 }
397
398 #[cfg(feature = "alloc")]
399 #[test]
400 fn char_accepts_single_scalar() {
401 assert_eq!(parse_str::<char>(r#""a""#).unwrap(), 'a');
402 assert_eq!(parse_str::<char>(r#""中""#).unwrap(), '中');
403 assert_eq!(parse_str::<char>(r#""\n""#).unwrap(), '\n');
405 assert_eq!(parse_str::<char>(r#""😀""#).unwrap(), '😀');
407 }
408
409 #[cfg(feature = "alloc")]
410 #[test]
411 #[allow(clippy::unicode_not_nfc)] fn char_rejects_empty_or_multiple() {
413 assert!(parse_str::<char>(r#""""#).is_err());
414 assert!(parse_str::<char>(r#""ab""#).is_err());
415 assert!(parse_str::<char>(r#""é""#).is_err());
419 assert!(parse_str::<char>("42").is_err());
421 }
422
423 #[test]
424 fn i128_round_trips_full_range() {
425 assert_eq!(parse_str::<i128>("0").unwrap(), 0);
426 assert_eq!(
427 parse_str::<i128>("170141183460469231731687303715884105727").unwrap(),
428 i128::MAX,
429 );
430 assert_eq!(
431 parse_str::<i128>("-170141183460469231731687303715884105728").unwrap(),
432 i128::MIN,
433 );
434 assert!(parse_str::<i128>("170141183460469231731687303715884105728").is_err());
435 }
436
437 #[test]
438 fn u128_round_trips_full_range() {
439 assert_eq!(parse_str::<u128>("0").unwrap(), 0);
440 assert_eq!(
441 parse_str::<u128>("340282366920938463463374607431768211455").unwrap(),
442 u128::MAX,
443 );
444 assert!(parse_str::<u128>("340282366920938463463374607431768211456").is_err());
445 assert!(parse_str::<u128>("-1").is_err());
447 }
448
449 #[test]
456 fn i128_38_vs_39_digit_boundary() {
457 let thirty_eight_nines = "9".repeat(38);
459 let v: i128 = parse_str(&thirty_eight_nines).unwrap();
460 assert_eq!(v.to_string(), thirty_eight_nines);
461
462 let ten_pow_38 = format!("1{}", "0".repeat(38));
464 let v: i128 = parse_str(&ten_pow_38).unwrap();
465 assert_eq!(v.to_string(), ten_pow_38);
466
467 let thirty_nine_nines = "9".repeat(39);
469 assert!(parse_str::<i128>(&thirty_nine_nines).is_err());
470 }
471
472 #[test]
473 fn vec_i128_round_trips() {
474 let v: Vec<i128> = parse_str(
476 "[0,1,-1,170141183460469231731687303715884105727,-170141183460469231731687303715884105728]",
477 )
478 .unwrap();
479 assert_eq!(v, vec![0, 1, -1, i128::MAX, i128::MIN]);
480 }
481
482 #[test]
483 fn vec_u128_round_trips() {
484 let v: Vec<u128> = parse_str("[0,1,2,340282366920938463463374607431768211455]").unwrap();
485 assert_eq!(v, vec![0, 1, 2, u128::MAX]);
486 }
487
488 #[test]
495 fn f32_rejects_overflow_to_infinity() {
496 let r = parse_str::<f32>("1e40");
499 assert_eq!(r.unwrap_err().kind, ErrorKind::NumberOutOfRange);
500 let r = parse_str::<f32>("-1e40");
501 assert_eq!(r.unwrap_err().kind, ErrorKind::NumberOutOfRange);
502 let v: f32 = parse_str("3.4028235e38").unwrap();
504 assert!(v.is_finite());
505 }
506
507 #[test]
508 fn f64_rejects_overflow_to_infinity() {
509 let r = parse_str::<f64>("1e400");
510 assert_eq!(r.unwrap_err().kind, ErrorKind::NumberOutOfRange);
511 let r = parse_str::<f64>("-1e400");
512 assert_eq!(r.unwrap_err().kind, ErrorKind::NumberOutOfRange);
513 }
514
515 #[test]
516 fn i64_min_is_parseable() {
517 assert_eq!(parse_str::<i64>("-9223372036854775808").unwrap(), i64::MIN);
518 assert_eq!(
519 parse_str::<i64>("-9223372036854775807").unwrap(),
520 i64::MIN + 1,
521 );
522 assert_eq!(parse_str::<i64>("9223372036854775807").unwrap(), i64::MAX);
523 assert!(parse_str::<i64>("-9223372036854775809").is_err());
525 assert!(parse_str::<i64>("9223372036854775808").is_err());
527 let v: Vec<i64> = parse_str("[-9223372036854775808]").unwrap();
529 assert_eq!(v, vec![i64::MIN]);
530 }
531
532 #[cfg(feature = "alloc")]
533 #[test]
534 fn vec_and_string() {
535 let v: Vec<i32> = parse_str("[10, 20, 30]").unwrap();
536 assert_eq!(v, vec![10, 20, 30]);
537 let s: String = parse_str(r#""owned""#).unwrap();
538 assert_eq!(s, "owned");
539 }
540
541 #[cfg(feature = "alloc")]
542 #[test]
543 fn nested_vec() {
544 let v: Vec<Vec<i32>> = parse_str("[[1,2],[3]]").unwrap();
545 assert_eq!(v, vec![vec![1, 2], vec![3]]);
546 }
547
548 #[cfg(feature = "alloc")]
553 #[test]
554 fn string_decodes_simple_escapes() {
555 let s: String = parse_str(r#""line1\nline2\ttab\"quote\\back\/slash""#).unwrap();
556 assert_eq!(s, "line1\nline2\ttab\"quote\\back/slash");
557 }
558
559 #[cfg(feature = "alloc")]
560 #[test]
561 fn string_decodes_b_and_f_escapes() {
562 let s: String = parse_str(r#""\b\f""#).unwrap();
564 assert_eq!(s, "\u{0008}\u{000C}");
565 }
566
567 #[cfg(feature = "alloc")]
568 #[test]
569 fn string_decodes_unicode_bmp_escape() {
570 let s: String = parse_str(r#""café 中文 ~""#).unwrap();
573 assert_eq!(s, "café 中文 ~");
574 }
575
576 #[cfg(feature = "alloc")]
577 #[test]
578 fn string_decodes_surrogate_pair() {
579 let s: String = parse_str(r#""hi 😀 there""#).unwrap();
582 assert_eq!(s, "hi 😀 there");
583 }
584
585 #[cfg(feature = "alloc")]
586 #[test]
587 fn string_rejects_lone_surrogate() {
588 let r = parse_str::<String>(r#""\uD800""#);
589 assert_eq!(r.unwrap_err().kind, ErrorKind::UnpairedSurrogate);
590 let r = parse_str::<String>(r#""\uDC00""#);
591 assert_eq!(r.unwrap_err().kind, ErrorKind::UnpairedSurrogate);
592 }
593
594 #[cfg(feature = "alloc")]
595 #[test]
596 fn string_rejects_high_surrogate_then_non_low() {
597 let r = parse_str::<String>(r#""\uD800A""#);
599 assert_eq!(r.unwrap_err().kind, ErrorKind::UnpairedSurrogate);
600 }
601
602 #[cfg(feature = "alloc")]
603 #[test]
604 fn string_decodes_long_mixed_input() {
605 let json = r#""one\ttwo\nthreeAfour\\five\"six""#;
609 let s: String = parse_str(json).unwrap();
610 assert_eq!(s, "one\ttwo\nthreeAfour\\five\"six");
611 }
612
613 #[cfg(feature = "alloc")]
614 #[test]
615 fn vec_string_with_escapes_roundtrips() {
616 let json = r#"["","a","\n","mixéd","\\\"\/"]"#;
620 let v: Vec<String> = parse_str(json).unwrap();
621 assert_eq!(v, vec!["", "a", "\n", "mixéd", "\\\"/"]);
622 }
623
624 #[cfg(feature = "alloc")]
625 #[test]
626 fn cow_borrows_when_no_escapes() {
627 use std::borrow::Cow;
628 let input = String::from(r#""borrowed""#);
629 let c: Cow<'_, str> = parse_str(&input).unwrap();
630 assert_eq!(c, "borrowed");
631 match c {
634 Cow::Borrowed(s) => {
635 let input_start = input.as_ptr() as usize;
636 let input_end = input_start + input.len();
637 let s_ptr = s.as_ptr() as usize;
638 assert!(
639 (input_start..input_end).contains(&s_ptr),
640 "Cow::Borrowed pointer should be inside input",
641 );
642 }
643 Cow::Owned(_) => panic!("expected Borrowed for un-escaped input"),
644 }
645 }
646
647 #[cfg(feature = "alloc")]
648 #[test]
649 fn cow_owns_when_escapes_present() {
650 use std::borrow::Cow;
651 let c: Cow<'_, str> = parse_str(r#""line\nwrap""#).unwrap();
652 assert_eq!(c, "line\nwrap");
653 assert!(matches!(c, Cow::Owned(_)));
654 }
655
656 #[test]
661 fn parser_object_key_lex_with_escapes() {
662 let input = br#"{"a\nb":1,"c":2}"#;
663 let mut p: Parser<'_> = Parser::new(input);
664 assert!(matches!(
665 p.next_event().unwrap().unwrap(),
666 Event::StartObject
667 ));
668 let k1 = p.object_first_key_lex().unwrap().unwrap();
669 assert!(k1.has_escapes());
670 assert_eq!(p.parse_i64_value().unwrap(), 1);
671 let k2 = p.object_next_key_lex().unwrap().unwrap();
672 assert!(!k2.has_escapes());
673 assert_eq!(p.parse_i64_value().unwrap(), 2);
674 assert!(p.object_next_key_lex().unwrap().is_none());
675 assert!(p.next_event().unwrap().is_none());
676 }
677
678 #[test]
679 fn parser_object_key_lex_empty() {
680 let mut p: Parser<'_> = Parser::new(b"{}");
681 assert!(matches!(
682 p.next_event().unwrap().unwrap(),
683 Event::StartObject
684 ));
685 assert!(p.object_first_key_lex().unwrap().is_none());
686 assert!(p.next_event().unwrap().is_none());
687 }
688
689 #[test]
694 fn parser_array_start_continue() {
695 let mut p: Parser<'_> = Parser::new(b"[1,2,3]");
696 assert!(!p.array_start().unwrap());
697 assert_eq!(p.parse_i64_value().unwrap(), 1);
698 assert!(!p.array_continue(b']').unwrap());
699 assert_eq!(p.parse_i64_value().unwrap(), 2);
700 assert!(!p.array_continue(b']').unwrap());
701 assert_eq!(p.parse_i64_value().unwrap(), 3);
702 assert!(p.array_continue(b']').unwrap());
703 assert!(p.next_event().unwrap().is_none());
704 }
705
706 #[test]
707 fn parser_array_start_empty() {
708 let mut p: Parser<'_> = Parser::new(b"[]");
709 assert!(p.array_start().unwrap());
710 assert!(p.next_event().unwrap().is_none());
711 }
712
713 #[test]
714 fn parser_array_nested_in_object() {
715 let mut p: Parser<'_> = Parser::new(br#"{"v":[1,2]}"#);
716 assert!(matches!(
717 p.next_event().unwrap().unwrap(),
718 Event::StartObject
719 ));
720 let key = p.object_first_key().unwrap().unwrap();
721 assert_eq!(key, "v");
722 assert!(!p.array_start().unwrap());
723 assert_eq!(p.parse_i64_value().unwrap(), 1);
724 assert!(!p.array_continue(b']').unwrap());
725 assert_eq!(p.parse_i64_value().unwrap(), 2);
726 assert!(p.array_continue(b']').unwrap());
727 assert!(p.object_next_key().unwrap().is_none());
728 assert!(p.next_event().unwrap().is_none());
729 }
730
731 #[test]
736 fn error_kind_display_covers_all_variants() {
737 use alloc::format;
738 let cases: &[(ErrorKind, &str)] = &[
739 (ErrorKind::UnexpectedEof, "unexpected end of input"),
740 (ErrorKind::InvalidEscape, "invalid string escape"),
741 (ErrorKind::InvalidUnicodeEscape, "invalid \\u escape"),
742 (
743 ErrorKind::UnpairedSurrogate,
744 "unpaired UTF-16 surrogate in \\u escape",
745 ),
746 (ErrorKind::InvalidUtf8, "invalid UTF-8"),
747 (ErrorKind::InvalidNumber, "invalid number literal"),
748 (
749 ErrorKind::NumberOutOfRange,
750 "number does not fit target type",
751 ),
752 (
753 ErrorKind::ControlCharInString,
754 "control character in string literal",
755 ),
756 (ErrorKind::TrailingData, "trailing data after JSON value"),
757 (
758 ErrorKind::DepthLimitExceeded,
759 "nesting depth limit exceeded",
760 ),
761 (ErrorKind::ExpectedValue, "expected JSON value"),
762 (ErrorKind::ExpectedString, "expected string"),
763 (ErrorKind::ExpectedNumber, "expected number"),
764 (ErrorKind::ExpectedBool, "expected boolean"),
765 (ErrorKind::ExpectedNull, "expected null"),
766 (ErrorKind::ExpectedArray, "expected array"),
767 (ErrorKind::ExpectedObject, "expected object"),
768 (ErrorKind::TypeMismatch, "type mismatch"),
769 (ErrorKind::DuplicateKey, "duplicate object key"),
770 (ErrorKind::MissingField, "missing required field"),
771 (ErrorKind::UnknownField, "unknown field"),
772 (
773 ErrorKind::NonFiniteFloat,
774 "non-finite float not representable in JSON",
775 ),
776 (ErrorKind::UnexpectedByte(0x7B), "unexpected byte 0x7b"),
777 ];
778 for (kind, expected) in cases {
779 assert_eq!(format!("{kind}"), *expected, "mismatch for {kind:?}");
780 }
781 }
782
783 #[test]
788 fn utf8_f4_leading_byte_valid() {
789 let s = "\"\u{100000}\"";
790 let v: &str = parse_str(s).unwrap();
791 assert_eq!(v, "\u{100000}");
792 }
793
794 #[test]
795 fn utf8_f4_leading_byte_invalid_continuation() {
796 let mut bytes = b"\"".to_vec();
797 bytes.push(0xF4);
798 bytes.push(0x90); bytes.push(0x80);
800 bytes.push(0x80);
801 bytes.push(b'"');
802 let r = parse::<&str>(&bytes);
803 assert_eq!(r.unwrap_err().kind, ErrorKind::InvalidUtf8);
804 }
805
806 #[test]
807 fn utf8_multibyte_all_leading_ranges() {
808 let cases: &[&str] = &[
809 "\"\u{0080}\"", "\"\u{0800}\"", "\"\u{1000}\"", "\"\u{D7FF}\"", "\"\u{E000}\"", "\"\u{10000}\"", "\"\u{40000}\"", "\"\u{100000}\"", ];
818 for input in cases {
819 let v: &str = parse_str(input).unwrap();
820 let expected = &input[1..input.len() - 1];
821 assert_eq!(v, expected);
822 }
823 }
824
825 #[test]
830 fn serialize_all_control_bytes() {
831 for b in 0x00_u8..=0x1F {
832 let s = alloc::string::String::from(b as char);
833 let json = to_string(&s).unwrap();
834 assert!(json.starts_with('"') && json.ends_with('"'));
835 let inner = &json[1..json.len() - 1];
836 match b {
837 b'"' | b'\\' => unreachable!(),
838 b'\n' => assert_eq!(inner, "\\n"),
839 b'\r' => assert_eq!(inner, "\\r"),
840 b'\t' => assert_eq!(inner, "\\t"),
841 0x08 => assert_eq!(inner, "\\b"),
842 0x0C => assert_eq!(inner, "\\f"),
843 _ => {
844 let expected = alloc::format!("\\u00{b:02x}");
845 assert_eq!(inner, expected, "byte 0x{b:02x}");
846 }
847 }
848 }
849 }
850
851 #[test]
856 fn next_event_rejects_trailing_comma_in_array() {
857 let mut p: Parser<'_> = Parser::new(b"[1,]");
858 assert!(matches!(
859 p.next_event().unwrap().unwrap(),
860 Event::StartArray
861 ));
862 let _ = p.next_event().unwrap().unwrap(); let err = p.next_event().unwrap_err();
864 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b']'));
865 }
866
867 #[test]
868 fn next_event_rejects_trailing_comma_in_object() {
869 let mut p: Parser<'_> = Parser::new(br#"{"a":1,}"#);
870 assert!(matches!(
871 p.next_event().unwrap().unwrap(),
872 Event::StartObject
873 ));
874 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Key(_)));
875 let _ = p.next_event().unwrap().unwrap(); let err = p.next_event().unwrap_err();
877 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b'}'));
878 }
879
880 #[test]
881 fn next_event_object_colon_eof() {
882 let mut p: Parser<'_> = Parser::new(br#"{"a""#);
883 assert!(matches!(
884 p.next_event().unwrap().unwrap(),
885 Event::StartObject
886 ));
887 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Key(_)));
888 let err = p.next_event().unwrap_err();
889 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
890 }
891
892 #[test]
893 fn next_event_object_colon_wrong_byte() {
894 let mut p: Parser<'_> = Parser::new(br#"{"a";"#);
895 assert!(matches!(
896 p.next_event().unwrap().unwrap(),
897 Event::StartObject
898 ));
899 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Key(_)));
900 let err = p.next_event().unwrap_err();
901 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b';'));
902 }
903
904 #[test]
905 fn next_event_empty_input() {
906 let mut p: Parser<'_> = Parser::new(b"");
907 let err = p.next_event().unwrap_err();
908 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
909 }
910
911 #[test]
912 fn next_event_eof_inside_array() {
913 let mut p: Parser<'_> = Parser::new(b"[");
914 assert!(matches!(
915 p.next_event().unwrap().unwrap(),
916 Event::StartArray
917 ));
918 let err = p.next_event().unwrap_err();
919 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
920 }
921
922 #[test]
923 fn next_event_eof_after_array_comma() {
924 let mut p: Parser<'_> = Parser::new(b"[1,");
925 assert!(matches!(
926 p.next_event().unwrap().unwrap(),
927 Event::StartArray
928 ));
929 let _ = p.next_event().unwrap().unwrap(); let err = p.next_event().unwrap_err();
931 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
932 }
933
934 #[test]
935 fn next_event_bad_byte_after_array_value() {
936 let mut p: Parser<'_> = Parser::new(b"[1;");
937 assert!(matches!(
938 p.next_event().unwrap().unwrap(),
939 Event::StartArray
940 ));
941 let _ = p.next_event().unwrap().unwrap(); let err = p.next_event().unwrap_err();
943 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b';'));
944 }
945
946 #[test]
947 fn next_event_eof_in_object_key_position() {
948 let mut p: Parser<'_> = Parser::new(b"{");
949 assert!(matches!(
950 p.next_event().unwrap().unwrap(),
951 Event::StartObject
952 ));
953 let err = p.next_event().unwrap_err();
954 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
955 }
956
957 #[test]
958 fn next_event_bad_byte_in_object_key_position() {
959 let mut p: Parser<'_> = Parser::new(b"{1");
960 assert!(matches!(
961 p.next_event().unwrap().unwrap(),
962 Event::StartObject
963 ));
964 let err = p.next_event().unwrap_err();
965 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b'1'));
966 }
967
968 #[test]
969 fn next_event_eof_after_object_value() {
970 let mut p: Parser<'_> = Parser::new(br#"{"a":1"#);
971 assert!(matches!(
972 p.next_event().unwrap().unwrap(),
973 Event::StartObject
974 ));
975 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Key(_)));
976 let _ = p.next_event().unwrap().unwrap(); let err = p.next_event().unwrap_err();
978 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
979 }
980
981 #[test]
982 fn next_event_bad_byte_after_object_value() {
983 let mut p: Parser<'_> = Parser::new(br#"{"a":1;"#);
984 assert!(matches!(
985 p.next_event().unwrap().unwrap(),
986 Event::StartObject
987 ));
988 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Key(_)));
989 let _ = p.next_event().unwrap().unwrap(); let err = p.next_event().unwrap_err();
991 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b';'));
992 }
993
994 #[test]
995 fn next_event_object_value_state_via_fast_path() {
996 let mut p: Parser<'_> = Parser::new(br#"{"x":42,"y":99}"#);
997 assert!(matches!(
998 p.next_event().unwrap().unwrap(),
999 Event::StartObject
1000 ));
1001 let k1 = p.object_first_key().unwrap().unwrap();
1002 assert_eq!(k1, "x");
1003 let v1 = p.next_event().unwrap().unwrap();
1004 assert!(matches!(v1, Event::Number(_)));
1005 let k2 = p.object_next_key().unwrap().unwrap();
1006 assert_eq!(k2, "y");
1007 let v2 = p.next_event().unwrap().unwrap();
1008 assert!(matches!(v2, Event::Number(_)));
1009 assert!(p.object_next_key().unwrap().is_none());
1010 assert!(p.next_event().unwrap().is_none());
1011 }
1012
1013 #[test]
1014 fn next_event_nested_containers_close_correctly() {
1015 let mut p: Parser<'_> = Parser::new(br#"{"a":[1],"b":{"c":2}}"#);
1016 assert!(matches!(
1017 p.next_event().unwrap().unwrap(),
1018 Event::StartObject
1019 ));
1020 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Key(_))); assert!(matches!(
1022 p.next_event().unwrap().unwrap(),
1023 Event::StartArray
1024 ));
1025 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Number(_)));
1026 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndArray));
1027 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Key(_))); assert!(matches!(
1029 p.next_event().unwrap().unwrap(),
1030 Event::StartObject
1031 ));
1032 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Key(_))); assert!(matches!(p.next_event().unwrap().unwrap(), Event::Number(_)));
1034 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndObject));
1035 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndObject));
1036 assert!(p.next_event().unwrap().is_none());
1037 }
1038
1039 #[test]
1040 fn next_event_nested_array_in_array() {
1041 let input = b"[[],[1,2]]";
1042 let mut p: Parser<'_> = Parser::new(input);
1043 assert!(matches!(
1044 p.next_event().unwrap().unwrap(),
1045 Event::StartArray
1046 ));
1047 assert!(matches!(
1048 p.next_event().unwrap().unwrap(),
1049 Event::StartArray
1050 ));
1051 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndArray));
1052 assert!(matches!(
1053 p.next_event().unwrap().unwrap(),
1054 Event::StartArray
1055 ));
1056 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Number(_)));
1057 assert!(matches!(p.next_event().unwrap().unwrap(), Event::Number(_)));
1058 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndArray));
1059 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndArray));
1060 assert!(p.next_event().unwrap().is_none());
1061 }
1062
1063 #[test]
1064 fn serialize_string_with_quote_and_backslash() {
1065 let s = "a\"b\\c";
1066 let json = to_string(&s).unwrap();
1067 assert_eq!(json, r#""a\"b\\c""#);
1068 }
1069
1070 #[test]
1071 fn serialize_string_with_all_named_escapes() {
1072 let s = "\x08\x0C\n\r\t";
1073 let json = to_string(&s).unwrap();
1074 assert_eq!(json, r#""\b\f\n\r\t""#);
1075 }
1076
1077 #[test]
1082 fn parser_object_first_key_empty_inside_array() {
1083 let mut p: Parser<'_> = Parser::new(b"[{}]");
1084 assert!(matches!(
1085 p.next_event().unwrap().unwrap(),
1086 Event::StartArray
1087 ));
1088 assert!(matches!(
1089 p.next_event().unwrap().unwrap(),
1090 Event::StartObject
1091 ));
1092 assert!(p.object_first_key().unwrap().is_none());
1093 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndArray));
1094 assert!(p.next_event().unwrap().is_none());
1095 }
1096
1097 #[test]
1098 fn parser_object_first_key_empty_inside_object() {
1099 let mut p: Parser<'_> = Parser::new(br#"{"a":{}}"#);
1100 assert!(matches!(
1101 p.next_event().unwrap().unwrap(),
1102 Event::StartObject
1103 ));
1104 let k = p.object_first_key().unwrap().unwrap();
1105 assert_eq!(k, "a");
1106 assert!(matches!(
1107 p.next_event().unwrap().unwrap(),
1108 Event::StartObject
1109 ));
1110 assert!(p.object_first_key().unwrap().is_none());
1111 assert!(p.object_next_key().unwrap().is_none());
1112 assert!(p.next_event().unwrap().is_none());
1113 }
1114
1115 #[test]
1116 fn parser_object_first_key_lex_empty_inside_array() {
1117 let mut p: Parser<'_> = Parser::new(b"[{}]");
1118 assert!(matches!(
1119 p.next_event().unwrap().unwrap(),
1120 Event::StartArray
1121 ));
1122 assert!(matches!(
1123 p.next_event().unwrap().unwrap(),
1124 Event::StartObject
1125 ));
1126 assert!(p.object_first_key_lex().unwrap().is_none());
1127 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndArray));
1128 assert!(p.next_event().unwrap().is_none());
1129 }
1130
1131 #[test]
1132 fn parser_object_next_key_close_inside_array() {
1133 let mut p: Parser<'_> = Parser::new(br#"[{"a":1}]"#);
1134 assert!(matches!(
1135 p.next_event().unwrap().unwrap(),
1136 Event::StartArray
1137 ));
1138 assert!(matches!(
1139 p.next_event().unwrap().unwrap(),
1140 Event::StartObject
1141 ));
1142 let k = p.object_first_key().unwrap().unwrap();
1143 assert_eq!(k, "a");
1144 assert_eq!(p.parse_i64_value().unwrap(), 1);
1145 assert!(p.object_next_key().unwrap().is_none());
1146 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndArray));
1147 assert!(p.next_event().unwrap().is_none());
1148 }
1149
1150 #[test]
1151 fn parser_object_next_key_lex_close_inside_array() {
1152 let mut p: Parser<'_> = Parser::new(br#"[{"a":1}]"#);
1153 assert!(matches!(
1154 p.next_event().unwrap().unwrap(),
1155 Event::StartArray
1156 ));
1157 assert!(matches!(
1158 p.next_event().unwrap().unwrap(),
1159 Event::StartObject
1160 ));
1161 let k = p.object_first_key_lex().unwrap().unwrap();
1162 assert!(!k.has_escapes());
1163 assert_eq!(p.parse_i64_value().unwrap(), 1);
1164 assert!(p.object_next_key_lex().unwrap().is_none());
1165 assert!(matches!(p.next_event().unwrap().unwrap(), Event::EndArray));
1166 assert!(p.next_event().unwrap().is_none());
1167 }
1168
1169 #[test]
1174 fn lexer_object_first_key_bad_byte() {
1175 let mut lex: Lexer<'_> = Lexer::new(b"{1");
1176 lex.object_start().unwrap();
1177 let err = lex.object_first_key().unwrap_err();
1178 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b'1'));
1179 }
1180
1181 #[test]
1182 fn lexer_object_first_key_eof() {
1183 let mut lex: Lexer<'_> = Lexer::new(b"{");
1184 lex.object_start().unwrap();
1185 let err = lex.object_first_key().unwrap_err();
1186 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
1187 }
1188
1189 #[test]
1190 fn lexer_object_first_key_lex_bad_byte() {
1191 let mut lex: Lexer<'_> = Lexer::new(b"{1");
1192 lex.object_start().unwrap();
1193 let err = lex.object_first_key_lex().unwrap_err();
1194 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b'1'));
1195 }
1196
1197 #[test]
1198 fn lexer_object_first_key_lex_eof() {
1199 let mut lex: Lexer<'_> = Lexer::new(b"{");
1200 lex.object_start().unwrap();
1201 let err = lex.object_first_key_lex().unwrap_err();
1202 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
1203 }
1204
1205 #[test]
1206 fn lexer_object_next_key_bad_byte() {
1207 let mut lex: Lexer<'_> = Lexer::new(br#"{"a":1;"#);
1208 lex.object_start().unwrap();
1209 let _ = lex.object_first_key().unwrap();
1210 let _ = lex.parse_i64_value().unwrap();
1211 let err = lex.object_next_key().unwrap_err();
1212 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b';'));
1213 }
1214
1215 #[test]
1216 fn lexer_object_next_key_eof() {
1217 let mut lex: Lexer<'_> = Lexer::new(br#"{"a":1"#);
1218 lex.object_start().unwrap();
1219 let _ = lex.object_first_key().unwrap();
1220 let _ = lex.parse_i64_value().unwrap();
1221 let err = lex.object_next_key().unwrap_err();
1222 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
1223 }
1224
1225 #[test]
1226 fn lexer_object_next_key_bad_byte_after_comma() {
1227 let mut lex: Lexer<'_> = Lexer::new(br#"{"a":1,2"#);
1228 lex.object_start().unwrap();
1229 let _ = lex.object_first_key().unwrap();
1230 let _ = lex.parse_i64_value().unwrap();
1231 let err = lex.object_next_key().unwrap_err();
1232 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b'2'));
1233 }
1234
1235 #[test]
1236 fn lexer_object_next_key_lex_bad_byte() {
1237 let mut lex: Lexer<'_> = Lexer::new(br#"{"a":1;"#);
1238 lex.object_start().unwrap();
1239 let _ = lex.object_first_key_lex().unwrap();
1240 let _ = lex.parse_i64_value().unwrap();
1241 let err = lex.object_next_key_lex().unwrap_err();
1242 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b';'));
1243 }
1244
1245 #[test]
1246 fn lexer_object_next_key_lex_eof() {
1247 let mut lex: Lexer<'_> = Lexer::new(br#"{"a":1"#);
1248 lex.object_start().unwrap();
1249 let _ = lex.object_first_key_lex().unwrap();
1250 let _ = lex.parse_i64_value().unwrap();
1251 let err = lex.object_next_key_lex().unwrap_err();
1252 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
1253 }
1254
1255 #[test]
1256 fn lexer_object_next_key_lex_bad_byte_after_comma() {
1257 let mut lex: Lexer<'_> = Lexer::new(br#"{"a":1,2"#);
1258 lex.object_start().unwrap();
1259 let _ = lex.object_first_key_lex().unwrap();
1260 let _ = lex.parse_i64_value().unwrap();
1261 let err = lex.object_next_key_lex().unwrap_err();
1262 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b'2'));
1263 }
1264
1265 #[test]
1266 fn lexer_expect_colon_bad_byte() {
1267 let mut lex: Lexer<'_> = Lexer::new(br#"{"a";"#);
1268 lex.object_start().unwrap();
1269 let err = lex.object_first_key().unwrap_err();
1270 assert_eq!(err.kind, ErrorKind::UnexpectedByte(b';'));
1271 }
1272
1273 #[test]
1274 fn lexer_expect_colon_eof() {
1275 let mut lex: Lexer<'_> = Lexer::new(br#"{"a""#);
1276 lex.object_start().unwrap();
1277 let err = lex.object_first_key().unwrap_err();
1278 assert_eq!(err.kind, ErrorKind::UnexpectedEof);
1279 }
1280
1281 #[test]
1286 fn fixed_array_zero_length() {
1287 let arr: [i32; 0] = parse_str("[]").unwrap();
1288 assert_eq!(arr, [0_i32; 0]);
1289 }
1290
1291 #[test]
1292 fn fixed_array_empty_but_expected_nonempty() {
1293 let r = parse_str::<[i32; 3]>("[]");
1294 assert!(r.is_err());
1295 }
1296
1297 #[test]
1298 fn fixed_array_closed_early() {
1299 let r = parse_str::<[i32; 3]>("[1]");
1300 assert!(r.is_err());
1301 }
1302
1303 #[test]
1308 fn static_msg_cross_category() {
1309 use alloc::format;
1310 let kind = ErrorKind::UnexpectedEof;
1311 let msg = format!("{kind}");
1312 assert_eq!(msg, "unexpected end of input");
1313
1314 let kind = ErrorKind::ExpectedNull;
1315 let msg = format!("{kind}");
1316 assert_eq!(msg, "expected null");
1317 }
1318
1319 #[test]
1324 fn serialize_string_containing_only_quote() {
1325 let s = "\"";
1326 let json = to_string(&s).unwrap();
1327 assert_eq!(json, r#""\"""#);
1328 }
1329
1330 #[test]
1331 fn serialize_string_containing_only_backslash() {
1332 let s = "\\";
1333 let json = to_string(&s).unwrap();
1334 assert_eq!(json, r#""\\""#);
1335 }
1336
1337 #[test]
1342 fn utf8_invalid_leading_byte() {
1343 let bytes = b"\"\xFF\"";
1344 let r = parse::<&str>(bytes);
1345 assert_eq!(r.unwrap_err().kind, ErrorKind::InvalidUtf8);
1346 }
1347
1348 #[test]
1349 fn utf8_truncated_3byte_sequence() {
1350 let mut bytes = b"\"".to_vec();
1351 bytes.push(0xE1);
1352 bytes.push(0x80);
1353 let r = parse::<&str>(&bytes);
1355 assert_eq!(r.unwrap_err().kind, ErrorKind::InvalidUtf8);
1356 }
1357
1358 #[test]
1359 fn utf8_bad_third_continuation_byte() {
1360 let mut bytes = b"\"".to_vec();
1361 bytes.push(0xE1);
1362 bytes.push(0x80);
1363 bytes.push(0x00); let r = parse::<&str>(&bytes);
1365 assert!(r.is_err());
1366 }
1367
1368 #[test]
1369 fn utf8_4byte_bad_third_continuation() {
1370 let mut bytes = b"\"".to_vec();
1371 bytes.push(0xF0);
1372 bytes.push(0x90);
1373 bytes.push(0x80);
1374 bytes.push(0x00); let r = parse::<&str>(&bytes);
1376 assert!(r.is_err());
1377 }
1378
1379 #[test]
1380 fn utf8_e0_bad_second_byte() {
1381 let mut bytes = b"\"".to_vec();
1382 bytes.push(0xE0);
1383 bytes.push(0x80); bytes.push(0x80);
1385 bytes.push(b'"');
1386 let r = parse::<&str>(&bytes);
1387 assert_eq!(r.unwrap_err().kind, ErrorKind::InvalidUtf8);
1388 }
1389
1390 #[test]
1391 fn utf8_ed_bad_second_byte() {
1392 let mut bytes = b"\"".to_vec();
1393 bytes.push(0xED);
1394 bytes.push(0xA0); bytes.push(0x80);
1396 bytes.push(b'"');
1397 let r = parse::<&str>(&bytes);
1398 assert_eq!(r.unwrap_err().kind, ErrorKind::InvalidUtf8);
1399 }
1400
1401 #[test]
1402 fn utf8_f0_bad_second_byte() {
1403 let mut bytes = b"\"".to_vec();
1404 bytes.push(0xF0);
1405 bytes.push(0x80); bytes.push(0x80);
1407 bytes.push(0x80);
1408 bytes.push(b'"');
1409 let r = parse::<&str>(&bytes);
1410 assert_eq!(r.unwrap_err().kind, ErrorKind::InvalidUtf8);
1411 }
1412
1413 #[test]
1418 fn fixed_array_non_array_input() {
1419 let r = parse_str::<[i32; 2]>("42");
1420 assert!(r.is_err());
1421 }
1422}
1423
1424#[cfg(all(test, feature = "std"))]
1430mod ser_roundtrip {
1431 use super::{parse_str, to_string};
1432
1433 #[allow(clippy::needless_pass_by_value)]
1439 fn rt<T>(v: T)
1440 where
1441 T: crate::ToJson + for<'a> crate::FromJson<'a> + PartialEq + core::fmt::Debug,
1442 {
1443 let s = to_string(&v).expect("serialize");
1444 let v2: T = parse_str(&s).expect("parse back");
1445 assert_eq!(v, v2, "round-trip diverged via {s:?}");
1446 }
1447
1448 #[test]
1449 fn bool_roundtrips() {
1450 rt(true);
1451 rt(false);
1452 }
1453
1454 #[test]
1455 fn unit_roundtrips() {
1456 rt(());
1457 }
1458
1459 #[test]
1460 fn signed_ints_roundtrip() {
1461 rt(0_i8);
1462 rt(i8::MIN);
1463 rt(i8::MAX);
1464 rt(0_i16);
1465 rt(i16::MIN);
1466 rt(i16::MAX);
1467 rt(0_i32);
1468 rt(i32::MIN);
1469 rt(i32::MAX);
1470 rt(0_i64);
1471 rt(i64::MIN);
1472 rt(i64::MAX);
1473 rt(0_isize);
1474 rt(isize::MIN);
1475 rt(isize::MAX);
1476 }
1477
1478 #[test]
1479 fn unsigned_ints_roundtrip() {
1480 rt(0_u8);
1481 rt(u8::MAX);
1482 rt(0_u16);
1483 rt(u16::MAX);
1484 rt(0_u32);
1485 rt(u32::MAX);
1486 rt(0_u64);
1487 rt(u64::MAX);
1488 rt(0_usize);
1489 rt(usize::MAX);
1490 }
1491
1492 #[test]
1493 fn wide_ints_roundtrip() {
1494 rt(0_i128);
1495 rt(i128::MIN);
1496 rt(i128::MAX);
1497 rt(0_u128);
1498 rt(u128::MAX);
1499 }
1500
1501 #[test]
1502 fn strings_roundtrip() {
1503 for s in [
1505 "",
1506 "hello",
1507 "a\\b",
1508 "with \"quotes\"",
1509 "tab\tnewline\nreturn\rbs\x08ff\x0cnul\x00ctl\x1f",
1510 "café 中文 😀",
1511 ] {
1512 rt(String::from(s));
1513 }
1514 }
1515
1516 #[test]
1521 fn cow_roundtrips() {
1522 use std::borrow::Cow;
1523 for src in ["owned", "with\nescape", ""] {
1524 let v = Cow::<str>::Owned(String::from(src));
1525 let s = to_string(&v).unwrap();
1526 let back: Cow<'_, str> = parse_str(&s).unwrap();
1527 assert_eq!(back, src);
1528 }
1529 }
1530
1531 #[test]
1532 fn char_roundtrips() {
1533 for c in ['a', 'Z', '中', '😀', '\n', '\t', '"', '\\'] {
1534 rt(c);
1535 }
1536 }
1537
1538 #[test]
1539 fn option_roundtrips() {
1540 rt(Option::<u32>::None);
1541 rt(Some(42_u32));
1542 rt(Option::<String>::None);
1543 rt(Some(String::from("x")));
1544 }
1545
1546 #[test]
1549 fn reference_forwarding() {
1550 let v: u32 = 7;
1551 let owned = to_string(&v).unwrap();
1552 let by_ref = to_string(&&v).unwrap();
1553 assert_eq!(owned, by_ref);
1554 }
1555
1556 #[test]
1559 fn wrapper_types_transparent() {
1560 use std::rc::Rc;
1561 use std::sync::Arc;
1562 let v: u32 = 9;
1563 assert_eq!(to_string(&v).unwrap(), to_string(&Box::new(v)).unwrap());
1564 assert_eq!(to_string(&v).unwrap(), to_string(&Rc::new(v)).unwrap());
1565 assert_eq!(to_string(&v).unwrap(), to_string(&Arc::new(v)).unwrap());
1566 }
1567
1568 #[test]
1572 fn pinned_wire_format() {
1573 assert_eq!(to_string(&true).unwrap(), "true");
1574 assert_eq!(to_string(&false).unwrap(), "false");
1575 assert_eq!(to_string(&()).unwrap(), "null");
1576 assert_eq!(to_string(&0_i64).unwrap(), "0");
1577 assert_eq!(to_string(&-1_i64).unwrap(), "-1");
1578 assert_eq!(to_string(&i64::MIN).unwrap(), "-9223372036854775808");
1579 assert_eq!(to_string(&u64::MAX).unwrap(), "18446744073709551615");
1580 assert_eq!(to_string(&"hi").unwrap(), "\"hi\"");
1581 assert_eq!(to_string(&"\x01").unwrap(), "\"\\u0001\"");
1583 }
1584
1585 #[test]
1586 fn vec_roundtrips() {
1587 rt(Vec::<i32>::new());
1588 rt(vec![1_i32, 2, 3]);
1589 rt(vec![String::from("a"), String::from("b")]);
1590 rt(vec![Some(1_u32), None, Some(3)]);
1591 }
1592
1593 #[test]
1594 fn nested_vec_roundtrips() {
1595 rt(vec![vec![1_i32, 2], vec![3], Vec::new()]);
1596 }
1597
1598 #[test]
1599 fn fixed_array_roundtrips() {
1600 rt([1_i32, 2, 3]);
1601 rt([true, false, true]);
1602 let zero: [i32; 0] = [];
1603 rt(zero);
1604 }
1605
1606 #[test]
1607 fn tuple_roundtrips() {
1608 rt((1_i32, String::from("hi"), true));
1609 rt((1_u8, 2_u16, 3_u32, 4_u64));
1610 }
1611
1612 #[test]
1613 fn slice_pinned() {
1614 let s: &[i32] = &[10, 20, 30];
1617 assert_eq!(to_string(&s).unwrap(), "[10,20,30]");
1618 let empty: &[u8] = &[];
1619 assert_eq!(to_string(&empty).unwrap(), "[]");
1620 }
1621
1622 #[test]
1623 fn btreemap_roundtrips() {
1624 use std::collections::BTreeMap;
1625 let mut m = BTreeMap::new();
1626 m.insert(String::from("a"), 1_i32);
1627 m.insert(String::from("b"), 2);
1628 rt(m);
1629 }
1630
1631 #[test]
1632 fn btreemap_with_escape_in_key() {
1633 use std::collections::BTreeMap;
1634 let mut m = BTreeMap::new();
1635 m.insert(String::from("a\nb"), 1_i32);
1636 rt(m);
1637 }
1638
1639 #[test]
1640 fn btreeset_roundtrips() {
1641 use std::collections::BTreeSet;
1642 let mut s = BTreeSet::new();
1643 s.insert(1_i32);
1644 s.insert(2);
1645 s.insert(3);
1646 rt(s);
1647 }
1648
1649 #[cfg(feature = "std")]
1650 #[test]
1651 fn hashmap_roundtrips() {
1652 use std::collections::HashMap;
1655 let mut m = HashMap::new();
1656 m.insert(String::from("alpha"), 1_i32);
1657 m.insert(String::from("beta"), 2);
1658 let s = to_string(&m).unwrap();
1659 let back: HashMap<String, i32> = parse_str(&s).unwrap();
1660 assert_eq!(back, m);
1661 }
1662
1663 #[cfg(feature = "std")]
1664 #[test]
1665 fn hashset_roundtrips() {
1666 use std::collections::HashSet;
1667 let mut s = HashSet::new();
1668 s.insert(1_i32);
1669 s.insert(2);
1670 s.insert(3);
1671 let json = to_string(&s).unwrap();
1672 let back: HashSet<i32> = parse_str(&json).unwrap();
1673 assert_eq!(back, s);
1674 }
1675
1676 #[cfg(feature = "std")]
1677 #[test]
1678 fn ip_addrs_roundtrip() {
1679 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
1680 rt(Ipv4Addr::LOCALHOST);
1681 rt(Ipv6Addr::LOCALHOST);
1682 rt(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)));
1683 rt(SocketAddr::from(([127, 0, 0, 1], 8080)));
1684 }
1685
1686 #[cfg(feature = "std")]
1687 #[test]
1688 fn pathbuf_roundtrips() {
1689 use std::path::PathBuf;
1690 rt(PathBuf::from("/etc/hosts"));
1691 }
1692
1693 #[test]
1694 fn empty_collections_pinned() {
1695 use std::collections::BTreeMap;
1696 assert_eq!(to_string(&Vec::<i32>::new()).unwrap(), "[]");
1697 let empty: [i32; 0] = [];
1698 assert_eq!(to_string(&empty).unwrap(), "[]");
1699 let m: BTreeMap<String, i32> = BTreeMap::new();
1700 assert_eq!(to_string(&m).unwrap(), "{}");
1701 }
1702
1703 #[test]
1708 fn finite_f64_roundtrips() {
1709 for v in [
1710 0.0_f64,
1711 -0.0,
1712 1.0,
1713 -1.0,
1714 1.5,
1715 -1.5,
1716 1.5e2,
1717 1.5e-2,
1718 f64::MIN_POSITIVE,
1719 f64::MAX,
1720 f64::MIN,
1721 std::f64::consts::PI,
1722 ] {
1723 rt(v);
1724 }
1725 }
1726
1727 #[test]
1728 fn finite_f32_roundtrips() {
1729 for v in [0.0_f32, 1.5, -1.5, f32::MIN_POSITIVE, f32::MAX] {
1730 rt(v);
1731 }
1732 }
1733
1734 #[test]
1735 fn nonfinite_f64_rejected() {
1736 use crate::ErrorKind;
1737 let r = to_string(&f64::INFINITY);
1738 assert_eq!(r.unwrap_err().kind, ErrorKind::NonFiniteFloat);
1739 let r = to_string(&f64::NEG_INFINITY);
1740 assert_eq!(r.unwrap_err().kind, ErrorKind::NonFiniteFloat);
1741 let r = to_string(&f64::NAN);
1742 assert_eq!(r.unwrap_err().kind, ErrorKind::NonFiniteFloat);
1743 }
1744
1745 #[cfg(feature = "std")]
1746 #[test]
1747 fn duration_roundtrips() {
1748 use std::time::Duration;
1749 rt(Duration::from_secs(0));
1750 rt(Duration::from_millis(1500));
1751 rt(Duration::new(42, 750_000_000));
1752 }
1753}
1754
1755#[cfg(all(test, feature = "std"))]
1760mod to_json_macro_tests {
1761 use super::{parse_str, to_string};
1762
1763 crate::to_json! {
1765 #[derive(Debug, PartialEq)]
1766 struct Plain {
1767 id: u32,
1768 name: String,
1769 }
1770 }
1771
1772 crate::from_json! {
1773 #[derive(Debug, PartialEq)]
1774 struct PlainParse {
1775 id: u32,
1776 name: String,
1777 }
1778 }
1779
1780 #[test]
1781 fn plain_struct_emits_object() {
1782 let v = Plain {
1783 id: 7,
1784 name: String::from("alice"),
1785 };
1786 let s = to_string(&v).unwrap();
1787 assert_eq!(s, r#"{"id":7,"name":"alice"}"#);
1789 let back: PlainParse = parse_str(&s).unwrap();
1791 assert_eq!(
1792 back,
1793 PlainParse {
1794 id: 7,
1795 name: String::from("alice")
1796 }
1797 );
1798 }
1799
1800 crate::to_json! {
1801 #[derive(Debug, PartialEq)]
1802 struct Borrowed<'input> {
1803 tag: &'input str,
1804 count: u32,
1805 }
1806 }
1807
1808 #[test]
1809 fn struct_with_lifetime() {
1810 let v = Borrowed {
1811 tag: "hi",
1812 count: 3,
1813 };
1814 let s = to_string(&v).unwrap();
1815 assert_eq!(s, r#"{"tag":"hi","count":3}"#);
1816 }
1817
1818 crate::to_json! {
1820 #[derive(Debug, PartialEq)]
1821 struct Decorated {
1822 #[bourne(rename = "user-id")]
1823 user_id: u32,
1824 #[bourne(skip)]
1825 cached: u32,
1826 #[bourne(skip_if_none)]
1827 note: Option<String>,
1828 value: u32,
1829 }
1830 }
1831
1832 #[test]
1833 fn rename_emits_new_key() {
1834 let v = Decorated {
1835 user_id: 1,
1836 cached: 99,
1837 note: None,
1838 value: 42,
1839 };
1840 let s = to_string(&v).unwrap();
1841 assert_eq!(s, r#"{"user-id":1,"value":42}"#);
1843 }
1844
1845 #[test]
1846 fn skip_if_none_emits_when_some() {
1847 let v = Decorated {
1848 user_id: 1,
1849 cached: 0,
1850 note: Some(String::from("hi")),
1851 value: 7,
1852 };
1853 let s = to_string(&v).unwrap();
1854 assert_eq!(s, r#"{"user-id":1,"note":"hi","value":7}"#);
1855 }
1856
1857 crate::to_json! {
1859 #[derive(Debug, PartialEq)]
1860 struct Empty {}
1861 }
1862
1863 #[test]
1864 fn empty_struct_emits_empty_object() {
1865 assert_eq!(to_string(&Empty {}).unwrap(), "{}");
1866 }
1867
1868 crate::to_json! {
1872 #[derive(Debug, PartialEq)]
1873 struct WithEscape {
1874 text: String,
1875 }
1876 }
1877
1878 #[test]
1879 fn macro_passes_strings_to_escape_path() {
1880 let v = WithEscape {
1881 text: String::from("a\nb\"c"),
1882 };
1883 let s = to_string(&v).unwrap();
1884 assert_eq!(s, r#"{"text":"a\nb\"c"}"#);
1885 }
1886
1887 crate::to_json! {
1889 #[derive(Debug, PartialEq)]
1890 struct UserId(u64);
1891 }
1892
1893 #[test]
1894 fn newtype_emits_bare_value() {
1895 let v = UserId(42);
1896 assert_eq!(to_string(&v).unwrap(), "42");
1897 }
1898
1899 crate::to_json! {
1900 #[derive(Debug, PartialEq)]
1901 struct BorrowedTag<'input>(&'input str);
1902 }
1903
1904 #[test]
1905 fn newtype_with_lifetime() {
1906 let v = BorrowedTag("hello");
1907 assert_eq!(to_string(&v).unwrap(), r#""hello""#);
1908 }
1909
1910 crate::to_json! {
1912 #[derive(Debug, PartialEq)]
1913 struct Point(i32, i32);
1914 }
1915
1916 #[test]
1917 fn tuple_struct_emits_array() {
1918 let v = Point(3, -7);
1919 assert_eq!(to_string(&v).unwrap(), "[3,-7]");
1920 }
1921
1922 crate::to_json! {
1923 #[derive(Debug, PartialEq)]
1924 struct Triple(i32, String, bool);
1925 }
1926
1927 #[test]
1928 fn three_field_tuple_struct() {
1929 let v = Triple(1, String::from("hi"), true);
1930 assert_eq!(to_string(&v).unwrap(), r#"[1,"hi",true]"#);
1931 }
1932
1933 crate::to_json! {
1935 #[derive(Debug, PartialEq)]
1936 enum Shape {
1937 Circle,
1938 Wrapper(u32),
1939 Pair(u32, String),
1940 Box { w: u32, h: u32 },
1941 #[bourne(rename = "tri")]
1942 Triangle,
1943 }
1944 }
1945
1946 #[test]
1947 fn enum_unit_emits_string() {
1948 assert_eq!(to_string(&Shape::Circle).unwrap(), r#""Circle""#);
1949 }
1950
1951 #[test]
1952 fn enum_renamed_unit() {
1953 assert_eq!(to_string(&Shape::Triangle).unwrap(), r#""tri""#);
1954 }
1955
1956 #[test]
1957 fn enum_newtype_emits_object() {
1958 assert_eq!(to_string(&Shape::Wrapper(7)).unwrap(), r#"{"Wrapper":7}"#);
1959 }
1960
1961 #[test]
1962 fn enum_tuple_emits_object_with_array() {
1963 let v = Shape::Pair(1, String::from("x"));
1964 assert_eq!(to_string(&v).unwrap(), r#"{"Pair":[1,"x"]}"#);
1965 }
1966
1967 #[test]
1968 fn enum_struct_variant_emits_nested_object() {
1969 let v = Shape::Box { w: 10, h: 20 };
1970 assert_eq!(to_string(&v).unwrap(), r#"{"Box":{"w":10,"h":20}}"#);
1971 }
1972
1973 crate::to_json! {
1975 #[bourne(tag = "type")]
1976 #[derive(Debug, PartialEq)]
1977 enum Event {
1978 Heartbeat,
1979 #[bourne(rename = "click")]
1980 Click { x: u32, y: u32 },
1981 }
1982 }
1983
1984 #[test]
1985 fn internal_tag_unit_emits_object_with_tag() {
1986 assert_eq!(
1987 to_string(&Event::Heartbeat).unwrap(),
1988 r#"{"type":"Heartbeat"}"#
1989 );
1990 }
1991
1992 #[test]
1993 fn internal_tag_struct_inlines_fields() {
1994 let v = Event::Click { x: 1, y: 2 };
1995 assert_eq!(to_string(&v).unwrap(), r#"{"type":"click","x":1,"y":2}"#);
1996 }
1997
1998 crate::to_json! {
2000 #[bourne(tag = "t", content = "c")]
2001 #[derive(Debug, PartialEq)]
2002 enum Msg {
2003 Ping,
2004 Echo(String),
2005 Pair(u32, u32),
2006 Body { text: String },
2007 }
2008 }
2009
2010 #[test]
2011 fn adjacent_unit_emits_only_tag() {
2012 assert_eq!(to_string(&Msg::Ping).unwrap(), r#"{"t":"Ping"}"#);
2013 }
2014
2015 #[test]
2016 fn adjacent_newtype_emits_content() {
2017 let v = Msg::Echo(String::from("hi"));
2018 assert_eq!(to_string(&v).unwrap(), r#"{"t":"Echo","c":"hi"}"#);
2019 }
2020
2021 #[test]
2022 fn adjacent_tuple_emits_content_array() {
2023 let v = Msg::Pair(1, 2);
2024 assert_eq!(to_string(&v).unwrap(), r#"{"t":"Pair","c":[1,2]}"#);
2025 }
2026
2027 #[test]
2028 fn adjacent_struct_emits_content_object() {
2029 let v = Msg::Body {
2030 text: String::from("ok"),
2031 };
2032 assert_eq!(to_string(&v).unwrap(), r#"{"t":"Body","c":{"text":"ok"}}"#);
2033 }
2034
2035 crate::to_json! {
2037 #[bourne(untagged)]
2038 #[derive(Debug, PartialEq)]
2039 enum Mixed {
2040 Nothing,
2041 One(u32),
2042 Two(u32, u32),
2043 Body { name: String },
2044 }
2045 }
2046
2047 #[test]
2048 fn untagged_unit_emits_null() {
2049 assert_eq!(to_string(&Mixed::Nothing).unwrap(), "null");
2050 }
2051
2052 #[test]
2053 fn untagged_newtype_emits_inner() {
2054 assert_eq!(to_string(&Mixed::One(42)).unwrap(), "42");
2055 }
2056
2057 #[test]
2058 fn untagged_tuple_emits_array() {
2059 assert_eq!(to_string(&Mixed::Two(1, 2)).unwrap(), "[1,2]");
2060 }
2061
2062 #[test]
2063 fn untagged_struct_emits_object() {
2064 let v = Mixed::Body {
2065 name: String::from("x"),
2066 };
2067 assert_eq!(to_string(&v).unwrap(), r#"{"name":"x"}"#);
2068 }
2069}
2070
2071#[cfg(all(test, feature = "std"))]
2074mod sink_adapter_tests {
2075 use super::{to_fmt, to_string};
2076
2077 #[test]
2078 fn fmt_sink_matches_to_string_for_struct() {
2079 let m = vec![("a", 1_i32), ("b", 2)]
2080 .into_iter()
2081 .collect::<std::collections::BTreeMap<_, _>>();
2082 let canonical = to_string(&m).unwrap();
2083 let mut out = String::new();
2084 to_fmt(&m, &mut out).unwrap();
2085 assert_eq!(out, canonical);
2086 }
2087
2088 #[test]
2089 fn fmt_sink_handles_floats_with_grisu3() {
2090 let canonical = to_string(&1.5_f64).unwrap();
2091 let mut out = String::new();
2092 to_fmt(&1.5_f64, &mut out).unwrap();
2093 assert_eq!(out, canonical);
2094 }
2095
2096 #[test]
2097 fn fmt_sink_rejects_non_finite() {
2098 let mut out = String::new();
2099 let err = to_fmt(&f64::INFINITY, &mut out).unwrap_err();
2100 assert_eq!(err.kind, crate::ErrorKind::NonFiniteFloat);
2101 }
2102
2103 #[cfg(feature = "std")]
2104 #[test]
2105 fn io_writer_matches_to_string_for_struct() {
2106 use super::to_writer;
2107 let v = vec![1_i32, 2, 3];
2108 let canonical = to_string(&v).unwrap();
2109 let mut buf = Vec::<u8>::new();
2110 to_writer(&v, &mut buf).unwrap();
2111 assert_eq!(String::from_utf8(buf).unwrap(), canonical);
2112 }
2113
2114 #[cfg(feature = "std")]
2115 #[test]
2116 fn io_writer_handles_floats() {
2117 use super::to_writer;
2118 let canonical = to_string(&-2.7e-5_f64).unwrap();
2119 let mut buf = Vec::<u8>::new();
2120 to_writer(&-2.7e-5_f64, &mut buf).unwrap();
2121 assert_eq!(String::from_utf8(buf).unwrap(), canonical);
2122 }
2123
2124 #[cfg(feature = "std")]
2125 #[test]
2126 fn io_writer_rejects_non_finite() {
2127 use super::to_writer;
2128 let mut buf = Vec::<u8>::new();
2129 let err = to_writer(&f64::NAN, &mut buf).unwrap_err();
2130 assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
2131 }
2132
2133 #[test]
2134 fn pretty_empty_object_compact() {
2135 use super::to_string_pretty;
2136 let m: std::collections::BTreeMap<String, i32> = std::collections::BTreeMap::new();
2137 assert_eq!(to_string_pretty(&m).unwrap(), "{}");
2138 }
2139
2140 #[test]
2141 fn pretty_empty_array_compact() {
2142 use super::to_string_pretty;
2143 let v: Vec<i32> = Vec::new();
2144 assert_eq!(to_string_pretty(&v).unwrap(), "[]");
2145 }
2146
2147 #[test]
2148 fn pretty_array_indents_two_spaces() {
2149 use super::to_string_pretty;
2150 let v = vec![1_i32, 2, 3];
2151 assert_eq!(to_string_pretty(&v).unwrap(), "[\n 1,\n 2,\n 3\n]");
2152 }
2153
2154 #[test]
2155 fn pretty_object_keys_have_one_space_after_colon() {
2156 use super::to_string_pretty;
2157 let m: std::collections::BTreeMap<&str, i32> = [("a", 1), ("b", 2)].into_iter().collect();
2158 assert_eq!(
2159 to_string_pretty(&m).unwrap(),
2160 "{\n \"a\": 1,\n \"b\": 2\n}",
2161 );
2162 }
2163
2164 #[test]
2165 fn pretty_nested_indents_proportionally() {
2166 use super::to_string_pretty;
2167 let v: Vec<Vec<i32>> = vec![vec![1, 2], vec![3]];
2168 assert_eq!(
2169 to_string_pretty(&v).unwrap(),
2170 "[\n [\n 1,\n 2\n ],\n [\n 3\n ]\n]",
2171 );
2172 }
2173
2174 #[cfg(feature = "indexmap")]
2175 #[test]
2176 fn indexmap_preserves_insertion_order_on_parse() {
2177 use crate::parse_str;
2178 let json = r#"{"zebra":1,"alpha":2,"mango":3}"#;
2182 let m: indexmap::IndexMap<String, i32> = parse_str(json).unwrap();
2183 let keys: Vec<&str> = m.keys().map(String::as_str).collect();
2184 assert_eq!(keys, ["zebra", "alpha", "mango"]);
2185 assert_eq!(m["alpha"], 2);
2186 }
2187
2188 #[cfg(feature = "indexmap")]
2189 #[test]
2190 fn indexmap_round_trips_preserving_order() {
2191 use super::to_string;
2192 use crate::parse_str;
2193 let mut m = indexmap::IndexMap::<String, i32>::new();
2194 m.insert("z".into(), 1);
2195 m.insert("a".into(), 2);
2196 m.insert("m".into(), 3);
2197 let s = to_string(&m).unwrap();
2198 assert_eq!(s, r#"{"z":1,"a":2,"m":3}"#);
2200 let back: indexmap::IndexMap<String, i32> = parse_str(&s).unwrap();
2202 assert_eq!(
2203 back.keys().map(String::as_str).collect::<Vec<_>>(),
2204 ["z", "a", "m"],
2205 );
2206 }
2207
2208 #[cfg(feature = "indexmap")]
2209 #[test]
2210 fn indexmap_rejects_duplicate_keys() {
2211 use crate::parse_str;
2212 let r: Result<indexmap::IndexMap<String, i32>, _> = parse_str(r#"{"a":1,"a":2}"#);
2213 assert_eq!(r.unwrap_err().kind, crate::ErrorKind::DuplicateKey);
2214 }
2215
2216 #[cfg(feature = "indexmap")]
2217 #[test]
2218 fn indexset_round_trips() {
2219 use super::to_string;
2220 use crate::parse_str;
2221 let mut s = indexmap::IndexSet::<i32>::new();
2222 s.insert(3);
2223 s.insert(1);
2224 s.insert(2);
2225 let json = to_string(&s).unwrap();
2226 assert_eq!(json, "[3,1,2]");
2227 let back: indexmap::IndexSet<i32> = parse_str(&json).unwrap();
2228 assert_eq!(back.iter().copied().collect::<Vec<_>>(), [3, 1, 2]);
2229 }
2230
2231 #[test]
2232 fn pretty_round_trips_through_compact_parse() {
2233 use super::{parse_str, to_string_pretty};
2234 let m: std::collections::BTreeMap<String, Vec<i32>> = [
2235 (String::from("a"), vec![1, 2]),
2236 (String::from("b"), vec![3]),
2237 ]
2238 .into_iter()
2239 .collect();
2240 let pretty = to_string_pretty(&m).unwrap();
2241 let back: std::collections::BTreeMap<String, Vec<i32>> = parse_str(&pretty).unwrap();
2244 assert_eq!(back, m);
2245 }
2246
2247 #[cfg(feature = "std")]
2248 #[test]
2249 fn io_writer_propagates_underlying_error() {
2250 use super::to_writer;
2251 struct FailingWriter;
2254 impl std::io::Write for FailingWriter {
2255 fn write(&mut self, _: &[u8]) -> std::io::Result<usize> {
2256 Err(std::io::Error::other("disk full"))
2257 }
2258 fn flush(&mut self) -> std::io::Result<()> {
2259 Ok(())
2260 }
2261 }
2262 let mut w = FailingWriter;
2263 let err = to_writer(&"hi", &mut w).unwrap_err();
2264 assert_eq!(err.to_string(), "disk full");
2265 }
2266}
2267
2268#[cfg(all(test, feature = "std"))]
2271mod json_macro_tests {
2272 use super::{parse_str, to_string};
2273
2274 crate::json! {
2275 #[derive(Debug, PartialEq)]
2276 struct Plain {
2277 id: u32,
2278 name: String,
2279 }
2280 }
2281
2282 #[test]
2283 fn plain_struct_round_trips() {
2284 let v = Plain {
2285 id: 7,
2286 name: String::from("alice"),
2287 };
2288 let s = to_string(&v).unwrap();
2289 assert_eq!(s, r#"{"id":7,"name":"alice"}"#);
2290 let back: Plain = parse_str(&s).unwrap();
2291 assert_eq!(back, v);
2292 }
2293
2294 crate::json! {
2295 #[derive(Debug, PartialEq)]
2296 struct Borrowed<'input> {
2297 tag: &'input str,
2298 count: u32,
2299 }
2300 }
2301
2302 #[test]
2303 fn struct_with_lifetime_round_trips() {
2304 let json = r#"{"tag":"hi","count":3}"#;
2305 let v: Borrowed<'_> = parse_str(json).unwrap();
2306 assert_eq!(
2307 v,
2308 Borrowed {
2309 tag: "hi",
2310 count: 3
2311 }
2312 );
2313 assert_eq!(to_string(&v).unwrap(), json);
2314 }
2315
2316 crate::json! {
2317 #[derive(Debug, PartialEq)]
2318 struct Decorated {
2319 #[bourne(rename = "user-id")]
2320 user_id: u32,
2321 #[bourne(skip)]
2322 cached: u32,
2323 #[bourne(skip_if_none)]
2324 note: Option<String>,
2325 value: u32,
2326 }
2327 }
2328
2329 #[test]
2330 fn rename_skip_skip_if_none() {
2331 let v = Decorated {
2332 user_id: 1,
2333 cached: 99,
2334 note: None,
2335 value: 42,
2336 };
2337 let s = to_string(&v).unwrap();
2338 assert_eq!(s, r#"{"user-id":1,"value":42}"#);
2339 let back: Decorated = parse_str(&s).unwrap();
2340 assert_eq!(back.user_id, 1);
2341 assert_eq!(back.value, 42);
2342 }
2343
2344 crate::json! {
2345 #[derive(Debug, PartialEq)]
2346 struct UserId(u64);
2347 }
2348
2349 #[test]
2350 fn newtype_round_trips() {
2351 let v = UserId(42);
2352 let s = to_string(&v).unwrap();
2353 assert_eq!(s, "42");
2354 let back: UserId = parse_str(&s).unwrap();
2355 assert_eq!(back, v);
2356 }
2357
2358 crate::json! {
2359 #[derive(Debug, PartialEq)]
2360 struct Pair(i32, i32);
2361 }
2362
2363 #[test]
2364 fn tuple_struct_round_trips() {
2365 let v = Pair(3, -7);
2366 let s = to_string(&v).unwrap();
2367 assert_eq!(s, "[3,-7]");
2368 let back: Pair = parse_str(&s).unwrap();
2369 assert_eq!(back, v);
2370 }
2371
2372 crate::json! {
2373 #[derive(Debug, PartialEq)]
2374 enum Shape {
2375 Circle,
2376 Wrapper(u32),
2377 Pair(u32, String),
2378 Box { w: u32, h: u32 },
2379 #[bourne(rename = "tri")]
2380 Triangle,
2381 }
2382 }
2383
2384 #[test]
2385 fn externally_tagged_enum_round_trips() {
2386 let cases: Vec<(Shape, &str)> = vec![
2387 (Shape::Circle, r#""Circle""#),
2388 (Shape::Wrapper(7), r#"{"Wrapper":7}"#),
2389 (Shape::Pair(1, String::from("x")), r#"{"Pair":[1,"x"]}"#),
2390 (Shape::Box { w: 10, h: 20 }, r#"{"Box":{"w":10,"h":20}}"#),
2391 (Shape::Triangle, r#""tri""#),
2392 ];
2393 for (val, expected) in cases {
2394 let s = to_string(&val).unwrap();
2395 assert_eq!(s, expected);
2396 let back: Shape = parse_str(&s).unwrap();
2397 assert_eq!(back, val);
2398 }
2399 }
2400
2401 crate::json! {
2402 #[bourne(tag = "type")]
2403 #[derive(Debug, PartialEq)]
2404 enum Event {
2405 Heartbeat,
2406 #[bourne(rename = "click")]
2407 Click { x: u32, y: u32 },
2408 }
2409 }
2410
2411 #[test]
2412 fn internally_tagged_enum_round_trips() {
2413 let hb = Event::Heartbeat;
2414 let s = to_string(&hb).unwrap();
2415 assert_eq!(s, r#"{"type":"Heartbeat"}"#);
2416 let back: Event = parse_str(&s).unwrap();
2417 assert_eq!(back, hb);
2418
2419 let click = Event::Click { x: 1, y: 2 };
2420 let s = to_string(&click).unwrap();
2421 assert_eq!(s, r#"{"type":"click","x":1,"y":2}"#);
2422 let back: Event = parse_str(&s).unwrap();
2423 assert_eq!(back, click);
2424 }
2425
2426 crate::json! {
2427 #[bourne(tag = "t", content = "c")]
2428 #[derive(Debug, PartialEq)]
2429 enum Msg {
2430 Ping,
2431 Echo(String),
2432 Pair(u32, u32),
2433 Body { text: String },
2434 }
2435 }
2436
2437 #[test]
2438 fn adjacently_tagged_enum_round_trips() {
2439 let cases: Vec<(Msg, &str)> = vec![
2440 (Msg::Ping, r#"{"t":"Ping"}"#),
2441 (Msg::Echo(String::from("hi")), r#"{"t":"Echo","c":"hi"}"#),
2442 (Msg::Pair(1, 2), r#"{"t":"Pair","c":[1,2]}"#),
2443 (
2444 Msg::Body {
2445 text: String::from("ok"),
2446 },
2447 r#"{"t":"Body","c":{"text":"ok"}}"#,
2448 ),
2449 ];
2450 for (val, expected) in cases {
2451 let s = to_string(&val).unwrap();
2452 assert_eq!(s, expected);
2453 let back: Msg = parse_str(&s).unwrap();
2454 assert_eq!(back, val);
2455 }
2456 }
2457
2458 crate::json! {
2459 #[bourne(untagged)]
2460 #[derive(Debug, PartialEq)]
2461 enum Mixed {
2462 Nothing,
2463 One(u32),
2464 Two(u32, u32),
2465 Body { name: String },
2466 }
2467 }
2468
2469 crate::json! {
2470 #[derive(Debug, PartialEq, Eq)]
2471 pub struct PubFields {
2472 pub id: u32,
2473 pub(crate) name: String,
2474 value: u32,
2475 }
2476 }
2477
2478 #[test]
2479 fn pub_fields_round_trip() {
2480 let v = PubFields {
2481 id: 1,
2482 name: String::from("hi"),
2483 value: 2,
2484 };
2485 let s = to_string(&v).unwrap();
2486 assert_eq!(s, r#"{"id":1,"name":"hi","value":2}"#);
2487 let back: PubFields = parse_str(&s).unwrap();
2488 assert_eq!(back, v);
2489 }
2490
2491 #[test]
2492 fn untagged_enum_serializes() {
2493 assert_eq!(to_string(&Mixed::Nothing).unwrap(), "null");
2494 assert_eq!(to_string(&Mixed::One(42)).unwrap(), "42");
2495 assert_eq!(to_string(&Mixed::Two(1, 2)).unwrap(), "[1,2]");
2496 assert_eq!(
2497 to_string(&Mixed::Body {
2498 name: String::from("x")
2499 })
2500 .unwrap(),
2501 r#"{"name":"x"}"#,
2502 );
2503 }
2504}
2505
2506#[cfg(all(test, feature = "std"))]
2515mod unsafe_boundary_tests {
2516 use super::*;
2517 use alloc::string::String;
2518 use alloc::vec::Vec;
2519
2520 #[test]
2527 fn bytesink_slice_floats_exact_capacity() {
2528 for n in [0usize, 1, 2, 3, 7, 16, 17, 32, 33] {
2529 #[allow(clippy::cast_precision_loss)]
2530 let data: Vec<f64> = (0..n).map(|i| i as f64 + 0.5).collect();
2531 let mut out: Vec<u8> = Vec::with_capacity(2 + n * 33);
2532 let mut sink = ByteSink::new(&mut out);
2533 (data.as_slice()).write_json(&mut sink).expect("ser");
2534 let s = core::str::from_utf8(&out).expect("ASCII");
2535 let back: Vec<f64> = parse_str(s).expect("parse back");
2537 assert_eq!(back.len(), n, "n={n}");
2538 #[allow(clippy::cast_precision_loss, clippy::float_cmp)]
2539 for (i, &v) in back.iter().enumerate() {
2540 assert_eq!(v, i as f64 + 0.5, "n={n} i={i}");
2541 }
2542 }
2543 }
2544
2545 #[test]
2548 fn bytesink_slice_f32_exact_capacity() {
2549 for n in [0usize, 1, 2, 16, 17] {
2550 #[allow(clippy::cast_precision_loss)]
2551 let data: Vec<f32> = (0..n).map(|i| i as f32 + 0.25).collect();
2552 let mut out: Vec<u8> = Vec::with_capacity(2 + n * 33);
2553 let mut sink = ByteSink::new(&mut out);
2554 (data.as_slice()).write_json(&mut sink).expect("ser");
2555 let s = core::str::from_utf8(&out).expect("ASCII");
2556 let back: Vec<f32> = parse_str(s).expect("parse back");
2557 assert_eq!(back.len(), n);
2558 #[allow(clippy::cast_precision_loss, clippy::float_cmp)]
2559 for (i, &v) in back.iter().enumerate() {
2560 assert_eq!(v, i as f32 + 0.25, "n={n} i={i}");
2561 }
2562 }
2563 }
2564
2565 #[test]
2569 fn bytesink_slice_nonfinite_taint_path() {
2570 for (name, bad_idx, bad_val) in [
2574 ("inf at 0", 0usize, f64::INFINITY),
2575 ("nan at end", 4usize, f64::NAN),
2576 ("neg_inf middle", 2usize, f64::NEG_INFINITY),
2577 ] {
2578 let mut data: Vec<f64> = (0..5).map(f64::from).collect();
2579 data[bad_idx] = bad_val;
2580 let r = to_string(data.as_slice());
2581 assert!(r.is_err(), "{name}: expected non-finite error");
2582 }
2583 }
2584
2585 #[test]
2589 fn bytesink_slice_ints_exact_capacity() {
2590 for n in [0usize, 1, 5, 16, 17] {
2593 #[allow(clippy::cast_possible_wrap)]
2594 let n_i64 = n as i64;
2595 #[allow(clippy::cast_possible_wrap)]
2596 let data: Vec<i64> = (0..n).map(|i| (i as i64) - n_i64 / 2).collect();
2597 let mut out: Vec<u8> = Vec::with_capacity(2 + n * 21);
2598 let mut sink = ByteSink::new(&mut out);
2599 (data.as_slice()).write_json(&mut sink).expect("ser");
2600 let s = core::str::from_utf8(&out).expect("ASCII");
2601 let back: Vec<i64> = parse_str(s).expect("parse back");
2602 assert_eq!(back, data, "n={n}");
2603 }
2604 }
2605
2606 #[test]
2612 fn decode_escapes_multibyte_in_literal_chunk() {
2613 let cases: &[(&str, &str)] = &[
2617 (r#""café\nfin""#, "café\nfin"),
2618 (r#""price: 5€\tea""#, "price: 5€\tea"),
2619 (r#""note 𝄞\nplayed""#, "note 𝄞\nplayed"),
2620 (r#""éé\nçç\tüü""#, "éé\nçç\tüü"),
2622 (r#""\n𝄞café\t""#, "\n𝄞café\t"),
2624 (
2627 r#""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaéé\n""#,
2628 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaéé\n",
2629 ),
2630 ];
2631 for (json, expected) in cases {
2632 let s: String = parse_str(json).expect("parse");
2633 assert_eq!(s, *expected, "case {json}");
2634 }
2635 }
2636
2637 #[test]
2640 fn bytesink_empty_slice_writes_brackets_only() {
2641 let empty: Vec<i64> = Vec::new();
2642 let s = to_string(empty.as_slice()).expect("ser");
2643 assert_eq!(s, "[]");
2644
2645 let empty: Vec<f64> = Vec::new();
2646 let s = to_string(empty.as_slice()).expect("ser");
2647 assert_eq!(s, "[]");
2648 }
2649
2650 #[test]
2653 fn bytesink_single_element_slice() {
2654 let one = [42_i64];
2655 assert_eq!(to_string(one.as_slice()).unwrap(), "[42]");
2656 let one = [1.5_f64];
2657 assert_eq!(to_string(one.as_slice()).unwrap(), "[1.5]");
2658 let one = [1.5_f32];
2659 assert_eq!(to_string(one.as_slice()).unwrap(), "[1.5]");
2660 }
2661
2662 #[test]
2666 fn decode_escapes_empty_string() {
2667 let s: String = parse_str(r#""""#).expect("parse");
2668 assert_eq!(s, "");
2669 }
2670
2671 #[test]
2675 fn decode_escapes_no_escapes_pure_ascii() {
2676 let v: Vec<String> = parse_str(r#"["hello world","no escapes here"]"#).expect("parse");
2679 assert_eq!(
2680 v,
2681 [String::from("hello world"), String::from("no escapes here")]
2682 );
2683 }
2684
2685 #[test]
2688 fn decode_escapes_escape_at_start() {
2689 let v: Vec<String> = parse_str(r#"["\nhello","\tworld"]"#).expect("parse");
2690 assert_eq!(v, [String::from("\nhello"), String::from("\tworld")]);
2691 }
2692
2693 #[test]
2696 fn decode_escapes_escape_at_end() {
2697 let v: Vec<String> = parse_str(r#"["hello\n","world\t"]"#).expect("parse");
2698 assert_eq!(v, [String::from("hello\n"), String::from("world\t")]);
2699 }
2700
2701 #[test]
2703 fn decode_escapes_consecutive_escapes() {
2704 let v: Vec<String> = parse_str(r#"["\n\t\r\\","\"\"\""]"#).expect("parse");
2705 assert_eq!(v, [String::from("\n\t\r\\"), String::from(r#"""""#)]);
2706 }
2707
2708 #[test]
2718 fn vec_borrowed_str_fast_path() {
2719 let v: Vec<&str> = parse_str("[]").expect("empty");
2721 assert_eq!(v, Vec::<&str>::new());
2722
2723 let v: Vec<&str> = parse_str(r#"["only"]"#).expect("single");
2725 assert_eq!(v, ["only"]);
2726
2727 let v: Vec<&str> = parse_str(r#"["a","b","c","d","e"]"#).expect("many");
2729 assert_eq!(v, ["a", "b", "c", "d", "e"]);
2730
2731 let r: Result<Vec<&str>, _> = parse_str(r#"["plain","esc\nbad"]"#);
2733 assert!(r.is_err(), "borrowed path must reject escape");
2734 }
2735
2736 #[cfg(feature = "std")]
2738 #[test]
2739 fn vec_duration_fast_path() {
2740 use std::time::Duration;
2741
2742 let v: Vec<Duration> = parse_str("[]").expect("empty");
2744 assert!(v.is_empty());
2745
2746 let v: Vec<Duration> = parse_str("[1.5]").expect("single");
2748 assert_eq!(v, [Duration::from_secs_f64(1.5)]);
2749
2750 let v: Vec<Duration> = parse_str("[0.0,1.0,1.5,2.25,100.125]").expect("many");
2752 assert_eq!(v.len(), 5);
2753 assert_eq!(v[0], Duration::ZERO);
2754 assert_eq!(v[4], Duration::from_secs_f64(100.125));
2755
2756 let r: Result<Vec<Duration>, _> = parse_str("[1.0,-2.0]");
2758 assert!(r.is_err());
2759 }
2760
2761 #[test]
2764 fn vec_i64_fast_path() {
2765 let v: Vec<i64> = parse_str("[]").expect("empty");
2766 assert!(v.is_empty());
2767
2768 let v: Vec<i64> = parse_str("[42]").expect("single");
2769 assert_eq!(v, [42]);
2770
2771 let v: Vec<i64> =
2772 parse_str("[1,-1,9223372036854775807,-9223372036854775808]").expect("many");
2773 assert_eq!(v, [1, -1, i64::MAX, i64::MIN]);
2774
2775 let r: Result<Vec<u32>, _> = parse_str("[1,99999999999]");
2777 assert!(r.is_err(), "u32 should overflow");
2778 }
2779
2780 #[test]
2782 fn vec_u128_fast_path() {
2783 let v: Vec<u128> = parse_str("[]").expect("empty");
2784 assert!(v.is_empty());
2785
2786 let v: Vec<u128> = parse_str("[0,170141183460469231731687303715884105727]").expect("many");
2787 assert_eq!(v, [0u128, i128::MAX as u128]);
2788 }
2789
2790 #[test]
2797 fn decode_all_simple_escapes() {
2798 let cases: &[(&str, &str)] = &[
2801 (r#""\b""#, "\u{0008}"), (r#""\f""#, "\u{000C}"), (r#""\/""#, "/"), (r#""\\""#, "\\"), (r#""\"""#, "\""), (r#""\n""#, "\n"),
2807 (r#""\r""#, "\r"),
2808 (r#""\t""#, "\t"),
2809 ];
2810 for &(json, expected) in cases {
2811 let s: String = parse_str(json).expect(json);
2812 assert_eq!(s, expected, "case {json}");
2813 }
2814 }
2815
2816 #[test]
2817 fn decode_unknown_escape_errors() {
2818 let r: Result<String, _> = parse_str(r#""\x""#);
2820 assert!(r.is_err(), "unknown escape should error");
2821
2822 let r: Result<String, _> = parse_str("\"\\\"");
2824 assert!(r.is_err(), "lone trailing backslash should error");
2825 }
2826
2827 #[test]
2828 fn decode_unicode_escape_short_input_errors() {
2829 let r: Result<String, _> = parse_str(r#""\u00""#);
2831 assert!(r.is_err(), "short \\u should error");
2832 let r: Result<String, _> = parse_str(r#""\u""#);
2833 assert!(r.is_err());
2834 }
2835
2836 #[test]
2837 fn decode_unicode_lone_low_surrogate_errors() {
2838 let r: Result<String, _> = parse_str(r#""\uDC00""#);
2841 assert!(r.is_err(), "lone low surrogate should error");
2842 }
2843
2844 #[test]
2845 fn decode_unicode_high_surrogate_then_invalid_low_errors() {
2846 let json = "\"\\uD800\\u0041\""; let r: Result<String, _> = parse_str(json);
2852 assert!(
2853 r.is_err(),
2854 "high surrogate then non-low-surrogate \\u must error"
2855 );
2856 }
2857
2858 #[test]
2862 fn decode_unicode_high_surrogate_then_short_second_escape_errors() {
2863 let json = r#""\uD800\u""#;
2864 let r: Result<String, _> = parse_str(json);
2865 assert!(r.is_err(), "high surrogate then truncated \\u must error");
2866 }
2867
2868 #[test]
2870 fn decode_unicode_high_surrogate_then_invalid_hex_errors() {
2871 let json = "\"\\uD800\\uZZZZ\"";
2872 let r: Result<String, _> = parse_str(json);
2873 assert!(r.is_err(), "high surrogate then bad hex must error");
2874 }
2875
2876 #[test]
2877 fn decode_unicode_high_surrogate_then_non_u_escape_errors() {
2878 let r: Result<String, _> = parse_str(r#""\uD800\n""#);
2880 assert!(
2881 r.is_err(),
2882 "high surrogate not followed by \\u should error"
2883 );
2884
2885 let r: Result<String, _> = parse_str(r#""\uD800A""#);
2887 assert!(
2888 r.is_err(),
2889 "high surrogate not followed by escape should error"
2890 );
2891 }
2892
2893 #[test]
2894 fn decode_unicode_surrogate_pair_round_trips() {
2895 let json = "\"\\uD83D\\uDE00\"";
2900 let s: String = parse_str(json).expect("parse");
2901 assert_eq!(s, "\u{1F600}");
2902
2903 let json = "\"a\\uD83D\\uDE00b\\uD83D\\uDE01c\"";
2905 let s: String = parse_str(json).expect("parse");
2906 assert_eq!(s, "a\u{1F600}b\u{1F601}c");
2907 }
2908
2909 #[test]
2910 fn decode_unicode_bmp_escape_round_trips() {
2911 let json = "\"\\u00E9\"";
2915 let s: String = parse_str(json).expect("parse");
2916 assert_eq!(s, "é");
2917
2918 let json = "\"A\\u00A3\\u20AC\""; let s: String = parse_str(json).expect("parse");
2921 assert_eq!(s, "A£€");
2922 }
2923
2924 #[test]
2925 fn decode_invalid_hex_in_u_escape_errors() {
2926 let r: Result<String, _> = parse_str(r#""\u00ZX""#);
2928 assert!(r.is_err(), "invalid hex should error");
2929 }
2930
2931 #[test]
2941 fn to_decimal_uncentred_powers_of_two_round_trip() {
2942 let cases = [
2945 2.0_f64,
2946 4.0,
2947 8.0,
2948 16.0,
2949 32.0,
2950 64.0,
2951 128.0,
2952 256.0,
2953 512.0,
2954 1024.0,
2955 2.0_f64.powi(20),
2956 2.0_f64.powi(50),
2957 2.0_f64.powi(100),
2958 2.0_f64.powi(500),
2959 2.0_f64.powi(1023), 2.0_f64.powi(-1), 2.0_f64.powi(-2), 2.0_f64.powi(-10),
2964 2.0_f64.powi(-50),
2965 2.0_f64.powi(-100),
2966 2.0_f64.powi(-1000),
2967 ];
2968 for &v in &cases {
2969 let s = to_string(&v).expect("ser");
2970 let back: f64 = parse_str(&s).expect("parse back");
2971 #[allow(clippy::float_cmp)]
2972 {
2973 assert_eq!(back, v, "round-trip for {v:e}: emitted {s:?}");
2974 }
2975 }
2976 }
2977
2978 #[test]
2980 fn to_decimal_uncentred_negative_powers_round_trip() {
2981 for k in [-30, -10, -1, 1, 10, 30, 100, 500] {
2982 let v = -(2.0_f64.powi(k));
2983 let s = to_string(&v).expect("ser");
2984 let back: f64 = parse_str(&s).expect("parse back");
2985 #[allow(clippy::float_cmp)]
2986 {
2987 assert_eq!(back, v, "round-trip for {v:e}: emitted {s:?}");
2988 }
2989 }
2990 }
2991
2992 #[test]
2995 fn to_decimal_uncentred_subnormals_round_trip() {
2996 let cases = [
2997 5e-324_f64, f64::MIN_POSITIVE, -f64::MIN_POSITIVE,
3000 f64::MAX,
3001 -f64::MAX,
3002 ];
3003 for &v in &cases {
3004 let s = to_string(&v).expect("ser");
3005 let back: f64 = parse_str(&s).expect("parse back");
3006 #[allow(clippy::float_cmp)]
3007 {
3008 assert_eq!(back, v, "round-trip for {v:e}: emitted {s:?}");
3009 }
3010 }
3011 }
3012
3013 #[test]
3022 fn string_sink_writes_directly() {
3023 let mut out = String::new();
3024 let mut sink = StringSink::new(&mut out);
3025 sink.write_byte(b'[').unwrap();
3027 sink.write_str_raw("1").unwrap();
3028 sink.write_byte(b',').unwrap();
3029 sink.write_float_f64(2.5).unwrap();
3031 sink.write_byte(b']').unwrap();
3032 assert_eq!(out, "[1,2.5]");
3033
3034 let mut out = String::new();
3036 let mut sink = StringSink::new(&mut out);
3037 assert!(sink.write_float_f64(f64::NAN).is_err());
3038 }
3039
3040 #[test]
3043 fn pretty_sink_with_indent_uses_custom_indent() {
3044 let mut out = String::new();
3045 let mut sink = PrettyStringSink::with_indent(&mut out, "\t");
3046 let data = (1_i32, 2_i32, 3_i32);
3047 data.write_json(&mut sink).unwrap();
3048 assert!(out.contains("\n\t"), "got: {out:?}");
3050 }
3051
3052 #[test]
3055 fn pretty_sink_handles_floats() {
3056 let v: alloc::vec::Vec<f64> = alloc::vec![1.5, 2.5, 3.0];
3057 let s = to_string_pretty(v.as_slice()).unwrap();
3058 assert!(s.contains("1.5"));
3059 assert!(s.contains("3.0"));
3060 }
3061
3062 #[test]
3065 fn bytesink_unchecked_float_nonfinite_returns_error() {
3066 let mut out: Vec<u8> = Vec::with_capacity(64);
3067 let mut sink = ByteSink::new(&mut out);
3068 #[allow(unsafe_code)]
3070 let r = unsafe { sink.write_float_f64_unchecked(f64::INFINITY) };
3071 assert!(r.is_err(), "non-finite must error through cold arm");
3072 }
3073
3074 #[test]
3077 fn bytesink_unchecked_finite_writes_value() {
3078 let mut out: Vec<u8> = Vec::with_capacity(64);
3079 let mut sink = ByteSink::new(&mut out);
3080 let value = 2.5_f64;
3084 #[allow(unsafe_code)]
3086 unsafe {
3087 sink.write_float_f64_unchecked_finite(value).unwrap();
3088 }
3089 let s = core::str::from_utf8(&out).unwrap();
3090 let parsed: f64 = s.parse().unwrap();
3091 assert_eq!(parsed.to_bits(), value.to_bits());
3093 }
3094
3095 #[cfg(feature = "std")]
3097 #[test]
3098 fn path_serializes_via_to_string() {
3099 use std::path::Path;
3100 let p = Path::new("/tmp/file.txt");
3101 let s = to_string(p).unwrap();
3102 assert_eq!(s, "\"/tmp/file.txt\"");
3103 }
3104
3105 #[test]
3108 fn map_with_cow_str_keys_serializes() {
3109 use alloc::borrow::Cow;
3110 use alloc::collections::BTreeMap;
3111 let mut m: BTreeMap<Cow<'_, str>, i32> = BTreeMap::new();
3112 m.insert(Cow::Borrowed("a"), 1);
3113 m.insert(Cow::Owned(String::from("b")), 2);
3114 let s = to_string(&m).unwrap();
3115 assert!(s.contains(r#""a":1"#));
3116 assert!(s.contains(r#""b":2"#));
3117 }
3118
3119 #[test]
3122 fn f64_pre_validate_slice_is_noop() {
3123 let slice: &[f64] = &[1.0, 2.0, f64::INFINITY];
3124 let r = <f64 as ToJson>::pre_validate_slice(slice);
3127 assert!(r.is_ok());
3128 }
3129
3130 #[test]
3136 fn to_fmt_writes_finite_and_rejects_nonfinite() {
3137 let mut s = String::new();
3138 to_fmt(&1.5_f64, &mut s).unwrap();
3139 assert_eq!(s, "1.5");
3140
3141 let mut s = String::new();
3142 assert!(to_fmt(&f64::INFINITY, &mut s).is_err());
3143 }
3144
3145 #[test]
3150 fn to_fmt_propagates_underlying_write_failure() {
3151 use core::fmt;
3152
3153 struct AlwaysFail;
3155 impl fmt::Write for AlwaysFail {
3156 fn write_str(&mut self, _s: &str) -> fmt::Result {
3157 Err(fmt::Error)
3158 }
3159 }
3160
3161 let mut sink = AlwaysFail;
3164 let r = to_fmt(&42_i64, &mut sink);
3165 assert!(r.is_err(), "expected propagated error from failing writer");
3166
3167 let mut sink = AlwaysFail;
3170 let r = to_fmt(&1.5_f64, &mut sink);
3171 assert!(r.is_err());
3172 }
3173}