diff options
Diffstat (limited to 'third_party/rust/serde_with/src')
-rw-r--r-- | third_party/rust/serde_with/src/chrono.rs | 160 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/duplicate_key_impls/error_on_duplicate.rs | 86 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/duplicate_key_impls/first_value_wins.rs | 104 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/duplicate_key_impls/mod.rs | 7 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/flatten_maybe.rs | 86 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/json.rs | 88 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/lib.rs | 140 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/rust.rs | 1534 | ||||
-rw-r--r-- | third_party/rust/serde_with/src/with_prefix.rs | 607 |
9 files changed, 2812 insertions, 0 deletions
diff --git a/third_party/rust/serde_with/src/chrono.rs b/third_party/rust/serde_with/src/chrono.rs new file mode 100644 index 0000000000..ea0118d798 --- /dev/null +++ b/third_party/rust/serde_with/src/chrono.rs @@ -0,0 +1,160 @@ +//! De/Serialization of [chrono][] types +//! +//! This modules is only available if using the `chrono` feature of the crate. +//! +//! [chrono]: https://docs.rs/chrono/ + +/// Deserialize a Unix timestamp with optional subsecond precision into a `DateTime<Utc>`. +/// +/// The `DateTime<Utc>` can be serialized from an integer, a float, or a string representing a number. +/// +/// # Examples +/// +/// ``` +/// # extern crate chrono; +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use chrono::{DateTime, Utc}; +/// # use serde_derive::{Deserialize, Serialize}; +/// # +/// #[derive(Debug, Deserialize)] +/// struct S { +/// #[serde(with = "serde_with::chrono::datetime_utc_ts_seconds_from_any")] +/// date: DateTime<Utc>, +/// } +/// +/// // Deserializes integers +/// assert!(serde_json::from_str::<S>(r#"{ "date": 1478563200 }"#).is_ok()); +/// // floats +/// assert!(serde_json::from_str::<S>(r#"{ "date": 1478563200.123 }"#).is_ok()); +/// // and strings with numbers, for high-precision values +/// assert!(serde_json::from_str::<S>(r#"{ "date": "1478563200.123" }"#).is_ok()); +/// ``` +/// +pub mod datetime_utc_ts_seconds_from_any { + use chrono_crate::{DateTime, NaiveDateTime, Utc}; + use serde::de::{Deserializer, Error, Unexpected, Visitor}; + + /// Deserialize a Unix timestamp with optional subsecond precision into a `DateTime<Utc>`. + pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error> + where + D: Deserializer<'de>, + { + struct Helper; + impl<'de> Visitor<'de> for Helper { + type Value = DateTime<Utc>; + + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str("Invalid timestamp. Must be an integer, float, or string with optional subsecond precision.") + } + + fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> + where + E: Error, + { + let ndt = NaiveDateTime::from_timestamp_opt(value, 0); + if let Some(ndt) = ndt { + Ok(DateTime::<Utc>::from_utc(ndt, Utc)) + } else { + Err(Error::custom(format!( + "Invalid or out of range value '{}' for DateTime", + value + ))) + } + } + + fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> + where + E: Error, + { + let ndt = NaiveDateTime::from_timestamp_opt(value as i64, 0); + if let Some(ndt) = ndt { + Ok(DateTime::<Utc>::from_utc(ndt, Utc)) + } else { + Err(Error::custom(format!( + "Invalid or out of range value '{}' for DateTime", + value + ))) + } + } + + fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> + where + E: Error, + { + let seconds = value.trunc() as i64; + let nsecs = (value.fract() * 1_000_000_000_f64).abs() as u32; + let ndt = NaiveDateTime::from_timestamp_opt(seconds, nsecs); + if let Some(ndt) = ndt { + Ok(DateTime::<Utc>::from_utc(ndt, Utc)) + } else { + Err(Error::custom(format!( + "Invalid or out of range value '{}' for DateTime", + value + ))) + } + } + + fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> + where + E: Error, + { + let parts: Vec<_> = value.split('.').collect(); + + match *parts.as_slice() { + [seconds] => { + if let Ok(seconds) = i64::from_str_radix(seconds, 10) { + let ndt = NaiveDateTime::from_timestamp_opt(seconds, 0); + if let Some(ndt) = ndt { + Ok(DateTime::<Utc>::from_utc(ndt, Utc)) + } else { + Err(Error::custom(format!( + "Invalid or out of range value '{}' for DateTime", + value + ))) + } + } else { + Err(Error::invalid_value(Unexpected::Str(value), &self)) + } + } + [seconds, subseconds] => { + if let Ok(seconds) = i64::from_str_radix(seconds, 10) { + let subseclen = subseconds.chars().count() as u32; + if subseclen > 9 { + return Err(Error::custom(format!( + "DateTimes only support nanosecond precision but '{}' has more than 9 digits.", + value + ))); + } + + if let Ok(mut subseconds) = u32::from_str_radix(subseconds, 10) { + // convert subseconds to nanoseconds (10^-9), require 9 places for nanoseconds + subseconds *= 10u32.pow(9 - subseclen); + let ndt = NaiveDateTime::from_timestamp_opt(seconds, subseconds); + if let Some(ndt) = ndt { + Ok(DateTime::<Utc>::from_utc(ndt, Utc)) + } else { + Err(Error::custom(format!( + "Invalid or out of range value '{}' for DateTime", + value + ))) + } + } else { + Err(Error::invalid_value(Unexpected::Str(value), &self)) + } + } else { + Err(Error::invalid_value(Unexpected::Str(value), &self)) + } + } + + _ => Err(Error::invalid_value(Unexpected::Str(value), &self)), + } + } + } + + deserializer.deserialize_any(Helper) + } +} diff --git a/third_party/rust/serde_with/src/duplicate_key_impls/error_on_duplicate.rs b/third_party/rust/serde_with/src/duplicate_key_impls/error_on_duplicate.rs new file mode 100644 index 0000000000..3fc08e8c57 --- /dev/null +++ b/third_party/rust/serde_with/src/duplicate_key_impls/error_on_duplicate.rs @@ -0,0 +1,86 @@ +use std::{ + collections::{BTreeMap, BTreeSet, HashMap, HashSet}, + hash::{BuildHasher, Hash}, +}; + +pub trait PreventDuplicateInsertsSet<T> { + fn new(size_hint: Option<usize>) -> Self; + + /// Return true if the insert was successful and the value did not exist in the set + fn insert(&mut self, value: T) -> bool; +} + +pub trait PreventDuplicateInsertsMap<K, V> { + fn new(size_hint: Option<usize>) -> Self; + + /// Return true if the insert was successful and the key did not exist in the map + fn insert(&mut self, key: K, value: V) -> bool; +} + +impl<T, S> PreventDuplicateInsertsSet<T> for HashSet<T, S> +where + T: Eq + Hash, + S: BuildHasher + Default, +{ + #[inline] + fn new(size_hint: Option<usize>) -> Self { + match size_hint { + Some(size) => Self::with_capacity_and_hasher(size, S::default()), + None => Self::with_hasher(S::default()), + } + } + + #[inline] + fn insert(&mut self, value: T) -> bool { + self.insert(value) + } +} + +impl<T> PreventDuplicateInsertsSet<T> for BTreeSet<T> +where + T: Ord, +{ + #[inline] + fn new(_size_hint: Option<usize>) -> Self { + Self::new() + } + + #[inline] + fn insert(&mut self, value: T) -> bool { + self.insert(value) + } +} + +impl<K, V, S> PreventDuplicateInsertsMap<K, V> for HashMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher + Default, +{ + #[inline] + fn new(size_hint: Option<usize>) -> Self { + match size_hint { + Some(size) => Self::with_capacity_and_hasher(size, S::default()), + None => Self::with_hasher(S::default()), + } + } + + #[inline] + fn insert(&mut self, key: K, value: V) -> bool { + self.insert(key, value).is_none() + } +} + +impl<K, V> PreventDuplicateInsertsMap<K, V> for BTreeMap<K, V> +where + K: Ord, +{ + #[inline] + fn new(_size_hint: Option<usize>) -> Self { + Self::new() + } + + #[inline] + fn insert(&mut self, key: K, value: V) -> bool { + self.insert(key, value).is_none() + } +} diff --git a/third_party/rust/serde_with/src/duplicate_key_impls/first_value_wins.rs b/third_party/rust/serde_with/src/duplicate_key_impls/first_value_wins.rs new file mode 100644 index 0000000000..e60ee9227a --- /dev/null +++ b/third_party/rust/serde_with/src/duplicate_key_impls/first_value_wins.rs @@ -0,0 +1,104 @@ +use std::{ + collections::{BTreeMap, BTreeSet, HashMap, HashSet}, + hash::{BuildHasher, Hash}, +}; + +pub trait DuplicateInsertsFirstWinsSet<T> { + fn new(size_hint: Option<usize>) -> Self; + + /// Insert the value into the set, if there is not already an existing value + fn insert(&mut self, value: T); +} + +pub trait DuplicateInsertsFirstWinsMap<K, V> { + fn new(size_hint: Option<usize>) -> Self; + + /// Insert the value into the map, if there is not already an existing value + fn insert(&mut self, key: K, value: V); +} + +impl<T, S> DuplicateInsertsFirstWinsSet<T> for HashSet<T, S> +where + T: Eq + Hash, + S: BuildHasher + Default, +{ + #[inline] + fn new(size_hint: Option<usize>) -> Self { + match size_hint { + Some(size) => Self::with_capacity_and_hasher(size, S::default()), + None => Self::with_hasher(S::default()), + } + } + + #[inline] + fn insert(&mut self, value: T) { + // Hashset already fullfils the contract and always keeps the first value + self.insert(value); + } +} + +impl<T> DuplicateInsertsFirstWinsSet<T> for BTreeSet<T> +where + T: Ord, +{ + #[inline] + fn new(_size_hint: Option<usize>) -> Self { + Self::new() + } + + #[inline] + fn insert(&mut self, value: T) { + // BTreeSet already fullfils the contract and always keeps the first value + self.insert(value); + } +} + +impl<K, V, S> DuplicateInsertsFirstWinsMap<K, V> for HashMap<K, V, S> +where + K: Eq + Hash, + S: BuildHasher + Default, +{ + #[inline] + fn new(size_hint: Option<usize>) -> Self { + match size_hint { + Some(size) => Self::with_capacity_and_hasher(size, S::default()), + None => Self::with_hasher(S::default()), + } + } + + #[inline] + fn insert(&mut self, key: K, value: V) { + use std::collections::hash_map::Entry; + + match self.entry(key) { + // we want to keep the first value, so do nothing + Entry::Occupied(_) => {} + Entry::Vacant(vacant) => { + vacant.insert(value); + } + } + } +} + +impl<K, V> DuplicateInsertsFirstWinsMap<K, V> for BTreeMap<K, V> +where + K: Ord, +{ + #[inline] + fn new(_size_hint: Option<usize>) -> Self { + Self::new() + } + + #[inline] + fn insert(&mut self, key: K, value: V) { + use std::collections::btree_map::Entry; + + match self.entry(key) { + // we want to keep the first value, so do nothing + Entry::Occupied(_) => {} + Entry::Vacant(vacant) => { + vacant.insert(value); + } + } + } +} diff --git a/third_party/rust/serde_with/src/duplicate_key_impls/mod.rs b/third_party/rust/serde_with/src/duplicate_key_impls/mod.rs new file mode 100644 index 0000000000..e433baa0ac --- /dev/null +++ b/third_party/rust/serde_with/src/duplicate_key_impls/mod.rs @@ -0,0 +1,7 @@ +mod error_on_duplicate; +mod first_value_wins; + +pub use self::{ + error_on_duplicate::{PreventDuplicateInsertsMap, PreventDuplicateInsertsSet}, + first_value_wins::{DuplicateInsertsFirstWinsMap, DuplicateInsertsFirstWinsSet}, +}; diff --git a/third_party/rust/serde_with/src/flatten_maybe.rs b/third_party/rust/serde_with/src/flatten_maybe.rs new file mode 100644 index 0000000000..6ea64ed4fd --- /dev/null +++ b/third_party/rust/serde_with/src/flatten_maybe.rs @@ -0,0 +1,86 @@ +/// Support deserializing from flattened and non-flattened representation +/// +/// When working with different serialization formats, sometimes it is more idiomatic to flatten +/// fields, while other formats prefer nesting. Using `#[serde(flatten)]` only the flattened form +/// is supported. +/// +/// This helper creates a function, which support deserializing from either the flattened or the +/// nested form. It gives an error, when both forms are provided. The `flatten` attribute is +/// required on the field such that the helper works. The serialization format will always be +/// flattened. +/// +/// # Examples +/// +/// ```rust +/// # extern crate serde; +/// # extern crate serde_json; +/// # #[macro_use] +/// # extern crate serde_with; +/// # +/// # use serde::Deserialize; +/// # +/// // Setup the types +/// #[derive(Deserialize, Debug)] +/// struct S { +/// #[serde(flatten, deserialize_with = "deserialize_t")] +/// t: T, +/// } +/// +/// #[derive(Deserialize, Debug)] +/// struct T { +/// i: i32, +/// } +/// +/// // The macro creates custom deserialization code. +/// // You need to specify a function name and the field name of the flattened field. +/// flattened_maybe!(deserialize_t, "t"); +/// +/// +/// # fn main() { +/// // Supports both flattened +/// let j = r#" {"i":1} "#; +/// assert!(serde_json::from_str::<S>(j).is_ok()); +/// +/// // and non-flattened versions. +/// let j = r#" {"t":{"i":1}} "#; +/// assert!(serde_json::from_str::<S>(j).is_ok()); +/// +/// // Ensure that the value is given +/// let j = r#" {} "#; +/// assert!(serde_json::from_str::<S>(j).is_err()); +/// +/// // and only occurs once, not multiple times. +/// let j = r#" {"i":1,"t":{"i":1}} "#; +/// assert!(serde_json::from_str::<S>(j).is_err()); +/// # } +/// ``` +#[macro_export] +macro_rules! flattened_maybe { + // TODO Change $field to literal, once the compiler version is bumped enough. + ($fn:ident, $field:expr) => { + fn $fn<'de, T, D>(deserializer: D) -> Result<T, D::Error> + where + T: serde::Deserialize<'de>, + D: serde::Deserializer<'de>, + { + #[derive(serde::Deserialize)] + struct Both<T> { + #[serde(flatten)] + flat: Option<T>, + #[serde(rename = $field)] + not_flat: Option<T>, + } + + let both: Both<T> = serde::Deserialize::deserialize(deserializer)?; + match (both.flat, both.not_flat) { + (Some(t), None) | (None, Some(t)) => Ok(t), + (None, None) => Err(serde::de::Error::missing_field($field)), + (Some(_), Some(_)) => Err(serde::de::Error::custom(concat!( + "`", + $field, + "` is both flattened and not" + ))), + } + } + }; +} diff --git a/third_party/rust/serde_with/src/json.rs b/third_party/rust/serde_with/src/json.rs new file mode 100644 index 0000000000..9123713856 --- /dev/null +++ b/third_party/rust/serde_with/src/json.rs @@ -0,0 +1,88 @@ +//! De/Serialization of JSON +//! +//! This modules is only available if using the `json` feature of the crate. + +/// Serialize value as string containing JSON +/// +/// # Examples +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # +/// #[derive(Deserialize, Serialize)] +/// struct A { +/// #[serde(with = "serde_with::json::nested")] +/// other_struct: B, +/// } +/// #[derive(Deserialize, Serialize)] +/// struct B { +/// value: usize, +/// } +/// +/// let v: A = serde_json::from_str(r#"{"other_struct":"{\"value\":5}"}"#).unwrap(); +/// assert_eq!(5, v.other_struct.value); +/// +/// let x = A { +/// other_struct: B { value: 10 }, +/// }; +/// assert_eq!(r#"{"other_struct":"{\"value\":10}"}"#, serde_json::to_string(&x).unwrap()); +/// ``` +/// +pub mod nested { + use serde::{ + de::{DeserializeOwned, Deserializer, Error, Visitor}, + ser::{self, Serialize, Serializer}, + }; + use serde_json; + use std::{fmt, marker::PhantomData}; + + /// Deserialize value from a string which is valid JSON + pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + T: DeserializeOwned, + { + #[derive(Default)] + struct Helper<S: DeserializeOwned>(PhantomData<S>); + + impl<'de, S> Visitor<'de> for Helper<S> + where + S: DeserializeOwned, + { + 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<S, E> + where + E: Error, + { + serde_json::from_str(value).map_err(Error::custom) + } + } + + deserializer.deserialize_str(Helper(PhantomData)) + } + + /// Serialize value as string containing JSON + /// + /// # Errors + /// + /// Serialization can fail if `T`'s implementation of `Serialize` decides to + /// fail, or if `T` contains a map with non-string keys. + pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error> + where + T: Serialize, + S: Serializer, + { + let s = serde_json::to_string(value).map_err(ser::Error::custom)?; + serializer.serialize_str(&*s) + } +} diff --git a/third_party/rust/serde_with/src/lib.rs b/third_party/rust/serde_with/src/lib.rs new file mode 100644 index 0000000000..5856a0d339 --- /dev/null +++ b/third_party/rust/serde_with/src/lib.rs @@ -0,0 +1,140 @@ +#![deny( + missing_debug_implementations, + missing_copy_implementations, + missing_docs, + trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + variant_size_differences +)] +#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] +#![doc(html_root_url = "https://docs.rs/serde_with/1.4.0")] + +//! [![docs.rs badge](https://docs.rs/serde_with/badge.svg)](https://docs.rs/serde_with/) +//! [![crates.io badge](https://img.shields.io/crates/v/serde_with.svg)](https://crates.io/crates/serde_with/) +//! [![Build Status](https://travis-ci.org/jonasbb/serde_with.svg?branch=master)](https://travis-ci.org/jonasbb/serde_with) +//! [![codecov](https://codecov.io/gh/jonasbb/serde_with/branch/master/graph/badge.svg)](https://codecov.io/gh/jonasbb/serde_with) +//! +//! --- +//! +//! This crate provides custom de/serialization helpers to use in combination with [serde's with-annotation][with-annotation]. +//! +//! Serde tracks a wishlist of similar helpers at [serde#553]. +//! +//! # Usage +//! +//! Add this to your `Cargo.toml`: +//! +//! ```toml +//! [dependencies.serde_with] +//! version = "1.4.0" +//! features = [ "..." ] +//! ``` +//! +//! The crate is divided into different modules. +//! They contain helpers for external crates and must be enabled with the correspondig feature. +//! +//! Annotate your struct or enum to enable the custom de/serializer. +//! +//! ```rust +//! # extern crate serde; +//! # extern crate serde_derive; +//! # extern crate serde_with; +//! # use serde_derive::{Deserialize, Serialize}; +//! #[derive(Deserialize, Serialize)] +//! struct Foo { +//! #[serde(with = "serde_with::rust::display_fromstr")] +//! bar: u8, +//! } +//! # fn main() {} +//! ``` +//! +//! Most helpers implement both deserialize and serialize. +//! If you do not want to derive both, you can simply derive only the necessary parts. +//! If you want to mix different helpers, you can write your annotations like +//! +//! ```rust +//! # extern crate serde; +//! # extern crate serde_derive; +//! # extern crate serde_with; +//! # use serde_derive::{Deserialize, Serialize}; +//! # #[cfg(feature = "json")] +//! #[derive(Deserialize, Serialize)] +//! struct Foo { +//! #[serde( +//! deserialize_with = "serde_with::rust::display_fromstr::deserialize", +//! serialize_with = "serde_with::json::nested::serialize" +//! )] +//! bar: u8, +//! } +//! # fn main() {} +//! ``` +//! +//! However, this will prohibit you from applying deserialize on the value returned by serializing a struct. +//! +//! # Attributes +//! +//! The crate comes with custom attributes, which futher extend how serde serialization can be customized. +//! They are enabled by default, but can be disabled, by removing the default features from this crate. +//! +//! The `serde_with` crate re-exports all items from `serde_with_macros`. +//! This means, if you want to use any proc_macros, import them like `use serde_with::skip_serializing_none`. +//! +//! [The documentation for the custom attributes can be found here.](serde_with_macros) +//! +//! [with-annotation]: https://serde.rs/field-attrs.html#serdewith--module +//! [serde#553]: https://github.com/serde-rs/serde/issues/553 + +#[cfg(feature = "chrono")] +extern crate chrono as chrono_crate; +#[doc(hidden)] +pub extern crate serde; +#[cfg(feature = "json")] +extern crate serde_json; +#[cfg(feature = "macros")] +extern crate serde_with_macros; + +#[cfg(feature = "chrono")] +pub mod chrono; +mod duplicate_key_impls; +mod flatten_maybe; +#[cfg(feature = "json")] +pub mod json; +pub mod rust; +#[doc(hidden)] +pub mod with_prefix; + +// Re-Export all proc_macros, as these should be seen as part of the serde_with crate +#[cfg(feature = "macros")] +#[doc(inline)] +pub use serde_with_macros::*; + +/// Separator for string-based collection de/serialization +pub trait Separator { + /// Return the string delimiting two elements in the string-based collection + fn separator() -> &'static str; +} + +/// Predefined separator using a single space +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)] +pub struct SpaceSeparator; + +impl Separator for SpaceSeparator { + #[inline] + fn separator() -> &'static str { + " " + } +} + +/// Predefined separator using a single comma +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)] +pub struct CommaSeparator; + +impl Separator for CommaSeparator { + #[inline] + fn separator() -> &'static str { + "," + } +} diff --git a/third_party/rust/serde_with/src/rust.rs b/third_party/rust/serde_with/src/rust.rs new file mode 100644 index 0000000000..3a984ed7e4 --- /dev/null +++ b/third_party/rust/serde_with/src/rust.rs @@ -0,0 +1,1534 @@ +//! De/Serialization for Rust's builtin and std types + +use serde::{ + de::{Deserialize, DeserializeOwned, Deserializer, Error, MapAccess, SeqAccess, Visitor}, + ser::{Serialize, SerializeMap, SerializeSeq, Serializer}, +}; +use std::{ + cmp::Eq, + collections::{BTreeMap, HashMap}, + fmt::{self, Display}, + hash::{BuildHasher, Hash}, + iter::FromIterator, + marker::PhantomData, + str::FromStr, +}; +use Separator; + +/// De/Serialize using [`Display`] and [`FromStr`] implementation +/// +/// This allows to deserialize a string as a number. +/// It can be very useful for serialization formats like JSON, which do not support integer +/// numbers and have to resort to strings to represent them. +/// +/// # Examples +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # use std::net::Ipv4Addr; +/// # +/// #[derive(Deserialize, Serialize)] +/// struct A { +/// #[serde(with = "serde_with::rust::display_fromstr")] +/// address: Ipv4Addr, +/// #[serde(with = "serde_with::rust::display_fromstr")] +/// b: bool, +/// } +/// +/// let v: A = serde_json::from_str(r#"{ +/// "address": "192.168.2.1", +/// "b": "true" +/// }"#).unwrap(); +/// assert_eq!(Ipv4Addr::new(192, 168, 2, 1), v.address); +/// assert!(v.b); +/// +/// let x = A { +/// address: Ipv4Addr::new(127, 53, 0, 1), +/// b: false, +/// }; +/// assert_eq!(r#"{"address":"127.53.0.1","b":"false"}"#, serde_json::to_string(&x).unwrap()); +/// ``` +pub mod display_fromstr { + use super::*; + use std::str::FromStr; + + /// Deserialize T using [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)) + } + + /// Serialize T using [Display] + 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()) + } +} + +/// De/Serialize sequences using [`FromIterator`] and [`IntoIterator`] implementation for it and [`Display`] and [`FromStr`] implementation for each element +/// +/// This allows to serialize and deserialize collections with elements which can be represented as strings. +/// +/// # Examples +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # +/// use std::collections::BTreeSet; +/// use std::net::Ipv4Addr; +/// +/// #[derive(Deserialize, Serialize)] +/// struct A { +/// #[serde(with = "serde_with::rust::seq_display_fromstr")] +/// addresses: BTreeSet<Ipv4Addr>, +/// #[serde(with = "serde_with::rust::seq_display_fromstr")] +/// bs: Vec<bool>, +/// } +/// +/// let v: A = serde_json::from_str(r#"{ +/// "addresses": ["192.168.2.1", "192.168.2.2", "192.168.1.1", "192.168.2.2"], +/// "bs": ["true", "false"] +/// }"#).unwrap(); +/// assert_eq!(v.addresses.len(), 3); +/// assert!(v.addresses.contains(&Ipv4Addr::new(192, 168, 2, 1))); +/// assert!(v.addresses.contains(&Ipv4Addr::new(192, 168, 2, 2))); +/// assert!(!v.addresses.contains(&Ipv4Addr::new(192, 168, 1, 2))); +/// assert_eq!(v.bs.len(), 2); +/// assert!(v.bs[0]); +/// assert!(!v.bs[1]); +/// +/// let x = A { +/// addresses: vec![ +/// Ipv4Addr::new(127, 53, 0, 1), +/// Ipv4Addr::new(127, 53, 1, 1), +/// Ipv4Addr::new(127, 53, 0, 2) +/// ].into_iter().collect(), +/// bs: vec![false, true], +/// }; +/// assert_eq!(r#"{"addresses":["127.53.0.1","127.53.0.2","127.53.1.1"],"bs":["false","true"]}"#, serde_json::to_string(&x).unwrap()); +/// ``` +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, + }; + + /// Deserialize collection T using [FromIterator] and [FromStr] for each element + 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) + } + + /// Serialize collection T using [IntoIterator] and [Display] for each element + 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() + } +} + +/// De/Serialize a delimited collection using [`Display`] and [`FromStr`] implementation +/// +/// You can define an arbitrary separator, by specifying a type which implements [`Separator`]. +/// Some common ones, like space and comma are already predefined and you can find them [here][Separator]. +/// +/// An empty string deserializes as an empty collection. +/// +/// # Examples +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # +/// use serde_with::{CommaSeparator, SpaceSeparator}; +/// use std::collections::BTreeSet; +/// +/// #[derive(Deserialize, Serialize)] +/// struct A { +/// #[serde(with = "serde_with::rust::StringWithSeparator::<SpaceSeparator>")] +/// tags: Vec<String>, +/// #[serde(with = "serde_with::rust::StringWithSeparator::<CommaSeparator>")] +/// more_tags: BTreeSet<String>, +/// } +/// +/// let v: A = serde_json::from_str(r##"{ +/// "tags": "#hello #world", +/// "more_tags": "foo,bar,bar" +/// }"##).unwrap(); +/// assert_eq!(vec!["#hello", "#world"], v.tags); +/// assert_eq!(2, v.more_tags.len()); +/// +/// let x = A { +/// tags: vec!["1".to_string(), "2".to_string(), "3".to_string()], +/// more_tags: BTreeSet::new(), +/// }; +/// assert_eq!(r#"{"tags":"1 2 3","more_tags":""}"#, serde_json::to_string(&x).unwrap()); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)] +pub struct StringWithSeparator<Sep>(PhantomData<Sep>); + +impl<Sep> StringWithSeparator<Sep> +where + Sep: Separator, +{ + /// Serialize collection into a string with separator symbol + 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() { + // remove trailing separator if present + &s[..s.len() - Sep::separator().len()] + } else { + &s[..] + }) + } + + /// Deserialize a collection from a string with separator symbol + 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) + } + } +} + +/// Makes a distinction between a missing, unset, or existing value +/// +/// Some serialization formats make a distinction between missing fields, fields with a `null` +/// value, and existing values. One such format is JSON. By default it is not easily possible to +/// differentiate between a missing value and a field which is `null`, as they deserialize to the +/// same value. This helper changes it, by using an `Option<Option<T>>` to deserialize into. +/// +/// * `None`: Represents a missing value. +/// * `Some(None)`: Represents a `null` value. +/// * `Some(Some(value))`: Represents an existing value. +/// +/// # Examples +/// +/// ```rust +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # +/// # #[derive(Debug, PartialEq, Eq)] +/// #[derive(Deserialize, Serialize)] +/// struct Doc { +/// #[serde( +/// default, // <- important for deserialization +/// skip_serializing_if = "Option::is_none", // <- important for serialization +/// with = "::serde_with::rust::double_option", +/// )] +/// a: Option<Option<u8>>, +/// } +/// // Missing Value +/// let s = r#"{}"#; +/// assert_eq!(Doc {a: None}, serde_json::from_str(s).unwrap()); +/// assert_eq!(s, serde_json::to_string(&Doc {a: None}).unwrap()); +/// +/// // Unset Value +/// let s = r#"{"a":null}"#; +/// assert_eq!(Doc {a: Some(None)}, serde_json::from_str(s).unwrap()); +/// assert_eq!(s, serde_json::to_string(&Doc {a: Some(None)}).unwrap()); +/// +/// // Existing Value +/// let s = r#"{"a":5}"#; +/// assert_eq!(Doc {a: Some(Some(5))}, serde_json::from_str(s).unwrap()); +/// assert_eq!(s, serde_json::to_string(&Doc {a: Some(Some(5))}).unwrap()); +/// ``` +#[cfg_attr(feature = "cargo-clippy", allow(option_option))] +pub mod double_option { + use super::*; + + /// Deserialize potentially non-existing optional value + 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) + } + + /// Serialize optional value + 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), + } + } +} + +/// Serialize inner value if [`Some`]`(T)`. If [`None`], serialize the unit struct `()`. +/// +/// When used in conjunction with `skip_serializing_if = "Option::is_none"` and +/// `default`, you can build an optional value by skipping if it is [`None`], or serializing its +/// inner value if [`Some`]`(T)`. +/// +/// Not all serialization formats easily support optional values. +/// While JSON uses the [`Option`] type to represent optional values and only serializes the inner +/// part of the [`Some`]`()`, other serialization formats, such as [RON][], choose to serialize the +/// [`Some`] around a value. +/// This helper helps building a truly optional value for such serializers. +/// +/// [RON]: https://github.com/ron-rs/ron +/// +/// # Example +/// +/// ```rust +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # extern crate ron; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # +/// # #[derive(Debug, Eq, PartialEq)] +/// #[derive(Deserialize, Serialize)] +/// struct Doc { +/// mandatory: usize, +/// #[serde( +/// default, // <- important for deserialization +/// skip_serializing_if = "Option::is_none", // <- important for serialization +/// with = "::serde_with::rust::unwrap_or_skip", +/// )] +/// optional: Option<usize>, +/// } +/// +/// // Transparently add/remove Some() wrapper +/// # let pretty_config = ron::ser::PrettyConfig { +/// # new_line: "\n".into(), +/// # ..Default::default() +/// # }; +/// let s = r#"( +/// mandatory: 1, +/// optional: 2, +/// )"#; +/// let v = Doc { +/// mandatory: 1, +/// optional: Some(2), +/// }; +/// assert_eq!(v, ron::de::from_str(s).unwrap()); +/// assert_eq!(s, ron::ser::to_string_pretty(&v, pretty_config).unwrap()); +/// +/// // Missing values are deserialized as `None` +/// // while `None` values are skipped during serialization. +/// # let pretty_config = ron::ser::PrettyConfig { +/// # new_line: "\n".into(), +/// # ..Default::default() +/// # }; +/// let s = r#"( +/// mandatory: 1, +/// )"#; +/// let v = Doc { +/// mandatory: 1, +/// optional: None, +/// }; +/// assert_eq!(v, ron::de::from_str(s).unwrap()); +/// assert_eq!(s, ron::ser::to_string_pretty(&v, pretty_config).unwrap()); +/// ``` +pub mod unwrap_or_skip { + use super::*; + + /// Deserialize value wrapped in Some(T) + pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error> + where + D: Deserializer<'de>, + T: DeserializeOwned, + { + T::deserialize(deserializer).map(Some) + } + + /// Serialize value if Some(T), unit struct if None + 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) + } + } +} + +/// Ensure no duplicate values exist in a set. +/// +/// By default serde has a last-value-wins implementation, if duplicate values for a set exist. +/// Sometimes it is desirable to know when such an event happens, as the first value is overwritten +/// and it can indicate an error in the serialized data. +/// +/// This helper returns an error if two identical values exist in a set. +/// +/// The implementation supports both the [`HashSet`] and the [`BTreeSet`] from the standard library. +/// +/// [`HashSet`]: std::collections::HashSet +/// [`BTreeSet`]: std::collections::HashSet +/// +/// # Example +/// +/// ```rust +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use std::{collections::HashSet, iter::FromIterator}; +/// # use serde_derive::{Deserialize, Serialize}; +/// # +/// # #[derive(Debug, Eq, PartialEq)] +/// #[derive(Deserialize)] +/// struct Doc { +/// #[serde(with = "::serde_with::rust::sets_duplicate_value_is_error")] +/// set: HashSet<usize>, +/// } +/// +/// // Sets are serialized normally, +/// let s = r#"{"set": [1, 2, 3, 4]}"#; +/// let v = Doc { +/// set: HashSet::from_iter(vec![1, 2, 3, 4]), +/// }; +/// assert_eq!(v, serde_json::from_str(s).unwrap()); +/// +/// // but create an error if duplicate values, like the `1`, exist. +/// let s = r#"{"set": [1, 2, 3, 4, 1]}"#; +/// let res: Result<Doc, _> = serde_json::from_str(s); +/// assert!(res.is_err()); +/// ``` +pub mod sets_duplicate_value_is_error { + use super::*; + use duplicate_key_impls::PreventDuplicateInsertsSet; + + /// Deserialize a set and return an error on duplicate values + 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) + } +} + +/// Ensure no duplicate keys exist in a map. +/// +/// By default serde has a last-value-wins implementation, if duplicate keys for a map exist. +/// Sometimes it is desirable to know when such an event happens, as the first value is overwritten +/// and it can indicate an error in the serialized data. +/// +/// This helper returns an error if two identical keys exist in a map. +/// +/// The implementation supports both the [`HashMap`] and the [`BTreeMap`] from the standard library. +/// +/// [`HashMap`]: std::collections::HashMap +/// [`BTreeMap`]: std::collections::HashMap +/// +/// # Example +/// +/// ```rust +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # use std::collections::HashMap; +/// # +/// # #[derive(Debug, Eq, PartialEq)] +/// #[derive(Deserialize)] +/// struct Doc { +/// #[serde(with = "::serde_with::rust::maps_duplicate_key_is_error")] +/// map: HashMap<usize, usize>, +/// } +/// +/// // Maps are serialized normally, +/// let s = r#"{"map": {"1": 1, "2": 2, "3": 3}}"#; +/// let mut v = Doc { +/// map: HashMap::new(), +/// }; +/// v.map.insert(1, 1); +/// v.map.insert(2, 2); +/// v.map.insert(3, 3); +/// assert_eq!(v, serde_json::from_str(s).unwrap()); +/// +/// // but create an error if duplicate keys, like the `1`, exist. +/// let s = r#"{"map": {"1": 1, "2": 2, "1": 3}}"#; +/// let res: Result<Doc, _> = serde_json::from_str(s); +/// assert!(res.is_err()); +/// ``` +pub mod maps_duplicate_key_is_error { + use super::*; + use duplicate_key_impls::PreventDuplicateInsertsMap; + + /// Deserialize a map and return an error on duplicate keys + 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) + } +} + +/// Ensure that the first value is taken, if duplicate values exist +/// +/// By default serde has a last-value-wins implementation, if duplicate keys for a set exist. +/// Sometimes the opposite strategy is desired. This helper implements a first-value-wins strategy. +/// +/// The implementation supports both the [`HashSet`] and the [`BTreeSet`] from the standard library. +/// +/// [`HashSet`]: std::collections::HashSet +/// [`BTreeSet`]: std::collections::HashSet +pub mod sets_first_value_wins { + use super::*; + use duplicate_key_impls::DuplicateInsertsFirstWinsSet; + + /// Deserialize a set and return an error on duplicate values + 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) + } +} + +/// Ensure that the first key is taken, if duplicate keys exist +/// +/// By default serde has a last-key-wins implementation, if duplicate keys for a map exist. +/// Sometimes the opposite strategy is desired. This helper implements a first-key-wins strategy. +/// +/// The implementation supports both the [`HashMap`] and the [`BTreeMap`] from the standard library. +/// +/// [`HashMap`]: std::collections::HashMap +/// [`BTreeMap`]: std::collections::HashMap +/// +/// # Example +/// +/// ```rust +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # use std::collections::HashMap; +/// # +/// # #[derive(Debug, Eq, PartialEq)] +/// #[derive(Deserialize)] +/// struct Doc { +/// #[serde(with = "::serde_with::rust::maps_first_key_wins")] +/// map: HashMap<usize, usize>, +/// } +/// +/// // Maps are serialized normally, +/// let s = r#"{"map": {"1": 1, "2": 2, "3": 3}}"#; +/// let mut v = Doc { +/// map: HashMap::new(), +/// }; +/// v.map.insert(1, 1); +/// v.map.insert(2, 2); +/// v.map.insert(3, 3); +/// assert_eq!(v, serde_json::from_str(s).unwrap()); +/// +/// // but create an error if duplicate keys, like the `1`, exist. +/// let s = r#"{"map": {"1": 1, "2": 2, "1": 3}}"#; +/// let mut v = Doc { +/// map: HashMap::new(), +/// }; +/// v.map.insert(1, 1); +/// v.map.insert(2, 2); +/// assert_eq!(v, serde_json::from_str(s).unwrap()); +/// ``` +pub mod maps_first_key_wins { + use super::*; + use duplicate_key_impls::DuplicateInsertsFirstWinsMap; + + /// Deserialize a map and return an error on duplicate keys + 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) + } +} + +/// De/Serialize a [`Option`]`<String>` type while transforming the empty string to [`None`] +/// +/// Convert an [`Option`]`<T>` from/to string using [`FromStr`] and [`AsRef`]`<str>` implementations. +/// An empty string is deserialized as [`None`] and a [`None`] vice versa. +/// +/// # Examples +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # +/// #[derive(Deserialize, Serialize)] +/// struct A { +/// #[serde(with = "serde_with::rust::string_empty_as_none")] +/// tags: Option<String>, +/// } +/// +/// let v: A = serde_json::from_str(r##"{ +/// "tags": "" +/// }"##).unwrap(); +/// assert!(v.tags.is_none()); +/// +/// let v: A = serde_json::from_str(r##"{ +/// "tags": "Hi" +/// }"##).unwrap(); +/// assert_eq!(Some("Hi".to_string()), v.tags); +/// +/// let x = A { +/// tags: Some("This is text".to_string()), +/// }; +/// assert_eq!(r#"{"tags":"This is text"}"#, serde_json::to_string(&x).unwrap()); +/// +/// let x = A { +/// tags: None, +/// }; +/// assert_eq!(r#"{"tags":""}"#, serde_json::to_string(&x).unwrap()); +/// ``` +pub mod string_empty_as_none { + use super::*; + + /// Deserialize an `Option<T>` from a string using `FromStr` + 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), + } + } + + // handles the `null` case + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: Error, + { + Ok(None) + } + } + + deserializer.deserialize_any(OptionStringEmptyNone(PhantomData)) + } + + /// Serialize a string from `Option<T>` using `AsRef<str>` or using the empty string if `None`. + 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) + } + } +} + +/// De/Serialize a [`HashMap`] into a list of tuples +/// +/// Some formats, like JSON, have limitations on the type of keys for maps. +/// In case of JSON, keys are restricted to strings. +/// Rust features more powerfull keys, for example tuple, which can not be serialized to JSON. +/// +/// This helper serializes the [`HashMap`] into a list of tuples, which does not have the same type restrictions. +/// +/// If you need to de/serialize a [`BTreeMap`] then use [`btreemap_as_tuple_list`]. +/// +/// # Examples +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # use serde_json::json; +/// # use std::collections::HashMap; +/// # +/// #[derive(Deserialize, Serialize)] +/// struct A { +/// #[serde(with = "serde_with::rust::hashmap_as_tuple_list")] +/// s: HashMap<(String, u32), u32>, +/// } +/// +/// let v: A = serde_json::from_value(json!({ +/// "s": [ +/// [["Hello", 123], 0], +/// [["World", 456], 1] +/// ] +/// })).unwrap(); +/// +/// assert_eq!(2, v.s.len()); +/// assert_eq!(1, v.s[&("World".to_string(), 456)]); +/// ``` +/// +/// The helper is generic over the hasher type of the [`HashMap`] and works with different variants, such as `FnvHashMap`. +/// +/// ``` +/// # extern crate fnv; +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # use serde_json::json; +/// # +/// use fnv::FnvHashMap; +/// +/// #[derive(Deserialize, Serialize)] +/// struct A { +/// #[serde(with = "serde_with::rust::hashmap_as_tuple_list")] +/// s: FnvHashMap<u32, bool>, +/// } +/// +/// let v: A = serde_json::from_value(json!({ +/// "s": [ +/// [0, false], +/// [1, true] +/// ] +/// })).unwrap(); +/// +/// assert_eq!(2, v.s.len()); +/// assert_eq!(true, v.s[&1]); +/// ``` +pub mod hashmap_as_tuple_list { + use super::{SerializeSeq, *}; // Needed to remove the unused import warning in the parent scope + + /// Serialize the [`HashMap`] as a list of tuples + 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() + } + + /// Deserialize a [`HashMap`] from a list of tuples + 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) + } + } +} + +/// De/Serialize a [`BTreeMap`] into a list of tuples +/// +/// Some formats, like JSON, have limitations on the type of keys for maps. +/// In case of JSON, keys are restricted to strings. +/// Rust features more powerfull keys, for example tuple, which can not be serialized to JSON. +/// +/// This helper serializes the [`BTreeMap`] into a list of tuples, which does not have the same type restrictions. +/// +/// If you need to de/serialize a [`HashMap`] then use [`hashmap_as_tuple_list`]. +/// +/// # Examples +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # use serde_json::json; +/// # use std::collections::BTreeMap; +/// # +/// #[derive(Deserialize, Serialize)] +/// struct A { +/// #[serde(with = "serde_with::rust::btreemap_as_tuple_list")] +/// s: BTreeMap<(String, u32), u32>, +/// } +/// +/// let v: A = serde_json::from_value(json!({ +/// "s": [ +/// [["Hello", 123], 0], +/// [["World", 456], 1] +/// ] +/// })).unwrap(); +/// +/// assert_eq!(2, v.s.len()); +/// assert_eq!(1, v.s[&("World".to_string(), 456)]); +/// ``` +pub mod btreemap_as_tuple_list { + use super::*; + + /// Serialize the [`BTreeMap`] as a list of tuples + 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() + } + + /// Deserialize a [`BTreeMap`] from a list of tuples + 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) + } + } +} + +/// This serializes a list of tuples into a map and back +/// +/// Normally, you want to use a [`HashMap`] or a [`BTreeMap`] when deserializing a map. +/// However, sometimes this is not possible due to type contains, e.g., if the type implements neither [`Hash`] nor [`Ord`]. +/// Another use case is deserializing a map with duplicate keys. +/// +/// The implementation is generic using the [`FromIterator`] and [`IntoIterator`] traits. +/// Therefore, all of [`Vec`], [`VecDeque`](std::collections::VecDeque), and [`LinkedList`](std::collections::LinkedList) and anything which implements those are supported. +/// +/// # Examples +/// +/// `Wrapper` does not implement [`Hash`] nor [`Ord`], thus prohibiting the use [`HashMap`] or [`BTreeMap`]. +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # use serde_json::json; +/// # +/// #[derive(Debug, Deserialize, Serialize, Default)] +/// struct S { +/// #[serde(with = "serde_with::rust::tuple_list_as_map")] +/// s: Vec<(Wrapper<i32>, Wrapper<String>)>, +/// } +/// +/// #[derive(Clone, Debug, Serialize, Deserialize)] +/// #[serde(transparent)] +/// struct Wrapper<T>(T); +/// +/// let from = r#"{ +/// "s": { +/// "1": "Hi", +/// "2": "Cake", +/// "99": "Lie" +/// } +/// }"#; +/// let mut expected = S::default(); +/// expected.s.push((Wrapper(1), Wrapper("Hi".into()))); +/// expected.s.push((Wrapper(2), Wrapper("Cake".into()))); +/// expected.s.push((Wrapper(99), Wrapper("Lie".into()))); +/// +/// let res: S = serde_json::from_str(from).unwrap(); +/// for ((exp_k, exp_v), (res_k, res_v)) in expected.s.iter().zip(&res.s) { +/// assert_eq!(exp_k.0, res_k.0); +/// assert_eq!(exp_v.0, res_v.0); +/// } +/// assert_eq!(from, serde_json::to_string_pretty(&expected).unwrap()); +/// ``` +/// +/// In this example, the serialized format contains duplicate keys, which is not supported with [`HashMap`] or [`BTreeMap`]. +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # use serde_json::json; +/// # +/// #[derive(Debug, Deserialize, Serialize, PartialEq, Default)] +/// struct S { +/// #[serde(with = "serde_with::rust::tuple_list_as_map")] +/// s: Vec<(i32, String)>, +/// } +/// +/// let from = r#"{ +/// "s": { +/// "1": "Hi", +/// "1": "Cake", +/// "1": "Lie" +/// } +/// }"#; +/// let mut expected = S::default(); +/// expected.s.push((1, "Hi".into())); +/// expected.s.push((1, "Cake".into())); +/// expected.s.push((1, "Lie".into())); +/// +/// let res: S = serde_json::from_str(from).unwrap(); +/// assert_eq!(3, res.s.len()); +/// assert_eq!(expected, res); +/// assert_eq!(from, serde_json::to_string_pretty(&expected).unwrap()); +/// ``` +pub mod tuple_list_as_map { + use super::{SerializeMap, *}; // Needed to remove the unused import warning in the parent scope + + /// Serialize any iteration of tuples into a map. + pub fn serialize<'a, I, K, V, S>(iter: I, serializer: S) -> Result<S::Ok, S::Error> + where + I: IntoIterator<Item = &'a (K, V)>, + I::IntoIter: ExactSizeIterator, + K: Serialize + 'a, + V: Serialize + 'a, + S: Serializer, + { + let iter = iter.into_iter(); + let mut map = serializer.serialize_map(Some(iter.len()))?; + for (key, value) in iter { + map.serialize_entry(&key, &value)?; + } + map.end() + } + + /// Deserialize a map into an iterator of tuples. + pub fn deserialize<'de, I, K, V, D>(deserializer: D) -> Result<I, D::Error> + where + I: FromIterator<(K, V)>, + K: Deserialize<'de>, + V: Deserialize<'de>, + D: Deserializer<'de>, + { + deserializer.deserialize_map(MapVisitor(PhantomData)) + } + + #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))] + struct MapVisitor<I, K, V>(PhantomData<fn() -> (I, K, V)>); + + impl<'de, I, K, V> Visitor<'de> for MapVisitor<I, K, V> + where + I: FromIterator<(K, V)>, + K: Deserialize<'de>, + V: Deserialize<'de>, + { + type Value = I; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a map") + } + + fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error> + where + A: MapAccess<'de>, + { + let iter = MapIter(map, PhantomData); + iter.collect() + } + } + + struct MapIter<'de, A, K, V>(A, PhantomData<(&'de (), A, K, V)>); + + impl<'de, A, K, V> Iterator for MapIter<'de, A, K, V> + where + A: MapAccess<'de>, + K: Deserialize<'de>, + V: Deserialize<'de>, + { + type Item = Result<(K, V), A::Error>; + + fn next(&mut self) -> Option<Self::Item> { + match self.0.next_entry() { + Ok(Some(x)) => Some(Ok(x)), + Ok(None) => None, + Err(err) => Some(Err(err)), + } + } + } +} + +/// Deserialize from bytes or String +/// +/// Any Rust [`String`] can be converted into bytes ([`Vec`]`<u8>`). +/// Accepting both as formats while deserializing can be helpful while interacting with language +/// which have a looser definition of string than Rust. +/// +/// # Example +/// ```rust +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::{Deserialize, Serialize}; +/// # use serde_json::json; +/// # +/// #[derive(Debug, Deserialize, Serialize, PartialEq, Default)] +/// struct S { +/// #[serde(deserialize_with = "serde_with::rust::bytes_or_string::deserialize")] +/// bos: Vec<u8>, +/// } +/// +/// // Here we deserialize from a byte array ... +/// let from = r#"{ +/// "bos": [ +/// 0, +/// 1, +/// 2, +/// 3 +/// ] +/// }"#; +/// let expected = S { +/// bos: vec![0, 1, 2, 3], +/// }; +/// +/// let res: S = serde_json::from_str(from).unwrap(); +/// assert_eq!(expected, res); +/// +/// // and serialization works too. +/// assert_eq!(from, serde_json::to_string_pretty(&expected).unwrap()); +/// +/// // But we also support deserializing from String +/// let from = r#"{ +/// "bos": "✨Works!" +/// }"#; +/// let expected = S { +/// bos: "✨Works!".as_bytes().to_vec(), +/// }; +/// +/// let res: S = serde_json::from_str(from).unwrap(); +/// assert_eq!(expected, res); +/// ``` +pub mod bytes_or_string { + use super::*; + + /// Deserialize a [`Vec`]`<u8>` from either bytes or string + pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_any(BytesOrStringVisitor) + } + + struct BytesOrStringVisitor; + + impl<'de> Visitor<'de> for BytesOrStringVisitor { + type Value = Vec<u8>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a list of bytes or a string") + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> { + Ok(v.to_vec()) + } + + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> { + Ok(v) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> { + Ok(v.as_bytes().to_vec()) + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> { + Ok(v.into_bytes()) + } + + fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> + where + A: SeqAccess<'de>, + { + let mut res = Vec::with_capacity(seq.size_hint().unwrap_or(0)); + while let Some(value) = seq.next_element()? { + res.push(value); + } + Ok(res) + } + } +} + +/// Deserialize value and return [`Default`] on error +/// +/// The main use case is ignoring error while deserializing. +/// Instead of erroring, it simply deserializes the [`Default`] variant of the type. +/// It is not possible to find the error location, i.e., which field had a deserialization error, with this method. +/// +/// # Examples +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::Deserialize; +/// # +/// #[derive(Deserialize)] +/// struct A { +/// #[serde(deserialize_with = "serde_with::rust::default_on_error::deserialize")] +/// value: u32, +/// } +/// +/// let a: A = serde_json::from_str(r#"{"value": 123}"#).unwrap(); +/// assert_eq!(123, a.value); +/// +/// // null is of invalid type +/// let a: A = serde_json::from_str(r#"{"value": null}"#).unwrap(); +/// assert_eq!(0, a.value); +/// +/// // String is of invalid type +/// let a: A = serde_json::from_str(r#"{"value": "123"}"#).unwrap(); +/// assert_eq!(0, a.value); +/// +/// // Missing entries still cause errors +/// assert!(serde_json::from_str::<A>(r#"{ }"#).is_err()); +/// ``` +/// +/// Deserializing missing values can be supported by adding the `default` field attribute: +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::Deserialize; +/// # +/// #[derive(Deserialize)] +/// struct B { +/// #[serde(default, deserialize_with = "serde_with::rust::default_on_error::deserialize")] +/// value: u32, +/// } +/// +/// +/// let b: B = serde_json::from_str(r#"{ }"#).unwrap(); +/// assert_eq!(0, b.value); +/// ``` +pub mod default_on_error { + use super::*; + + /// Deserialize T and return the [`Default`] value on error + pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + T: Deserialize<'de> + Default, + { + T::deserialize(deserializer).or_else(|_| Ok(Default::default())) + } +} + +/// Deserialize default value if encountering `null`. +/// +/// One use case are JSON APIs in which the `null` value represents some default state. +/// This adapter allows to turn the `null` directly into the [`Default`] value of the type. +/// +/// # Examples +/// +/// ``` +/// # extern crate serde; +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # extern crate serde_with; +/// # +/// # use serde_derive::Deserialize; +/// # +/// #[derive(Deserialize)] +/// struct A { +/// #[serde(deserialize_with = "serde_with::rust::default_on_null::deserialize")] +/// value: u32, +/// } +/// +/// let a: A = serde_json::from_str(r#"{"value": 123}"#).unwrap(); +/// assert_eq!(123, a.value); +/// +/// let a: A = serde_json::from_str(r#"{"value": null}"#).unwrap(); +/// assert_eq!(0, a.value); +/// +/// // String is invalid type +/// assert!(serde_json::from_str::<A>(r#"{"value": "123"}"#).is_err()); +/// ``` +pub mod default_on_null { + use super::*; + + /// Deserialize T and return the [`Default`] value if original value is `null` + pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error> + where + D: Deserializer<'de>, + T: Deserialize<'de> + Default, + { + Ok(Option::deserialize(deserializer)?.unwrap_or_default()) + } +} diff --git a/third_party/rust/serde_with/src/with_prefix.rs b/third_party/rust/serde_with/src/with_prefix.rs new file mode 100644 index 0000000000..776927d365 --- /dev/null +++ b/third_party/rust/serde_with/src/with_prefix.rs @@ -0,0 +1,607 @@ +use std::fmt; + +use serde::{ + de::{self, DeserializeSeed, Deserializer, IgnoredAny, IntoDeserializer, MapAccess, Visitor}, + forward_to_deserialize_any, + ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer}, +}; + +/// Serialize with an added prefix on every field name and deserialize by +/// trimming away the prefix. +/// +/// **Note:** Use of this macro is incompatible with applying the [`deny_unknown_fields`] attribute +/// on the container. +/// While deserializing, it will always warn about unknown fields, even though they are processed +/// by the `with_prefix` wrapper. +/// More details can be found in [this issue][issue-with_prefix-deny_unknown_fields]. +/// +/// # Example +/// +/// The [Challonge REST API] likes to use prefixes to group related fields. In +/// simplified form, their JSON may resemble the following: +/// +/// [Challonge REST API]: https://api.challonge.com/v1/documents/matches/show +/// +/// ```json +/// { +/// "player1_name": "name1", +/// "player1_votes": 1, +/// "player2_name": "name2", +/// "player2_votes": 2 +/// } +/// ``` +/// +/// In Rust we would ideally like to model this data as a pair of `Player` +/// structs, rather than repeating the fields of `Player` for each prefix. +/// +/// ```rust +/// struct Match { +/// player1: Player, +/// player2: Player, +/// } +/// +/// struct Player { +/// name: String, +/// votes: u64, +/// } +/// ``` +/// +/// This `with_prefix!` macro produces an adapter that adds a prefix onto field +/// names during serialization and trims away the prefix during deserialization. +/// An implementation of the Challonge API would use `with_prefix!` like this: +/// +/// ```rust +/// extern crate serde_derive; +/// extern crate serde_json; +/// extern crate serde_with; +/// +/// use serde_derive::{Deserialize, Serialize}; +/// use serde_json::json; +/// use serde_with::with_prefix; +/// +/// #[derive(Serialize, Deserialize)] +/// struct Match { +/// #[serde(flatten, with = "prefix_player1")] +/// player1: Player, +/// #[serde(flatten, with = "prefix_player2")] +/// player2: Player, +/// } +/// +/// #[derive(Serialize, Deserialize)] +/// struct Player { +/// name: String, +/// votes: u64, +/// } +/// +/// with_prefix!(prefix_player1 "player1_"); +/// with_prefix!(prefix_player2 "player2_"); +/// # +/// # const EXPECTED: &str = r#"{ +/// # "player1_name": "name1", +/// # "player1_votes": 1, +/// # "player2_name": "name2", +/// # "player2_votes": 2 +/// # }"#; +/// +/// fn main() { +/// let m = Match { +/// player1: Player { +/// name: "name1".to_owned(), +/// votes: 1, +/// }, +/// player2: Player { +/// name: "name2".to_owned(), +/// votes: 2, +/// }, +/// }; +/// +/// let j = serde_json::to_string_pretty(&m).unwrap(); +/// println!("{}", j); +/// # +/// # assert_eq!(j, EXPECTED); +/// } +/// ``` +/// +/// [`deny_unknown_fields`]: https://serde.rs/container-attrs.html#deny_unknown_fields +/// [issue-with_prefix-deny_unknown_fields]: https://github.com/jonasbb/serde_with/issues/57 +#[macro_export] +macro_rules! with_prefix { + ($module:ident $prefix:expr) => { + mod $module { + use $crate::{ + serde::{Deserialize, Deserializer, Serialize, Serializer}, + with_prefix::WithPrefix, + }; + + #[allow(dead_code)] + pub fn serialize<T, S>(object: &T, serializer: S) -> Result<S::Ok, S::Error> + where + T: Serialize, + S: Serializer, + { + object.serialize(WithPrefix { + delegate: serializer, + prefix: $prefix, + }) + } + + #[allow(dead_code)] + pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error> + where + T: Deserialize<'de>, + D: Deserializer<'de>, + { + T::deserialize(WithPrefix { + delegate: deserializer, + prefix: $prefix, + }) + } + } + }; +} + +#[allow(missing_debug_implementations)] +pub struct WithPrefix<'a, T> { + pub delegate: T, + pub prefix: &'a str, +} + +impl<'a, T> Serialize for WithPrefix<'a, T> +where + T: Serialize, +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + self.delegate.serialize(WithPrefix { + delegate: serializer, + prefix: self.prefix, + }) + } +} + +impl<'a, S> Serializer for WithPrefix<'a, S> +where + S: Serializer, +{ + type Ok = S::Ok; + type Error = S::Error; + type SerializeSeq = Impossible<Self::Ok, Self::Error>; + type SerializeTuple = Impossible<Self::Ok, Self::Error>; + type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>; + type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>; + type SerializeMap = WithPrefix<'a, S::SerializeMap>; + type SerializeStruct = WithPrefix<'a, S::SerializeMap>; + type SerializeStructVariant = Impossible<Self::Ok, Self::Error>; + + fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + self.delegate + .collect_str(&format_args!("{}{}", self.prefix, v)) + } + + fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + self.delegate.serialize_none() + } + + fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Serialize, + { + self.delegate.serialize_some(&WithPrefix { + delegate: value, + prefix: self.prefix, + }) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_newtype_struct<T>( + self, + _name: &'static str, + _value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Serialize, + { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_newtype_variant<T>( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Serialize, + { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + Ok(WithPrefix { + delegate: self.delegate.serialize_map(len)?, + prefix: self.prefix, + }) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(ser::Error::custom("wrong type for with_prefix")) + } +} + +impl<'a, S> SerializeMap for WithPrefix<'a, S> +where + S: SerializeMap, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + self.delegate.serialize_key(&WithPrefix { + delegate: key, + prefix: self.prefix, + }) + } + + fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + self.delegate.serialize_value(value) + } + + fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<(), Self::Error> + where + K: ?Sized + Serialize, + V: ?Sized + Serialize, + { + self.delegate.serialize_entry( + &WithPrefix { + delegate: key, + prefix: self.prefix, + }, + value, + ) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + self.delegate.end() + } +} + +impl<'a, S> SerializeStruct for WithPrefix<'a, S> +where + S: SerializeMap, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + self.delegate + .serialize_entry(&format!("{}{}", self.prefix, key), value) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + self.delegate.end() + } +} + +impl<'de, 'a, T> DeserializeSeed<'de> for WithPrefix<'a, T> +where + T: DeserializeSeed<'de>, +{ + type Value = T::Value; + + fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: Deserializer<'de>, + { + self.delegate.deserialize(WithPrefix { + delegate: deserializer, + prefix: self.prefix, + }) + } +} + +impl<'de, 'a, D> Deserializer<'de> for WithPrefix<'a, D> +where + D: Deserializer<'de>, +{ + type Error = D::Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: Visitor<'de>, + { + self.delegate.deserialize_map(WithPrefix { + delegate: visitor, + prefix: self.prefix, + }) + } + + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: Visitor<'de>, + { + self.delegate.deserialize_any(WithPrefixOption { + first_key: None, + delegate: visitor, + prefix: self.prefix, + }) + } + + fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: Visitor<'de>, + { + self.delegate.deserialize_identifier(WithPrefix { + delegate: visitor, + prefix: self.prefix, + }) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf unit unit_struct newtype_struct seq tuple tuple_struct + map struct enum ignored_any + } +} + +impl<'de, 'a, V> Visitor<'de> for WithPrefix<'a, V> +where + V: Visitor<'de>, +{ + type Value = V::Value; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + self.delegate.expecting(formatter) + } + + fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error> + where + A: MapAccess<'de>, + { + self.delegate.visit_map(WithPrefix { + delegate: map, + prefix: self.prefix, + }) + } +} + +impl<'de, 'a, A> MapAccess<'de> for WithPrefix<'a, A> +where + A: MapAccess<'de>, +{ + type Error = A::Error; + + fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> + where + K: DeserializeSeed<'de>, + { + while let Some(s) = self.delegate.next_key::<String>()? { + if s.starts_with(self.prefix) { + let without_prefix = s[self.prefix.len()..].into_deserializer(); + return seed.deserialize(without_prefix).map(Some); + } + self.delegate.next_value::<IgnoredAny>()?; + } + Ok(None) + } + + fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> + where + V: DeserializeSeed<'de>, + { + self.delegate.next_value_seed(seed) + } +} + +#[allow(missing_debug_implementations)] +pub struct WithPrefixOption<'a, T> { + first_key: Option<String>, + delegate: T, + prefix: &'a str, +} + +impl<'de, 'a, V> Visitor<'de> for WithPrefixOption<'a, V> +where + V: Visitor<'de>, +{ + type Value = V::Value; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + self.delegate.expecting(formatter) + } + + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_none() + } + + fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> + where + A: MapAccess<'de>, + { + while let Some(s) = map.next_key::<String>()? { + if s.starts_with(self.prefix) { + return self.delegate.visit_some(WithPrefixOption { + first_key: Some(s), + delegate: map, + prefix: self.prefix, + }); + } + map.next_value::<IgnoredAny>()?; + } + self.delegate.visit_none() + } +} + +impl<'de, 'a, A> Deserializer<'de> for WithPrefixOption<'a, A> +where + A: MapAccess<'de>, +{ + type Error = A::Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: Visitor<'de>, + { + visitor.visit_map(self) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +impl<'de, 'a, A> MapAccess<'de> for WithPrefixOption<'a, A> +where + A: MapAccess<'de>, +{ + type Error = A::Error; + + fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> + where + K: DeserializeSeed<'de>, + { + if let Some(s) = self.first_key.take() { + let without_prefix = s[self.prefix.len()..].into_deserializer(); + return seed.deserialize(without_prefix).map(Some); + } + while let Some(s) = self.delegate.next_key::<String>()? { + if s.starts_with(self.prefix) { + let without_prefix = s[self.prefix.len()..].into_deserializer(); + return seed.deserialize(without_prefix).map(Some); + } + self.delegate.next_value::<IgnoredAny>()?; + } + Ok(None) + } + + fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> + where + V: DeserializeSeed<'de>, + { + self.delegate.next_value_seed(seed) + } +} |