From 8d0c712872e9aac7de05af28f8643c90847a6150 Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Tue, 9 Jan 2024 20:42:06 +1100 Subject: [PATCH] Decimal encoding for U256 (#5) --- src/lib.rs | 1 + src/u256_dec.rs | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/u256_dec.rs diff --git a/src/lib.rs b/src/lib.rs index 5c5dafc..1813f95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ pub mod hex_vec; pub mod json_str; pub mod list_of_bytes_lists; pub mod quoted_u64_vec; +pub mod u256_dec; pub mod u256_hex_be; pub mod u32_hex; pub mod u64_hex_be; diff --git a/src/u256_dec.rs b/src/u256_dec.rs new file mode 100644 index 0000000..de39795 --- /dev/null +++ b/src/u256_dec.rs @@ -0,0 +1,107 @@ +use ethereum_types::U256; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +pub fn serialize(num: &U256, serializer: S) -> Result +where + S: Serializer, +{ + num.to_string().serialize(serializer) +} + +pub fn deserialize<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + U256::from_dec_str(&s).map_err(|e| de::Error::custom(format!("Invalid U256 string: {e}"))) +} + +#[cfg(test)] +mod test { + use ethereum_types::U256; + use serde::{Deserialize, Serialize}; + use serde_json; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(transparent)] + struct Wrapper { + #[serde(with = "super")] + val: U256, + } + + #[test] + fn encoding() { + assert_eq!( + &serde_json::to_string(&Wrapper { val: 0.into() }).unwrap(), + "\"0\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { val: 1.into() }).unwrap(), + "\"1\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { val: 256.into() }).unwrap(), + "\"256\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { val: 65.into() }).unwrap(), + "\"65\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { val: 1024.into() }).unwrap(), + "\"1024\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: U256::max_value() - 1 + }) + .unwrap(), + "\"115792089237316195423570985008687907853269984665640564039457584007913129639934\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: U256::max_value() + }) + .unwrap(), + "\"115792089237316195423570985008687907853269984665640564039457584007913129639935\"" + ); + } + + #[test] + fn decoding() { + assert_eq!( + serde_json::from_str::("\"0\"").unwrap(), + Wrapper { val: 0.into() }, + ); + assert_eq!( + serde_json::from_str::("\"65\"").unwrap(), + Wrapper { val: 65.into() }, + ); + assert_eq!( + serde_json::from_str::("\"1024\"").unwrap(), + Wrapper { val: 1024.into() }, + ); + assert_eq!( + serde_json::from_str::( + "\"115792089237316195423570985008687907853269984665640564039457584007913129639934\"" + ) + .unwrap(), + Wrapper { + val: U256::max_value() - 1 + }, + ); + assert_eq!( + serde_json::from_str::( + "\"115792089237316195423570985008687907853269984665640564039457584007913129639935\"" + ) + .unwrap(), + Wrapper { + val: U256::max_value() + }, + ); + serde_json::from_str::("\"0x0\"").unwrap_err(); + serde_json::from_str::("\"0x0400\"").unwrap_err(); + serde_json::from_str::("\"-1\"").unwrap_err(); + serde_json::from_str::("\"ff\"").unwrap_err(); + } +}