1use std::ops::Deref;
2
3use crate::error::WalletKitError;
4use ruint::aliases::U256;
5use serde::{Deserialize, Serialize};
6
7#[allow(clippy::module_name_repetitions)]
16#[derive(Debug, PartialEq, Eq, Clone, Copy)]
17#[cfg_attr(feature = "ffi", derive(uniffi::Object))]
18pub struct U256Wrapper(pub U256);
19
20#[cfg_attr(feature = "ffi", uniffi::export)]
21impl U256Wrapper {
22 #[must_use]
24 pub fn to_hex_string(&self) -> String {
25 format!("{:#066x}", self.0)
26 }
27
28 #[cfg_attr(feature = "ffi", uniffi::constructor)]
33 pub fn try_from_hex_string(hex_string: &str) -> Result<Self, WalletKitError> {
34 let hex_string = hex_string.trim().trim_start_matches("0x");
35
36 let number = U256::from_str_radix(hex_string, 16)
37 .map_err(|_| WalletKitError::InvalidNumber)?;
38
39 Ok(Self(number))
40 }
41
42 #[must_use]
46 #[cfg_attr(feature = "ffi", uniffi::constructor)]
47 pub fn from_u64(value: u64) -> Self {
48 Self(U256::from(value))
49 }
50
51 #[must_use]
55 #[cfg_attr(feature = "ffi", uniffi::constructor)]
56 pub fn from_u32(value: u32) -> Self {
57 Self(U256::from(value))
58 }
59
60 #[cfg_attr(feature = "ffi", uniffi::constructor)]
68 pub fn from_limbs(limbs: Vec<u64>) -> Result<Self, WalletKitError> {
69 let limbs = limbs
70 .try_into()
71 .map_err(|_| WalletKitError::InvalidNumber)?;
72
73 Ok(Self(U256::from_limbs(limbs)))
74 }
75
76 #[must_use]
80 pub fn into_limbs(self) -> Vec<u64> {
81 self.0.into_limbs().to_vec()
82 }
83}
84
85impl From<U256Wrapper> for U256 {
86 fn from(val: U256Wrapper) -> Self {
87 val.0
88 }
89}
90
91impl From<U256> for U256Wrapper {
92 fn from(val: U256) -> Self {
93 Self(val)
94 }
95}
96
97impl std::fmt::Display for U256Wrapper {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 write!(f, "{}", self.to_hex_string())
100 }
101}
102
103impl Deref for U256Wrapper {
104 type Target = U256;
105
106 fn deref(&self) -> &Self::Target {
107 &self.0
108 }
109}
110
111impl Serialize for U256Wrapper {
112 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113 where
114 S: serde::Serializer,
115 {
116 serializer.serialize_str(&self.to_hex_string())
117 }
118}
119
120impl<'de> Deserialize<'de> for U256Wrapper {
121 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
122 where
123 D: serde::Deserializer<'de>,
124 {
125 let s = String::deserialize(deserializer)?;
126 Self::try_from_hex_string(&s).map_err(serde::de::Error::custom)
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 #![allow(clippy::unreadable_literal)]
133
134 use super::*;
135 use ruint::uint;
136
137 #[test]
138 fn test_to_hex_string_for_u256() {
139 assert_eq!(
140 U256Wrapper(U256::from(1)).to_hex_string(),
141 "0x0000000000000000000000000000000000000000000000000000000000000001"
142 );
143 assert_eq!(
144 U256Wrapper(U256::from(42)).to_hex_string(),
145 "0x000000000000000000000000000000000000000000000000000000000000002a"
146 );
147
148 assert_eq!(
149 U256Wrapper(uint!(999999_U256)).to_hex_string(),
150 "0x00000000000000000000000000000000000000000000000000000000000f423f"
151 );
152
153 assert_eq!(
154 U256Wrapper(uint!(
155 80084422859880547211683076133703299733277748156566366325829078699459944778998_U256
156 ))
157 .to_hex_string(),
158 "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"
159 );
160
161 assert_eq!(
162 U256Wrapper(uint!(
163 0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0_U256
164 ))
165 .to_hex_string(),
166 "0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0"
167 );
168 }
169
170 #[test]
171 fn test_from_hex_string_for_u256() {
172 assert_eq!(
173 U256Wrapper::try_from_hex_string(
174 "0x0000000000000000000000000000000000000000000000000000000000000001"
175 )
176 .unwrap(),
177 U256Wrapper(U256::from(1))
178 );
179 assert_eq!(
180 U256Wrapper::try_from_hex_string(
181 "0x000000000000000000000000000000000000000000000000000000000000002a"
182 )
183 .unwrap(),
184 U256Wrapper(U256::from(42))
185 );
186
187 assert_eq!(
188 U256Wrapper::try_from_hex_string(
189 "0x00000000000000000000000000000000000000000000000000000000000f423f"
190 )
191 .unwrap(),
192 U256Wrapper(uint!(999999_U256))
193 );
194
195 assert_eq!(
196 U256Wrapper::try_from_hex_string("0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6").unwrap(),
197 U256Wrapper(uint!(
198 80084422859880547211683076133703299733277748156566366325829078699459944778998_U256
199 ))
200 );
201
202 assert_eq!(
203 U256Wrapper::try_from_hex_string(
204 "0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0"
205 )
206 .unwrap()
207 .0,
208 uint!(
209 0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0_U256
210 )
211 );
212 }
213
214 #[test]
215 fn test_invalid_hex_string() {
216 assert!(U256Wrapper::try_from_hex_string("0xZZZZ").is_err());
217 assert!(U256Wrapper::try_from_hex_string("1g").is_err());
218 assert!(U256Wrapper::try_from_hex_string("not a hex string").is_err());
219 }
220
221 #[test]
222 fn test_json_serializing() {
223 let number = U256Wrapper(uint!(
224 0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0_U256
225 ));
226
227 let json = serde_json::to_string(&number).unwrap();
228 assert_eq!(
229 json,
230 "\"0x036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0\""
231 );
232 }
233
234 #[test]
235 fn test_from_u64() {
236 assert_eq!(U256Wrapper::from_u64(1).0, uint!(1_U256));
237 assert_eq!(U256Wrapper::from_u64(42).0, uint!(42_U256));
238 assert_eq!(U256Wrapper::from_u64(999_999).0, uint!(999_999_U256));
239
240 assert_eq!(
241 U256Wrapper::from_u64(2).to_hex_string(),
242 "0x0000000000000000000000000000000000000000000000000000000000000002"
243 );
244 assert_eq!(
245 U256Wrapper::from_u64(u64::MAX).to_hex_string(),
246 "0x000000000000000000000000000000000000000000000000ffffffffffffffff"
247 );
248 }
249
250 #[test]
251 fn test_from_u32() {
252 assert_eq!(U256Wrapper::from_u32(1).0, U256::from(1));
253 assert_eq!(U256Wrapper::from_u32(42).0, U256::from(42));
254 assert_eq!(U256Wrapper::from_u32(999999).0, U256::from(999999));
255 }
256
257 #[test]
258 fn test_from_limbs() {
259 assert_eq!(
260 U256Wrapper::from_limbs(vec![1, 0, 0, 0]).unwrap().0,
261 U256::from(1)
262 );
263
264 assert_eq!(
265 U256Wrapper::from_limbs(vec![0, 0, 0, 2161727821137838080])
266 .unwrap()
267 .to_hex_string(),
268 "0x1e00000000000000000000000000000000000000000000000000000000000000"
269 );
270
271 assert_eq!(
272 U256Wrapper::from_limbs(vec![1, 0, 0, 2161727821137838080])
273 .unwrap()
274 .to_hex_string(),
275 "0x1e00000000000000000000000000000000000000000000000000000000000001"
276 );
277 }
278
279 #[test]
280 fn test_from_limbs_invalid_length() {
281 assert!(U256Wrapper::from_limbs(vec![1, 0, 0]).is_err()); assert!(U256Wrapper::from_limbs(vec![1, 0, 0, 0, 5]).is_err());
283 assert!(U256Wrapper::from_limbs(vec![1, 0, 0, 0, 0]).is_err());
284 }
285}