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>
50 where
51 T: Serialize + Ord,
52 S: Serializer,
53 {
54 let mut sorted: Vec<&T> = set.iter().collect();
55 sorted.sort_unstable();
56 sorted.serialize(s)
57 }
58
59 pub fn deserialize<'de, T, D>(d: D) -> Result<AHashSet<T>, D::Error>
66 where
67 T: Deserialize<'de> + Eq + std::hash::Hash,
68 D: Deserializer<'de>,
69 {
70 let vec = Vec::<T>::deserialize(d)?;
71 Ok(vec.into_iter().collect())
72 }
73}
74
75struct BoolVisitor;
76
77struct DecimalVisitor;
82
83impl Visitor<'_> for DecimalVisitor {
84 type Value = Decimal;
85
86 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
87 formatter.write_str("a decimal number as string, integer, or float")
88 }
89
90 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
92 if v.is_empty() {
93 return Ok(Decimal::ZERO);
94 }
95 if v.contains('e') || v.contains('E') {
97 Decimal::from_scientific(v).map_err(E::custom)
98 } else {
99 Decimal::from_str(v).map_err(E::custom)
100 }
101 }
102
103 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
105 self.visit_str(&v)
106 }
107
108 fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
110 Ok(Decimal::from(v))
111 }
112
113 fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
114 Ok(Decimal::from(v))
115 }
116
117 fn visit_i128<E: Error>(self, v: i128) -> Result<Self::Value, E> {
118 Ok(Decimal::from(v))
119 }
120
121 fn visit_u128<E: Error>(self, v: u128) -> Result<Self::Value, E> {
122 Ok(Decimal::from(v))
123 }
124
125 fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
127 if v.is_nan() {
128 return Err(E::invalid_value(Unexpected::Float(v), &self));
129 }
130
131 if v.is_infinite() {
132 return Err(E::invalid_value(Unexpected::Float(v), &self));
133 }
134 Decimal::try_from(v).map_err(E::custom)
135 }
136
137 fn visit_unit<E: Error>(self) -> Result<Self::Value, E> {
139 Ok(Decimal::ZERO)
140 }
141
142 fn visit_none<E: Error>(self) -> Result<Self::Value, E> {
143 Ok(Decimal::ZERO)
144 }
145}
146
147struct OptionalDecimalVisitor;
152
153impl Visitor<'_> for OptionalDecimalVisitor {
154 type Value = Option<Decimal>;
155
156 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
157 formatter.write_str("null or a decimal number as string, integer, or float")
158 }
159
160 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
163 if v.is_empty() {
164 return Ok(None);
165 }
166 DecimalVisitor.visit_str(v).map(Some)
167 }
168
169 fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
170 self.visit_str(&v)
171 }
172
173 fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
174 DecimalVisitor.visit_i64(v).map(Some)
175 }
176
177 fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
178 DecimalVisitor.visit_u64(v).map(Some)
179 }
180
181 fn visit_i128<E: Error>(self, v: i128) -> Result<Self::Value, E> {
182 DecimalVisitor.visit_i128(v).map(Some)
183 }
184
185 fn visit_u128<E: Error>(self, v: u128) -> Result<Self::Value, E> {
186 DecimalVisitor.visit_u128(v).map(Some)
187 }
188
189 fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
190 DecimalVisitor.visit_f64(v).map(Some)
191 }
192
193 fn visit_unit<E: Error>(self) -> Result<Self::Value, E> {
195 Ok(None)
196 }
197
198 fn visit_none<E: Error>(self) -> Result<Self::Value, E> {
199 Ok(None)
200 }
201}
202
203pub trait Serializable: Serialize + for<'de> Deserialize<'de> {
205 fn from_json_bytes(data: &[u8]) -> Result<Self, serde_json::Error> {
211 serde_json::from_slice(data)
212 }
213
214 fn to_json_bytes(&self) -> Result<Bytes, serde_json::Error> {
220 serde_json::to_vec(self).map(Bytes::from)
221 }
222}
223
224pub use self::msgpack::{FromMsgPack, MsgPackSerializable, ToMsgPack};
225
226pub mod msgpack {
231 use bytes::Bytes;
232 use serde::{Deserialize, Serialize};
233
234 use super::Serializable;
235
236 pub trait FromMsgPack: for<'de> Deserialize<'de> + Sized {
238 fn from_msgpack_bytes(data: &[u8]) -> Result<Self, rmp_serde::decode::Error> {
244 rmp_serde::from_slice(data)
245 }
246 }
247
248 pub trait ToMsgPack: Serialize {
250 fn to_msgpack_bytes(&self) -> Result<Bytes, rmp_serde::encode::Error> {
256 rmp_serde::to_vec_named(self).map(Bytes::from)
257 }
258 }
259
260 pub trait MsgPackSerializable: Serializable + FromMsgPack + ToMsgPack {}
264
265 impl<T> FromMsgPack for T where T: Serializable {}
266
267 impl<T> ToMsgPack for T where T: Serializable {}
268
269 impl<T> MsgPackSerializable for T where T: Serializable {}
270}
271
272impl Visitor<'_> for BoolVisitor {
273 type Value = u8;
274
275 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
276 formatter.write_str("a boolean as u8")
277 }
278
279 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
280 where
281 E: serde::de::Error,
282 {
283 Ok(u8::from(value))
284 }
285
286 #[expect(
287 clippy::cast_possible_truncation,
288 reason = "Intentional for parsing, value range validated"
289 )]
290 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
291 where
292 E: serde::de::Error,
293 {
294 if value > 1 {
299 Err(E::invalid_value(Unexpected::Unsigned(value), &self))
300 } else {
301 Ok(value as u8)
302 }
303 }
304}
305
306#[must_use]
310pub const fn default_true() -> bool {
311 true
312}
313
314#[must_use]
318pub const fn default_false() -> bool {
319 false
320}
321
322pub fn from_bool_as_u8<'de, D>(deserializer: D) -> Result<u8, D::Error>
328where
329 D: Deserializer<'de>,
330{
331 deserializer.deserialize_any(BoolVisitor)
332}
333
334pub fn deserialize_decimal<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
356where
357 D: Deserializer<'de>,
358{
359 deserializer.deserialize_any(DecimalVisitor)
360}
361
362pub fn deserialize_optional_decimal<'de, D>(deserializer: D) -> Result<Option<Decimal>, D::Error>
385where
386 D: Deserializer<'de>,
387{
388 deserializer.deserialize_any(OptionalDecimalVisitor)
391}
392
393pub fn serialize_decimal<S: Serializer>(d: &Decimal, s: S) -> Result<S::Ok, S::Error> {
401 rust_decimal::serde::float::serialize(d, s)
402}
403
404pub fn serialize_optional_decimal<S: Serializer>(
410 d: &Option<Decimal>,
411 s: S,
412) -> Result<S::Ok, S::Error> {
413 match d {
414 Some(decimal) => rust_decimal::serde::float::serialize(decimal, s),
415 None => s.serialize_none(),
416 }
417}
418
419pub fn deserialize_decimal_from_str<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
428where
429 D: Deserializer<'de>,
430{
431 let s = String::deserialize(deserializer)?;
432 Decimal::from_str(&s).map_err(D::Error::custom)
433}
434
435pub fn deserialize_decimal_or_zero<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
443where
444 D: Deserializer<'de>,
445{
446 let s: String = Deserialize::deserialize(deserializer)?;
447 if s.is_empty() || s == "0" {
448 Ok(Decimal::ZERO)
449 } else {
450 Decimal::from_str(&s).map_err(D::Error::custom)
451 }
452}
453
454pub fn deserialize_optional_decimal_str<'de, D>(
464 deserializer: D,
465) -> Result<Option<Decimal>, D::Error>
466where
467 D: Deserializer<'de>,
468{
469 let s: String = Deserialize::deserialize(deserializer)?;
470 if s.is_empty() || s == "0" {
471 Ok(None)
472 } else {
473 Decimal::from_str(&s).map(Some).map_err(D::Error::custom)
474 }
475}
476
477pub fn deserialize_optional_decimal_from_str<'de, D>(
486 deserializer: D,
487) -> Result<Option<Decimal>, D::Error>
488where
489 D: Deserializer<'de>,
490{
491 let opt = Option::<String>::deserialize(deserializer)?;
492 match opt {
493 Some(s) if !s.is_empty() => Decimal::from_str(&s).map(Some).map_err(D::Error::custom),
494 _ => Ok(None),
495 }
496}
497
498pub fn deserialize_optional_decimal_or_zero<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
506where
507 D: Deserializer<'de>,
508{
509 let opt: Option<String> = Deserialize::deserialize(deserializer)?;
510 match opt {
511 None => Ok(Decimal::ZERO),
512 Some(s) if s.is_empty() || s == "0" => Ok(Decimal::ZERO),
513 Some(s) => Decimal::from_str(&s).map_err(D::Error::custom),
514 }
515}
516
517pub fn deserialize_vec_decimal_from_str<'de, D>(deserializer: D) -> Result<Vec<Decimal>, D::Error>
523where
524 D: Deserializer<'de>,
525{
526 let strings = Vec::<String>::deserialize(deserializer)?;
527 strings
528 .into_iter()
529 .map(|s| Decimal::from_str(&s).map_err(D::Error::custom))
530 .collect()
531}
532
533pub fn serialize_decimal_as_str<S>(decimal: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
539where
540 S: Serializer,
541{
542 serializer.serialize_str(&decimal.to_string())
543}
544
545pub fn serialize_optional_decimal_as_str<S>(
551 decimal: &Option<Decimal>,
552 serializer: S,
553) -> Result<S::Ok, S::Error>
554where
555 S: Serializer,
556{
557 match decimal {
558 Some(d) => serializer.serialize_str(&d.to_string()),
559 None => serializer.serialize_none(),
560 }
561}
562
563pub fn serialize_vec_decimal_as_str<S>(
569 decimals: &Vec<Decimal>,
570 serializer: S,
571) -> Result<S::Ok, S::Error>
572where
573 S: Serializer,
574{
575 let mut seq = serializer.serialize_seq(Some(decimals.len()))?;
576 for decimal in decimals {
577 seq.serialize_element(&decimal.to_string())?;
578 }
579 seq.end()
580}
581
582pub fn parse_decimal(s: &str) -> anyhow::Result<Decimal> {
588 Decimal::from_str(s).map_err(|e| anyhow::anyhow!("Failed to parse decimal from '{s}': {e}"))
589}
590
591pub fn parse_optional_decimal(s: &Option<String>) -> anyhow::Result<Option<Decimal>> {
597 match s {
598 None => Ok(None),
599 Some(s) if s.is_empty() => Ok(None),
600 Some(s) => parse_decimal(s).map(Some),
601 }
602}
603
604pub fn deserialize_empty_string_as_none<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
616where
617 D: Deserializer<'de>,
618{
619 let opt = Option::<String>::deserialize(deserializer)?;
620 Ok(opt.filter(|s| !s.is_empty()))
621}
622
623pub fn deserialize_empty_ustr_as_none<'de, D>(deserializer: D) -> Result<Option<Ustr>, D::Error>
629where
630 D: Deserializer<'de>,
631{
632 let opt = Option::<Ustr>::deserialize(deserializer)?;
633 Ok(opt.filter(|s| !s.is_empty()))
634}
635
636pub fn deserialize_string_to_u8<'de, D>(deserializer: D) -> Result<u8, D::Error>
644where
645 D: Deserializer<'de>,
646{
647 let s: String = Deserialize::deserialize(deserializer)?;
648 if s.is_empty() {
649 return Ok(0);
650 }
651 s.parse::<u8>().map_err(D::Error::custom)
652}
653
654pub fn deserialize_string_to_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
662where
663 D: Deserializer<'de>,
664{
665 let s = String::deserialize(deserializer)?;
666 if s.is_empty() {
667 Ok(0)
668 } else {
669 s.parse::<u64>().map_err(D::Error::custom)
670 }
671}
672
673pub fn deserialize_optional_string_to_u64<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
681where
682 D: Deserializer<'de>,
683{
684 let s: Option<String> = Option::deserialize(deserializer)?;
685 match s {
686 Some(s) if s.is_empty() => Ok(None),
687 Some(s) => s.parse().map(Some).map_err(D::Error::custom),
688 None => Ok(None),
689 }
690}
691
692#[cfg(test)]
693mod tests {
694 use rstest::*;
695 use rust_decimal::Decimal;
696 use rust_decimal_macros::dec;
697 use serde::{Deserialize, Serialize};
698 use ustr::Ustr;
699
700 use super::{
701 Serializable, deserialize_decimal, deserialize_decimal_from_str,
702 deserialize_decimal_or_zero, deserialize_empty_string_as_none,
703 deserialize_empty_ustr_as_none, deserialize_optional_decimal,
704 deserialize_optional_decimal_or_zero, deserialize_optional_decimal_str,
705 deserialize_optional_string_to_u64, deserialize_string_to_u8, deserialize_string_to_u64,
706 deserialize_vec_decimal_from_str, from_bool_as_u8,
707 msgpack::{FromMsgPack, ToMsgPack},
708 parse_decimal, parse_optional_decimal, serialize_decimal, serialize_decimal_as_str,
709 serialize_optional_decimal, serialize_optional_decimal_as_str,
710 serialize_vec_decimal_as_str,
711 };
712
713 #[derive(Deserialize)]
714 pub struct TestStruct {
715 #[serde(deserialize_with = "from_bool_as_u8")]
716 pub value: u8,
717 }
718
719 #[rstest]
720 #[case(r#"{"value": true}"#, 1)]
721 #[case(r#"{"value": false}"#, 0)]
722 fn test_deserialize_bool_as_u8_with_boolean(#[case] json_str: &str, #[case] expected: u8) {
723 let test_struct: TestStruct = serde_json::from_str(json_str).unwrap();
724 assert_eq!(test_struct.value, expected);
725 }
726
727 #[rstest]
728 #[case(r#"{"value": 1}"#, 1)]
729 #[case(r#"{"value": 0}"#, 0)]
730 fn test_deserialize_bool_as_u8_with_u64(#[case] json_str: &str, #[case] expected: u8) {
731 let test_struct: TestStruct = serde_json::from_str(json_str).unwrap();
732 assert_eq!(test_struct.value, expected);
733 }
734
735 #[rstest]
736 fn test_deserialize_bool_as_u8_with_invalid_integer() {
737 let json = r#"{"value": 2}"#;
739 let result: Result<TestStruct, _> = serde_json::from_str(json);
740 assert!(result.is_err());
741 }
742
743 #[derive(Serialize, Deserialize, PartialEq, Debug)]
744 struct SerializableTestStruct {
745 id: u32,
746 name: String,
747 value: f64,
748 }
749
750 impl Serializable for SerializableTestStruct {}
751
752 #[rstest]
753 fn test_serializable_json_roundtrip() {
754 let original = SerializableTestStruct {
755 id: 42,
756 name: "test".to_string(),
757 value: std::f64::consts::PI,
758 };
759
760 let json_bytes = original.to_json_bytes().unwrap();
761 let deserialized = SerializableTestStruct::from_json_bytes(&json_bytes).unwrap();
762
763 assert_eq!(original, deserialized);
764 }
765
766 #[rstest]
767 fn test_serializable_msgpack_roundtrip() {
768 let original = SerializableTestStruct {
769 id: 123,
770 name: "msgpack_test".to_string(),
771 value: std::f64::consts::E,
772 };
773
774 let msgpack_bytes = original.to_msgpack_bytes().unwrap();
775 let deserialized = SerializableTestStruct::from_msgpack_bytes(&msgpack_bytes).unwrap();
776
777 assert_eq!(original, deserialized);
778 }
779
780 #[rstest]
781 fn test_serializable_json_invalid_data() {
782 let invalid_json = b"invalid json data";
783 let result = SerializableTestStruct::from_json_bytes(invalid_json);
784 assert!(result.is_err());
785 }
786
787 #[rstest]
788 fn test_serializable_msgpack_invalid_data() {
789 let invalid_msgpack = b"invalid msgpack data";
790 let result = SerializableTestStruct::from_msgpack_bytes(invalid_msgpack);
791 assert!(result.is_err());
792 }
793
794 #[rstest]
795 fn test_serializable_json_empty_values() {
796 let test_struct = SerializableTestStruct {
797 id: 0,
798 name: String::new(),
799 value: 0.0,
800 };
801
802 let json_bytes = test_struct.to_json_bytes().unwrap();
803 let deserialized = SerializableTestStruct::from_json_bytes(&json_bytes).unwrap();
804
805 assert_eq!(test_struct, deserialized);
806 }
807
808 #[rstest]
809 fn test_serializable_msgpack_empty_values() {
810 let test_struct = SerializableTestStruct {
811 id: 0,
812 name: String::new(),
813 value: 0.0,
814 };
815
816 let msgpack_bytes = test_struct.to_msgpack_bytes().unwrap();
817 let deserialized = SerializableTestStruct::from_msgpack_bytes(&msgpack_bytes).unwrap();
818
819 assert_eq!(test_struct, deserialized);
820 }
821
822 #[derive(Deserialize)]
823 struct TestOptionalDecimalStr {
824 #[serde(deserialize_with = "deserialize_optional_decimal_str")]
825 value: Option<Decimal>,
826 }
827
828 #[derive(Deserialize)]
829 struct TestDecimalOrZero {
830 #[serde(deserialize_with = "deserialize_decimal_or_zero")]
831 value: Decimal,
832 }
833
834 #[derive(Deserialize)]
835 struct TestOptionalDecimalOrZero {
836 #[serde(deserialize_with = "deserialize_optional_decimal_or_zero")]
837 value: Decimal,
838 }
839
840 #[derive(Serialize, Deserialize, PartialEq, Debug)]
841 struct TestDecimalRoundtrip {
842 #[serde(
843 serialize_with = "serialize_decimal_as_str",
844 deserialize_with = "deserialize_decimal_from_str"
845 )]
846 value: Decimal,
847 #[serde(
848 serialize_with = "serialize_optional_decimal_as_str",
849 deserialize_with = "super::deserialize_optional_decimal_from_str"
850 )]
851 optional_value: Option<Decimal>,
852 }
853
854 #[rstest]
855 #[case(r#"{"value":"123.45"}"#, Some(dec!(123.45)))]
856 #[case(r#"{"value":"0"}"#, None)]
857 #[case(r#"{"value":""}"#, None)]
858 fn test_deserialize_optional_decimal_str(
859 #[case] json: &str,
860 #[case] expected: Option<Decimal>,
861 ) {
862 let result: TestOptionalDecimalStr = serde_json::from_str(json).unwrap();
863 assert_eq!(result.value, expected);
864 }
865
866 #[rstest]
867 #[case(r#"{"value":"123.45"}"#, dec!(123.45))]
868 #[case(r#"{"value":"0"}"#, Decimal::ZERO)]
869 #[case(r#"{"value":""}"#, Decimal::ZERO)]
870 fn test_deserialize_decimal_or_zero(#[case] json: &str, #[case] expected: Decimal) {
871 let result: TestDecimalOrZero = serde_json::from_str(json).unwrap();
872 assert_eq!(result.value, expected);
873 }
874
875 #[rstest]
876 #[case(r#"{"value":"123.45"}"#, dec!(123.45))]
877 #[case(r#"{"value":"0"}"#, Decimal::ZERO)]
878 #[case(r#"{"value":null}"#, Decimal::ZERO)]
879 fn test_deserialize_optional_decimal_or_zero(#[case] json: &str, #[case] expected: Decimal) {
880 let result: TestOptionalDecimalOrZero = serde_json::from_str(json).unwrap();
881 assert_eq!(result.value, expected);
882 }
883
884 #[rstest]
885 fn test_decimal_serialization_roundtrip() {
886 let original = TestDecimalRoundtrip {
887 value: dec!(123.456789012345678),
888 optional_value: Some(dec!(0.000000001)),
889 };
890
891 let json = serde_json::to_string(&original).unwrap();
892
893 assert!(json.contains("\"123.456789012345678\""));
895 assert!(json.contains("\"0.000000001\""));
896
897 let deserialized: TestDecimalRoundtrip = serde_json::from_str(&json).unwrap();
898 assert_eq!(original.value, deserialized.value);
899 assert_eq!(original.optional_value, deserialized.optional_value);
900 }
901
902 #[rstest]
903 fn test_decimal_optional_none_handling() {
904 let test_struct = TestDecimalRoundtrip {
905 value: dec!(42.0),
906 optional_value: None,
907 };
908
909 let json = serde_json::to_string(&test_struct).unwrap();
910 assert!(json.contains("null"));
911
912 let parsed: TestDecimalRoundtrip = serde_json::from_str(&json).unwrap();
913 assert_eq!(test_struct.value, parsed.value);
914 assert_eq!(None, parsed.optional_value);
915 }
916
917 #[derive(Deserialize)]
918 struct TestEmptyStringAsNone {
919 #[serde(deserialize_with = "deserialize_empty_string_as_none")]
920 value: Option<String>,
921 }
922
923 #[rstest]
924 #[case(r#"{"value":"hello"}"#, Some("hello".to_string()))]
925 #[case(r#"{"value":""}"#, None)]
926 #[case(r#"{"value":null}"#, None)]
927 fn test_deserialize_empty_string_as_none(#[case] json: &str, #[case] expected: Option<String>) {
928 let result: TestEmptyStringAsNone = serde_json::from_str(json).unwrap();
929 assert_eq!(result.value, expected);
930 }
931
932 #[derive(Deserialize)]
933 struct TestEmptyUstrAsNone {
934 #[serde(deserialize_with = "deserialize_empty_ustr_as_none")]
935 value: Option<Ustr>,
936 }
937
938 #[rstest]
939 #[case(r#"{"value":"hello"}"#, Some(Ustr::from("hello")))]
940 #[case(r#"{"value":""}"#, None)]
941 #[case(r#"{"value":null}"#, None)]
942 fn test_deserialize_empty_ustr_as_none(#[case] json: &str, #[case] expected: Option<Ustr>) {
943 let result: TestEmptyUstrAsNone = serde_json::from_str(json).unwrap();
944 assert_eq!(result.value, expected);
945 }
946
947 #[derive(Serialize, Deserialize, PartialEq, Debug)]
948 struct TestVecDecimal {
949 #[serde(
950 serialize_with = "serialize_vec_decimal_as_str",
951 deserialize_with = "deserialize_vec_decimal_from_str"
952 )]
953 values: Vec<Decimal>,
954 }
955
956 #[rstest]
957 fn test_vec_decimal_roundtrip() {
958 let original = TestVecDecimal {
959 values: vec![dec!(1.5), dec!(2.25), dec!(100.001)],
960 };
961
962 let json = serde_json::to_string(&original).unwrap();
963 assert!(json.contains("[\"1.5\",\"2.25\",\"100.001\"]"));
964
965 let parsed: TestVecDecimal = serde_json::from_str(&json).unwrap();
966 assert_eq!(original.values, parsed.values);
967 }
968
969 #[rstest]
970 fn test_vec_decimal_empty() {
971 let original = TestVecDecimal { values: vec![] };
972
973 let json = serde_json::to_string(&original).unwrap();
974 let parsed: TestVecDecimal = serde_json::from_str(&json).unwrap();
975 assert_eq!(original.values, parsed.values);
976 }
977
978 #[derive(Deserialize)]
979 struct TestStringToU8 {
980 #[serde(deserialize_with = "deserialize_string_to_u8")]
981 value: u8,
982 }
983
984 #[rstest]
985 #[case(r#"{"value":"42"}"#, 42)]
986 #[case(r#"{"value":"0"}"#, 0)]
987 #[case(r#"{"value":"255"}"#, 255)]
988 #[case(r#"{"value":""}"#, 0)]
989 fn test_deserialize_string_to_u8(#[case] json: &str, #[case] expected: u8) {
990 let result: TestStringToU8 = serde_json::from_str(json).unwrap();
991 assert_eq!(result.value, expected);
992 }
993
994 #[rstest]
995 #[case(r#"{"value":"256"}"#)]
996 #[case(r#"{"value":"999"}"#)]
997 #[case(r#"{"value":"abc"}"#)]
998 fn test_deserialize_string_to_u8_invalid(#[case] json: &str) {
999 let result: Result<TestStringToU8, _> = serde_json::from_str(json);
1000 assert!(result.is_err());
1001 }
1002
1003 #[derive(Deserialize)]
1004 struct TestStringToU64 {
1005 #[serde(deserialize_with = "deserialize_string_to_u64")]
1006 value: u64,
1007 }
1008
1009 #[rstest]
1010 #[case(r#"{"value":"12345678901234"}"#, 12_345_678_901_234)]
1011 #[case(r#"{"value":"0"}"#, 0)]
1012 #[case(r#"{"value":"18446744073709551615"}"#, u64::MAX)]
1013 #[case(r#"{"value":""}"#, 0)]
1014 fn test_deserialize_string_to_u64(#[case] json: &str, #[case] expected: u64) {
1015 let result: TestStringToU64 = serde_json::from_str(json).unwrap();
1016 assert_eq!(result.value, expected);
1017 }
1018
1019 #[rstest]
1020 #[case(r#"{"value":"18446744073709551616"}"#)]
1021 #[case(r#"{"value":"abc"}"#)]
1022 #[case(r#"{"value":"-1"}"#)]
1023 fn test_deserialize_string_to_u64_invalid(#[case] json: &str) {
1024 let result: Result<TestStringToU64, _> = serde_json::from_str(json);
1025 assert!(result.is_err());
1026 }
1027
1028 #[derive(Deserialize)]
1029 struct TestOptionalStringToU64 {
1030 #[serde(deserialize_with = "deserialize_optional_string_to_u64")]
1031 value: Option<u64>,
1032 }
1033
1034 #[rstest]
1035 #[case(r#"{"value":"12345678901234"}"#, Some(12_345_678_901_234))]
1036 #[case(r#"{"value":"0"}"#, Some(0))]
1037 #[case(r#"{"value":""}"#, None)]
1038 #[case(r#"{"value":null}"#, None)]
1039 fn test_deserialize_optional_string_to_u64(#[case] json: &str, #[case] expected: Option<u64>) {
1040 let result: TestOptionalStringToU64 = serde_json::from_str(json).unwrap();
1041 assert_eq!(result.value, expected);
1042 }
1043
1044 #[rstest]
1045 #[case("123.45", dec!(123.45))]
1046 #[case("0", Decimal::ZERO)]
1047 #[case("0.0", Decimal::ZERO)]
1048 fn test_parse_decimal(#[case] input: &str, #[case] expected: Decimal) {
1049 let result = parse_decimal(input).unwrap();
1050 assert_eq!(result, expected);
1051 }
1052
1053 #[rstest]
1054 fn test_parse_decimal_invalid() {
1055 assert!(parse_decimal("invalid").is_err());
1056 assert!(parse_decimal("").is_err());
1057 }
1058
1059 #[rstest]
1060 #[case(&Some("123.45".to_string()), Some(dec!(123.45)))]
1061 #[case(&Some("0".to_string()), Some(Decimal::ZERO))]
1062 #[case(&Some(String::new()), None)]
1063 #[case(&None, None)]
1064 fn test_parse_optional_decimal(
1065 #[case] input: &Option<String>,
1066 #[case] expected: Option<Decimal>,
1067 ) {
1068 let result = parse_optional_decimal(input).unwrap();
1069 assert_eq!(result, expected);
1070 }
1071
1072 #[derive(Debug, Serialize, Deserialize, PartialEq)]
1075 struct TestFlexibleDecimal {
1076 #[serde(
1077 serialize_with = "serialize_decimal",
1078 deserialize_with = "deserialize_decimal"
1079 )]
1080 value: Decimal,
1081 #[serde(
1082 serialize_with = "serialize_optional_decimal",
1083 deserialize_with = "deserialize_optional_decimal"
1084 )]
1085 optional_value: Option<Decimal>,
1086 }
1087
1088 #[rstest]
1089 #[case(r#"{"value": 123.456, "optional_value": 789.012}"#, dec!(123.456), Some(dec!(789.012)))]
1090 #[case(r#"{"value": "123.456", "optional_value": "789.012"}"#, dec!(123.456), Some(dec!(789.012)))]
1091 #[case(r#"{"value": 100, "optional_value": null}"#, dec!(100), None)]
1092 #[case(r#"{"value": null, "optional_value": null}"#, Decimal::ZERO, None)]
1093 fn test_deserialize_flexible_decimal(
1094 #[case] json: &str,
1095 #[case] expected_value: Decimal,
1096 #[case] expected_optional: Option<Decimal>,
1097 ) {
1098 let result: TestFlexibleDecimal = serde_json::from_str(json).unwrap();
1099 assert_eq!(result.value, expected_value);
1100 assert_eq!(result.optional_value, expected_optional);
1101 }
1102
1103 #[rstest]
1104 fn test_flexible_decimal_roundtrip() {
1105 let original = TestFlexibleDecimal {
1106 value: dec!(123.456),
1107 optional_value: Some(dec!(789.012)),
1108 };
1109
1110 let json = serde_json::to_string(&original).unwrap();
1111 let deserialized: TestFlexibleDecimal = serde_json::from_str(&json).unwrap();
1112
1113 assert_eq!(original.value, deserialized.value);
1114 assert_eq!(original.optional_value, deserialized.optional_value);
1115 }
1116
1117 #[rstest]
1118 fn test_flexible_decimal_scientific_notation() {
1119 let json = r#"{"value": 0.00000001, "optional_value": 12345678.12345}"#;
1123 let parsed: TestFlexibleDecimal = serde_json::from_str(json).unwrap();
1124 assert_eq!(parsed.value, dec!(0.00000001));
1125 assert_eq!(parsed.optional_value, Some(dec!(12345678.12345)));
1126 }
1127
1128 #[rstest]
1129 fn test_flexible_decimal_empty_string_optional() {
1130 let json = r#"{"value": 100, "optional_value": ""}"#;
1131 let parsed: TestFlexibleDecimal = serde_json::from_str(json).unwrap();
1132 assert_eq!(parsed.value, dec!(100));
1133 assert_eq!(parsed.optional_value, None);
1134 }
1135
1136 #[derive(Debug, Deserialize)]
1139 struct TestDecimalOnly {
1140 #[serde(deserialize_with = "deserialize_decimal")]
1141 value: Decimal,
1142 }
1143
1144 #[rstest]
1145 #[case(r#"{"value": "1.5e-8"}"#, dec!(0.000000015))]
1146 #[case(r#"{"value": "1E10"}"#, dec!(10000000000))]
1147 #[case(r#"{"value": "-1.23e5"}"#, dec!(-123000))]
1148 fn test_deserialize_decimal_scientific_string(#[case] json: &str, #[case] expected: Decimal) {
1149 let result: TestDecimalOnly = serde_json::from_str(json).unwrap();
1150 assert_eq!(result.value, expected);
1151 }
1152
1153 #[rstest]
1154 #[case(r#"{"value": 9223372036854775807}"#, dec!(9223372036854775807))] #[case(r#"{"value": -9223372036854775808}"#, dec!(-9223372036854775808))] #[case(r#"{"value": 0}"#, Decimal::ZERO)]
1157 fn test_deserialize_decimal_large_integers(#[case] json: &str, #[case] expected: Decimal) {
1158 let result: TestDecimalOnly = serde_json::from_str(json).unwrap();
1159 assert_eq!(result.value, expected);
1160 }
1161
1162 #[rstest]
1163 #[case(r#"{"value": "-123.456789"}"#, dec!(-123.456789))]
1164 #[case(r#"{"value": -999.99}"#, dec!(-999.99))]
1165 fn test_deserialize_decimal_negative(#[case] json: &str, #[case] expected: Decimal) {
1166 let result: TestDecimalOnly = serde_json::from_str(json).unwrap();
1167 assert_eq!(result.value, expected);
1168 }
1169
1170 #[rstest]
1171 #[case(r#"{"value": "123456789.123456789012345678"}"#)] fn test_deserialize_decimal_high_precision(#[case] json: &str) {
1173 let result: TestDecimalOnly = serde_json::from_str(json).unwrap();
1174 assert_eq!(result.value, dec!(123456789.123456789012345678));
1175 }
1176
1177 #[derive(Debug, Deserialize)]
1178 struct TestOptionalDecimalOnly {
1179 #[serde(deserialize_with = "deserialize_optional_decimal")]
1180 value: Option<Decimal>,
1181 }
1182
1183 #[rstest]
1184 #[case(r#"{"value": "1.5e-8"}"#, Some(dec!(0.000000015)))]
1185 #[case(r#"{"value": null}"#, None)]
1186 #[case(r#"{"value": ""}"#, None)]
1187 #[case(r#"{"value": 42}"#, Some(dec!(42)))]
1188 #[case(r#"{"value": -100.5}"#, Some(dec!(-100.5)))]
1189 fn test_deserialize_optional_decimal_various(
1190 #[case] json: &str,
1191 #[case] expected: Option<Decimal>,
1192 ) {
1193 let result: TestOptionalDecimalOnly = serde_json::from_str(json).unwrap();
1194 assert_eq!(result.value, expected);
1195 }
1196}