From 026663f1d955dd1dcffc87e6e6508584170d8fa7 Mon Sep 17 00:00:00 2001 From: DoTheBestToGetTheBest <146037313+DoTheBestToGetTheBest@users.noreply.github.com> Date: Thu, 2 Nov 2023 05:47:03 -0700 Subject: [PATCH] feat(primitives): extended display and formatting for JsonU256 (#5199) Co-authored-by: Matthias Seitz --- .../primitives/src/serde_helper/jsonu256.rs | 131 ------------------ crates/primitives/src/serde_helper/mod.rs | 3 +- .../rpc-types/src/serde_helpers/json_u256.rs | 47 +++++++ 3 files changed, 48 insertions(+), 133 deletions(-) delete mode 100644 crates/primitives/src/serde_helper/jsonu256.rs diff --git a/crates/primitives/src/serde_helper/jsonu256.rs b/crates/primitives/src/serde_helper/jsonu256.rs deleted file mode 100644 index 5b8544518..000000000 --- a/crates/primitives/src/serde_helper/jsonu256.rs +++ /dev/null @@ -1,131 +0,0 @@ -use crate::U256; -use serde::{ - de::{Error, Visitor}, - Deserialize, Deserializer, Serialize, Serializer, -}; -use std::{fmt, str::FromStr}; - -/// Wrapper around primitive U256 type that also supports deserializing numbers -#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] -pub struct JsonU256(pub U256); - -impl From for U256 { - fn from(value: JsonU256) -> Self { - value.0 - } -} - -impl From for JsonU256 { - fn from(value: U256) -> Self { - JsonU256(value) - } -} - -impl Serialize for JsonU256 { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.0.serialize(serializer) - } -} - -impl<'a> Deserialize<'a> for JsonU256 { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'a>, - { - deserializer.deserialize_any(JsonU256Visitor) - } -} - -struct JsonU256Visitor; - -impl<'a> Visitor<'a> for JsonU256Visitor { - type Value = JsonU256; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(formatter, "a hex encoding or decimal number") - } - - fn visit_u64(self, value: u64) -> Result - where - E: Error, - { - Ok(JsonU256(U256::from(value))) - } - - fn visit_str(self, value: &str) -> Result - where - E: Error, - { - let value = match value.len() { - 0 => U256::ZERO, - 2 if value.starts_with("0x") => U256::ZERO, - _ if value.starts_with("0x") => U256::from_str(value).map_err(|e| { - Error::custom(format!("Parsing JsonU256 as hex failed {value}: {e}")) - })?, - _ => U256::from_str_radix(value, 10).map_err(|e| { - Error::custom(format!("Parsing JsonU256 as decimal failed {value}: {e:?}")) - })?, - }; - - Ok(JsonU256(value)) - } - - fn visit_string(self, value: String) -> Result - where - E: Error, - { - self.visit_str(value.as_ref()) - } -} - -/// Supports parsing `U256` numbers as strings via [JsonU256] -pub fn deserialize_json_u256<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let num = JsonU256::deserialize(deserializer)?; - Ok(num.into()) -} - -/// Supports parsing `U256` numbers as strings via [JsonU256] -pub fn deserialize_json_u256_opt<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let num = Option::::deserialize(deserializer)?; - Ok(num.map(Into::into)) -} - -#[cfg(test)] -mod test { - use super::JsonU256; - use crate::U256; - - #[test] - fn jsonu256_deserialize() { - let deserialized: Vec = - serde_json::from_str(r#"["","0", "0x","10",10,"0x10"]"#).unwrap(); - assert_eq!( - deserialized, - vec![ - JsonU256(U256::ZERO), - JsonU256(U256::ZERO), - JsonU256(U256::ZERO), - JsonU256(U256::from(10)), - JsonU256(U256::from(10)), - JsonU256(U256::from(16)), - ] - ); - } - - #[test] - fn jsonu256_serialize() { - let data = JsonU256(U256::from(16)); - let serialized = serde_json::to_string(&data).unwrap(); - - assert_eq!(serialized, r#""0x10""#); - } -} diff --git a/crates/primitives/src/serde_helper/mod.rs b/crates/primitives/src/serde_helper/mod.rs index 4792c2e98..6e78c5a79 100644 --- a/crates/primitives/src/serde_helper/mod.rs +++ b/crates/primitives/src/serde_helper/mod.rs @@ -6,8 +6,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; mod storage; pub use storage::*; -mod jsonu256; -pub use jsonu256::*; +pub use reth_rpc_types::json_u256::*; pub mod num; diff --git a/crates/rpc/rpc-types/src/serde_helpers/json_u256.rs b/crates/rpc/rpc-types/src/serde_helpers/json_u256.rs index 162d55a82..5566a2f7d 100644 --- a/crates/rpc/rpc-types/src/serde_helpers/json_u256.rs +++ b/crates/rpc/rpc-types/src/serde_helpers/json_u256.rs @@ -23,6 +23,12 @@ impl From for JsonU256 { } } +impl fmt::Display for JsonU256 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + impl Serialize for JsonU256 { fn serialize(&self, serializer: S) -> Result where @@ -41,6 +47,7 @@ impl<'a> Deserialize<'a> for JsonU256 { } } +/// Visitor pattern for `JsonU256` deserialization. struct JsonU256Visitor; impl<'a> Visitor<'a> for JsonU256Visitor { @@ -91,3 +98,43 @@ where let num = JsonU256::deserialize(deserializer)?; Ok(num.into()) } + +/// Supports parsing `U256` numbers as strings via [JsonU256] +pub fn deserialize_json_u256_opt<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let num = Option::::deserialize(deserializer)?; + Ok(num.map(Into::into)) +} + +#[cfg(test)] +mod test { + use super::JsonU256; + use alloy_primitives::U256; + + #[test] + fn jsonu256_deserialize() { + let deserialized: Vec = + serde_json::from_str(r#"["","0", "0x","10",10,"0x10"]"#).unwrap(); + assert_eq!( + deserialized, + vec![ + JsonU256(U256::ZERO), + JsonU256(U256::ZERO), + JsonU256(U256::ZERO), + JsonU256(U256::from(10)), + JsonU256(U256::from(10)), + JsonU256(U256::from(16)), + ] + ); + } + + #[test] + fn jsonu256_serialize() { + let data = JsonU256(U256::from(16)); + let serialized = serde_json::to_string(&data).unwrap(); + + assert_eq!(serialized, r#""0x10""#); + } +}