1use serde::{Deserialize, Deserializer, Serializer, de};
2
3#[derive(Debug, Deserialize)]
4#[serde(untagged)]
5enum StringOrNumber {
6 String(String),
7 Number(serde_json::Number),
8}
9
10fn parse_u32<E>(value: StringOrNumber) -> Result<u32, E>
11where
12 E: de::Error,
13{
14 let raw = match value {
15 StringOrNumber::String(value) => value,
16 StringOrNumber::Number(value) => value.to_string(),
17 };
18
19 raw.parse::<u32>()
20 .map_err(|error| E::custom(format!("invalid integer value `{raw}`: {error}")))
21}
22
23pub fn deserialize_u32_from_string_or_number<'de, D>(deserializer: D) -> Result<u32, D::Error>
24where
25 D: Deserializer<'de>,
26{
27 parse_u32(StringOrNumber::deserialize(deserializer)?)
28}
29
30pub fn deserialize_option_u32_from_string_or_number<'de, D>(
31 deserializer: D,
32) -> Result<Option<u32>, D::Error>
33where
34 D: Deserializer<'de>,
35{
36 Option::<StringOrNumber>::deserialize(deserializer)?
37 .map(parse_u32)
38 .transpose()
39}
40
41pub mod string_contract {
42 use super::*;
43
44 pub fn serialize_u32<S>(value: &u32, serializer: S) -> Result<S::Ok, S::Error>
45 where
46 S: Serializer,
47 {
48 serializer.serialize_str(&value.to_string())
49 }
50
51 pub fn serialize_option_u32<S>(value: &Option<u32>, serializer: S) -> Result<S::Ok, S::Error>
52 where
53 S: Serializer,
54 {
55 match value {
56 Some(value) => serialize_u32(value, serializer),
57 None => serializer.serialize_none(),
58 }
59 }
60}