raiden_primitives/
deserializers.rs

1#![warn(clippy::missing_docs_in_private_items)]
2
3use std::{
4	fmt,
5	str::FromStr,
6};
7
8use serde::{
9	de::{
10		Error,
11		Visitor,
12	},
13	Deserialize,
14	Deserializer,
15};
16use web3::types::{
17	H256,
18	U256,
19};
20
21use crate::types::{
22	ChainID,
23	Signature,
24	U64,
25};
26
27/// Deserialize u64 into U256
28pub fn u256_from_u64<'de, D>(deserializer: D) -> Result<U256, D::Error>
29where
30	D: Deserializer<'de>,
31{
32	let buf = u64::deserialize(deserializer)?;
33	Ok(U256::from(buf))
34}
35
36/// Deserialize string to U256.
37pub fn u256_from_str<'de, D>(deserializer: D) -> Result<U256, D::Error>
38where
39	D: Deserializer<'de>,
40{
41	let binding = serde_json::Value::deserialize(deserializer)?;
42	if let Some(value) = binding.as_u64() {
43		return Ok(U256::from(value))
44	}
45	let v = binding.as_str().ok_or_else(|| D::Error::custom("Could not parse U256"))?;
46	U256::from_dec_str(v).map_err(|_| D::Error::custom("Invalid U256"))
47}
48
49/// Deserialize an optional string (none) into U256.
50pub fn u256_from_optional_str<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
51where
52	D: Deserializer<'de>,
53{
54	let binding = serde_json::Value::deserialize(deserializer)?;
55	if let Some(value) = binding.as_u64() {
56		return Ok(Some(U256::from(value)))
57	}
58	let v = binding.as_str().ok_or_else(|| D::Error::custom("Could not parse U256"))?;
59	Ok(Some(U256::from_dec_str(v).map_err(|_| D::Error::custom("Invalid U256"))?))
60}
61
62/// Deserialize string to u64.
63pub fn u64_from_str<'de, D>(deserializer: D) -> Result<u64, D::Error>
64where
65	D: Deserializer<'de>,
66{
67	let value = serde_json::Value::deserialize(deserializer)?;
68	let v = match value.as_u64() {
69		Some(v) => v,
70		None => value
71			.as_str()
72			.and_then(|s| s.parse().ok())
73			.ok_or_else(|| D::Error::custom("non-integer"))?,
74	};
75	Ok(v)
76}
77
78/// Deserialize string into H256.
79pub fn h256_from_str<'de, D>(deserializer: D) -> Result<H256, D::Error>
80where
81	D: Deserializer<'de>,
82{
83	let binding = serde_json::Value::deserialize(deserializer)?;
84	let str_value = binding.as_str().ok_or_else(|| D::Error::custom("Could not parse H256"))?;
85	let hex_value = hex::decode(str_value.trim_start_matches("0x"))
86		.map_err(|e| D::Error::custom(format!("Could not decode hex: {:?}", e)))?;
87	Ok(H256::from_slice(&hex_value))
88}
89
90/// Deserialize string to signature.
91pub fn signature_from_str<'de, D>(deserializer: D) -> Result<Signature, D::Error>
92where
93	D: Deserializer<'de>,
94{
95	let v = serde_json::Value::deserialize(deserializer)?;
96	let v = v
97		.as_str()
98		.ok_or_else(|| D::Error::custom("Invalid signature"))?
99		.trim_start_matches("0x");
100	Ok(Signature::from(hex::decode(v).map_err(|_| D::Error::custom("Invalid signature"))?))
101}
102
103impl<'de> Deserialize<'de> for ChainID {
104	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
105	where
106		D: Deserializer<'de>,
107	{
108		/// Visitor for Chain Identifier to try to parse from different types
109		struct IdVisitor;
110
111		impl<'de> Visitor<'de> for IdVisitor {
112			type Value = ChainID;
113
114			fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
115				f.write_str("Chain ID as a number or string")
116			}
117
118			fn visit_u64<E>(self, id: u64) -> Result<Self::Value, E>
119			where
120				E: Error,
121			{
122				Ok(id.into())
123			}
124
125			fn visit_str<E>(self, id: &str) -> Result<Self::Value, E>
126			where
127				E: Error,
128			{
129				ChainID::from_str(id)
130					.map_err(|_| Error::custom("Could not parse ChainID from string"))
131			}
132		}
133
134		deserializer.deserialize_any(IdVisitor)
135	}
136}
137
138impl<'de> Deserialize<'de> for U64 {
139	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
140	where
141		D: Deserializer<'de>,
142	{
143		/// Visitor for U64 to try to parse from different types
144		struct NumVisitor;
145
146		impl<'de> Visitor<'de> for NumVisitor {
147			type Value = U64;
148
149			fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
150				f.write_str("U64 as a number or string")
151			}
152
153			fn visit_u64<E>(self, num: u64) -> Result<Self::Value, E>
154			where
155				E: Error,
156			{
157				Ok(U64::from(num))
158			}
159
160			fn visit_str<E>(self, num: &str) -> Result<Self::Value, E>
161			where
162				E: Error,
163			{
164				U64::from_str(num).map_err(|_| Error::custom("Could not parse U64 from string"))
165			}
166		}
167
168		deserializer.deserialize_any(NumVisitor)
169	}
170}