ethers-rs/ethers-solc/src/artifacts/serde_helpers.rs

198 lines
5.3 KiB
Rust
Raw Normal View History

//! serde helpers
use ethers_core::types::Bytes;
use serde::{Deserialize, Deserializer};
pub fn deserialize_bytes<'de, D>(d: D) -> std::result::Result<Bytes, D::Error>
where
D: Deserializer<'de>,
{
String::deserialize(d)?.parse::<Bytes>().map_err(|e| serde::de::Error::custom(e.to_string()))
}
pub fn deserialize_opt_bytes<'de, D>(d: D) -> std::result::Result<Option<Bytes>, D::Error>
where
D: Deserializer<'de>,
{
let value = Option::<String>::deserialize(d)?;
if let Some(value) = value {
Ok(Some(
if let Some(value) = value.strip_prefix("0x") {
hex::decode(value)
} else {
hex::decode(&value)
}
.map_err(|e| serde::de::Error::custom(e.to_string()))?
.into(),
))
} else {
Ok(None)
}
}
pub fn default_for_null<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de> + Default,
{
Ok(Option::<T>::deserialize(deserializer)?.unwrap_or_default())
}
pub mod json_string_opt {
use serde::{
de::{self, DeserializeOwned},
ser, Deserialize, Deserializer, Serialize, Serializer,
};
pub fn serialize<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Serialize,
{
if let Some(value) = value {
let value = serde_json::to_string(value).map_err(ser::Error::custom)?;
serializer.serialize_str(&value)
} else {
serializer.serialize_none()
}
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
D: Deserializer<'de>,
T: DeserializeOwned,
{
if let Some(s) = Option::<String>::deserialize(deserializer)? {
serde_json::from_str(&s).map_err(de::Error::custom).map(Some)
} else {
Ok(None)
}
}
}
/// serde support for string
pub mod string_bytes {
use serde::{Deserialize, Deserializer, Serializer};
pub fn serialize<S>(value: &String, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if value.starts_with("0x") {
serializer.serialize_str(value.as_str())
} else {
serializer.serialize_str(&format!("0x{}", value))
}
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let value = String::deserialize(deserializer)?;
if let Some(rem) = value.strip_prefix("0x") {
Ok(rem.to_string())
} else {
Ok(value)
}
}
}
pub mod display_from_str_opt {
use serde::{de, Deserialize, Deserializer, Serializer};
use std::{fmt, str::FromStr};
pub fn serialize<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
where
T: fmt::Display,
S: Serializer,
{
if let Some(value) = value {
serializer.collect_str(value)
} else {
serializer.serialize_none()
}
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where
D: Deserializer<'de>,
T: FromStr,
T::Err: fmt::Display,
{
if let Some(s) = Option::<String>::deserialize(deserializer)? {
s.parse().map_err(de::Error::custom).map(Some)
} else {
Ok(None)
}
}
}
/// (De)serialize vec of tuples as map
pub mod tuple_vec_map {
use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize, Serializer};
pub fn serialize<K, V, S>(data: &[(K, V)], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
K: Serialize,
V: Serialize,
{
serializer.collect_map(data.iter().map(|x| (&x.0, &x.1)))
}
pub fn deserialize<'de, K, V, D>(deserializer: D) -> Result<Vec<(K, V)>, D::Error>
where
D: Deserializer<'de>,
K: DeserializeOwned,
V: DeserializeOwned,
{
use serde::de::{MapAccess, Visitor};
use std::{fmt, marker::PhantomData};
struct TupleVecMapVisitor<K, V> {
marker: PhantomData<Vec<(K, V)>>,
}
impl<K, V> TupleVecMapVisitor<K, V> {
pub fn new() -> Self {
TupleVecMapVisitor { marker: PhantomData }
}
}
impl<'de, K, V> Visitor<'de> for TupleVecMapVisitor<K, V>
where
K: Deserialize<'de>,
V: Deserialize<'de>,
{
type Value = Vec<(K, V)>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a map")
}
#[inline]
fn visit_unit<E>(self) -> Result<Vec<(K, V)>, E> {
Ok(Vec::new())
}
#[inline]
fn visit_map<T>(self, mut access: T) -> Result<Vec<(K, V)>, T::Error>
where
T: MapAccess<'de>,
{
let mut values =
Vec::with_capacity(std::cmp::min(access.size_hint().unwrap_or(0), 4096));
while let Some((key, value)) = access.next_entry()? {
values.push((key, value));
}
Ok(values)
}
}
deserializer.deserialize_map(TupleVecMapVisitor::new())
}
}