use serde::de::{self, Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::fmt;
use std::marker::PhantomData;
pub fn deserialize_true_or_struct<'de, T, D>(d: D) -> Result<T, D::Error>
where
T: Deserialize<'de> + Default,
D: Deserializer<'de>,
{
struct TrueOrStruct<T>(PhantomData<T>);
impl<'de, T> de::Visitor<'de> for TrueOrStruct<T>
where
T: Deserialize<'de> + Default,
{
type Value = T;
fn visit_bool<E>(self, value: bool) -> Result<T, E>
where
E: de::Error,
{
if value {
Ok(Default::default())
} else {
Err(de::Error::custom(
"expected true or struct, got false".to_owned(),
))
}
}
fn visit_map<M>(self, visitor: M) -> Result<T, M::Error>
where
M: de::MapAccess<'de>,
{
let mvd = de::value::MapAccessDeserializer::new(visitor);
Deserialize::deserialize(mvd)
}
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a map or a boolean")
}
}
d.deserialize_any(TrueOrStruct(PhantomData))
}
pub fn deserialize_opt_true_or_struct<'de, T, D>(d: D) -> Result<Option<T>, D::Error>
where
T: Deserialize<'de> + Default,
D: Deserializer<'de>,
{
struct OptTrueOrStruct<T>(PhantomData<T>);
impl<'de, T> de::Visitor<'de> for OptTrueOrStruct<T>
where
T: Deserialize<'de> + Default,
{
type Value = Option<T>;
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(None)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserialize_true_or_struct(deserializer).map(Some)
}
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a map or a list of strings")
}
}
d.deserialize_option(OptTrueOrStruct(PhantomData))
}
pub fn serialize_true_or_struct<T, S>(
value: &T,
serializer: S,
) -> Result<S::Ok, S::Error>
where
T: Serialize + Default + Eq,
S: Serializer,
{
if value == &Default::default() {
serializer.serialize_bool(true)
} else {
value.serialize(serializer)
}
}
pub fn serialize_opt_true_or_struct<T, S>(
value: &Option<T>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
T: Serialize + Default + Eq,
S: Serializer,
{
struct Wrap<'a, T>(&'a T)
where
T: Serialize + Default + Eq;
impl<'a, T> Serialize for Wrap<'a, T>
where
T: 'a + Serialize + Default + Eq,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
Wrap(v) => serialize_true_or_struct(v, serializer),
}
}
}
match *value {
None => serializer.serialize_none(),
Some(ref v) => serializer.serialize_some(&Wrap(v)),
}
}