1use cfx_types::{U256, U64};
2use core::str::FromStr;
3use serde::{de, Deserialize, Deserializer};
4use std::fmt;
5
6#[derive(Debug, Deserialize)]
9#[serde(untagged)]
10pub enum NumberOrHexU256 {
11 Int(serde_json::Number),
13 Hex(U256),
15}
16
17impl NumberOrHexU256 {
18 pub fn try_into_u256<E: de::Error>(self) -> Result<U256, E> {
20 match self {
21 NumberOrHexU256::Int(num) => {
22 U256::from_str(num.to_string().as_str()).map_err(E::custom)
23 }
24 NumberOrHexU256::Hex(val) => Ok(val),
25 }
26 }
27}
28
29pub fn from_int_or_hex_to_u256<'de, D>(
33 deserializer: D,
34) -> Result<U256, D::Error>
35where D: Deserializer<'de> {
36 NumberOrHexU256::deserialize(deserializer)?.try_into_u256()
37}
38
39pub fn from_int_or_hex_to_u256_opt<'de, D>(
42 deserializer: D,
43) -> Result<Option<U256>, D::Error>
44where D: Deserializer<'de> {
45 match Option::<NumberOrHexU256>::deserialize(deserializer)? {
46 Some(val) => val.try_into_u256().map(Some),
47 None => Ok(None),
48 }
49}
50
51#[derive(Debug, Deserialize)]
54#[serde(untagged)]
55pub enum NumberOrHexU64 {
56 Int(serde_json::Number),
58 Hex(U64),
60}
61
62impl NumberOrHexU64 {
63 pub fn try_into_u64<E: de::Error>(self) -> Result<U64, E> {
65 match self {
66 NumberOrHexU64::Int(num) => {
67 U64::from_str(num.to_string().as_str()).map_err(E::custom)
68 }
69 NumberOrHexU64::Hex(val) => Ok(val),
70 }
71 }
72}
73
74pub fn from_int_or_hex_to_u64<'de, D>(
78 deserializer: D,
79) -> Result<U64, D::Error>
80where D: Deserializer<'de> {
81 NumberOrHexU64::deserialize(deserializer)?.try_into_u64()
82}
83
84pub fn from_int_or_hex_to_u64_opt<'de, D>(
87 deserializer: D,
88) -> Result<Option<U64>, D::Error>
89where D: Deserializer<'de> {
90 match Option::<NumberOrHexU64>::deserialize(deserializer)? {
91 Some(val) => val.try_into_u64().map(Some),
92 None => Ok(None),
93 }
94}
95
96pub fn deserialize_u64_from_num_or_hex<'de, D>(
97 deserializer: D,
98) -> Result<u64, D::Error>
99where D: Deserializer<'de> {
100 struct U64OrHexVisitor;
101
102 impl<'de> serde::de::Visitor<'de> for U64OrHexVisitor {
103 type Value = u64;
104
105 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
106 formatter
107 .write_str("a u64 integer or a hex string representing a u64")
108 }
109
110 fn visit_u64<E>(self, value: u64) -> Result<u64, E> { Ok(value) }
111
112 fn visit_str<E>(self, value: &str) -> Result<u64, E>
113 where E: serde::de::Error {
114 if let Some(stripped) = value.strip_prefix("0x") {
115 u64::from_str_radix(stripped, 16).map_err(E::custom)
116 } else {
117 Err(E::custom("expected hex string to start with '0x'"))
118 }
119 }
120 }
121
122 deserializer.deserialize_any(U64OrHexVisitor)
123}