solana-program-library/token/program-2022/src/serialization.rs

79 lines
2.0 KiB
Rust

//! serialization module
/// helper function to ser/deser COption wrapped values
pub mod coption_fromstr {
use {
serde::{
de::{Error, Unexpected, Visitor},
Deserializer, Serializer,
},
solana_program::program_option::COption,
std::{
fmt::{self, Display},
marker::PhantomData,
str::FromStr,
},
};
/// serialize values supporting Display trait wrapped in COption
pub fn serialize<S, T>(x: &COption<T>, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Display,
{
match *x {
COption::Some(ref value) => s.serialize_some(&value.to_string()),
COption::None => s.serialize_none(),
}
}
struct COptionVisitor<T> {
s: PhantomData<T>,
}
impl<'de, T> Visitor<'de> for COptionVisitor<T>
where
T: FromStr,
{
type Value = COption<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a FromStr type")
}
fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
d.deserialize_str(self)
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
T::from_str(v)
.map(|r| COption::Some(r))
.map_err(|_| E::invalid_value(Unexpected::Str(v), &"value string"))
}
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: Error,
{
Ok(COption::None)
}
}
/// deserialize values supporting Display trait wrapped in COption
pub fn deserialize<'de, D, T>(d: D) -> Result<COption<T>, D::Error>
where
D: Deserializer<'de>,
T: FromStr,
{
d.deserialize_option(COptionVisitor {
s: PhantomData::default(),
})
}
}