Skip to content

Commit

Permalink
Merge #572
Browse files Browse the repository at this point in the history
572: Revert a breaking change to the Seq trait bound r=jonasbb a=jonasbb

The code released in #566 broke multiple thing. It broke compatability with bincode #570 and #571.

It broke this atribute combination:

```rust
 #[serde_as(as = "Seq<(_, Vec<_>)>")]
BTreeMap<usize, Vec<usize>>,
```

```
error[E0277]: the trait bound `serde_with::Seq<(serde_with::Same, std::vec::Vec<serde_with::Same>)>: serde_with::SerializeAs<_>` is not satisfied
```

bors r+

Co-authored-by: Jonas Bushart <jonas@bushart.org>
  • Loading branch information
bors[bot] and jonasbb authored Mar 10, 2023
2 parents 404f7b5 + 6c95416 commit e7f805b
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 177 deletions.
8 changes: 8 additions & 0 deletions serde_with/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Fixed

* Undo the changes to the trait bound for `Seq`. (#570, #571)
The new implementation caused issues with serialization formats that require the sequence length beforehand.
It also caused problems, that certain attributes which worked before no longer worked, due to mismatching number of references.

Thanks to @stefunctional for reporting and for @stephaneyfx for providing a test case.

## [2.3.0] - 2023-03-09

### Added
Expand Down
28 changes: 17 additions & 11 deletions serde_with/src/de/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,23 +545,25 @@ tuple_impl!(16 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7

#[cfg(feature = "alloc")]
macro_rules! map_as_tuple_seq_intern {
($tyorig:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident <TAs>) => {
impl<'de, K, V, TAs> DeserializeAs<'de, $tyorig<K, V>> for $ty<TAs>
($tyorig:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident <(KAs, VAs)>) => {
impl<'de, K, KAs, V, VAs> DeserializeAs<'de, $tyorig<K, V>> for $ty<(KAs, VAs)>
where
TAs: DeserializeAs<'de, (K, V)>,
KAs: DeserializeAs<'de, K>,
VAs: DeserializeAs<'de, V>,
$(K: $kbound1 $(+ $kbound2)*,)*
{
fn deserialize_as<D>(deserializer: D) -> Result<$tyorig<K, V>, D::Error>
where
D: Deserializer<'de>,
{
struct SeqVisitor<K, V, TAs> {
marker: PhantomData<(K, V, TAs)>,
struct SeqVisitor<K, KAs, V, VAs> {
marker: PhantomData<(K, KAs, V, VAs)>,
}

impl<'de, K, V, TAs> Visitor<'de> for SeqVisitor<K, V, TAs>
impl<'de, K, KAs, V, VAs> Visitor<'de> for SeqVisitor<K, KAs, V, VAs>
where
TAs: DeserializeAs<'de, (K, V)>,
KAs: DeserializeAs<'de, K>,
VAs: DeserializeAs<'de, V>,
$(K: $kbound1 $(+ $kbound2)*,)*
{
type Value = $tyorig<K, V>;
Expand All @@ -577,13 +579,17 @@ macro_rules! map_as_tuple_seq_intern {
{
let iter = utils::SeqIter::new(access);
iter.map(|res| {
res.map(<DeserializeAsWrap<(K, V), TAs>>::into_inner)
res.map(
|(k, v): (DeserializeAsWrap<K, KAs>, DeserializeAsWrap<V, VAs>)| {
(k.into_inner(), v.into_inner())
},
)
})
.collect()
}
}

let visitor = SeqVisitor::<K, V, TAs> {
let visitor = SeqVisitor::<K, KAs, V, VAs> {
marker: PhantomData,
};
deserializer.deserialize_seq(visitor)
Expand All @@ -594,9 +600,9 @@ macro_rules! map_as_tuple_seq_intern {
#[cfg(feature = "alloc")]
macro_rules! map_as_tuple_seq {
($tyorig:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >) => {
map_as_tuple_seq_intern!($tyorig < K $(: $kbound1 $(+ $kbound2)*)* , V $(, $typaram : $bound1 $(+ $bound2)*)* > , Seq<TAs>);
map_as_tuple_seq_intern!($tyorig < K $(: $kbound1 $(+ $kbound2)*)* , V $(, $typaram : $bound1 $(+ $bound2)*)* > , Seq<(KAs, VAs)>);
#[cfg(feature = "alloc")]
map_as_tuple_seq_intern!($tyorig < K $(: $kbound1 $(+ $kbound2)*)* , V $(, $typaram : $bound1 $(+ $bound2)*)* >, Vec<TAs>);
map_as_tuple_seq_intern!($tyorig < K $(: $kbound1 $(+ $kbound2)*)* , V $(, $typaram : $bound1 $(+ $bound2)*)* >, Vec<(KAs, VAs)>);
}
}
foreach_map!(map_as_tuple_seq);
Expand Down
86 changes: 1 addition & 85 deletions serde_with/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2146,14 +2146,13 @@ pub struct StringWithSeparator<Sep, T>(PhantomData<(Sep, T)>);
/// ```
pub struct Map<K, V>(PhantomData<(K, V)>);

/// De/Serialize a Map into a list of tuples or custom type
/// De/Serialize a Map into a list of tuples
///
/// Some formats, like JSON, have limitations on the types of keys for maps.
/// In case of JSON, keys are restricted to strings.
/// Rust features more powerful keys, for example tuples, which can not be serialized to JSON.
///
/// This helper serializes the Map into a list of tuples, which do not have the same type restrictions.
/// Other types can be used to, if they implement `SerializeAs<(K, V)>`.
///
/// # Examples
///
Expand Down Expand Up @@ -2192,89 +2191,6 @@ pub struct Map<K, V>(PhantomData<(K, V)>);
/// assert_eq!(data, serde_json::from_value(value).unwrap());
/// # }
/// ```
///
/// ## Use a custom representation
///
/// ```rust
/// # #[cfg(feature = "macros")] {
/// # use serde::{Deserialize, Serialize};
/// # use serde_json::json;
/// # use serde_with::{serde_as, Seq};
/// # use std::{collections::BTreeMap, net::IpAddr};
/// #
/// use serde_with::{de::DeserializeAsWrap, ser::SerializeAsWrap, DeserializeAs, SerializeAs};
///
/// #[derive(Serialize, Deserialize)]
/// struct Custom<K, V> {
/// custom_key: K,
/// v: V,
/// }
///
/// impl<K, KAs, V, VAs> SerializeAs<(K, V)> for Custom<KAs, VAs>
/// where
/// KAs: SerializeAs<K>,
/// VAs: SerializeAs<V>,
/// {
/// fn serialize_as<S>((k, v): &(K, V), serializer: S) -> Result<S::Ok, S::Error>
/// where
/// S: serde::Serializer,
/// {
/// (Custom {
/// custom_key: SerializeAsWrap::<K, KAs>::new(k),
/// v: SerializeAsWrap::<V, VAs>::new(v),
/// })
/// .serialize(serializer)
/// }
/// }
///
/// impl<'de, K, KAs, V, VAs> DeserializeAs<'de, (K, V)> for Custom<KAs, VAs>
/// where
/// KAs: DeserializeAs<'de, K>,
/// VAs: DeserializeAs<'de, V>,
/// {
/// fn deserialize_as<D>(deserializer: D) -> Result<(K, V), D::Error>
/// where
/// D: serde::Deserializer<'de>,
/// {
/// let c = <Custom<DeserializeAsWrap<K, KAs>, DeserializeAsWrap<V, VAs>>>::deserialize(
/// deserializer,
/// )?;
/// Ok((c.custom_key.into_inner(), c.v.into_inner()))
/// }
/// }
///
/// #[serde_as]
/// # #[derive(Debug, PartialEq)]
/// #[derive(Serialize, Deserialize)]
/// struct SM(#[serde_as(as = "Seq<Custom<_, _>>")] BTreeMap<u32, IpAddr>);
///
/// // This converts the Rust type
/// let ip = "1.2.3.4".parse().unwrap();
/// let ip2 = "255.255.255.255".parse().unwrap();
/// let data = SM(vec![(1, ip), (10, ip), (200, ip2)].into_iter().collect());
///
/// // into this JSON
/// let value = serde_json::json!(
/// [
/// {
/// "custom_key": 1,
/// "v": "1.2.3.4"
/// },
/// {
/// "custom_key": 10,
/// "v": "1.2.3.4"
/// },
/// {
/// "custom_key": 200,
/// "v": "255.255.255.255"
/// }
/// ]
/// );
///
/// assert_eq!(value, serde_json::to_value(&data).unwrap());
/// assert_eq!(data, serde_json::from_value(value).unwrap());
/// # }
/// ```
pub struct Seq<V>(PhantomData<V>);

/// Ensure no duplicate keys exist in a map.
Expand Down
22 changes: 12 additions & 10 deletions serde_with/src/ser/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,31 +348,33 @@ tuple_impl!(16 0 T0 As0 1 T1 As1 2 T2 As2 3 T3 As3 4 T4 As4 5 T5 As5 6 T6 As6 7

#[cfg(feature = "alloc")]
macro_rules! map_as_tuple_seq_intern {
($tyorig:ident < K, V $(, $typaram:ident : $bound:ident)* >, $ty:ident <TAs>) => {
impl<K, V, TAs $(, $typaram)*> SerializeAs<$tyorig<K, V $(, $typaram)*>> for $ty<TAs>
($tyorig:ident < K, V $(, $typaram:ident : $bound:ident)* >, $ty:ident <(K, V)>) => {
impl<K, KAs, V, VAs $(, $typaram)*> SerializeAs<$tyorig<K, V $(, $typaram)*>> for $ty<(KAs, VAs)>
where
for<'a> TAs: SerializeAs<(&'a K, &'a V)>,
KAs: SerializeAs<K>,
VAs: SerializeAs<V>,
$($typaram: ?Sized + $bound,)*
{
fn serialize_as<S>(source: &$tyorig<K, V $(, $typaram)*>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(None)?;
for (k, v) in source {
seq.serialize_element(&SerializeAsWrap::<(&K, &V), TAs>::new(&(k, v)))?;
}
seq.end()
serializer.collect_seq(source.iter().map(|(k, v)| {
(
SerializeAsWrap::<K, KAs>::new(k),
SerializeAsWrap::<V, VAs>::new(v),
)
}))
}
}
};
}
#[cfg(feature = "alloc")]
macro_rules! map_as_tuple_seq {
($tyorig:ident < K, V $(, $typaram:ident : $bound:ident)* >) => {
map_as_tuple_seq_intern!($tyorig<K, V $(, $typaram: $bound)* >, Seq<TAs>);
map_as_tuple_seq_intern!($tyorig<K, V $(, $typaram: $bound)* >, Seq<(K, V)>);
#[cfg(feature = "alloc")]
map_as_tuple_seq_intern!($tyorig<K, V $(, $typaram: $bound)* >, Vec<TAs>);
map_as_tuple_seq_intern!($tyorig<K, V $(, $typaram: $bound)* >, Vec<(K, V)>);
}
}
foreach_map!(map_as_tuple_seq);
Expand Down
71 changes: 0 additions & 71 deletions serde_with/tests/serde_as/map_tuple_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,74 +319,3 @@ fn test_tuple_array_as_map() {
}"#]],
);
}

#[test]
fn test_map_as_custom_struct() {
let ip = "1.2.3.4".parse().unwrap();
let ip2 = "255.255.255.255".parse().unwrap();

use serde_with::{de::DeserializeAsWrap, ser::SerializeAsWrap, DeserializeAs, SerializeAs};

#[derive(serde::Serialize, serde::Deserialize)]
struct Custom<K, V> {
custom_key: K,
v: V,
}

impl<K, KAs, V, VAs> SerializeAs<(K, V)> for Custom<KAs, VAs>
where
KAs: SerializeAs<K>,
VAs: SerializeAs<V>,
{
fn serialize_as<S>((k, v): &(K, V), serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
(Custom {
custom_key: SerializeAsWrap::<K, KAs>::new(k),
v: SerializeAsWrap::<V, VAs>::new(v),
})
.serialize(serializer)
}
}

impl<'de, K, KAs, V, VAs> DeserializeAs<'de, (K, V)> for Custom<KAs, VAs>
where
KAs: DeserializeAs<'de, K>,
VAs: DeserializeAs<'de, V>,
{
fn deserialize_as<D>(deserializer: D) -> Result<(K, V), D::Error>
where
D: serde::Deserializer<'de>,
{
let c = <Custom<DeserializeAsWrap<K, KAs>, DeserializeAsWrap<V, VAs>>>::deserialize(
deserializer,
)?;
Ok((c.custom_key.into_inner(), c.v.into_inner()))
}
}

#[serde_as]
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct SM(#[serde_as(as = "Seq<Custom<_, _>>")] BTreeMap<u32, IpAddr>);

let map: BTreeMap<_, _> = vec![(1, ip), (10, ip), (200, ip2)].into_iter().collect();
is_equal(
SM(map),
expect![[r#"
[
{
"custom_key": 1,
"v": "1.2.3.4"
},
{
"custom_key": 10,
"v": "1.2.3.4"
},
{
"custom_key": 200,
"v": "255.255.255.255"
}
]"#]],
);
}

0 comments on commit e7f805b

Please sign in to comment.