use ethereum_types::U256; use serde::de::Visitor; use serde::{de, Deserializer, Serialize, Serializer}; use std::fmt; use std::str::FromStr; pub fn serialize(num: &U256, serializer: S) -> Result where S: Serializer, { num.serialize(serializer) } pub struct U256Visitor; impl<'de> Visitor<'de> for U256Visitor { type Value = String; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a well formatted hex string") } fn visit_str(self, value: &str) -> Result where E: de::Error, { if !value.starts_with("0x") { return Err(de::Error::custom("must start with 0x")); } let stripped = &value[2..]; if stripped.is_empty() { Err(de::Error::custom(format!( "quantity cannot be {:?}", stripped ))) } else if stripped == "0" { Ok(value.to_string()) } else if stripped.starts_with('0') { Err(de::Error::custom("cannot have leading zero")) } else { Ok(value.to_string()) } } } pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let decoded = deserializer.deserialize_string(U256Visitor)?; U256::from_str(&decoded).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(), "\"0x0\"" ); assert_eq!( &serde_json::to_string(&Wrapper { val: 1.into() }).unwrap(), "\"0x1\"" ); assert_eq!( &serde_json::to_string(&Wrapper { val: 256.into() }).unwrap(), "\"0x100\"" ); assert_eq!( &serde_json::to_string(&Wrapper { val: 65.into() }).unwrap(), "\"0x41\"" ); assert_eq!( &serde_json::to_string(&Wrapper { val: 1024.into() }).unwrap(), "\"0x400\"" ); assert_eq!( &serde_json::to_string(&Wrapper { val: U256::max_value() - 1 }) .unwrap(), "\"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe\"" ); assert_eq!( &serde_json::to_string(&Wrapper { val: U256::max_value() }) .unwrap(), "\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" ); } #[test] fn decoding() { assert_eq!( serde_json::from_str::("\"0x0\"").unwrap(), Wrapper { val: 0.into() }, ); assert_eq!( serde_json::from_str::("\"0x41\"").unwrap(), Wrapper { val: 65.into() }, ); assert_eq!( serde_json::from_str::("\"0x400\"").unwrap(), Wrapper { val: 1024.into() }, ); assert_eq!( serde_json::from_str::( "\"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe\"" ) .unwrap(), Wrapper { val: U256::max_value() - 1 }, ); assert_eq!( serde_json::from_str::( "\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" ) .unwrap(), Wrapper { val: U256::max_value() }, ); serde_json::from_str::("\"0x\"").unwrap_err(); serde_json::from_str::("\"0x0400\"").unwrap_err(); serde_json::from_str::("\"400\"").unwrap_err(); serde_json::from_str::("\"ff\"").unwrap_err(); } }