diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd49909b2..8487ba65d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,5 +168,6 @@ jobs: timeout-minutes: 45 steps: - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable - uses: dtolnay/install@cargo-outdated - run: cargo outdated --workspace --exit-code 1 diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 73732672f..3a844eed3 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "1.0.197" +version = "1.0.199" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] @@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] -serde_derive = { version = "=1.0.197", path = "../serde_derive" } +serde_derive = { version = "=1.0.199", path = "../serde_derive" } ### FEATURES ################################################################# diff --git a/serde/build.rs b/serde/build.rs index fe5486a7a..0074df63f 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -64,6 +64,12 @@ fn main() { if minor < 64 { println!("cargo:rustc-cfg=no_core_cstr"); } + + // Support for core::num::Saturating and std::num::Saturating stabilized in Rust 1.74 + // https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html#stabilized-apis + if minor < 74 { + println!("cargo:rustc-cfg=no_core_num_saturating"); + } } fn rustc_minor_version() -> Option { diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 413c997af..140878aec 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -104,6 +104,28 @@ macro_rules! impl_deserialize_num { deserializer.$deserialize(NonZeroVisitor) } } + + #[cfg(not(no_core_num_saturating))] + impl<'de> Deserialize<'de> for Saturating<$primitive> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SaturatingVisitor; + + impl<'de> Visitor<'de> for SaturatingVisitor { + type Value = Saturating<$primitive>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("integer with support for saturating semantics") + } + + $($($method!(saturating $primitive $val : $visit);)*)* + } + + deserializer.$deserialize(SaturatingVisitor) + } + } }; ($primitive:ident, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => { @@ -154,6 +176,15 @@ macro_rules! num_self { } } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + Ok(Saturating(v)) + } + }; } macro_rules! num_as_self { @@ -179,6 +210,15 @@ macro_rules! num_as_self { } } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + Ok(Saturating(v as $primitive)) + } + }; } macro_rules! num_as_copysign_self { @@ -235,6 +275,21 @@ macro_rules! int_to_int { Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if (v as i64) < $primitive::MIN as i64 { + Ok(Saturating($primitive::MIN)) + } else if ($primitive::MAX as i64) < v as i64 { + Ok(Saturating($primitive::MAX)) + } else { + Ok(Saturating(v as $primitive)) + } + } + }; } macro_rules! int_to_uint { @@ -265,6 +320,21 @@ macro_rules! int_to_uint { Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if v < 0 { + Ok(Saturating(0)) + } else if ($primitive::MAX as u64) < v as u64 { + Ok(Saturating($primitive::MAX)) + } else { + Ok(Saturating(v as $primitive)) + } + } + }; } macro_rules! uint_to_self { @@ -295,6 +365,19 @@ macro_rules! uint_to_self { Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self)) } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if v as u64 <= $primitive::MAX as u64 { + Ok(Saturating(v as $primitive)) + } else { + Ok(Saturating($primitive::MAX)) + } + } + }; } impl_deserialize_num! { @@ -427,6 +510,21 @@ macro_rules! num_128 { } } }; + + (saturating $primitive:ident $ty:ident : $visit:ident) => { + fn $visit(self, v: $ty) -> Result + where + E: Error, + { + if (v as i128) < $primitive::MIN as i128 { + Ok(Saturating($primitive::MIN)) + } else if ($primitive::MAX as u128) < v as u128 { + Ok(Saturating($primitive::MAX)) + } else { + Ok(Saturating(v as $primitive)) + } + } + }; } impl_deserialize_num! { @@ -852,7 +950,10 @@ struct PhantomDataVisitor { marker: PhantomData, } -impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor { +impl<'de, T> Visitor<'de> for PhantomDataVisitor +where + T: ?Sized, +{ type Value = PhantomData; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -868,7 +969,10 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor { } } -impl<'de, T: ?Sized> Deserialize<'de> for PhantomData { +impl<'de, T> Deserialize<'de> for PhantomData +where + T: ?Sized, +{ fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, @@ -1877,9 +1981,9 @@ forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] -impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> +impl<'de, 'a, T> Deserialize<'de> for Cow<'a, T> where - T: ToOwned, + T: ?Sized + ToOwned, T::Owned: Deserialize<'de>, { #[inline] @@ -1902,7 +2006,7 @@ where doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] -impl<'de, T: ?Sized> Deserialize<'de> for RcWeak +impl<'de, T> Deserialize<'de> for RcWeak where T: Deserialize<'de>, { @@ -1924,7 +2028,7 @@ where doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] -impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak +impl<'de, T> Deserialize<'de> for ArcWeak where T: Deserialize<'de>, { @@ -1945,8 +2049,9 @@ macro_rules! box_forwarded_impl { $t:ident ) => { $(#[$attr])* - impl<'de, T: ?Sized> Deserialize<'de> for $t + impl<'de, T> Deserialize<'de> for $t where + T: ?Sized, Box: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 1924fe3d8..4c5a5f9b7 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -1735,9 +1735,9 @@ pub trait SeqAccess<'de> { } } -impl<'de, 'a, A: ?Sized> SeqAccess<'de> for &'a mut A +impl<'de, 'a, A> SeqAccess<'de> for &'a mut A where - A: SeqAccess<'de>, + A: ?Sized + SeqAccess<'de>, { type Error = A::Error; @@ -1888,9 +1888,9 @@ pub trait MapAccess<'de> { } } -impl<'de, 'a, A: ?Sized> MapAccess<'de> for &'a mut A +impl<'de, 'a, A> MapAccess<'de> for &'a mut A where - A: MapAccess<'de>, + A: ?Sized + MapAccess<'de>, { type Error = A::Error; diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 5cf44c1c1..3da33efde 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -95,7 +95,7 @@ //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/serde/1.0.197")] +#![doc(html_root_url = "https://docs.rs/serde/1.0.199")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. @@ -118,6 +118,7 @@ // integer and float ser/de requires these sorts of casts clippy::cast_possible_truncation, clippy::cast_possible_wrap, + clippy::cast_precision_loss, clippy::cast_sign_loss, // things are often more readable this way clippy::cast_lossless, @@ -274,6 +275,9 @@ mod lib { pub use std::sync::atomic::{AtomicI64, AtomicU64}; #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))] pub use std::sync::atomic::{AtomicIsize, AtomicUsize}; + + #[cfg(not(no_core_num_saturating))] + pub use self::core::num::Saturating; } // None of this crate's error handling needs the `From::from` error conversion diff --git a/serde/src/macros.rs b/serde/src/macros.rs index a8fd85a37..9646cb375 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -123,7 +123,7 @@ macro_rules! forward_to_deserialize_any { macro_rules! forward_to_deserialize_any_method { ($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => { #[inline] - fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, Self::Error> + fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, >::Error> where $v: $crate::de::Visitor<$l>, { diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 883e6909c..c402d2c66 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -313,6 +313,8 @@ mod content { } } + /// Used to capture data in [`Content`] from other deserializers. + /// Cannot capture externally tagged enums, `i128` and `u128`. struct ContentVisitor<'de> { value: PhantomData>, } @@ -528,6 +530,8 @@ mod content { Content(Content<'de>), } + /// Serves as a seed for deserializing a key of internally tagged enum. + /// Cannot capture externally tagged enums, `i128` and `u128`. struct TagOrContentVisitor<'de> { name: &'static str, value: PhantomData>, @@ -814,6 +818,9 @@ mod content { /// Used by generated code to deserialize an internally tagged enum. /// + /// Captures map or sequence from the original deserializer and searches + /// a tag in it (in case of sequence, tag is the first element of sequence). + /// /// Not public API. pub struct TaggedContentVisitor { tag_name: &'static str, diff --git a/serde/src/private/doc.rs b/serde/src/private/doc.rs index 1b18fe6b4..1f17c8db5 100644 --- a/serde/src/private/doc.rs +++ b/serde/src/private/doc.rs @@ -56,7 +56,10 @@ macro_rules! __serialize_unimplemented { #[macro_export] macro_rules! __serialize_unimplemented_method { ($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => { - fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::__private::Result { + fn $func $(<$t>)* (self $(, _: $arg)*) -> $crate::__private::Result + where + $($t: ?Sized + $crate::Serialize,)* + { unimplemented!() } }; diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs index 50bcb251e..40cc6cbdb 100644 --- a/serde/src/private/ser.rs +++ b/serde/src/private/ser.rs @@ -174,9 +174,9 @@ where Err(self.bad_type(Unsupported::Optional)) } - fn serialize_some(self, _: &T) -> Result + fn serialize_some(self, _: &T) -> Result where - T: Serialize, + T: ?Sized + Serialize, { Err(self.bad_type(Unsupported::Optional)) } @@ -205,18 +205,18 @@ where map.end() } - fn serialize_newtype_struct( + fn serialize_newtype_struct( self, _: &'static str, value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { value.serialize(self) } - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, _: &'static str, _: u32, @@ -224,7 +224,7 @@ where inner_value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { let mut map = tri!(self.delegate.serialize_map(Some(2))); tri!(map.serialize_entry(self.tag, self.variant_name)); @@ -327,9 +327,9 @@ where } #[cfg(not(any(feature = "std", feature = "alloc")))] - fn collect_str(self, _: &T) -> Result + fn collect_str(self, _: &T) -> Result where - T: Display, + T: ?Sized + Display, { Err(self.bad_type(Unsupported::String)) } @@ -364,9 +364,9 @@ mod content { type Ok = M::Ok; type Error = M::Error; - fn serialize_field(&mut self, value: &T) -> Result<(), M::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), M::Error> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); @@ -404,13 +404,9 @@ mod content { type Ok = M::Ok; type Error = M::Error; - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), M::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), M::Error> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); @@ -635,9 +631,9 @@ mod content { Ok(Content::None) } - fn serialize_some(self, value: &T) -> Result + fn serialize_some(self, value: &T) -> Result where - T: Serialize, + T: ?Sized + Serialize, { Ok(Content::Some(Box::new(tri!(value.serialize(self))))) } @@ -659,13 +655,9 @@ mod content { Ok(Content::UnitVariant(name, variant_index, variant)) } - fn serialize_newtype_struct( - self, - name: &'static str, - value: &T, - ) -> Result + fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result where - T: Serialize, + T: ?Sized + Serialize, { Ok(Content::NewtypeStruct( name, @@ -673,7 +665,7 @@ mod content { )) } - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, @@ -681,7 +673,7 @@ mod content { value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { Ok(Content::NewtypeVariant( name, @@ -782,9 +774,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_element(&mut self, value: &T) -> Result<(), E> + fn serialize_element(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.elements.push(value); @@ -808,9 +800,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_element(&mut self, value: &T) -> Result<(), E> + fn serialize_element(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.elements.push(value); @@ -835,9 +827,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_field(&mut self, value: &T) -> Result<(), E> + fn serialize_field(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); @@ -864,9 +856,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_field(&mut self, value: &T) -> Result<(), E> + fn serialize_field(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); @@ -896,18 +888,18 @@ mod content { type Ok = Content; type Error = E; - fn serialize_key(&mut self, key: &T) -> Result<(), E> + fn serialize_key(&mut self, key: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let key = tri!(key.serialize(ContentSerializer::::new())); self.key = Some(key); Ok(()) } - fn serialize_value(&mut self, value: &T) -> Result<(), E> + fn serialize_value(&mut self, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let key = self .key @@ -922,10 +914,10 @@ mod content { Ok(Content::Map(self.entries)) } - fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), E> + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), E> where - K: Serialize, - V: Serialize, + K: ?Sized + Serialize, + V: ?Sized + Serialize, { let key = tri!(key.serialize(ContentSerializer::::new())); let value = tri!(value.serialize(ContentSerializer::::new())); @@ -947,9 +939,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); @@ -976,9 +968,9 @@ mod content { type Ok = Content; type Error = E; - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); @@ -1088,9 +1080,9 @@ where Ok(()) } - fn serialize_some(self, value: &T) -> Result + fn serialize_some(self, value: &T) -> Result where - T: Serialize, + T: ?Sized + Serialize, { value.serialize(self) } @@ -1112,18 +1104,18 @@ where Err(Self::bad_type(Unsupported::Enum)) } - fn serialize_newtype_struct( + fn serialize_newtype_struct( self, _: &'static str, value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { value.serialize(self) } - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, _: &'static str, _: u32, @@ -1131,7 +1123,7 @@ where value: &T, ) -> Result where - T: Serialize, + T: ?Sized + Serialize, { tri!(self.0.serialize_key(variant)); self.0.serialize_value(value) @@ -1202,28 +1194,24 @@ where type Ok = (); type Error = M::Error; - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { self.0.serialize_key(key) } - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { self.0.serialize_value(value) } - fn serialize_entry( - &mut self, - key: &K, - value: &V, - ) -> Result<(), Self::Error> + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> where - K: Serialize, - V: Serialize, + K: ?Sized + Serialize, + V: ?Sized + Serialize, { self.0.serialize_entry(key, value) } @@ -1244,13 +1232,9 @@ where type Ok = (); type Error = M::Error; - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { self.0.serialize_entry(key, value) } @@ -1289,9 +1273,9 @@ where type Ok = (); type Error = M::Error; - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); @@ -1335,13 +1319,9 @@ where type Ok = (); type Error = M::Error; - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: Serialize, + T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); diff --git a/serde/src/ser/fmt.rs b/serde/src/ser/fmt.rs index 0650ab6f1..04684aded 100644 --- a/serde/src/ser/fmt.rs +++ b/serde/src/ser/fmt.rs @@ -74,9 +74,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { Display::fmt(variant, self) } - fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> fmt::Result + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> fmt::Result where - T: Serialize, + T: ?Sized + Serialize, { Serialize::serialize(value, self) } @@ -89,9 +89,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { Err(fmt::Error) } - fn serialize_some(self, _value: &T) -> fmt::Result + fn serialize_some(self, _value: &T) -> fmt::Result where - T: Serialize, + T: ?Sized + Serialize, { Err(fmt::Error) } @@ -100,7 +100,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { Err(fmt::Error) } - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, @@ -108,7 +108,7 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { _value: &T, ) -> fmt::Result where - T: Serialize, + T: ?Sized + Serialize, { Err(fmt::Error) } @@ -161,9 +161,9 @@ impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> { Err(fmt::Error) } - fn collect_str(self, value: &T) -> fmt::Result + fn collect_str(self, value: &T) -> fmt::Result where - T: Display, + T: ?Sized + Display, { Display::fmt(value, self) } diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 8c70634af..ffc4c70f9 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -114,7 +114,10 @@ where //////////////////////////////////////////////////////////////////////////////// -impl Serialize for PhantomData { +impl Serialize for PhantomData +where + T: ?Sized, +{ #[inline] fn serialize(&self, serializer: S) -> Result where @@ -504,17 +507,17 @@ macro_rules! deref_impl { } deref_impl! { - <'a, T: ?Sized> Serialize for &'a T where T: Serialize + <'a, T> Serialize for &'a T where T: ?Sized + Serialize } deref_impl! { - <'a, T: ?Sized> Serialize for &'a mut T where T: Serialize + <'a, T> Serialize for &'a mut T where T: ?Sized + Serialize } deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] - Serialize for Box where T: Serialize + Serialize for Box where T: ?Sized + Serialize } deref_impl! { @@ -528,7 +531,7 @@ deref_impl! { /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] - Serialize for Rc where T: Serialize + Serialize for Rc where T: ?Sized + Serialize } deref_impl! { @@ -542,13 +545,13 @@ deref_impl! { /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr(doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] - Serialize for Arc where T: Serialize + Serialize for Arc where T: ?Sized + Serialize } deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "alloc"))))] - <'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned + <'a, T> Serialize for Cow<'a, T> where T: ?Sized + Serialize + ToOwned } //////////////////////////////////////////////////////////////////////////////// @@ -561,9 +564,9 @@ deref_impl! { doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] -impl Serialize for RcWeak +impl Serialize for RcWeak where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -581,9 +584,9 @@ where doc_cfg, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] -impl Serialize for ArcWeak +impl Serialize for ArcWeak where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -641,9 +644,9 @@ where } } -impl Serialize for RefCell +impl Serialize for RefCell where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -658,9 +661,9 @@ where #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] -impl Serialize for Mutex +impl Serialize for Mutex where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -675,9 +678,9 @@ where #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] -impl Serialize for RwLock +impl Serialize for RwLock where - T: Serialize, + T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -1023,6 +1026,20 @@ where } } +#[cfg(not(no_core_num_saturating))] +impl Serialize for Saturating +where + T: Serialize, +{ + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } +} + impl Serialize for Reverse where T: Serialize, diff --git a/serde/src/ser/impossible.rs b/serde/src/ser/impossible.rs index 479be9407..6432d5775 100644 --- a/serde/src/ser/impossible.rs +++ b/serde/src/ser/impossible.rs @@ -72,9 +72,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_element(&mut self, value: &T) -> Result<(), Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -92,9 +92,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_element(&mut self, value: &T) -> Result<(), Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -112,9 +112,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_field(&mut self, value: &T) -> Result<(), Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -132,9 +132,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_field(&mut self, value: &T) -> Result<(), Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -152,17 +152,17 @@ where type Ok = Ok; type Error = Error; - fn serialize_key(&mut self, key: &T) -> Result<(), Error> + fn serialize_key(&mut self, key: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = key; match self.void {} } - fn serialize_value(&mut self, value: &T) -> Result<(), Error> + fn serialize_value(&mut self, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = value; match self.void {} @@ -180,9 +180,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = key; let _ = value; @@ -201,9 +201,9 @@ where type Ok = Ok; type Error = Error; - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> where - T: Serialize, + T: ?Sized + Serialize, { let _ = key; let _ = value; diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 75c45140e..74b5e0769 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -796,9 +796,9 @@ pub trait Serializer: Sized { /// ``` /// /// [`Some(T)`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some - fn serialize_some(self, value: &T) -> Result + fn serialize_some(self, value: &T) -> Result where - T: Serialize; + T: ?Sized + Serialize; /// Serialize a `()` value. /// @@ -891,13 +891,13 @@ pub trait Serializer: Sized { /// } /// } /// ``` - fn serialize_newtype_struct( + fn serialize_newtype_struct( self, name: &'static str, value: &T, ) -> Result where - T: Serialize; + T: ?Sized + Serialize; /// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`. /// @@ -925,7 +925,7 @@ pub trait Serializer: Sized { /// } /// } /// ``` - fn serialize_newtype_variant( + fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, @@ -933,7 +933,7 @@ pub trait Serializer: Sized { value: &T, ) -> Result where - T: Serialize; + T: ?Sized + Serialize; /// Begin to serialize a variably sized sequence. This call must be /// followed by zero or more calls to `serialize_element`, then a call to @@ -1170,7 +1170,8 @@ pub trait Serializer: Sized { /// then a call to `end`. /// /// The `name` is the name of the struct and the `len` is the number of - /// data fields that will be serialized. + /// data fields that will be serialized. `len` does not include fields + /// which are skipped with [`SerializeStruct::skip_field`]. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; @@ -1207,6 +1208,8 @@ pub trait Serializer: Sized { /// The `name` is the name of the enum, the `variant_index` is the index of /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. + /// `len` does not include fields which are skipped with + /// [`SerializeStructVariant::skip_field`]. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; @@ -1346,9 +1349,9 @@ pub trait Serializer: Sized { /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html /// [`serialize_str`]: #tymethod.serialize_str #[cfg(any(feature = "std", feature = "alloc"))] - fn collect_str(self, value: &T) -> Result + fn collect_str(self, value: &T) -> Result where - T: Display, + T: ?Sized + Display, { self.serialize_str(&value.to_string()) } @@ -1379,9 +1382,9 @@ pub trait Serializer: Sized { /// } /// ``` #[cfg(not(any(feature = "std", feature = "alloc")))] - fn collect_str(self, value: &T) -> Result + fn collect_str(self, value: &T) -> Result where - T: Display; + T: ?Sized + Display; /// Determine whether `Serialize` implementations should serialize in /// human-readable form. @@ -1493,9 +1496,9 @@ pub trait SerializeSeq { type Error: Error; /// Serialize a sequence element. - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Finish serializing a sequence. fn end(self) -> Result; @@ -1593,9 +1596,9 @@ pub trait SerializeTuple { type Error: Error; /// Serialize a tuple element. - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Finish serializing a tuple. fn end(self) -> Result; @@ -1638,9 +1641,9 @@ pub trait SerializeTupleStruct { type Error: Error; /// Serialize a tuple struct field. - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Finish serializing a tuple struct. fn end(self) -> Result; @@ -1696,9 +1699,9 @@ pub trait SerializeTupleVariant { type Error: Error; /// Serialize a tuple variant field. - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Finish serializing a tuple variant. fn end(self) -> Result; @@ -1767,9 +1770,9 @@ pub trait SerializeMap { /// `serialize_entry` instead as it may be implemented more efficiently in /// some formats compared to a pair of calls to `serialize_key` and /// `serialize_value`. - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Serialize a map value. /// @@ -1777,9 +1780,9 @@ pub trait SerializeMap { /// /// Calling `serialize_value` before `serialize_key` is incorrect and is /// allowed to panic or produce bogus results. - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Serialize a map entry consisting of a key and a value. /// @@ -1798,14 +1801,10 @@ pub trait SerializeMap { /// [`Serialize`]: ../trait.Serialize.html /// [`serialize_key`]: #tymethod.serialize_key /// [`serialize_value`]: #tymethod.serialize_value - fn serialize_entry( - &mut self, - key: &K, - value: &V, - ) -> Result<(), Self::Error> + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> where - K: Serialize, - V: Serialize, + K: ?Sized + Serialize, + V: ?Sized + Serialize, { tri!(self.serialize_key(key)); self.serialize_value(value) @@ -1856,15 +1855,13 @@ pub trait SerializeStruct { type Error: Error; /// Serialize a struct field. - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Indicate that a struct field has been skipped. + /// + /// The default implementation does nothing. #[inline] fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { let _ = key; @@ -1922,15 +1919,13 @@ pub trait SerializeStructVariant { type Error: Error; /// Serialize a struct variant field. - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where - T: Serialize; + T: ?Sized + Serialize; /// Indicate that a struct variant field has been skipped. + /// + /// The default implementation does nothing. #[inline] fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { let _ = key; diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index cd3c4b798..772aa429d 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,10 +1,11 @@ [package] name = "serde_derive" -version = "1.0.197" +version = "1.0.199" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" documentation = "https://serde.rs/derive.html" +edition = "2015" homepage = "https://serde.rs" keywords = ["serde", "serialization", "no_std", "derive"] license = "MIT OR Apache-2.0" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index b91f17b1a..a6cee61bc 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -13,7 +13,7 @@ //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html -#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.197")] +#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.199")] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 3be51ee52..7d89d2212 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -289,7 +289,7 @@ fn serialize_tuple_struct( } fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { - assert!(fields.len() as u64 <= u64::from(u32::max_value())); + assert!(fields.len() as u64 <= u64::from(u32::MAX)); if cattrs.has_flatten() { serialize_struct_as_map(params, fields, cattrs) @@ -397,7 +397,7 @@ fn serialize_struct_as_map( } fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment { - assert!(variants.len() as u64 <= u64::from(u32::max_value())); + assert!(variants.len() as u64 <= u64::from(u32::MAX)); let self_var = ¶ms.self_var; diff --git a/serde_derive_internals/Cargo.toml b/serde_derive_internals/Cargo.toml index 6ce277974..095a7439c 100644 --- a/serde_derive_internals/Cargo.toml +++ b/serde_derive_internals/Cargo.toml @@ -4,6 +4,7 @@ version = "0.29.0" authors = ["Erick Tryzelaar ", "David Tolnay "] description = "AST representation used by Serde derive macros. Unstable." documentation = "https://docs.rs/serde_derive_internals" +edition = "2015" exclude = ["build.rs"] homepage = "https://serde.rs" keywords = ["serde", "serialization"] diff --git a/test_suite/tests/regression/issue2371.rs b/test_suite/tests/regression/issue2371.rs index e4832af38..7668af1db 100644 --- a/test_suite/tests/regression/issue2371.rs +++ b/test_suite/tests/regression/issue2371.rs @@ -7,7 +7,9 @@ pub struct Nested; pub enum ExternallyTagged { Flatten { #[serde(flatten)] + #[allow(dead_code)] nested: Nested, + #[allow(dead_code)] string: &'static str, }, } @@ -17,7 +19,9 @@ pub enum ExternallyTagged { pub enum InternallyTagged { Flatten { #[serde(flatten)] + #[allow(dead_code)] nested: Nested, + #[allow(dead_code)] string: &'static str, }, } @@ -27,7 +31,9 @@ pub enum InternallyTagged { pub enum AdjacentlyTagged { Flatten { #[serde(flatten)] + #[allow(dead_code)] nested: Nested, + #[allow(dead_code)] string: &'static str, }, } @@ -37,7 +43,9 @@ pub enum AdjacentlyTagged { pub enum UntaggedWorkaround { Flatten { #[serde(flatten)] + #[allow(dead_code)] nested: Nested, + #[allow(dead_code)] string: &'static str, }, } diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 3ca0fde36..8a7310cd2 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -23,7 +23,7 @@ use std::iter; use std::net; use std::num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, - NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping, + NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Saturating, Wrapping, }; use std::ops::Bound; use std::path::{Path, PathBuf}; @@ -2065,6 +2065,43 @@ fn test_wrapping() { test(Wrapping(1usize), &[Token::U64(1)]); } +#[test] +fn test_saturating() { + test(Saturating(1usize), &[Token::U32(1)]); + test(Saturating(1usize), &[Token::U64(1)]); + test(Saturating(0u8), &[Token::I8(0)]); + test(Saturating(0u16), &[Token::I16(0)]); + + // saturate input values at the minimum or maximum value + test(Saturating(u8::MAX), &[Token::U16(u16::MAX)]); + test(Saturating(u8::MAX), &[Token::U16(u8::MAX as u16 + 1)]); + test(Saturating(u16::MAX), &[Token::U32(u32::MAX)]); + test(Saturating(u32::MAX), &[Token::U64(u64::MAX)]); + test(Saturating(u8::MIN), &[Token::I8(i8::MIN)]); + test(Saturating(u16::MIN), &[Token::I16(i16::MIN)]); + test(Saturating(u32::MIN), &[Token::I32(i32::MIN)]); + test(Saturating(i8::MIN), &[Token::I16(i16::MIN)]); + test(Saturating(i16::MIN), &[Token::I32(i32::MIN)]); + test(Saturating(i32::MIN), &[Token::I64(i64::MIN)]); + + test(Saturating(u8::MIN), &[Token::I8(-1)]); + test(Saturating(u16::MIN), &[Token::I16(-1)]); + + #[cfg(target_pointer_width = "64")] + { + test(Saturating(usize::MIN), &[Token::U64(u64::MIN)]); + test(Saturating(usize::MAX), &[Token::U64(u64::MAX)]); + test(Saturating(isize::MIN), &[Token::I64(i64::MIN)]); + test(Saturating(isize::MAX), &[Token::I64(i64::MAX)]); + test(Saturating(0usize), &[Token::I64(i64::MIN)]); + + test( + Saturating(9_223_372_036_854_775_807usize), + &[Token::I64(i64::MAX)], + ); + } +} + #[test] fn test_rc_dst() { test(Rc::::from("s"), &[Token::Str("s")]); diff --git a/test_suite/tests/test_de_error.rs b/test_suite/tests/test_de_error.rs index d1ea2b910..cf4bec86b 100644 --- a/test_suite/tests/test_de_error.rs +++ b/test_suite/tests/test_de_error.rs @@ -1459,7 +1459,7 @@ fn test_duration_overflow_seq() { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::U32(1_000_000_000), Token::SeqEnd, ], @@ -1476,7 +1476,7 @@ fn test_duration_overflow_struct() { len: 2, }, Token::Str("secs"), - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::Str("nanos"), Token::U32(1_000_000_000), Token::StructEnd, @@ -1490,7 +1490,7 @@ fn test_systemtime_overflow_seq() { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::U32(1_000_000_000), Token::SeqEnd, ], @@ -1507,7 +1507,7 @@ fn test_systemtime_overflow_struct() { len: 2, }, Token::Str("secs_since_epoch"), - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::Str("nanos_since_epoch"), Token::U32(1_000_000_000), Token::StructEnd, @@ -1522,7 +1522,7 @@ fn test_systemtime_overflow() { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, - Token::U64(u64::max_value()), + Token::U64(u64::MAX), Token::U32(0), Token::SeqEnd, ], diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index 97b0a96e9..4aaf06a8b 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -687,8 +687,16 @@ fn test_gen() { #[derive(Deserialize)] #[serde(untagged)] pub enum UntaggedWithBorrow<'a> { - Single(#[serde(borrow)] RelObject<'a>), - Many(#[serde(borrow)] Vec>), + Single( + #[serde(borrow)] + #[allow(dead_code)] + RelObject<'a>, + ), + Many( + #[serde(borrow)] + #[allow(dead_code)] + Vec>, + ), } #[derive(Deserialize)] @@ -730,6 +738,7 @@ fn test_gen() { #[derive(Serialize)] #[repr(packed)] + #[allow(dead_code)] struct Packed { x: u8, y: u16, @@ -761,6 +770,7 @@ fn test_gen() { } #[derive(Serialize)] + #[allow(dead_code)] struct Struct { #[serde(serialize_with = "vec_first_element")] vec: Vec, diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 02c36c413..7bd7a94e7 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -1081,6 +1081,15 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() { Log { level: Level }, } + assert_de_tokens( + &Level::Info, + &[ + Token::Enum { name: "Level" }, + Token::BorrowedStr("Info"), + Token::Unit, + ], + ); + assert_de_tokens( &Message::Log { level: Level::Info }, &[ @@ -1091,7 +1100,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() { Token::Str("action"), Token::Str("Log"), Token::Str("level"), + Token::Enum { name: "Level" }, Token::BorrowedStr("Info"), + Token::Unit, Token::StructEnd, ], ); @@ -1103,7 +1114,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() { Token::Str("action"), Token::Str("Log"), Token::Str("level"), + Token::Enum { name: "Level" }, Token::BorrowedStr("Info"), + Token::Unit, Token::MapEnd, ], ); @@ -1113,7 +1126,9 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() { &[ Token::Seq { len: Some(2) }, Token::Str("Log"), + Token::Enum { name: "Level" }, Token::BorrowedStr("Info"), + Token::Unit, Token::SeqEnd, ], ); @@ -2219,24 +2234,28 @@ fn test_internally_tagged_newtype_variant_containing_unit_struct() { fn test_packed_struct_can_derive_serialize() { #[derive(Copy, Clone, Serialize)] #[repr(packed, C)] + #[allow(dead_code)] struct PackedC { t: f32, } #[derive(Copy, Clone, Serialize)] #[repr(C, packed)] + #[allow(dead_code)] struct CPacked { t: f32, } #[derive(Copy, Clone, Serialize)] #[repr(C, packed(2))] + #[allow(dead_code)] struct CPacked2 { t: f32, } #[derive(Copy, Clone, Serialize)] #[repr(packed(2), C)] + #[allow(dead_code)] struct Packed2C { t: f32, } diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 71ec3bc57..b60d03ab2 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -8,7 +8,7 @@ use std::cell::RefCell; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::ffi::CString; use std::net; -use std::num::Wrapping; +use std::num::{Saturating, Wrapping}; use std::ops::Bound; use std::path::{Path, PathBuf}; use std::rc::{Rc, Weak as RcWeak}; @@ -624,6 +624,11 @@ fn test_wrapping() { assert_ser_tokens(&Wrapping(1usize), &[Token::U64(1)]); } +#[test] +fn test_saturating() { + assert_ser_tokens(&Saturating(1usize), &[Token::U64(1)]); +} + #[test] fn test_rc_dst() { assert_ser_tokens(&Rc::::from("s"), &[Token::Str("s")]);