use serde::{
de::{Deserialize, DeserializeOwned, Deserializer, Error, MapAccess, SeqAccess, Visitor},
ser::{Serialize, SerializeSeq, Serializer},
};
use std::{
cmp::Eq,
collections::{BTreeMap, HashMap},
fmt::{self, Display},
hash::{BuildHasher, Hash},
iter::FromIterator,
marker::PhantomData,
str::FromStr,
};
use Separator;
pub mod display_fromstr {
use super::*;
use std::str::FromStr;
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: FromStr,
T::Err: Display,
{
struct Helper<S>(PhantomData<S>);
impl<'de, S> Visitor<'de> for Helper<S>
where
S: FromStr,
<S as FromStr>::Err: Display,
{
type Value = S;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "valid json object")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
value.parse::<Self::Value>().map_err(Error::custom)
}
}
deserializer.deserialize_str(Helper(PhantomData))
}
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: Display,
S: Serializer,
{
serializer.serialize_str(&*value.to_string())
}
}
pub mod seq_display_fromstr {
use serde::{
de::{Deserializer, Error, SeqAccess, Visitor},
ser::{SerializeSeq, Serializer},
};
use std::{
fmt::{self, Display},
iter::{FromIterator, IntoIterator},
marker::PhantomData,
str::FromStr,
};
pub fn deserialize<'de, D, T, I>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: FromIterator<I> + Sized,
I: FromStr,
I::Err: Display,
{
struct Helper<S>(PhantomData<S>);
impl<'de, S> Visitor<'de> for Helper<S>
where
S: FromStr,
<S as FromStr>::Err: Display,
{
type Value = Vec<S>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a sequence")
}
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut values = access
.size_hint()
.map(Self::Value::with_capacity)
.unwrap_or_else(Self::Value::new);
while let Some(value) = access.next_element::<&str>()? {
values.push(value.parse::<S>().map_err(Error::custom)?);
}
Ok(values)
}
}
deserializer
.deserialize_seq(Helper(PhantomData))
.map(T::from_iter)
}
pub fn serialize<S, T, I>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
for<'a> &'a T: IntoIterator<Item = &'a I>,
I: Display,
{
let iter = value.into_iter();
let (_, to) = iter.size_hint();
let mut seq = serializer.serialize_seq(to)?;
for item in iter {
seq.serialize_element(&item.to_string())?;
}
seq.end()
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub struct StringWithSeparator<Sep>(PhantomData<Sep>);
impl<Sep> StringWithSeparator<Sep>
where
Sep: Separator,
{
pub fn serialize<S, T, V>(values: T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: IntoIterator<Item = V>,
V: Display,
{
let mut s = String::new();
for v in values {
s.push_str(&*v.to_string());
s.push_str(Sep::separator());
}
serializer.serialize_str(if !s.is_empty() {
&s[..s.len() - Sep::separator().len()]
} else {
&s[..]
})
}
pub fn deserialize<'de, D, T, V>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: FromIterator<V>,
V: FromStr,
V::Err: Display,
{
let s = String::deserialize(deserializer)?;
if s.is_empty() {
Ok(None.into_iter().collect())
} else {
s.split(Sep::separator())
.map(FromStr::from_str)
.collect::<Result<_, _>>()
.map_err(Error::custom)
}
}
}
#[cfg_attr(feature = "cargo-clippy", allow(option_option))]
pub mod double_option {
use super::*;
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<Option<Option<T>>, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de>,
{
Deserialize::deserialize(deserializer).map(Some)
}
pub fn serialize<S, T>(values: &Option<Option<T>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Serialize,
{
match values {
None => serializer.serialize_unit(),
Some(None) => serializer.serialize_none(),
Some(Some(v)) => serializer.serialize_some(&v),
}
}
}
pub mod unwrap_or_skip {
use super::*;
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
where
D: Deserializer<'de>,
T: DeserializeOwned,
{
T::deserialize(deserializer).map(Some)
}
pub fn serialize<T, S>(option: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
where
T: Serialize,
S: Serializer,
{
if let Some(value) = option {
value.serialize(serializer)
} else {
().serialize(serializer)
}
}
}
pub mod sets_duplicate_value_is_error {
use super::*;
use duplicate_key_impls::PreventDuplicateInsertsSet;
pub fn deserialize<'de, D, T, V>(deserializer: D) -> Result<T, D::Error>
where
T: PreventDuplicateInsertsSet<V>,
V: Deserialize<'de>,
D: Deserializer<'de>,
{
struct SeqVisitor<T, V> {
marker: PhantomData<T>,
set_item_type: PhantomData<V>,
};
impl<'de, T, V> Visitor<'de> for SeqVisitor<T, V>
where
T: PreventDuplicateInsertsSet<V>,
V: Deserialize<'de>,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}
#[inline]
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut values = Self::Value::new(access.size_hint());
while let Some(value) = access.next_element()? {
if !values.insert(value) {
return Err(Error::custom("invalid entry: found duplicate value"));
};
}
Ok(values)
}
}
let visitor = SeqVisitor {
marker: PhantomData,
set_item_type: PhantomData,
};
deserializer.deserialize_seq(visitor)
}
}
pub mod maps_duplicate_key_is_error {
use super::*;
use duplicate_key_impls::PreventDuplicateInsertsMap;
pub fn deserialize<'de, D, T, K, V>(deserializer: D) -> Result<T, D::Error>
where
T: PreventDuplicateInsertsMap<K, V>,
K: Deserialize<'de>,
V: Deserialize<'de>,
D: Deserializer<'de>,
{
struct MapVisitor<T, K, V> {
marker: PhantomData<T>,
map_key_type: PhantomData<K>,
map_value_type: PhantomData<V>,
};
impl<'de, T, K, V> Visitor<'de> for MapVisitor<T, K, V>
where
T: PreventDuplicateInsertsMap<K, V>,
K: Deserialize<'de>,
V: Deserialize<'de>,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a map")
}
#[inline]
fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut values = Self::Value::new(access.size_hint());
while let Some((key, value)) = access.next_entry()? {
if !values.insert(key, value) {
return Err(Error::custom("invalid entry: found duplicate key"));
};
}
Ok(values)
}
}
let visitor = MapVisitor {
marker: PhantomData,
map_key_type: PhantomData,
map_value_type: PhantomData,
};
deserializer.deserialize_map(visitor)
}
}
pub mod sets_first_value_wins {
use super::*;
use duplicate_key_impls::DuplicateInsertsFirstWinsSet;
pub fn deserialize<'de, D, T, V>(deserializer: D) -> Result<T, D::Error>
where
T: DuplicateInsertsFirstWinsSet<V>,
V: Deserialize<'de>,
D: Deserializer<'de>,
{
struct SeqVisitor<T, V> {
marker: PhantomData<T>,
set_item_type: PhantomData<V>,
};
impl<'de, T, V> Visitor<'de> for SeqVisitor<T, V>
where
T: DuplicateInsertsFirstWinsSet<V>,
V: Deserialize<'de>,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}
#[inline]
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut values = Self::Value::new(access.size_hint());
while let Some(value) = access.next_element()? {
values.insert(value);
}
Ok(values)
}
}
let visitor = SeqVisitor {
marker: PhantomData,
set_item_type: PhantomData,
};
deserializer.deserialize_seq(visitor)
}
}
pub mod maps_first_key_wins {
use super::*;
use duplicate_key_impls::DuplicateInsertsFirstWinsMap;
pub fn deserialize<'de, D, T, K, V>(deserializer: D) -> Result<T, D::Error>
where
T: DuplicateInsertsFirstWinsMap<K, V>,
K: Deserialize<'de>,
V: Deserialize<'de>,
D: Deserializer<'de>,
{
struct MapVisitor<T, K, V> {
marker: PhantomData<T>,
map_key_type: PhantomData<K>,
map_value_type: PhantomData<V>,
};
impl<'de, T, K, V> Visitor<'de> for MapVisitor<T, K, V>
where
T: DuplicateInsertsFirstWinsMap<K, V>,
K: Deserialize<'de>,
V: Deserialize<'de>,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a map")
}
#[inline]
fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut values = Self::Value::new(access.size_hint());
while let Some((key, value)) = access.next_entry()? {
values.insert(key, value);
}
Ok(values)
}
}
let visitor = MapVisitor {
marker: PhantomData,
map_key_type: PhantomData,
map_value_type: PhantomData,
};
deserializer.deserialize_map(visitor)
}
}
pub mod string_empty_as_none {
use super::*;
pub fn deserialize<'de, D, S>(deserializer: D) -> Result<Option<S>, D::Error>
where
D: Deserializer<'de>,
S: FromStr,
S::Err: Display,
{
struct OptionStringEmptyNone<S>(PhantomData<S>);
impl<'de, S> Visitor<'de> for OptionStringEmptyNone<S>
where
S: FromStr,
S::Err: Display,
{
type Value = Option<S>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("any string")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
match value {
"" => Ok(None),
v => S::from_str(v).map(Some).map_err(Error::custom),
}
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
match &*value {
"" => Ok(None),
v => S::from_str(v).map(Some).map_err(Error::custom),
}
}
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: Error,
{
Ok(None)
}
}
deserializer.deserialize_any(OptionStringEmptyNone(PhantomData))
}
pub fn serialize<T, S>(option: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
where
T: AsRef<str>,
S: Serializer,
{
if let Some(value) = option {
value.as_ref().serialize(serializer)
} else {
"".serialize(serializer)
}
}
}
pub mod hashmap_as_tuple_list {
use super::SerializeSeq; use super::*;
pub fn serialize<K, V, S, BH>(map: &HashMap<K, V, BH>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
K: Eq + Hash + Serialize,
V: Serialize,
BH: BuildHasher,
{
let mut seq = serializer.serialize_seq(Some(map.len()))?;
for item in map.iter() {
seq.serialize_element(&item)?;
}
seq.end()
}
pub fn deserialize<'de, K, V, BH, D>(deserializer: D) -> Result<HashMap<K, V, BH>, D::Error>
where
D: Deserializer<'de>,
K: Eq + Hash + Deserialize<'de>,
V: Deserialize<'de>,
BH: BuildHasher + Default,
{
deserializer.deserialize_seq(HashMapVisitor(PhantomData))
}
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
struct HashMapVisitor<K, V, BH>(PhantomData<fn() -> HashMap<K, V, BH>>);
impl<'de, K, V, BH> Visitor<'de> for HashMapVisitor<K, V, BH>
where
K: Deserialize<'de> + Eq + Hash,
V: Deserialize<'de>,
BH: BuildHasher + Default,
{
type Value = HashMap<K, V, BH>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a list of key-value pairs")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut map =
HashMap::with_capacity_and_hasher(seq.size_hint().unwrap_or(0), BH::default());
while let Some((key, value)) = seq.next_element()? {
map.insert(key, value);
}
Ok(map)
}
}
}
pub mod btreemap_as_tuple_list {
use super::*;
pub fn serialize<K, V, S>(map: &BTreeMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
K: Eq + Hash + Serialize,
V: Serialize,
{
let mut seq = serializer.serialize_seq(Some(map.len()))?;
for item in map.iter() {
seq.serialize_element(&item)?;
}
seq.end()
}
pub fn deserialize<'de, K, V, D>(deserializer: D) -> Result<BTreeMap<K, V>, D::Error>
where
D: Deserializer<'de>,
K: Deserialize<'de> + Ord,
V: Deserialize<'de>,
{
deserializer.deserialize_seq(BTreeMapVisitor(PhantomData))
}
#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
struct BTreeMapVisitor<K, V>(PhantomData<fn() -> BTreeMap<K, V>>);
impl<'de, K, V> Visitor<'de> for BTreeMapVisitor<K, V>
where
K: Deserialize<'de> + Ord,
V: Deserialize<'de>,
{
type Value = BTreeMap<K, V>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a list of key-value pairs")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut map = BTreeMap::default();
while let Some((key, value)) = seq.next_element()? {
map.insert(key, value);
}
Ok(map)
}
}
}