use serde::de::{self, Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::fmt::Display;
use std::marker::PhantomData;
use std::str::FromStr;
pub fn deserialize_string_or_struct<T, D>(d: &mut D) -> Result<T, D::Error>
where T: Deserialize + FromStr,
<T as FromStr>::Err: Display,
D: Deserializer,
{
struct StringOrStruct<T>(PhantomData<T>);
impl<T> de::Visitor for StringOrStruct<T>
where T: Deserialize + FromStr,
<T as FromStr>::Err: Display,
{
type Value = T;
fn visit_str<E>(&mut self, value: &str) -> Result<T, E>
where E: de::Error
{
FromStr::from_str(value).map_err(|err| {
de::Error::custom(format!("{}", err))
})
}
fn visit_map<M>(&mut self, visitor: M) -> Result<T, M::Error>
where M: de::MapVisitor
{
let mut mvd = de::value::MapVisitorDeserializer::new(visitor);
Deserialize::deserialize(&mut mvd)
}
}
d.deserialize(StringOrStruct(PhantomData))
}
pub fn deserialize_opt_string_or_struct<T, D>(d: &mut D) ->
Result<Option<T>, D::Error>
where T: Deserialize + FromStr,
<T as FromStr>::Err: Display,
D: Deserializer,
{
struct OptStringOrStruct<T>(PhantomData<T>);
impl<T> de::Visitor for OptStringOrStruct<T>
where T: Deserialize + FromStr,
<T as FromStr>::Err: Display,
{
type Value = Option<T>;
fn visit_none<E>(&mut self) -> Result<Self::Value, E>
where E: de::Error
{
Ok(None)
}
fn visit_some<D>(&mut self, deserializer: &mut D) ->
Result<Self::Value, D::Error>
where D: Deserializer
{
deserialize_string_or_struct(deserializer).map(Some)
}
}
d.deserialize_option(OptStringOrStruct(PhantomData))
}
pub trait SerializeStringOrStruct: Serialize {
fn serialize_string_or_struct<S>(&self, serializer: &mut S) ->
Result<(), S::Error>
where S: Serializer;
}
pub fn serialize_string_or_struct<T, S>(value: &T, serializer: &mut S) ->
Result<(), S::Error>
where T: SerializeStringOrStruct,
S: Serializer
{
value.serialize_string_or_struct(serializer)
}
pub fn serialize_opt_string_or_struct<T, S>(value: &Option<T>,
serializer: &mut S) ->
Result<(), S::Error>
where T: SerializeStringOrStruct,
S: Serializer
{
struct Wrap<'a, T>(&'a T) where T: 'a + SerializeStringOrStruct;
impl<'a, T> Serialize for Wrap<'a, T> where T: 'a + SerializeStringOrStruct {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer
{
match self {
&Wrap(v) => serialize_string_or_struct(v, serializer),
}
}
}
match value {
&None => serializer.serialize_none(),
&Some(ref v) => serializer.serialize_some(Wrap(v)),
}
}