1pub(crate) const JS_MAX_SAFE_INTEGER: u64 = 9_007_199_254_740_991;
21
22pub mod json_safe_u64 {
24 use serde::de::{self, Deserializer, Visitor};
25 use serde::ser::Serializer;
26
27 use super::JS_MAX_SAFE_INTEGER;
28
29 pub fn serialize<S: Serializer>(value: &u64, serializer: S) -> Result<S::Ok, S::Error> {
30 if serializer.is_human_readable() && *value > JS_MAX_SAFE_INTEGER {
31 serializer.serialize_str(&value.to_string())
32 } else {
33 serializer.serialize_u64(*value)
34 }
35 }
36
37 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u64, D::Error> {
38 if deserializer.is_human_readable() {
39 deserializer.deserialize_any(U64OrStringVisitor)
40 } else {
41 serde::Deserialize::deserialize(deserializer)
42 }
43 }
44
45 struct U64OrStringVisitor;
46
47 impl<'de> Visitor<'de> for U64OrStringVisitor {
48 type Value = u64;
49
50 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
51 formatter.write_str("a u64 or a string containing a u64")
52 }
53
54 fn visit_u64<E: de::Error>(self, v: u64) -> Result<Self::Value, E> {
55 Ok(v)
56 }
57
58 fn visit_i64<E: de::Error>(self, v: i64) -> Result<Self::Value, E> {
59 u64::try_from(v)
60 .map_err(|_| de::Error::custom(format!("i64 value {v} out of u64 range")))
61 }
62
63 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
64 v.parse::<u64>()
65 .map_err(|_| de::Error::custom(format!("invalid u64 string: {v}")))
66 }
67 }
68}
69
70pub mod json_safe_u128 {
76 use serde::de::{self, Deserializer, Visitor};
77 use serde::ser::Serializer;
78
79 use super::JS_MAX_SAFE_INTEGER;
80
81 pub fn serialize<S: Serializer>(value: &u128, serializer: S) -> Result<S::Ok, S::Error> {
82 if serializer.is_human_readable() && *value > JS_MAX_SAFE_INTEGER as u128 {
83 serializer.serialize_str(&value.to_string())
84 } else {
85 serializer.serialize_u128(*value)
86 }
87 }
88
89 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u128, D::Error> {
90 if deserializer.is_human_readable() {
91 deserializer.deserialize_any(U128OrStringVisitor)
92 } else {
93 serde::Deserialize::deserialize(deserializer)
94 }
95 }
96
97 struct U128OrStringVisitor;
98
99 impl<'de> Visitor<'de> for U128OrStringVisitor {
100 type Value = u128;
101
102 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
103 formatter.write_str("a u128 or a string containing a u128")
104 }
105
106 fn visit_u64<E: de::Error>(self, v: u64) -> Result<Self::Value, E> {
107 Ok(v as u128)
108 }
109
110 fn visit_u128<E: de::Error>(self, v: u128) -> Result<Self::Value, E> {
111 Ok(v)
112 }
113
114 fn visit_i64<E: de::Error>(self, v: i64) -> Result<Self::Value, E> {
115 u128::try_from(v)
116 .map_err(|_| de::Error::custom(format!("i64 value {v} out of u128 range")))
117 }
118
119 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
120 v.parse::<u128>()
121 .map_err(|_| de::Error::custom(format!("invalid u128 string: {v}")))
122 }
123 }
124}
125
126pub mod json_safe_u128_content {
139 use serde::de::{self, Visitor};
140 use serde::{Deserializer, Serializer};
141
142 use super::JS_MAX_SAFE_INTEGER;
143
144 pub fn serialize<S: Serializer>(value: &u128, serializer: S) -> Result<S::Ok, S::Error> {
145 let stringify_above = if serializer.is_human_readable() {
146 JS_MAX_SAFE_INTEGER as u128
147 } else {
148 u64::MAX as u128
149 };
150 if *value > stringify_above {
151 serializer.serialize_str(&value.to_string())
152 } else {
153 serializer.serialize_u64(*value as u64)
154 }
155 }
156
157 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u128, D::Error> {
158 struct V;
159 impl Visitor<'_> for V {
160 type Value = u128;
161 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
162 f.write_str("a u128 as a number or string")
163 }
164 fn visit_u64<E: de::Error>(self, v: u64) -> Result<u128, E> {
165 Ok(v as u128)
166 }
167 fn visit_u128<E: de::Error>(self, v: u128) -> Result<u128, E> {
168 Ok(v)
169 }
170 fn visit_str<E: de::Error>(self, v: &str) -> Result<u128, E> {
171 v.parse()
172 .map_err(|_| de::Error::custom(format!("invalid u128 string: {v}")))
173 }
174 }
175 deserializer.deserialize_any(V)
176 }
177}
178
179pub mod json_safe_i64 {
181 use serde::de::{self, Deserializer, Visitor};
182 use serde::ser::Serializer;
183
184 use super::JS_MAX_SAFE_INTEGER;
185
186 const JS_MIN_SAFE_INTEGER: i64 = -(JS_MAX_SAFE_INTEGER as i64);
187
188 pub fn serialize<S: Serializer>(value: &i64, serializer: S) -> Result<S::Ok, S::Error> {
189 if serializer.is_human_readable()
190 && (*value > JS_MAX_SAFE_INTEGER as i64 || *value < JS_MIN_SAFE_INTEGER)
191 {
192 serializer.serialize_str(&value.to_string())
193 } else {
194 serializer.serialize_i64(*value)
195 }
196 }
197
198 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<i64, D::Error> {
199 if deserializer.is_human_readable() {
200 deserializer.deserialize_any(I64OrStringVisitor)
201 } else {
202 serde::Deserialize::deserialize(deserializer)
203 }
204 }
205
206 struct I64OrStringVisitor;
207
208 impl<'de> Visitor<'de> for I64OrStringVisitor {
209 type Value = i64;
210
211 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
212 formatter.write_str("an i64 or a string containing an i64")
213 }
214
215 fn visit_i64<E: de::Error>(self, v: i64) -> Result<Self::Value, E> {
216 Ok(v)
217 }
218
219 fn visit_u64<E: de::Error>(self, v: u64) -> Result<Self::Value, E> {
220 i64::try_from(v)
221 .map_err(|_| de::Error::custom(format!("u64 value {v} out of i64 range")))
222 }
223
224 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
225 v.parse::<i64>()
226 .map_err(|_| de::Error::custom(format!("invalid i64 string: {v}")))
227 }
228 }
229}
230
231pub mod json_safe_option_u64 {
233 use serde::de::{self, Deserializer, Visitor};
234 use serde::ser::Serializer;
235
236 pub fn serialize<S: Serializer>(value: &Option<u64>, serializer: S) -> Result<S::Ok, S::Error> {
237 match value {
238 Some(v) => super::json_safe_u64::serialize(v, serializer),
239 None => serializer.serialize_none(),
240 }
241 }
242
243 pub fn deserialize<'de, D: Deserializer<'de>>(
244 deserializer: D,
245 ) -> Result<Option<u64>, D::Error> {
246 if deserializer.is_human_readable() {
247 deserializer.deserialize_option(OptionU64Visitor)
248 } else {
249 serde::Deserialize::deserialize(deserializer)
250 }
251 }
252
253 struct OptionU64Visitor;
254
255 impl<'de> Visitor<'de> for OptionU64Visitor {
256 type Value = Option<u64>;
257
258 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
259 formatter.write_str("null, a u64, or a string containing a u64")
260 }
261
262 fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
263 Ok(None)
264 }
265
266 fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
267 Ok(None)
268 }
269
270 fn visit_some<D: Deserializer<'de>>(
271 self,
272 deserializer: D,
273 ) -> Result<Self::Value, D::Error> {
274 super::json_safe_u64::deserialize(deserializer).map(Some)
275 }
276 }
277}
278
279pub mod json_safe_option_i64 {
281 use serde::de::{self, Deserializer, Visitor};
282 use serde::ser::Serializer;
283
284 pub fn serialize<S: Serializer>(value: &Option<i64>, serializer: S) -> Result<S::Ok, S::Error> {
285 match value {
286 Some(v) => super::json_safe_i64::serialize(v, serializer),
287 None => serializer.serialize_none(),
288 }
289 }
290
291 pub fn deserialize<'de, D: Deserializer<'de>>(
292 deserializer: D,
293 ) -> Result<Option<i64>, D::Error> {
294 if deserializer.is_human_readable() {
295 deserializer.deserialize_option(OptionI64Visitor)
296 } else {
297 serde::Deserialize::deserialize(deserializer)
298 }
299 }
300
301 struct OptionI64Visitor;
302
303 impl<'de> Visitor<'de> for OptionI64Visitor {
304 type Value = Option<i64>;
305
306 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
307 formatter.write_str("null, an i64, or a string containing an i64")
308 }
309
310 fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
311 Ok(None)
312 }
313
314 fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
315 Ok(None)
316 }
317
318 fn visit_some<D: Deserializer<'de>>(
319 self,
320 deserializer: D,
321 ) -> Result<Self::Value, D::Error> {
322 super::json_safe_i64::deserialize(deserializer).map(Some)
323 }
324 }
325}
326
327pub mod json_safe_option_string_u64_tuple {
335 use serde::de::{self, Deserializer, SeqAccess, Visitor};
336 use serde::ser::{SerializeTuple, Serializer};
337
338 pub fn serialize<S: Serializer>(
339 value: &Option<(String, u64)>,
340 serializer: S,
341 ) -> Result<S::Ok, S::Error> {
342 match value {
343 Some((s, n)) => {
344 let stringify = serializer.is_human_readable() && *n > super::JS_MAX_SAFE_INTEGER;
345 let mut tup = serializer.serialize_tuple(2)?;
346 tup.serialize_element(s)?;
347 if stringify {
348 tup.serialize_element(&n.to_string())?;
349 } else {
350 tup.serialize_element(n)?;
351 }
352 tup.end()
353 }
354 None => serializer.serialize_none(),
355 }
356 }
357
358 pub fn deserialize<'de, D: Deserializer<'de>>(
359 deserializer: D,
360 ) -> Result<Option<(String, u64)>, D::Error> {
361 deserializer.deserialize_option(OptStringU64TupleVisitor)
362 }
363
364 struct OptStringU64TupleVisitor;
365
366 impl<'de> Visitor<'de> for OptStringU64TupleVisitor {
367 type Value = Option<(String, u64)>;
368
369 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
370 formatter.write_str("null or a 2-tuple [String, u64-or-string]")
371 }
372
373 fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
374 Ok(None)
375 }
376
377 fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
378 Ok(None)
379 }
380
381 fn visit_some<D: Deserializer<'de>>(
382 self,
383 deserializer: D,
384 ) -> Result<Self::Value, D::Error> {
385 deserializer
386 .deserialize_tuple(2, StringU64TupleVisitor)
387 .map(Some)
388 }
389
390 fn visit_seq<A: SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
393 StringU64TupleVisitor.visit_seq(seq).map(Some)
394 }
395 }
396
397 #[derive(serde::Deserialize)]
400 #[serde(transparent)]
401 struct SafeU64(#[serde(with = "super::json_safe_u64")] u64);
402
403 struct StringU64TupleVisitor;
404
405 impl<'de> Visitor<'de> for StringU64TupleVisitor {
406 type Value = (String, u64);
407
408 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
409 formatter.write_str("a 2-tuple [String, u64-or-string]")
410 }
411
412 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
413 let s: String = seq
414 .next_element()?
415 .ok_or_else(|| de::Error::invalid_length(0, &"a 2-tuple"))?;
416 let n: SafeU64 = seq
417 .next_element()?
418 .ok_or_else(|| de::Error::invalid_length(1, &"a 2-tuple"))?;
419 Ok((s, n.0))
420 }
421 }
422}
423
424pub mod json_safe_option_encrypted_note {
434 use serde::de::{self, Deserializer, SeqAccess, Visitor};
435 use serde::ser::{SerializeTuple, Serializer};
436
437 struct BytesAsBytes<'a>(&'a [u8]);
442
443 impl<'a> serde::Serialize for BytesAsBytes<'a> {
444 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
445 s.serialize_bytes(self.0)
446 }
447 }
448
449 pub fn serialize<S: Serializer>(
450 value: &Option<(u32, u32, Vec<u8>)>,
451 serializer: S,
452 ) -> Result<S::Ok, S::Error> {
453 match value {
454 Some((a, b, bytes)) => {
455 let is_hr = serializer.is_human_readable();
456 let mut tup = serializer.serialize_tuple(3)?;
457 tup.serialize_element(a)?;
458 tup.serialize_element(b)?;
459 if is_hr {
460 use base64::Engine;
461 let s = base64::engine::general_purpose::STANDARD.encode(bytes);
462 tup.serialize_element(&s)?;
463 } else {
464 tup.serialize_element(&BytesAsBytes(bytes))?;
465 }
466 tup.end()
467 }
468 None => serializer.serialize_none(),
469 }
470 }
471
472 #[allow(clippy::type_complexity)]
473 pub fn deserialize<'de, D: Deserializer<'de>>(
474 deserializer: D,
475 ) -> Result<Option<(u32, u32, Vec<u8>)>, D::Error> {
476 deserializer.deserialize_option(OptEncryptedNoteVisitor)
477 }
478
479 struct OptEncryptedNoteVisitor;
480
481 impl<'de> Visitor<'de> for OptEncryptedNoteVisitor {
482 type Value = Option<(u32, u32, Vec<u8>)>;
483
484 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
485 formatter.write_str("null or a 3-tuple [u32, u32, base64-string-or-bytes]")
486 }
487
488 fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
489 Ok(None)
490 }
491
492 fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
493 Ok(None)
494 }
495
496 fn visit_some<D: Deserializer<'de>>(
497 self,
498 deserializer: D,
499 ) -> Result<Self::Value, D::Error> {
500 deserializer
501 .deserialize_tuple(3, EncryptedNoteVisitor)
502 .map(Some)
503 }
504
505 fn visit_seq<A: SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
506 EncryptedNoteVisitor.visit_seq(seq).map(Some)
507 }
508 }
509
510 struct BytesField(Vec<u8>);
513
514 impl<'de> serde::Deserialize<'de> for BytesField {
515 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
516 struct V;
517 impl<'de> Visitor<'de> for V {
518 type Value = Vec<u8>;
519
520 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
521 f.write_str("base64 string or byte sequence")
522 }
523
524 fn visit_str<E: de::Error>(self, s: &str) -> Result<Vec<u8>, E> {
525 use base64::Engine;
526 base64::engine::general_purpose::STANDARD
527 .decode(s)
528 .map_err(|e| E::custom(format!("invalid base64: {e}")))
529 }
530
531 fn visit_bytes<E: de::Error>(self, b: &[u8]) -> Result<Vec<u8>, E> {
532 Ok(b.to_vec())
533 }
534
535 fn visit_byte_buf<E: de::Error>(self, b: Vec<u8>) -> Result<Vec<u8>, E> {
536 Ok(b)
537 }
538
539 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Vec<u8>, A::Error> {
540 let mut out = Vec::new();
541 while let Some(b) = seq.next_element::<u8>()? {
542 out.push(b);
543 }
544 Ok(out)
545 }
546 }
547 d.deserialize_any(V).map(BytesField)
550 }
551 }
552
553 struct EncryptedNoteVisitor;
554
555 impl<'de> Visitor<'de> for EncryptedNoteVisitor {
556 type Value = (u32, u32, Vec<u8>);
557
558 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
559 formatter.write_str("a 3-tuple [u32, u32, base64-string-or-bytes]")
560 }
561
562 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
563 let a: u32 = seq
564 .next_element()?
565 .ok_or_else(|| de::Error::invalid_length(0, &"a 3-tuple"))?;
566 let b: u32 = seq
567 .next_element()?
568 .ok_or_else(|| de::Error::invalid_length(1, &"a 3-tuple"))?;
569 let bytes: BytesField = seq
570 .next_element()?
571 .ok_or_else(|| de::Error::invalid_length(2, &"a 3-tuple"))?;
572 Ok((a, b, bytes.0))
573 }
574 }
575}
576
577#[cfg(test)]
578mod tests {
579 use super::*;
580 use serde::{Deserialize, Serialize};
581
582 #[derive(Debug, PartialEq, Serialize, Deserialize)]
583 struct TestU64 {
584 #[serde(with = "json_safe_u64")]
585 value: u64,
586 }
587
588 #[derive(Debug, PartialEq, Serialize, Deserialize)]
589 struct TestU128 {
590 #[serde(with = "json_safe_u128")]
591 value: u128,
592 }
593
594 #[derive(Debug, PartialEq, Serialize, Deserialize)]
595 struct TestI64 {
596 #[serde(with = "json_safe_i64")]
597 value: i64,
598 }
599
600 #[derive(Debug, PartialEq, Serialize, Deserialize)]
601 struct TestOptionU64 {
602 #[serde(default, with = "json_safe_option_u64")]
603 value: Option<u64>,
604 }
605
606 #[derive(Debug, PartialEq, Serialize, Deserialize)]
607 struct TestOptionI64 {
608 #[serde(default, with = "json_safe_option_i64")]
609 value: Option<i64>,
610 }
611
612 #[test]
613 fn u64_small_value_stays_number() {
614 let t = TestU64 { value: 42 };
615 let json = serde_json::to_value(&t).unwrap();
616 assert!(json["value"].is_number());
617 assert_eq!(json["value"].as_u64().unwrap(), 42);
618
619 let restored: TestU64 = serde_json::from_value(json).unwrap();
620 assert_eq!(t, restored);
621 }
622
623 #[test]
624 fn u64_large_value_becomes_string() {
625 let t = TestU64 { value: u64::MAX };
626 let json = serde_json::to_value(&t).unwrap();
627 assert!(json["value"].is_string());
628 assert_eq!(json["value"].as_str().unwrap(), "18446744073709551615");
629
630 let restored: TestU64 = serde_json::from_value(json).unwrap();
631 assert_eq!(t, restored);
632 }
633
634 #[test]
635 fn u128_small_value_stays_number() {
636 let t = TestU128 { value: 42 };
637 let json = serde_json::to_value(&t).unwrap();
638 assert!(json["value"].is_number());
639 assert_eq!(json["value"].as_u64().unwrap(), 42);
640
641 let restored: TestU128 = serde_json::from_value(json).unwrap();
642 assert_eq!(t, restored);
643 }
644
645 #[test]
646 fn u128_large_value_becomes_string() {
647 let t = TestU128 {
649 value: (u64::MAX as u128) + 1,
650 };
651 let json = serde_json::to_value(&t).unwrap();
652 assert!(json["value"].is_string());
653 assert_eq!(json["value"].as_str().unwrap(), "18446744073709551616");
654
655 let restored: TestU128 = serde_json::from_value(json).unwrap();
656 assert_eq!(t, restored);
657 }
658
659 #[test]
660 fn u128_value_round_trips_through_non_human_readable() {
661 let t = TestU128 {
663 value: (u64::MAX as u128) + 12345,
664 };
665 let value = platform_value::to_value(&t).unwrap();
666 let restored: TestU128 = platform_value::from_value(value).unwrap();
667 assert_eq!(t, restored);
668 }
669
670 #[test]
671 fn u64_at_max_safe_integer_stays_number() {
672 let t = TestU64 {
673 value: JS_MAX_SAFE_INTEGER,
674 };
675 let json = serde_json::to_value(&t).unwrap();
676 assert!(json["value"].is_number());
677 }
678
679 #[test]
680 fn u64_above_max_safe_integer_becomes_string() {
681 let t = TestU64 {
682 value: JS_MAX_SAFE_INTEGER + 1,
683 };
684 let json = serde_json::to_value(&t).unwrap();
685 assert!(json["value"].is_string());
686 }
687
688 #[test]
689 fn i64_small_value_stays_number() {
690 let t = TestI64 { value: -42 };
691 let json = serde_json::to_value(&t).unwrap();
692 assert!(json["value"].is_number());
693
694 let restored: TestI64 = serde_json::from_value(json).unwrap();
695 assert_eq!(t, restored);
696 }
697
698 #[test]
699 fn i64_large_value_becomes_string() {
700 let t = TestI64 { value: i64::MAX };
701 let json = serde_json::to_value(&t).unwrap();
702 assert!(json["value"].is_string());
703
704 let restored: TestI64 = serde_json::from_value(json).unwrap();
705 assert_eq!(t, restored);
706 }
707
708 #[test]
709 fn i64_large_negative_becomes_string() {
710 let t = TestI64 { value: i64::MIN };
711 let json = serde_json::to_value(&t).unwrap();
712 assert!(json["value"].is_string());
713
714 let restored: TestI64 = serde_json::from_value(json).unwrap();
715 assert_eq!(t, restored);
716 }
717
718 #[test]
719 fn option_u64_none_round_trip() {
720 let t = TestOptionU64 { value: None };
721 let json = serde_json::to_value(&t).unwrap();
722 assert!(json["value"].is_null());
723
724 let restored: TestOptionU64 = serde_json::from_value(json).unwrap();
725 assert_eq!(t, restored);
726 }
727
728 #[test]
729 fn option_u64_large_round_trip() {
730 let t = TestOptionU64 {
731 value: Some(u64::MAX),
732 };
733 let json = serde_json::to_value(&t).unwrap();
734 assert!(json["value"].is_string());
735
736 let restored: TestOptionU64 = serde_json::from_value(json).unwrap();
737 assert_eq!(t, restored);
738 }
739
740 #[test]
741 fn platform_value_u64_stays_native() {
742 let t = TestU64 { value: u64::MAX };
743 let pv = platform_value::to_value(&t).unwrap();
744
745 let restored: TestU64 = platform_value::from_value(pv).unwrap();
747 assert_eq!(t, restored);
748 }
749
750 #[test]
751 fn option_i64_none_round_trip() {
752 let t = TestOptionI64 { value: None };
753 let json = serde_json::to_value(&t).unwrap();
754 assert!(json["value"].is_null());
755
756 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
757 assert_eq!(t, restored);
758 }
759
760 #[test]
761 fn option_i64_large_round_trip() {
762 let t = TestOptionI64 {
763 value: Some(i64::MAX),
764 };
765 let json = serde_json::to_value(&t).unwrap();
766 assert!(json["value"].is_string());
767
768 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
769 assert_eq!(t, restored);
770 }
771
772 #[test]
773 fn option_i64_large_negative_round_trip() {
774 let t = TestOptionI64 {
775 value: Some(i64::MIN),
776 };
777 let json = serde_json::to_value(&t).unwrap();
778 assert!(json["value"].is_string());
779
780 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
781 assert_eq!(t, restored);
782 }
783
784 #[test]
785 fn option_i64_missing_field_deserializes_as_none() {
786 let json = serde_json::json!({});
787 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
788 assert_eq!(restored.value, None);
789 }
790
791 #[test]
792 fn option_u64_missing_field_deserializes_as_none() {
793 let json = serde_json::json!({});
794 let restored: TestOptionU64 = serde_json::from_value(json).unwrap();
795 assert_eq!(restored.value, None);
796 }
797
798 #[test]
799 fn u64_deserialize_from_i64_value() {
800 let json = serde_json::json!({"value": 42});
802 let restored: TestU64 = serde_json::from_value(json).unwrap();
803 assert_eq!(restored.value, 42);
804 }
805
806 #[test]
807 fn u64_deserialize_negative_i64_fails() {
808 let json = serde_json::json!({"value": -1});
810 let result = serde_json::from_value::<TestU64>(json);
811 assert!(result.is_err());
812 assert!(result.unwrap_err().to_string().contains("out of u64 range"));
813 }
814
815 #[test]
816 fn u64_deserialize_invalid_string_fails() {
817 let json = serde_json::json!({"value": "not_a_number"});
818 let result = serde_json::from_value::<TestU64>(json);
819 assert!(result.is_err());
820 assert!(result
821 .unwrap_err()
822 .to_string()
823 .contains("invalid u64 string"));
824 }
825
826 #[test]
827 fn i64_deserialize_u64_overflow_fails() {
828 let json = serde_json::json!({"value": u64::MAX.to_string()});
830 let result = serde_json::from_value::<TestI64>(json);
832 assert!(result.is_err());
833 }
834
835 #[test]
836 fn i64_deserialize_invalid_string_fails() {
837 let json = serde_json::json!({"value": "not_a_number"});
838 let result = serde_json::from_value::<TestI64>(json);
839 assert!(result.is_err());
840 assert!(result
841 .unwrap_err()
842 .to_string()
843 .contains("invalid i64 string"));
844 }
845
846 #[test]
847 fn platform_value_i64_stays_native() {
848 let t = TestI64 { value: i64::MAX };
849 let pv = platform_value::to_value(&t).unwrap();
850 let restored: TestI64 = platform_value::from_value(pv).unwrap();
851 assert_eq!(t, restored);
852 }
853
854 #[test]
855 fn platform_value_option_u64_round_trip() {
856 let t = TestOptionU64 {
857 value: Some(u64::MAX),
858 };
859 let pv = platform_value::to_value(&t).unwrap();
860 let restored: TestOptionU64 = platform_value::from_value(pv).unwrap();
861 assert_eq!(t, restored);
862 }
863
864 #[test]
865 fn platform_value_option_i64_round_trip() {
866 let t = TestOptionI64 {
867 value: Some(i64::MIN),
868 };
869 let pv = platform_value::to_value(&t).unwrap();
870 let restored: TestOptionI64 = platform_value::from_value(pv).unwrap();
871 assert_eq!(t, restored);
872 }
873
874 #[test]
875 fn option_u64_small_value_stays_number() {
876 let t = TestOptionU64 { value: Some(42) };
877 let json = serde_json::to_value(&t).unwrap();
878 assert!(json["value"].is_number());
879
880 let restored: TestOptionU64 = serde_json::from_value(json).unwrap();
881 assert_eq!(t, restored);
882 }
883
884 #[test]
885 fn option_i64_small_value_stays_number() {
886 let t = TestOptionI64 { value: Some(-42) };
887 let json = serde_json::to_value(&t).unwrap();
888 assert!(json["value"].is_number());
889
890 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
891 assert_eq!(t, restored);
892 }
893
894 #[test]
895 fn tagged_enum_with_u64_round_trip() {
896 #[derive(Debug, PartialEq, Serialize, Deserialize)]
897 #[serde(tag = "$formatVersion")]
898 enum Versioned {
899 #[serde(rename = "0")]
900 V0(TestU64),
901 }
902
903 let v = Versioned::V0(TestU64 { value: u64::MAX });
904 let json = serde_json::to_value(&v).unwrap();
905 assert_eq!(json["$formatVersion"], "0");
906 assert!(json["value"].is_string());
907
908 let restored: Versioned = serde_json::from_value(json).unwrap();
909 assert_eq!(v, restored);
910 }
911
912 #[test]
915 fn option_i64_some_safe_value_stays_number() {
916 let t = TestOptionI64 { value: Some(1000) };
917 let json = serde_json::to_value(&t).unwrap();
918 assert!(json["value"].is_number());
919 assert_eq!(json["value"].as_i64().unwrap(), 1000);
920
921 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
922 assert_eq!(t, restored);
923 }
924
925 #[test]
926 fn option_i64_some_unsafe_positive_becomes_string() {
927 let unsafe_val = (JS_MAX_SAFE_INTEGER + 1) as i64;
929 let t = TestOptionI64 {
930 value: Some(unsafe_val),
931 };
932 let json = serde_json::to_value(&t).unwrap();
933 assert!(json["value"].is_string());
934
935 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
936 assert_eq!(t, restored);
937 }
938
939 #[test]
940 fn option_i64_some_unsafe_negative_becomes_string() {
941 let unsafe_neg = -(JS_MAX_SAFE_INTEGER as i64) - 1;
943 let t = TestOptionI64 {
944 value: Some(unsafe_neg),
945 };
946 let json = serde_json::to_value(&t).unwrap();
947 assert!(json["value"].is_string());
948
949 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
950 assert_eq!(t, restored);
951 }
952
953 #[test]
956 fn u64_exactly_at_max_safe_integer_round_trip() {
957 let t = TestU64 {
958 value: JS_MAX_SAFE_INTEGER,
959 };
960 let json = serde_json::to_value(&t).unwrap();
961 assert!(json["value"].is_number());
962
963 let restored: TestU64 = serde_json::from_value(json).unwrap();
964 assert_eq!(t, restored);
965 }
966
967 #[test]
968 fn u64_one_above_max_safe_integer_round_trip() {
969 let t = TestU64 {
970 value: JS_MAX_SAFE_INTEGER + 1,
971 };
972 let json = serde_json::to_value(&t).unwrap();
973 assert!(json["value"].is_string());
974 assert_eq!(
975 json["value"].as_str().unwrap(),
976 (JS_MAX_SAFE_INTEGER + 1).to_string()
977 );
978
979 let restored: TestU64 = serde_json::from_value(json).unwrap();
980 assert_eq!(t, restored);
981 }
982
983 #[test]
984 fn i64_exactly_at_positive_safe_boundary_stays_number() {
985 let t = TestI64 {
986 value: JS_MAX_SAFE_INTEGER as i64,
987 };
988 let json = serde_json::to_value(&t).unwrap();
989 assert!(json["value"].is_number());
990
991 let restored: TestI64 = serde_json::from_value(json).unwrap();
992 assert_eq!(t, restored);
993 }
994
995 #[test]
996 fn i64_one_above_positive_safe_boundary_becomes_string() {
997 let t = TestI64 {
998 value: JS_MAX_SAFE_INTEGER as i64 + 1,
999 };
1000 let json = serde_json::to_value(&t).unwrap();
1001 assert!(json["value"].is_string());
1002
1003 let restored: TestI64 = serde_json::from_value(json).unwrap();
1004 assert_eq!(t, restored);
1005 }
1006
1007 #[test]
1008 fn i64_exactly_at_negative_safe_boundary_stays_number() {
1009 let t = TestI64 {
1010 value: -(JS_MAX_SAFE_INTEGER as i64),
1011 };
1012 let json = serde_json::to_value(&t).unwrap();
1013 assert!(json["value"].is_number());
1014
1015 let restored: TestI64 = serde_json::from_value(json).unwrap();
1016 assert_eq!(t, restored);
1017 }
1018
1019 #[test]
1020 fn i64_one_below_negative_safe_boundary_becomes_string() {
1021 let t = TestI64 {
1022 value: -(JS_MAX_SAFE_INTEGER as i64) - 1,
1023 };
1024 let json = serde_json::to_value(&t).unwrap();
1025 assert!(json["value"].is_string());
1026
1027 let restored: TestI64 = serde_json::from_value(json).unwrap();
1028 assert_eq!(t, restored);
1029 }
1030
1031 #[test]
1034 fn u64_zero_stays_number() {
1035 let t = TestU64 { value: 0 };
1036 let json = serde_json::to_value(&t).unwrap();
1037 assert!(json["value"].is_number());
1038 assert_eq!(json["value"].as_u64().unwrap(), 0);
1039
1040 let restored: TestU64 = serde_json::from_value(json).unwrap();
1041 assert_eq!(t, restored);
1042 }
1043
1044 #[test]
1045 fn i64_zero_stays_number() {
1046 let t = TestI64 { value: 0 };
1047 let json = serde_json::to_value(&t).unwrap();
1048 assert!(json["value"].is_number());
1049 assert_eq!(json["value"].as_i64().unwrap(), 0);
1050
1051 let restored: TestI64 = serde_json::from_value(json).unwrap();
1052 assert_eq!(t, restored);
1053 }
1054
1055 #[test]
1056 fn i64_negative_one_stays_number() {
1057 let t = TestI64 { value: -1 };
1058 let json = serde_json::to_value(&t).unwrap();
1059 assert!(json["value"].is_number());
1060
1061 let restored: TestI64 = serde_json::from_value(json).unwrap();
1062 assert_eq!(t, restored);
1063 }
1064
1065 #[test]
1066 fn option_i64_zero_round_trip() {
1067 let t = TestOptionI64 { value: Some(0) };
1068 let json = serde_json::to_value(&t).unwrap();
1069 assert!(json["value"].is_number());
1070
1071 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
1072 assert_eq!(t, restored);
1073 }
1074
1075 #[test]
1076 fn option_u64_zero_round_trip() {
1077 let t = TestOptionU64 { value: Some(0) };
1078 let json = serde_json::to_value(&t).unwrap();
1079 assert!(json["value"].is_number());
1080
1081 let restored: TestOptionU64 = serde_json::from_value(json).unwrap();
1082 assert_eq!(t, restored);
1083 }
1084
1085 #[test]
1086 fn option_u64_at_max_safe_integer_stays_number() {
1087 let t = TestOptionU64 {
1088 value: Some(JS_MAX_SAFE_INTEGER),
1089 };
1090 let json = serde_json::to_value(&t).unwrap();
1091 assert!(json["value"].is_number());
1092
1093 let restored: TestOptionU64 = serde_json::from_value(json).unwrap();
1094 assert_eq!(t, restored);
1095 }
1096
1097 #[test]
1098 fn option_u64_above_max_safe_integer_becomes_string() {
1099 let t = TestOptionU64 {
1100 value: Some(JS_MAX_SAFE_INTEGER + 1),
1101 };
1102 let json = serde_json::to_value(&t).unwrap();
1103 assert!(json["value"].is_string());
1104
1105 let restored: TestOptionU64 = serde_json::from_value(json).unwrap();
1106 assert_eq!(t, restored);
1107 }
1108
1109 #[test]
1110 fn option_i64_at_positive_safe_boundary_stays_number() {
1111 let t = TestOptionI64 {
1112 value: Some(JS_MAX_SAFE_INTEGER as i64),
1113 };
1114 let json = serde_json::to_value(&t).unwrap();
1115 assert!(json["value"].is_number());
1116
1117 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
1118 assert_eq!(t, restored);
1119 }
1120
1121 #[test]
1122 fn option_i64_above_positive_safe_boundary_becomes_string() {
1123 let t = TestOptionI64 {
1124 value: Some(JS_MAX_SAFE_INTEGER as i64 + 1),
1125 };
1126 let json = serde_json::to_value(&t).unwrap();
1127 assert!(json["value"].is_string());
1128
1129 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
1130 assert_eq!(t, restored);
1131 }
1132
1133 #[test]
1134 fn option_i64_at_negative_safe_boundary_stays_number() {
1135 let t = TestOptionI64 {
1136 value: Some(-(JS_MAX_SAFE_INTEGER as i64)),
1137 };
1138 let json = serde_json::to_value(&t).unwrap();
1139 assert!(json["value"].is_number());
1140
1141 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
1142 assert_eq!(t, restored);
1143 }
1144
1145 #[test]
1146 fn option_i64_below_negative_safe_boundary_becomes_string() {
1147 let t = TestOptionI64 {
1148 value: Some(-(JS_MAX_SAFE_INTEGER as i64) - 1),
1149 };
1150 let json = serde_json::to_value(&t).unwrap();
1151 assert!(json["value"].is_string());
1152
1153 let restored: TestOptionI64 = serde_json::from_value(json).unwrap();
1154 assert_eq!(t, restored);
1155 }
1156
1157 #[test]
1158 fn platform_value_option_i64_none_round_trip() {
1159 let t = TestOptionI64 { value: None };
1160 let pv = platform_value::to_value(&t).unwrap();
1161 let restored: TestOptionI64 = platform_value::from_value(pv).unwrap();
1162 assert_eq!(t, restored);
1163 }
1164
1165 #[test]
1166 fn platform_value_option_u64_none_round_trip() {
1167 let t = TestOptionU64 { value: None };
1168 let pv = platform_value::to_value(&t).unwrap();
1169 let restored: TestOptionU64 = platform_value::from_value(pv).unwrap();
1170 assert_eq!(t, restored);
1171 }
1172
1173 #[test]
1174 fn u64_deserialize_from_string_number() {
1175 let json = serde_json::json!({"value": "42"});
1177 let restored: TestU64 = serde_json::from_value(json).unwrap();
1178 assert_eq!(restored.value, 42);
1179 }
1180
1181 #[test]
1182 fn i64_deserialize_from_string_number() {
1183 let json = serde_json::json!({"value": "-12345"});
1184 let restored: TestI64 = serde_json::from_value(json).unwrap();
1185 assert_eq!(restored.value, -12345);
1186 }
1187}