1use std::str::FromStr;
26
27use bytes::Bytes;
28use rust_decimal::Decimal;
29use serde::{
30 Deserialize, Deserializer, Serialize, Serializer,
31 de::{Error, Unexpected, Visitor},
32 ser::SerializeSeq,
33};
34use ustr::Ustr;
35
36pub mod sorted_hashset {
40 use ahash::AHashSet;
41 use serde::{Deserialize, Deserializer, Serialize, Serializer};
42
43 pub fn serialize<T, S>(set: &AHashSet<T>, s: S) -> Result<S::Ok, S::Error>
45 where
46 T: Serialize + Ord,
47 S: Serializer,
48 {
49 let mut sorted: Vec<&T> = set.iter().collect();
50 sorted.sort_unstable();
51 sorted.serialize(s)
52 }
53
54 pub fn deserialize<'de, T, D>(d: D) -> Result<AHashSet<T>, D::Error>
56 where
57 T: Deserialize<'de> + Eq + std::hash::Hash,
58 D: Deserializer<'de>,
59 {
60 let vec = Vec::<T>::deserialize(d)?;
61 Ok(vec.into_iter().collect())
62 }
63}
64
65struct BoolVisitor;
66
67struct DecimalVisitor;
72
73impl Visitor<'_> for DecimalVisitor {
74 type Value = Decimal;
75
76 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
77 formatter.write_str("a decimal number as string, integer, or float")
78 }
79
80 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
82 if v.is_empty() {
83 return Ok(Decimal::ZERO);
84 }
85 if v.contains('e') || v.contains('E') {
87 Decimal::from_scientific(v).map_err(E::custom)
88 } else {
89 Decimal::from_str(v).map_err(E::custom)
90 }
91 }
92
93 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
95 self.visit_str(&v)
96 }
97
98 fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
100 Ok(Decimal::from(v))
101 }
102
103 fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
104 Ok(Decimal::from(v))
105 }
106
107 fn visit_i128<E: Error>(self, v: i128) -> Result<Self::Value, E> {
108 Ok(Decimal::from(v))
109 }
110
111 fn visit_u128<E: Error>(self, v: u128) -> Result<Self::Value, E> {
112 Ok(Decimal::from(v))
113 }
114
115 fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
117 if v.is_nan() {
118 return Err(E::invalid_value(Unexpected::Float(v), &self));
119 }
120
121 if v.is_infinite() {
122 return Err(E::invalid_value(Unexpected::Float(v), &self));
123 }
124 Decimal::try_from(v).map_err(E::custom)
125 }
126
127 fn visit_unit<E: Error>(self) -> Result<Self::Value, E> {
129 Ok(Decimal::ZERO)
130 }
131
132 fn visit_none<E: Error>(self) -> Result<Self::Value, E> {
133 Ok(Decimal::ZERO)
134 }
135}
136
137struct OptionalDecimalVisitor;
142
143impl Visitor<'_> for OptionalDecimalVisitor {
144 type Value = Option<Decimal>;
145
146 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
147 formatter.write_str("null or a decimal number as string, integer, or float")
148 }
149
150 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
153 if v.is_empty() {
154 return Ok(None);
155 }
156 DecimalVisitor.visit_str(v).map(Some)
157 }
158
159 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
160 self.visit_str(&v)
161 }
162
163 fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
164 DecimalVisitor.visit_i64(v).map(Some)
165 }
166
167 fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
168 DecimalVisitor.visit_u64(v).map(Some)
169 }
170
171 fn visit_i128<E: Error>(self, v: i128) -> Result<Self::Value, E> {
172 DecimalVisitor.visit_i128(v).map(Some)
173 }
174
175 fn visit_u128<E: Error>(self, v: u128) -> Result<Self::Value, E> {
176 DecimalVisitor.visit_u128(v).map(Some)
177 }
178
179 fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
180 DecimalVisitor.visit_f64(v).map(Some)
181 }
182
183 fn visit_unit<E: Error>(self) -> Result<Self::Value, E> {
185 Ok(None)
186 }
187
188 fn visit_none<E: Error>(self) -> Result<Self::Value, E> {
189 Ok(None)
190 }
191}
192
193pub trait Serializable: Serialize + for<'de> Deserialize<'de> {
195 fn from_json_bytes(data: &[u8]) -> Result<Self, serde_json::Error> {
201 serde_json::from_slice(data)
202 }
203
204 fn to_json_bytes(&self) -> Result<Bytes, serde_json::Error> {
210 serde_json::to_vec(self).map(Bytes::from)
211 }
212}
213
214pub use self::msgpack::{FromMsgPack, MsgPackSerializable, ToMsgPack};
215
216pub mod msgpack {
221 use bytes::Bytes;
222 use serde::{Deserialize, Serialize};
223
224 use super::Serializable;
225
226 pub trait FromMsgPack: for<'de> Deserialize<'de> + Sized {
228 fn from_msgpack_bytes(data: &[u8]) -> Result<Self, rmp_serde::decode::Error> {
234 rmp_serde::from_slice(data)
235 }
236 }
237
238 pub trait ToMsgPack: Serialize {
240 fn to_msgpack_bytes(&self) -> Result<Bytes, rmp_serde::encode::Error> {
246 rmp_serde::to_vec_named(self).map(Bytes::from)
247 }
248 }
249
250 pub trait MsgPackSerializable: Serializable + FromMsgPack + ToMsgPack {}
254
255 impl<T> FromMsgPack for T where T: Serializable {}
256
257 impl<T> ToMsgPack for T where T: Serializable {}
258
259 impl<T> MsgPackSerializable for T where T: Serializable {}
260}
261
262impl Visitor<'_> for BoolVisitor {
263 type Value = u8;
264
265 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266 formatter.write_str("a boolean as u8")
267 }
268
269 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
270 where
271 E: serde::de::Error,
272 {
273 Ok(u8::from(value))
274 }
275
276 #[allow(
277 clippy::cast_possible_truncation,
278 reason = "Intentional for parsing, value range validated"
279 )]
280 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
281 where
282 E: serde::de::Error,
283 {
284 if value > 1 {
289 Err(E::invalid_value(Unexpected::Unsigned(value), &self))
290 } else {
291 Ok(value as u8)
292 }
293 }
294}
295
296#[must_use]
300pub const fn default_true() -> bool {
301 true
302}
303
304#[must_use]
308pub const fn default_false() -> bool {
309 false
310}
311
312pub fn from_bool_as_u8<'de, D>(deserializer: D) -> Result<u8, D::Error>
318where
319 D: Deserializer<'de>,
320{
321 deserializer.deserialize_any(BoolVisitor)
322}
323
324pub fn deserialize_decimal<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
346where
347 D: Deserializer<'de>,
348{
349 deserializer.deserialize_any(DecimalVisitor)
350}
351
352pub fn deserialize_optional_decimal<'de, D>(deserializer: D) -> Result<Option<Decimal>, D::Error>
375where
376 D: Deserializer<'de>,
377{
378 deserializer.deserialize_any(OptionalDecimalVisitor)
381}
382
383pub fn serialize_decimal<S: Serializer>(d: &Decimal, s: S) -> Result<S::Ok, S::Error> {
391 rust_decimal::serde::float::serialize(d, s)
392}
393
394pub fn serialize_optional_decimal<S: Serializer>(
400 d: &Option<Decimal>,
401 s: S,
402) -> Result<S::Ok, S::Error> {
403 match d {
404 Some(decimal) => rust_decimal::serde::float::serialize(decimal, s),
405 None => s.serialize_none(),
406 }
407}
408
409pub fn deserialize_decimal_from_str<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
418where
419 D: Deserializer<'de>,
420{
421 let s = String::deserialize(deserializer)?;
422 Decimal::from_str(&s).map_err(D::Error::custom)
423}
424
425pub fn deserialize_decimal_or_zero<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
433where
434 D: Deserializer<'de>,
435{
436 let s: String = Deserialize::deserialize(deserializer)?;
437 if s.is_empty() || s == "0" {
438 Ok(Decimal::ZERO)
439 } else {
440 Decimal::from_str(&s).map_err(D::Error::custom)
441 }
442}
443
444pub fn deserialize_optional_decimal_str<'de, D>(
454 deserializer: D,
455) -> Result<Option<Decimal>, D::Error>
456where
457 D: Deserializer<'de>,
458{
459 let s: String = Deserialize::deserialize(deserializer)?;
460 if s.is_empty() || s == "0" {
461 Ok(None)
462 } else {
463 Decimal::from_str(&s).map(Some).map_err(D::Error::custom)
464 }
465}
466
467pub fn deserialize_optional_decimal_from_str<'de, D>(
476 deserializer: D,
477) -> Result<Option<Decimal>, D::Error>
478where
479 D: Deserializer<'de>,
480{
481 let opt = Option::<String>::deserialize(deserializer)?;
482 match opt {
483 Some(s) if !s.is_empty() => Decimal::from_str(&s).map(Some).map_err(D::Error::custom),
484 _ => Ok(None),
485 }
486}
487
488pub fn deserialize_optional_decimal_or_zero<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
496where
497 D: Deserializer<'de>,
498{
499 let opt: Option<String> = Deserialize::deserialize(deserializer)?;
500 match opt {
501 None => Ok(Decimal::ZERO),
502 Some(s) if s.is_empty() || s == "0" => Ok(Decimal::ZERO),
503 Some(s) => Decimal::from_str(&s).map_err(D::Error::custom),
504 }
505}
506
507pub fn deserialize_vec_decimal_from_str<'de, D>(deserializer: D) -> Result<Vec<Decimal>, D::Error>
513where
514 D: Deserializer<'de>,
515{
516 let strings = Vec::<String>::deserialize(deserializer)?;
517 strings
518 .into_iter()
519 .map(|s| Decimal::from_str(&s).map_err(D::Error::custom))
520 .collect()
521}
522
523pub fn serialize_decimal_as_str<S>(decimal: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
529where
530 S: Serializer,
531{
532 serializer.serialize_str(&decimal.to_string())
533}
534
535pub fn serialize_optional_decimal_as_str<S>(
541 decimal: &Option<Decimal>,
542 serializer: S,
543) -> Result<S::Ok, S::Error>
544where
545 S: Serializer,
546{
547 match decimal {
548 Some(d) => serializer.serialize_str(&d.to_string()),
549 None => serializer.serialize_none(),
550 }
551}
552
553pub fn serialize_vec_decimal_as_str<S>(
559 decimals: &Vec<Decimal>,
560 serializer: S,
561) -> Result<S::Ok, S::Error>
562where
563 S: Serializer,
564{
565 let mut seq = serializer.serialize_seq(Some(decimals.len()))?;
566 for decimal in decimals {
567 seq.serialize_element(&decimal.to_string())?;
568 }
569 seq.end()
570}
571
572pub fn parse_decimal(s: &str) -> anyhow::Result<Decimal> {
578 Decimal::from_str(s).map_err(|e| anyhow::anyhow!("Failed to parse decimal from '{s}': {e}"))
579}
580
581pub fn parse_optional_decimal(s: &Option<String>) -> anyhow::Result<Option<Decimal>> {
587 match s {
588 None => Ok(None),
589 Some(s) if s.is_empty() => Ok(None),
590 Some(s) => parse_decimal(s).map(Some),
591 }
592}
593
594pub fn deserialize_empty_string_as_none<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
606where
607 D: Deserializer<'de>,
608{
609 let opt = Option::<String>::deserialize(deserializer)?;
610 Ok(opt.filter(|s| !s.is_empty()))
611}
612
613pub fn deserialize_empty_ustr_as_none<'de, D>(deserializer: D) -> Result<Option<Ustr>, D::Error>
619where
620 D: Deserializer<'de>,
621{
622 let opt = Option::<Ustr>::deserialize(deserializer)?;
623 Ok(opt.filter(|s| !s.is_empty()))
624}
625
626pub fn deserialize_string_to_u8<'de, D>(deserializer: D) -> Result<u8, D::Error>
634where
635 D: Deserializer<'de>,
636{
637 let s: String = Deserialize::deserialize(deserializer)?;
638 if s.is_empty() {
639 return Ok(0);
640 }
641 s.parse::<u8>().map_err(D::Error::custom)
642}
643
644pub fn deserialize_string_to_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
652where
653 D: Deserializer<'de>,
654{
655 let s = String::deserialize(deserializer)?;
656 if s.is_empty() {
657 Ok(0)
658 } else {
659 s.parse::<u64>().map_err(D::Error::custom)
660 }
661}
662
663pub fn deserialize_optional_string_to_u64<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
671where
672 D: Deserializer<'de>,
673{
674 let s: Option<String> = Option::deserialize(deserializer)?;
675 match s {
676 Some(s) if s.is_empty() => Ok(None),
677 Some(s) => s.parse().map(Some).map_err(D::Error::custom),
678 None => Ok(None),
679 }
680}
681
682#[cfg(test)]
683mod tests {
684 use rstest::*;
685 use rust_decimal::Decimal;
686 use rust_decimal_macros::dec;
687 use serde::{Deserialize, Serialize};
688 use ustr::Ustr;
689
690 use super::{
691 Serializable, deserialize_decimal, deserialize_decimal_from_str,
692 deserialize_decimal_or_zero, deserialize_empty_string_as_none,
693 deserialize_empty_ustr_as_none, deserialize_optional_decimal,
694 deserialize_optional_decimal_or_zero, deserialize_optional_decimal_str,
695 deserialize_optional_string_to_u64, deserialize_string_to_u8, deserialize_string_to_u64,
696 deserialize_vec_decimal_from_str, from_bool_as_u8,
697 msgpack::{FromMsgPack, ToMsgPack},
698 parse_decimal, parse_optional_decimal, serialize_decimal, serialize_decimal_as_str,
699 serialize_optional_decimal, serialize_optional_decimal_as_str,
700 serialize_vec_decimal_as_str,
701 };
702
703 #[derive(Deserialize)]
704 pub struct TestStruct {
705 #[serde(deserialize_with = "from_bool_as_u8")]
706 pub value: u8,
707 }
708
709 #[rstest]
710 #[case(r#"{"value": true}"#, 1)]
711 #[case(r#"{"value": false}"#, 0)]
712 fn test_deserialize_bool_as_u8_with_boolean(#[case] json_str: &str, #[case] expected: u8) {
713 let test_struct: TestStruct = serde_json::from_str(json_str).unwrap();
714 assert_eq!(test_struct.value, expected);
715 }
716
717 #[rstest]
718 #[case(r#"{"value": 1}"#, 1)]
719 #[case(r#"{"value": 0}"#, 0)]
720 fn test_deserialize_bool_as_u8_with_u64(#[case] json_str: &str, #[case] expected: u8) {
721 let test_struct: TestStruct = serde_json::from_str(json_str).unwrap();
722 assert_eq!(test_struct.value, expected);
723 }
724
725 #[rstest]
726 fn test_deserialize_bool_as_u8_with_invalid_integer() {
727 let json = r#"{"value": 2}"#;
729 let result: Result<TestStruct, _> = serde_json::from_str(json);
730 assert!(result.is_err());
731 }
732
733 #[derive(Serialize, Deserialize, PartialEq, Debug)]
734 struct SerializableTestStruct {
735 id: u32,
736 name: String,
737 value: f64,
738 }
739
740 impl Serializable for SerializableTestStruct {}
741
742 #[rstest]
743 fn test_serializable_json_roundtrip() {
744 let original = SerializableTestStruct {
745 id: 42,
746 name: "test".to_string(),
747 value: std::f64::consts::PI,
748 };
749
750 let json_bytes = original.to_json_bytes().unwrap();
751 let deserialized = SerializableTestStruct::from_json_bytes(&json_bytes).unwrap();
752
753 assert_eq!(original, deserialized);
754 }
755
756 #[rstest]
757 fn test_serializable_msgpack_roundtrip() {
758 let original = SerializableTestStruct {
759 id: 123,
760 name: "msgpack_test".to_string(),
761 value: std::f64::consts::E,
762 };
763
764 let msgpack_bytes = original.to_msgpack_bytes().unwrap();
765 let deserialized = SerializableTestStruct::from_msgpack_bytes(&msgpack_bytes).unwrap();
766
767 assert_eq!(original, deserialized);
768 }
769
770 #[rstest]
771 fn test_serializable_json_invalid_data() {
772 let invalid_json = b"invalid json data";
773 let result = SerializableTestStruct::from_json_bytes(invalid_json);
774 assert!(result.is_err());
775 }
776
777 #[rstest]
778 fn test_serializable_msgpack_invalid_data() {
779 let invalid_msgpack = b"invalid msgpack data";
780 let result = SerializableTestStruct::from_msgpack_bytes(invalid_msgpack);
781 assert!(result.is_err());
782 }
783
784 #[rstest]
785 fn test_serializable_json_empty_values() {
786 let test_struct = SerializableTestStruct {
787 id: 0,
788 name: String::new(),
789 value: 0.0,
790 };
791
792 let json_bytes = test_struct.to_json_bytes().unwrap();
793 let deserialized = SerializableTestStruct::from_json_bytes(&json_bytes).unwrap();
794
795 assert_eq!(test_struct, deserialized);
796 }
797
798 #[rstest]
799 fn test_serializable_msgpack_empty_values() {
800 let test_struct = SerializableTestStruct {
801 id: 0,
802 name: String::new(),
803 value: 0.0,
804 };
805
806 let msgpack_bytes = test_struct.to_msgpack_bytes().unwrap();
807 let deserialized = SerializableTestStruct::from_msgpack_bytes(&msgpack_bytes).unwrap();
808
809 assert_eq!(test_struct, deserialized);
810 }
811
812 #[derive(Deserialize)]
813 struct TestOptionalDecimalStr {
814 #[serde(deserialize_with = "deserialize_optional_decimal_str")]
815 value: Option<Decimal>,
816 }
817
818 #[derive(Deserialize)]
819 struct TestDecimalOrZero {
820 #[serde(deserialize_with = "deserialize_decimal_or_zero")]
821 value: Decimal,
822 }
823
824 #[derive(Deserialize)]
825 struct TestOptionalDecimalOrZero {
826 #[serde(deserialize_with = "deserialize_optional_decimal_or_zero")]
827 value: Decimal,
828 }
829
830 #[derive(Serialize, Deserialize, PartialEq, Debug)]
831 struct TestDecimalRoundtrip {
832 #[serde(
833 serialize_with = "serialize_decimal_as_str",
834 deserialize_with = "deserialize_decimal_from_str"
835 )]
836 value: Decimal,
837 #[serde(
838 serialize_with = "serialize_optional_decimal_as_str",
839 deserialize_with = "super::deserialize_optional_decimal_from_str"
840 )]
841 optional_value: Option<Decimal>,
842 }
843
844 #[rstest]
845 #[case(r#"{"value":"123.45"}"#, Some(dec!(123.45)))]
846 #[case(r#"{"value":"0"}"#, None)]
847 #[case(r#"{"value":""}"#, None)]
848 fn test_deserialize_optional_decimal_str(
849 #[case] json: &str,
850 #[case] expected: Option<Decimal>,
851 ) {
852 let result: TestOptionalDecimalStr = serde_json::from_str(json).unwrap();
853 assert_eq!(result.value, expected);
854 }
855
856 #[rstest]
857 #[case(r#"{"value":"123.45"}"#, dec!(123.45))]
858 #[case(r#"{"value":"0"}"#, Decimal::ZERO)]
859 #[case(r#"{"value":""}"#, Decimal::ZERO)]
860 fn test_deserialize_decimal_or_zero(#[case] json: &str, #[case] expected: Decimal) {
861 let result: TestDecimalOrZero = serde_json::from_str(json).unwrap();
862 assert_eq!(result.value, expected);
863 }
864
865 #[rstest]
866 #[case(r#"{"value":"123.45"}"#, dec!(123.45))]
867 #[case(r#"{"value":"0"}"#, Decimal::ZERO)]
868 #[case(r#"{"value":null}"#, Decimal::ZERO)]
869 fn test_deserialize_optional_decimal_or_zero(#[case] json: &str, #[case] expected: Decimal) {
870 let result: TestOptionalDecimalOrZero = serde_json::from_str(json).unwrap();
871 assert_eq!(result.value, expected);
872 }
873
874 #[rstest]
875 fn test_decimal_serialization_roundtrip() {
876 let original = TestDecimalRoundtrip {
877 value: dec!(123.456789012345678),
878 optional_value: Some(dec!(0.000000001)),
879 };
880
881 let json = serde_json::to_string(&original).unwrap();
882
883 assert!(json.contains("\"123.456789012345678\""));
885 assert!(json.contains("\"0.000000001\""));
886
887 let deserialized: TestDecimalRoundtrip = serde_json::from_str(&json).unwrap();
888 assert_eq!(original.value, deserialized.value);
889 assert_eq!(original.optional_value, deserialized.optional_value);
890 }
891
892 #[rstest]
893 fn test_decimal_optional_none_handling() {
894 let test_struct = TestDecimalRoundtrip {
895 value: dec!(42.0),
896 optional_value: None,
897 };
898
899 let json = serde_json::to_string(&test_struct).unwrap();
900 assert!(json.contains("null"));
901
902 let parsed: TestDecimalRoundtrip = serde_json::from_str(&json).unwrap();
903 assert_eq!(test_struct.value, parsed.value);
904 assert_eq!(None, parsed.optional_value);
905 }
906
907 #[derive(Deserialize)]
908 struct TestEmptyStringAsNone {
909 #[serde(deserialize_with = "deserialize_empty_string_as_none")]
910 value: Option<String>,
911 }
912
913 #[rstest]
914 #[case(r#"{"value":"hello"}"#, Some("hello".to_string()))]
915 #[case(r#"{"value":""}"#, None)]
916 #[case(r#"{"value":null}"#, None)]
917 fn test_deserialize_empty_string_as_none(#[case] json: &str, #[case] expected: Option<String>) {
918 let result: TestEmptyStringAsNone = serde_json::from_str(json).unwrap();
919 assert_eq!(result.value, expected);
920 }
921
922 #[derive(Deserialize)]
923 struct TestEmptyUstrAsNone {
924 #[serde(deserialize_with = "deserialize_empty_ustr_as_none")]
925 value: Option<Ustr>,
926 }
927
928 #[rstest]
929 #[case(r#"{"value":"hello"}"#, Some(Ustr::from("hello")))]
930 #[case(r#"{"value":""}"#, None)]
931 #[case(r#"{"value":null}"#, None)]
932 fn test_deserialize_empty_ustr_as_none(#[case] json: &str, #[case] expected: Option<Ustr>) {
933 let result: TestEmptyUstrAsNone = serde_json::from_str(json).unwrap();
934 assert_eq!(result.value, expected);
935 }
936
937 #[derive(Serialize, Deserialize, PartialEq, Debug)]
938 struct TestVecDecimal {
939 #[serde(
940 serialize_with = "serialize_vec_decimal_as_str",
941 deserialize_with = "deserialize_vec_decimal_from_str"
942 )]
943 values: Vec<Decimal>,
944 }
945
946 #[rstest]
947 fn test_vec_decimal_roundtrip() {
948 let original = TestVecDecimal {
949 values: vec![dec!(1.5), dec!(2.25), dec!(100.001)],
950 };
951
952 let json = serde_json::to_string(&original).unwrap();
953 assert!(json.contains("[\"1.5\",\"2.25\",\"100.001\"]"));
954
955 let parsed: TestVecDecimal = serde_json::from_str(&json).unwrap();
956 assert_eq!(original.values, parsed.values);
957 }
958
959 #[rstest]
960 fn test_vec_decimal_empty() {
961 let original = TestVecDecimal { values: vec![] };
962
963 let json = serde_json::to_string(&original).unwrap();
964 let parsed: TestVecDecimal = serde_json::from_str(&json).unwrap();
965 assert_eq!(original.values, parsed.values);
966 }
967
968 #[derive(Deserialize)]
969 struct TestStringToU8 {
970 #[serde(deserialize_with = "deserialize_string_to_u8")]
971 value: u8,
972 }
973
974 #[rstest]
975 #[case(r#"{"value":"42"}"#, 42)]
976 #[case(r#"{"value":"0"}"#, 0)]
977 #[case(r#"{"value":"255"}"#, 255)]
978 #[case(r#"{"value":""}"#, 0)]
979 fn test_deserialize_string_to_u8(#[case] json: &str, #[case] expected: u8) {
980 let result: TestStringToU8 = serde_json::from_str(json).unwrap();
981 assert_eq!(result.value, expected);
982 }
983
984 #[rstest]
985 #[case(r#"{"value":"256"}"#)]
986 #[case(r#"{"value":"999"}"#)]
987 #[case(r#"{"value":"abc"}"#)]
988 fn test_deserialize_string_to_u8_invalid(#[case] json: &str) {
989 let result: Result<TestStringToU8, _> = serde_json::from_str(json);
990 assert!(result.is_err());
991 }
992
993 #[derive(Deserialize)]
994 struct TestStringToU64 {
995 #[serde(deserialize_with = "deserialize_string_to_u64")]
996 value: u64,
997 }
998
999 #[rstest]
1000 #[case(r#"{"value":"12345678901234"}"#, 12345678901234)]
1001 #[case(r#"{"value":"0"}"#, 0)]
1002 #[case(r#"{"value":"18446744073709551615"}"#, u64::MAX)]
1003 #[case(r#"{"value":""}"#, 0)]
1004 fn test_deserialize_string_to_u64(#[case] json: &str, #[case] expected: u64) {
1005 let result: TestStringToU64 = serde_json::from_str(json).unwrap();
1006 assert_eq!(result.value, expected);
1007 }
1008
1009 #[rstest]
1010 #[case(r#"{"value":"18446744073709551616"}"#)]
1011 #[case(r#"{"value":"abc"}"#)]
1012 #[case(r#"{"value":"-1"}"#)]
1013 fn test_deserialize_string_to_u64_invalid(#[case] json: &str) {
1014 let result: Result<TestStringToU64, _> = serde_json::from_str(json);
1015 assert!(result.is_err());
1016 }
1017
1018 #[derive(Deserialize)]
1019 struct TestOptionalStringToU64 {
1020 #[serde(deserialize_with = "deserialize_optional_string_to_u64")]
1021 value: Option<u64>,
1022 }
1023
1024 #[rstest]
1025 #[case(r#"{"value":"12345678901234"}"#, Some(12345678901234))]
1026 #[case(r#"{"value":"0"}"#, Some(0))]
1027 #[case(r#"{"value":""}"#, None)]
1028 #[case(r#"{"value":null}"#, None)]
1029 fn test_deserialize_optional_string_to_u64(#[case] json: &str, #[case] expected: Option<u64>) {
1030 let result: TestOptionalStringToU64 = serde_json::from_str(json).unwrap();
1031 assert_eq!(result.value, expected);
1032 }
1033
1034 #[rstest]
1035 #[case("123.45", dec!(123.45))]
1036 #[case("0", Decimal::ZERO)]
1037 #[case("0.0", Decimal::ZERO)]
1038 fn test_parse_decimal(#[case] input: &str, #[case] expected: Decimal) {
1039 let result = parse_decimal(input).unwrap();
1040 assert_eq!(result, expected);
1041 }
1042
1043 #[rstest]
1044 fn test_parse_decimal_invalid() {
1045 assert!(parse_decimal("invalid").is_err());
1046 assert!(parse_decimal("").is_err());
1047 }
1048
1049 #[rstest]
1050 #[case(&Some("123.45".to_string()), Some(dec!(123.45)))]
1051 #[case(&Some("0".to_string()), Some(Decimal::ZERO))]
1052 #[case(&Some(String::new()), None)]
1053 #[case(&None, None)]
1054 fn test_parse_optional_decimal(
1055 #[case] input: &Option<String>,
1056 #[case] expected: Option<Decimal>,
1057 ) {
1058 let result = parse_optional_decimal(input).unwrap();
1059 assert_eq!(result, expected);
1060 }
1061
1062 #[derive(Debug, Serialize, Deserialize, PartialEq)]
1065 struct TestFlexibleDecimal {
1066 #[serde(
1067 serialize_with = "serialize_decimal",
1068 deserialize_with = "deserialize_decimal"
1069 )]
1070 value: Decimal,
1071 #[serde(
1072 serialize_with = "serialize_optional_decimal",
1073 deserialize_with = "deserialize_optional_decimal"
1074 )]
1075 optional_value: Option<Decimal>,
1076 }
1077
1078 #[rstest]
1079 #[case(r#"{"value": 123.456, "optional_value": 789.012}"#, dec!(123.456), Some(dec!(789.012)))]
1080 #[case(r#"{"value": "123.456", "optional_value": "789.012"}"#, dec!(123.456), Some(dec!(789.012)))]
1081 #[case(r#"{"value": 100, "optional_value": null}"#, dec!(100), None)]
1082 #[case(r#"{"value": null, "optional_value": null}"#, Decimal::ZERO, None)]
1083 fn test_deserialize_flexible_decimal(
1084 #[case] json: &str,
1085 #[case] expected_value: Decimal,
1086 #[case] expected_optional: Option<Decimal>,
1087 ) {
1088 let result: TestFlexibleDecimal = serde_json::from_str(json).unwrap();
1089 assert_eq!(result.value, expected_value);
1090 assert_eq!(result.optional_value, expected_optional);
1091 }
1092
1093 #[rstest]
1094 fn test_flexible_decimal_roundtrip() {
1095 let original = TestFlexibleDecimal {
1096 value: dec!(123.456),
1097 optional_value: Some(dec!(789.012)),
1098 };
1099
1100 let json = serde_json::to_string(&original).unwrap();
1101 let deserialized: TestFlexibleDecimal = serde_json::from_str(&json).unwrap();
1102
1103 assert_eq!(original.value, deserialized.value);
1104 assert_eq!(original.optional_value, deserialized.optional_value);
1105 }
1106
1107 #[rstest]
1108 fn test_flexible_decimal_scientific_notation() {
1109 let json = r#"{"value": 0.00000001, "optional_value": 12345678.12345}"#;
1113 let parsed: TestFlexibleDecimal = serde_json::from_str(json).unwrap();
1114 assert_eq!(parsed.value, dec!(0.00000001));
1115 assert_eq!(parsed.optional_value, Some(dec!(12345678.12345)));
1116 }
1117
1118 #[rstest]
1119 fn test_flexible_decimal_empty_string_optional() {
1120 let json = r#"{"value": 100, "optional_value": ""}"#;
1121 let parsed: TestFlexibleDecimal = serde_json::from_str(json).unwrap();
1122 assert_eq!(parsed.value, dec!(100));
1123 assert_eq!(parsed.optional_value, None);
1124 }
1125
1126 #[derive(Debug, Deserialize)]
1129 struct TestDecimalOnly {
1130 #[serde(deserialize_with = "deserialize_decimal")]
1131 value: Decimal,
1132 }
1133
1134 #[rstest]
1135 #[case(r#"{"value": "1.5e-8"}"#, dec!(0.000000015))]
1136 #[case(r#"{"value": "1E10"}"#, dec!(10000000000))]
1137 #[case(r#"{"value": "-1.23e5"}"#, dec!(-123000))]
1138 fn test_deserialize_decimal_scientific_string(#[case] json: &str, #[case] expected: Decimal) {
1139 let result: TestDecimalOnly = serde_json::from_str(json).unwrap();
1140 assert_eq!(result.value, expected);
1141 }
1142
1143 #[rstest]
1144 #[case(r#"{"value": 9223372036854775807}"#, dec!(9223372036854775807))] #[case(r#"{"value": -9223372036854775808}"#, dec!(-9223372036854775808))] #[case(r#"{"value": 0}"#, Decimal::ZERO)]
1147 fn test_deserialize_decimal_large_integers(#[case] json: &str, #[case] expected: Decimal) {
1148 let result: TestDecimalOnly = serde_json::from_str(json).unwrap();
1149 assert_eq!(result.value, expected);
1150 }
1151
1152 #[rstest]
1153 #[case(r#"{"value": "-123.456789"}"#, dec!(-123.456789))]
1154 #[case(r#"{"value": -999.99}"#, dec!(-999.99))]
1155 fn test_deserialize_decimal_negative(#[case] json: &str, #[case] expected: Decimal) {
1156 let result: TestDecimalOnly = serde_json::from_str(json).unwrap();
1157 assert_eq!(result.value, expected);
1158 }
1159
1160 #[rstest]
1161 #[case(r#"{"value": "123456789.123456789012345678"}"#)] fn test_deserialize_decimal_high_precision(#[case] json: &str) {
1163 let result: TestDecimalOnly = serde_json::from_str(json).unwrap();
1164 assert_eq!(result.value, dec!(123456789.123456789012345678));
1165 }
1166
1167 #[derive(Debug, Deserialize)]
1168 struct TestOptionalDecimalOnly {
1169 #[serde(deserialize_with = "deserialize_optional_decimal")]
1170 value: Option<Decimal>,
1171 }
1172
1173 #[rstest]
1174 #[case(r#"{"value": "1.5e-8"}"#, Some(dec!(0.000000015)))]
1175 #[case(r#"{"value": null}"#, None)]
1176 #[case(r#"{"value": ""}"#, None)]
1177 #[case(r#"{"value": 42}"#, Some(dec!(42)))]
1178 #[case(r#"{"value": -100.5}"#, Some(dec!(-100.5)))]
1179 fn test_deserialize_optional_decimal_various(
1180 #[case] json: &str,
1181 #[case] expected: Option<Decimal>,
1182 ) {
1183 let result: TestOptionalDecimalOnly = serde_json::from_str(json).unwrap();
1184 assert_eq!(result.value, expected);
1185 }
1186}