foundry_common/
serde_helpers.rs1use alloy_primitives::U256;
4use serde::{Deserialize, Deserializer, de};
5use std::str::FromStr;
6
7#[derive(Copy, Clone, Deserialize)]
9#[serde(untagged)]
10pub enum Numeric {
11 U256(U256),
13 Num(u64),
15}
16
17impl From<Numeric> for U256 {
18 fn from(n: Numeric) -> Self {
19 match n {
20 Numeric::U256(n) => n,
21 Numeric::Num(n) => Self::from(n),
22 }
23 }
24}
25
26impl FromStr for Numeric {
27 type Err = String;
28
29 fn from_str(s: &str) -> Result<Self, Self::Err> {
30 if let Ok(val) = s.parse::<u128>() {
31 Ok(Self::U256(U256::from(val)))
32 } else if s.starts_with("0x") {
33 U256::from_str_radix(s, 16).map(Numeric::U256).map_err(|err| err.to_string())
34 } else {
35 U256::from_str(s).map(Numeric::U256).map_err(|err| err.to_string())
36 }
37 }
38}
39
40#[derive(Debug, Deserialize)]
42#[serde(untagged)]
43pub enum NumberOrHexU256 {
44 Int(serde_json::Number),
46 Hex(U256),
48}
49
50impl NumberOrHexU256 {
51 pub fn try_into_u256<E: de::Error>(self) -> Result<U256, E> {
53 match self {
54 Self::Int(num) => U256::from_str(&num.to_string()).map_err(E::custom),
55 Self::Hex(val) => Ok(val),
56 }
57 }
58}
59
60pub fn from_int_or_hex<'de, D>(deserializer: D) -> Result<U256, D::Error>
63where
64 D: Deserializer<'de>,
65{
66 NumberOrHexU256::deserialize(deserializer)?.try_into_u256()
67}
68
69#[derive(Deserialize)]
71#[serde(untagged)]
72pub enum NumericSeq {
73 Seq([Numeric; 1]),
75 U256(U256),
77 Num(u64),
79}
80
81pub fn deserialize_number<'de, D>(deserializer: D) -> Result<U256, D::Error>
83where
84 D: Deserializer<'de>,
85{
86 Numeric::deserialize(deserializer).map(Into::into)
87}
88
89pub fn deserialize_number_opt<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
91where
92 D: Deserializer<'de>,
93{
94 let num = match Option::<Numeric>::deserialize(deserializer)? {
95 Some(Numeric::U256(n)) => Some(n),
96 Some(Numeric::Num(n)) => Some(U256::from(n)),
97 _ => None,
98 };
99
100 Ok(num)
101}
102
103pub fn deserialize_number_seq<'de, D>(deserializer: D) -> Result<U256, D::Error>
105where
106 D: Deserializer<'de>,
107{
108 let num = match NumericSeq::deserialize(deserializer)? {
109 NumericSeq::Seq(seq) => seq[0].into(),
110 NumericSeq::U256(n) => n,
111 NumericSeq::Num(n) => U256::from(n),
112 };
113
114 Ok(num)
115}
116
117pub mod duration {
118 use serde::{Deserialize, Deserializer};
119 use std::time::Duration;
120
121 pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
122 where
123 S: serde::Serializer,
124 {
125 let d = jiff::SignedDuration::try_from(*duration).map_err(serde::ser::Error::custom)?;
126 serializer.serialize_str(&format!("{d:#}"))
127 }
128
129 pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
130 where
131 D: Deserializer<'de>,
132 {
133 let s = String::deserialize(deserializer)?;
134 let d = s.parse::<jiff::SignedDuration>().map_err(serde::de::Error::custom)?;
135 d.try_into().map_err(serde::de::Error::custom)
136 }
137}