1use std::fmt;
8
9use serde::Serialize;
10use serde::ser::{self, Impossible};
11use serde_json::Value;
12
13#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
15#[error("{0}")]
16pub struct JsonError(pub String);
17
18impl ser::Error for JsonError {
19 fn custom<T: fmt::Display>(msg: T) -> Self {
20 JsonError(msg.to_string())
21 }
22}
23
24pub fn to_value<T: Serialize + ?Sized>(v: &T) -> Result<Value, JsonError> {
26 v.serialize(&mut Check { path: Vec::new() })?;
27 serde_json::to_value(v).map_err(|e| JsonError(e.to_string()))
28}
29
30pub fn to_vec<T: Serialize + ?Sized>(v: &T, pretty: bool) -> Result<Vec<u8>, JsonError> {
36 v.serialize(&mut Check { path: Vec::new() })?;
37 let mut out = Vec::new();
38 let written = if pretty {
39 v.serialize(&mut serde_json::Serializer::with_formatter(
40 &mut out,
41 ExactF32(serde_json::ser::PrettyFormatter::new()),
42 ))
43 } else {
44 v.serialize(&mut serde_json::Serializer::with_formatter(
45 &mut out,
46 ExactF32(serde_json::ser::CompactFormatter),
47 ))
48 };
49 written.map_err(|e| JsonError(e.to_string()))?;
50 if pretty {
51 out.push(b'\n');
52 }
53 Ok(out)
54}
55
56struct ExactF32<F>(F);
59
60impl<F: serde_json::ser::Formatter> serde_json::ser::Formatter for ExactF32<F> {
61 fn write_f32<W: ?Sized + std::io::Write>(&mut self, writer: &mut W, value: f32) -> std::io::Result<()> {
62 match f32_decimal(value) {
63 Ok(d) => self.0.write_f64(writer, d),
64 Err(_) => self.0.write_null(writer),
66 }
67 }
68 fn write_f64<W: ?Sized + std::io::Write>(&mut self, writer: &mut W, value: f64) -> std::io::Result<()> {
69 self.0.write_f64(writer, value)
70 }
71 fn begin_array<W: ?Sized + std::io::Write>(&mut self, writer: &mut W) -> std::io::Result<()> {
72 self.0.begin_array(writer)
73 }
74 fn end_array<W: ?Sized + std::io::Write>(&mut self, writer: &mut W) -> std::io::Result<()> {
75 self.0.end_array(writer)
76 }
77 fn begin_array_value<W: ?Sized + std::io::Write>(
78 &mut self,
79 writer: &mut W,
80 first: bool,
81 ) -> std::io::Result<()> {
82 self.0.begin_array_value(writer, first)
83 }
84 fn end_array_value<W: ?Sized + std::io::Write>(&mut self, writer: &mut W) -> std::io::Result<()> {
85 self.0.end_array_value(writer)
86 }
87 fn begin_object<W: ?Sized + std::io::Write>(&mut self, writer: &mut W) -> std::io::Result<()> {
88 self.0.begin_object(writer)
89 }
90 fn end_object<W: ?Sized + std::io::Write>(&mut self, writer: &mut W) -> std::io::Result<()> {
91 self.0.end_object(writer)
92 }
93 fn begin_object_key<W: ?Sized + std::io::Write>(
94 &mut self,
95 writer: &mut W,
96 first: bool,
97 ) -> std::io::Result<()> {
98 self.0.begin_object_key(writer, first)
99 }
100 fn end_object_key<W: ?Sized + std::io::Write>(&mut self, writer: &mut W) -> std::io::Result<()> {
101 self.0.end_object_key(writer)
102 }
103 fn begin_object_value<W: ?Sized + std::io::Write>(&mut self, writer: &mut W) -> std::io::Result<()> {
104 self.0.begin_object_value(writer)
105 }
106 fn end_object_value<W: ?Sized + std::io::Write>(&mut self, writer: &mut W) -> std::io::Result<()> {
107 self.0.end_object_value(writer)
108 }
109}
110
111pub fn f32_value(x: f32) -> Result<Value, JsonError> {
115 Ok(Value::from(f32_decimal(x)?))
116}
117
118pub fn f32_decimal(x: f32) -> Result<f64, JsonError> {
124 if !x.is_finite() {
125 return Err(JsonError(format!("{x}: JSON has no non-finite numbers")));
126 }
127 let shortest: f64 = x
128 .to_string()
129 .parse()
130 .map_err(|e| JsonError(format!("{x}: its decimal does not read back: {e}")))?;
131 Ok(if (shortest as f32).to_bits() == x.to_bits() {
132 shortest
133 } else {
134 f64::from(x)
135 })
136}
137
138pub fn f32s_value(xs: &[f32]) -> Result<Value, JsonError> {
140 xs.iter()
141 .map(|&x| f32_value(x))
142 .collect::<Result<Vec<_>, _>>()
143 .map(Value::Array)
144}
145
146pub fn f64_value(x: f64) -> Result<Value, JsonError> {
148 if !x.is_finite() {
149 return Err(JsonError(format!("{x}: JSON has no non-finite numbers")));
150 }
151 Ok(Value::from(x))
152}
153
154struct Check {
156 path: Vec<String>,
157}
158
159impl Check {
160 fn float(&self, x: f64) -> Result<(), JsonError> {
161 if x.is_finite() {
162 Ok(())
163 } else {
164 let at = if self.path.is_empty() {
165 "the value".to_owned()
166 } else {
167 self.path.join(".")
168 };
169 Err(JsonError(format!("{x} at {at}: JSON has no non-finite numbers")))
170 }
171 }
172
173 fn at<T: Serialize + ?Sized>(&mut self, key: String, v: &T) -> Result<(), JsonError> {
174 self.path.push(key);
175 let r = v.serialize(&mut *self);
176 self.path.pop();
177 r
178 }
179}
180
181struct Items<'a> {
183 c: &'a mut Check,
184 i: usize,
185}
186
187impl Items<'_> {
188 fn item<T: Serialize + ?Sized>(&mut self, v: &T) -> Result<(), JsonError> {
189 let key = format!("[{}]", self.i);
190 self.i += 1;
191 self.c.at(key, v)
192 }
193}
194
195impl<'a> ser::Serializer for &'a mut Check {
196 type Ok = ();
197 type Error = JsonError;
198 type SerializeSeq = Items<'a>;
199 type SerializeTuple = Items<'a>;
200 type SerializeTupleStruct = Items<'a>;
201 type SerializeTupleVariant = Items<'a>;
202 type SerializeMap = Items<'a>;
203 type SerializeStruct = Items<'a>;
204 type SerializeStructVariant = Items<'a>;
205
206 fn serialize_bool(self, _: bool) -> Result<(), JsonError> {
207 Ok(())
208 }
209 fn serialize_i8(self, _: i8) -> Result<(), JsonError> {
210 Ok(())
211 }
212 fn serialize_i16(self, _: i16) -> Result<(), JsonError> {
213 Ok(())
214 }
215 fn serialize_i32(self, _: i32) -> Result<(), JsonError> {
216 Ok(())
217 }
218 fn serialize_i64(self, _: i64) -> Result<(), JsonError> {
219 Ok(())
220 }
221 fn serialize_u8(self, _: u8) -> Result<(), JsonError> {
222 Ok(())
223 }
224 fn serialize_u16(self, _: u16) -> Result<(), JsonError> {
225 Ok(())
226 }
227 fn serialize_u32(self, _: u32) -> Result<(), JsonError> {
228 Ok(())
229 }
230 fn serialize_u64(self, _: u64) -> Result<(), JsonError> {
231 Ok(())
232 }
233 fn serialize_i128(self, _: i128) -> Result<(), JsonError> {
234 Ok(())
235 }
236 fn serialize_u128(self, _: u128) -> Result<(), JsonError> {
237 Ok(())
238 }
239 fn serialize_f32(self, v: f32) -> Result<(), JsonError> {
240 self.float(f64::from(v))
241 }
242 fn serialize_f64(self, v: f64) -> Result<(), JsonError> {
243 self.float(v)
244 }
245 fn serialize_char(self, _: char) -> Result<(), JsonError> {
246 Ok(())
247 }
248 fn serialize_str(self, _: &str) -> Result<(), JsonError> {
249 Ok(())
250 }
251 fn serialize_bytes(self, _: &[u8]) -> Result<(), JsonError> {
252 Ok(())
253 }
254 fn serialize_none(self) -> Result<(), JsonError> {
255 Ok(())
256 }
257 fn serialize_some<T: Serialize + ?Sized>(self, v: &T) -> Result<(), JsonError> {
258 v.serialize(self)
259 }
260 fn serialize_unit(self) -> Result<(), JsonError> {
261 Ok(())
262 }
263 fn serialize_unit_struct(self, _: &'static str) -> Result<(), JsonError> {
264 Ok(())
265 }
266 fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result<(), JsonError> {
267 Ok(())
268 }
269 fn serialize_newtype_struct<T: Serialize + ?Sized>(
270 self,
271 _: &'static str,
272 v: &T,
273 ) -> Result<(), JsonError> {
274 v.serialize(self)
275 }
276 fn serialize_newtype_variant<T: Serialize + ?Sized>(
277 self,
278 _: &'static str,
279 _: u32,
280 variant: &'static str,
281 v: &T,
282 ) -> Result<(), JsonError> {
283 self.at(variant.to_owned(), v)
284 }
285 fn serialize_seq(self, _: Option<usize>) -> Result<Items<'a>, JsonError> {
286 Ok(Items { c: self, i: 0 })
287 }
288 fn serialize_tuple(self, _: usize) -> Result<Items<'a>, JsonError> {
289 Ok(Items { c: self, i: 0 })
290 }
291 fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result<Items<'a>, JsonError> {
292 Ok(Items { c: self, i: 0 })
293 }
294 fn serialize_tuple_variant(
295 self,
296 _: &'static str,
297 _: u32,
298 _: &'static str,
299 _: usize,
300 ) -> Result<Items<'a>, JsonError> {
301 Ok(Items { c: self, i: 0 })
302 }
303 fn serialize_map(self, _: Option<usize>) -> Result<Items<'a>, JsonError> {
304 Ok(Items { c: self, i: 0 })
305 }
306 fn serialize_struct(self, _: &'static str, _: usize) -> Result<Items<'a>, JsonError> {
307 Ok(Items { c: self, i: 0 })
308 }
309 fn serialize_struct_variant(
310 self,
311 _: &'static str,
312 _: u32,
313 _: &'static str,
314 _: usize,
315 ) -> Result<Items<'a>, JsonError> {
316 Ok(Items { c: self, i: 0 })
317 }
318}
319
320impl ser::SerializeSeq for Items<'_> {
321 type Ok = ();
322 type Error = JsonError;
323 fn serialize_element<T: Serialize + ?Sized>(&mut self, v: &T) -> Result<(), JsonError> {
324 self.item(v)
325 }
326 fn end(self) -> Result<(), JsonError> {
327 Ok(())
328 }
329}
330
331impl ser::SerializeTuple for Items<'_> {
332 type Ok = ();
333 type Error = JsonError;
334 fn serialize_element<T: Serialize + ?Sized>(&mut self, v: &T) -> Result<(), JsonError> {
335 self.item(v)
336 }
337 fn end(self) -> Result<(), JsonError> {
338 Ok(())
339 }
340}
341
342impl ser::SerializeTupleStruct for Items<'_> {
343 type Ok = ();
344 type Error = JsonError;
345 fn serialize_field<T: Serialize + ?Sized>(&mut self, v: &T) -> Result<(), JsonError> {
346 self.item(v)
347 }
348 fn end(self) -> Result<(), JsonError> {
349 Ok(())
350 }
351}
352
353impl ser::SerializeTupleVariant for Items<'_> {
354 type Ok = ();
355 type Error = JsonError;
356 fn serialize_field<T: Serialize + ?Sized>(&mut self, v: &T) -> Result<(), JsonError> {
357 self.item(v)
358 }
359 fn end(self) -> Result<(), JsonError> {
360 Ok(())
361 }
362}
363
364impl ser::SerializeMap for Items<'_> {
366 type Ok = ();
367 type Error = JsonError;
368 fn serialize_key<T: Serialize + ?Sized>(&mut self, k: &T) -> Result<(), JsonError> {
369 self.c
371 .path
372 .push(k.serialize(KeyText).unwrap_or_else(|_| "?".to_owned()));
373 Ok(())
374 }
375 fn serialize_value<T: Serialize + ?Sized>(&mut self, v: &T) -> Result<(), JsonError> {
376 let r = v.serialize(&mut *self.c);
377 self.c.path.pop();
378 r
379 }
380 fn end(self) -> Result<(), JsonError> {
381 Ok(())
382 }
383}
384
385impl ser::SerializeStruct for Items<'_> {
386 type Ok = ();
387 type Error = JsonError;
388 fn serialize_field<T: Serialize + ?Sized>(&mut self, key: &'static str, v: &T) -> Result<(), JsonError> {
389 self.c.at(key.to_owned(), v)
390 }
391 fn end(self) -> Result<(), JsonError> {
392 Ok(())
393 }
394}
395
396impl ser::SerializeStructVariant for Items<'_> {
397 type Ok = ();
398 type Error = JsonError;
399 fn serialize_field<T: Serialize + ?Sized>(&mut self, key: &'static str, v: &T) -> Result<(), JsonError> {
400 self.c.at(key.to_owned(), v)
401 }
402 fn end(self) -> Result<(), JsonError> {
403 Ok(())
404 }
405}
406
407struct KeyText;
409
410macro_rules! key_int {
411 ($($f:ident: $t:ty),*) => {$(
412 fn $f(self, v: $t) -> Result<String, JsonError> {
413 Ok(v.to_string())
414 }
415 )*};
416}
417
418impl ser::Serializer for KeyText {
419 type Ok = String;
420 type Error = JsonError;
421 type SerializeSeq = Impossible<String, JsonError>;
422 type SerializeTuple = Impossible<String, JsonError>;
423 type SerializeTupleStruct = Impossible<String, JsonError>;
424 type SerializeTupleVariant = Impossible<String, JsonError>;
425 type SerializeMap = Impossible<String, JsonError>;
426 type SerializeStruct = Impossible<String, JsonError>;
427 type SerializeStructVariant = Impossible<String, JsonError>;
428
429 key_int!(serialize_i8: i8, serialize_i16: i16, serialize_i32: i32, serialize_i64: i64, serialize_u8: u8,
430 serialize_u16: u16, serialize_u32: u32, serialize_u64: u64, serialize_bool: bool, serialize_char: char,
431 serialize_f32: f32, serialize_f64: f64);
432
433 fn serialize_str(self, v: &str) -> Result<String, JsonError> {
434 Ok(v.to_owned())
435 }
436 fn serialize_bytes(self, _: &[u8]) -> Result<String, JsonError> {
437 Err(JsonError("key".into()))
438 }
439 fn serialize_none(self) -> Result<String, JsonError> {
440 Err(JsonError("key".into()))
441 }
442 fn serialize_some<T: Serialize + ?Sized>(self, v: &T) -> Result<String, JsonError> {
443 v.serialize(self)
444 }
445 fn serialize_unit(self) -> Result<String, JsonError> {
446 Err(JsonError("key".into()))
447 }
448 fn serialize_unit_struct(self, n: &'static str) -> Result<String, JsonError> {
449 Ok(n.to_owned())
450 }
451 fn serialize_unit_variant(self, _: &'static str, _: u32, v: &'static str) -> Result<String, JsonError> {
452 Ok(v.to_owned())
453 }
454 fn serialize_newtype_struct<T: Serialize + ?Sized>(
455 self,
456 _: &'static str,
457 v: &T,
458 ) -> Result<String, JsonError> {
459 v.serialize(self)
460 }
461 fn serialize_newtype_variant<T: Serialize + ?Sized>(
462 self,
463 _: &'static str,
464 _: u32,
465 _: &'static str,
466 _: &T,
467 ) -> Result<String, JsonError> {
468 Err(JsonError("key".into()))
469 }
470 fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, JsonError> {
471 Err(JsonError("key".into()))
472 }
473 fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, JsonError> {
474 Err(JsonError("key".into()))
475 }
476 fn serialize_tuple_struct(
477 self,
478 _: &'static str,
479 _: usize,
480 ) -> Result<Self::SerializeTupleStruct, JsonError> {
481 Err(JsonError("key".into()))
482 }
483 fn serialize_tuple_variant(
484 self,
485 _: &'static str,
486 _: u32,
487 _: &'static str,
488 _: usize,
489 ) -> Result<Self::SerializeTupleVariant, JsonError> {
490 Err(JsonError("key".into()))
491 }
492 fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, JsonError> {
493 Err(JsonError("key".into()))
494 }
495 fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct, JsonError> {
496 Err(JsonError("key".into()))
497 }
498 fn serialize_struct_variant(
499 self,
500 _: &'static str,
501 _: u32,
502 _: &'static str,
503 _: usize,
504 ) -> Result<Self::SerializeStructVariant, JsonError> {
505 Err(JsonError("key".into()))
506 }
507}
508
509#[cfg(test)]
510mod tests {
511 use super::*;
512 use std::collections::BTreeMap;
513
514 #[derive(Serialize)]
515 struct T {
516 cols: [[f32; 3]; 2],
517 m: BTreeMap<u32, Vec<f64>>,
518 o: Option<f32>,
519 }
520
521 #[test]
524 fn f32_text_round_trips() {
525 let mut x: u32 = 0x9E37_79B9;
526 let check = |bits: u32| {
527 let f = f32::from_bits(bits);
528 if !f.is_finite() {
529 return;
530 }
531 let text = serde_json::to_string(&f32_value(f).unwrap()).unwrap();
532 let back: Value = serde_json::from_str(&text).unwrap();
533 let g = back.as_f64().unwrap() as f32;
534 assert_eq!(g.to_bits(), bits, "{f:?} -> {text} -> {g:?}");
535 };
536 for bits in [
537 0,
538 0x8000_0000,
539 1,
540 0x8000_0001,
541 0x007F_FFFF,
542 0x0080_0000,
543 0x7F7F_FFFF,
544 0xFF7F_FFFF,
545 ] {
546 check(bits);
547 }
548 for _ in 0..2_000_000 {
549 x ^= x << 13;
551 x ^= x >> 17;
552 x ^= x << 5;
553 check(x);
554 }
555 assert_eq!(serde_json::to_string(&f32_value(-0.0).unwrap()).unwrap(), "-0.0");
556 assert_eq!(serde_json::to_string(&f32_value(0.1).unwrap()).unwrap(), "0.1");
557 for bits in [0x15ae_43fd, 0x95ae_43fd] {
559 check(bits);
560 let f = f32::from_bits(bits);
561 assert_eq!(f32_decimal(f).unwrap(), f64::from(f), "{bits:#x}");
562 }
563 assert!(
564 f32_value(f32::NAN).is_err()
565 && f32_decimal(f32::INFINITY).is_err()
566 && f64_value(f64::NAN).is_err()
567 );
568 }
569
570 #[test]
574 fn json_text_f32_fields_read_back_through_f64() {
575 #[derive(Serialize)]
576 struct R {
577 x: f32,
578 v: Vec<f32>,
579 }
580 #[derive(serde::Deserialize)]
581 struct R2 {
582 v: Vec<f32>,
583 }
584 let hard: Vec<f32> = [0x15ae_43fd, 0x95ae_43fd].map(f32::from_bits).to_vec();
585 for pretty in [false, true] {
586 let text = to_vec(
587 &R {
588 x: 0.1,
589 v: hard.clone(),
590 },
591 pretty,
592 )
593 .unwrap();
594 let back: serde_json::Value = serde_json::from_slice(&text).unwrap();
595 assert_eq!(back["x"].as_f64().unwrap() as f32, 0.1);
596 assert!(
597 String::from_utf8_lossy(&text).contains("0.1"),
598 "{}",
599 String::from_utf8_lossy(&text)
600 );
601 for (k, f) in hard.iter().enumerate() {
602 assert_eq!(
603 (back["v"][k].as_f64().unwrap() as f32).to_bits(),
604 f.to_bits(),
605 "pretty {pretty}"
606 );
607 let r: Vec<f32> = serde_json::from_slice::<R2>(&text).unwrap().v;
609 assert_eq!(r[k].to_bits(), f.to_bits());
610 }
611 }
612 }
613
614 #[test]
616 fn wide_integers_pass_the_check() {
617 assert_eq!(to_value(&5i128).unwrap(), Value::from(5));
618 assert_eq!(
619 to_vec(&(u128::from(u64::MAX) + 1), false).unwrap(),
620 b"18446744073709551616"
621 );
622 }
623
624 #[test]
626 fn json_text_is_exact_and_finite() {
627 #[derive(Serialize)]
628 struct R {
629 x: f32,
630 v: [f32; 2],
631 d: f64,
632 }
633 let r = R {
634 x: 0.1,
635 v: [-0.0, 1e-30],
636 d: 0.1,
637 };
638 assert_eq!(
639 String::from_utf8(to_vec(&r, false).unwrap()).unwrap(),
640 r#"{"x":0.1,"v":[-0.0,1e-30],"d":0.1}"#
641 );
642 assert!(to_vec(&r, true).unwrap().ends_with(b"}\n"));
643 let bad = R { x: f32::NAN, ..r };
644 assert_eq!(
645 to_vec(&bad, false).unwrap_err().0,
646 "NaN at x: JSON has no non-finite numbers"
647 );
648 }
649
650 #[test]
651 fn non_finite_floats_are_errors_with_their_path() {
652 let ok = T {
653 cols: [[1., 2., 3.], [4., 5., 6.]],
654 m: BTreeMap::from([(7, vec![0.5])]),
655 o: Some(-0.0),
656 };
657 assert_eq!(
658 to_value(&ok).unwrap(),
659 serde_json::json!({"cols": [[1., 2., 3.], [4., 5., 6.]], "m": {"7": [0.5]}, "o": -0.0})
660 );
661 let mut bad = ok;
662 bad.cols[1][2] = f32::NAN;
663 assert_eq!(
664 to_value(&bad).unwrap_err().0,
665 "NaN at cols.[1].[2]: JSON has no non-finite numbers"
666 );
667 bad.cols[1][2] = 0.0;
668 bad.m.insert(9, vec![1.0, f64::INFINITY]);
669 assert_eq!(
670 to_value(&bad).unwrap_err().0,
671 "inf at m.9.[1]: JSON has no non-finite numbers"
672 );
673 bad.m.remove(&9);
674 bad.o = Some(f32::NEG_INFINITY);
675 assert_eq!(
676 to_value(&bad).unwrap_err().0,
677 "-inf at o: JSON has no non-finite numbers"
678 );
679 }
680}