diff --git a/serde/src/de/ignored_any.rs b/serde/src/de/ignored_any.rs index 2360a1742..eff2f145c 100644 --- a/serde/src/de/ignored_any.rs +++ b/serde/src/de/ignored_any.rs @@ -153,6 +153,13 @@ impl<'de> Visitor<'de> for IgnoredAny { Ok(IgnoredAny) } + #[inline] + #[cfg(feature = "unstable")] + fn visit_f128(self, x: f128) -> Result { + let _ = x; + Ok(IgnoredAny) + } + #[inline] fn visit_str(self, s: &str) -> Result where diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index f62b0f16d..51ec6d0cd 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -448,6 +448,15 @@ impl_deserialize_num! { uint_to_self!(u32:visit_u32 u64:visit_u64); } +#[cfg(feature = "unstable")] +impl_deserialize_num! { + f16, deserialize_f16 + num_self!(f16:visit_f16); + num_as_copysign_self!(f32:visit_f32 f64:visit_f64); + num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); +} + impl_deserialize_num! { f32, deserialize_f32 num_self!(f32:visit_f32); @@ -517,6 +526,17 @@ macro_rules! num_128 { }; } +#[cfg(feature = "unstable")] +impl_deserialize_num! { + f128, deserialize_f128 + num_self!(f128:visit_f128); + num_as_copysign_self!(f32:visit_f32 f64:visit_f64); + num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); + num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); + num_128!(u128:visit_u128); + num_128!(i128:visit_i128); +} + impl_deserialize_num! { i128, NonZeroI128, deserialize_i128 num_self!(i128:visit_i128); diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 15e32ccaf..a83834f2d 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -996,6 +996,18 @@ pub trait Deserializer<'de>: Sized { Err(Error::custom("u128 is not supported")) } + /// Hint that the `Deserialize` type is expecting a `f16` value. + /// + /// The default behavior unconditionally returns an error. + #[cfg(feature = "unstable")] + fn deserialize_f16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let _ = visitor; + Err(Error::custom("f16 is not supported")) + } + /// Hint that the `Deserialize` type is expecting a `f32` value. fn deserialize_f32(self, visitor: V) -> Result where @@ -1006,6 +1018,18 @@ pub trait Deserializer<'de>: Sized { where V: Visitor<'de>; + /// Hint that the `Deserialize` type is expecting a `f128` value. + /// + /// The default behavior unconditionally returns an error. + #[cfg(feature = "unstable")] + fn deserialize_f128(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let _ = visitor; + Err(Error::custom("f128 is not supported")) + } + /// Hint that the `Deserialize` type is expecting a `char` value. fn deserialize_char(self, visitor: V) -> Result where @@ -1439,6 +1463,19 @@ pub trait Visitor<'de>: Sized { )) } + /// The input contains a `f16`. + /// + /// The default implementation forwards to [`visit_f64`]. + /// + /// [`visit_f64`]: #method.visit_f64 + #[cfg(feature = "unstable")] + fn visit_f16(self, v: f16) -> Result + where + E: Error, + { + self.visit_f64(v as f64) + } + /// The input contains an `f32`. /// /// The default implementation forwards to [`visit_f64`]. @@ -1461,6 +1498,28 @@ pub trait Visitor<'de>: Sized { Err(Error::invalid_type(Unexpected::Float(v), &self)) } + /// The input contains a `f128`. + /// + /// The default implementation fails with a type error. + #[cfg(feature = "unstable")] + fn visit_f128(self, v: f128) -> Result + where + E: Error, + { + let mut buf = [0u8; 64]; + let mut writer = crate::format::Buf::new(&mut buf); + fmt::Write::write_fmt( + &mut writer, + format_args!("float `{:x}` as f128", v.to_bits()), + ) + .unwrap(); + + Err(Error::invalid_type( + Unexpected::Other(writer.as_str()), + &self, + )) + } + /// The input contains a `char`. /// /// The default implementation forwards to [`visit_str`] as a one-character diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 8f9c0b48e..112c035b8 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -160,6 +160,11 @@ where map struct enum identifier ignored_any } + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } + fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, @@ -230,7 +235,7 @@ where } forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f16 f32 f64 f128 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } @@ -294,6 +299,11 @@ macro_rules! primitive_deserializer { tuple tuple_struct map struct enum identifier ignored_any } + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } + fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, @@ -336,8 +346,12 @@ primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16); primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64); primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128); primitive_deserializer!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64); +#[cfg(feature = "unstable")] +primitive_deserializer!(f16, "an `f16`.", F16Deserializer, visit_f16); primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32); primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64); +#[cfg(feature = "unstable")] +primitive_deserializer!(f128, "an `f128`.", F128Deserializer, visit_f128); primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char); /// A deserializer holding a `u32`. @@ -381,6 +395,11 @@ where tuple_struct map struct identifier ignored_any } + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } + fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, @@ -501,6 +520,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'de, 'a, E> IntoDeserializer<'de, E> for StrDeserializer<'a, E> @@ -591,6 +615,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'de, E> IntoDeserializer<'de, E> for BorrowedStrDeserializer<'de, E> @@ -705,6 +734,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } #[cfg(any(feature = "std", feature = "alloc"))] @@ -825,6 +859,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } #[cfg(any(feature = "std", feature = "alloc"))] @@ -914,6 +953,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'de, 'a, E> IntoDeserializer<'de, E> for BytesDeserializer<'a, E> @@ -973,6 +1017,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'de, E> IntoDeserializer<'de, E> for BorrowedBytesDeserializer<'de, E> @@ -1063,6 +1112,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'de, I, T, E> IntoDeserializer<'de, E> for SeqDeserializer @@ -1207,6 +1261,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'de, A> IntoDeserializer<'de, A::Error> for SeqAccessDeserializer @@ -1332,6 +1391,11 @@ where bytes byte_buf option unit unit_struct newtype_struct tuple_struct map struct enum identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'de, I, E> IntoDeserializer<'de, E> for MapDeserializer<'de, I, E> @@ -1487,6 +1551,11 @@ where struct enum identifier ignored_any } + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } + fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, @@ -1648,6 +1717,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'de, A> IntoDeserializer<'de, A::Error> for MapAccessDeserializer diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 03b4fabcc..4b27cd81a 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -105,8 +105,13 @@ // discussion of these features please refer to this issue: // // https://github.com/serde-rs/serde/issues/812 -#![cfg_attr(feature = "unstable", feature(never_type))] -#![allow(unknown_lints, bare_trait_objects, deprecated, mismatched_lifetime_syntaxes)] +#![cfg_attr(feature = "unstable", feature(never_type, f16, f128))] +#![allow( + unknown_lints, + bare_trait_objects, + deprecated, + mismatched_lifetime_syntaxes +)] // Ignored clippy and clippy_pedantic lints #![allow( // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 @@ -304,12 +309,12 @@ macro_rules! tri { #[macro_use] mod macros; -#[macro_use] -mod integer128; - pub mod de; pub mod ser; +#[macro_use] +mod integer128; + mod format; #[doc(inline)] diff --git a/serde/src/macros.rs b/serde/src/macros.rs index 82a1105b1..3a0a607e7 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -109,6 +109,8 @@ /// [`Deserializer::deserialize_any`]: crate::Deserializer::deserialize_any #[macro_export(local_inner_macros)] macro_rules! forward_to_deserialize_any { + // there should be just a special case called all that implements all of this, + // this is a pain to update (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => { $(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})* }; @@ -171,12 +173,18 @@ macro_rules! forward_to_deserialize_any_helper { (u128<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()} }; + (f16<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_f16<$l, $v>()} + }; (f32<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()} }; (f64<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_f64<$l, $v>()} }; + (f128<$l:tt, $v:ident>) => { + forward_to_deserialize_any_method!{deserialize_f128<$l, $v>()} + }; (char<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_char<$l, $v>()} }; diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 34bfcb663..00901de9a 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -52,6 +52,11 @@ where bytes byte_buf unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } let deserializer = MissingFieldDeserializer(field, PhantomData); @@ -2402,6 +2407,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } pub struct BorrowedStrDeserializer<'de, E> { @@ -2427,6 +2437,11 @@ where bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'a, E> IdentifierDeserializer<'a, E> for &'a str diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 930f0b88d..480574712 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -31,8 +31,12 @@ primitive_impl!(u16, serialize_u16); primitive_impl!(u32, serialize_u32); primitive_impl!(u64, serialize_u64); primitive_impl!(u128, serialize_u128); +#[cfg(feature = "unstable")] +primitive_impl!(f16, serialize_f16); primitive_impl!(f32, serialize_f32); primitive_impl!(f64, serialize_f64); +#[cfg(feature = "unstable")] +primitive_impl!(f128, serialize_f128); primitive_impl!(char, serialize_char); //////////////////////////////////////////////////////////////////////////////// diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 23418f9f8..65fe2d091 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -625,6 +625,34 @@ pub trait Serializer: Sized { Err(Error::custom("u128 is not supported")) } + /// Serialize an `f16` value. + /// + /// If the format does not differentiate between `f16` and `f32`, a + /// reasonable implementation would be to cast the value to `f32` and + /// forward to `serialize_f32`. + /// + /// ```edition2021 + /// # #![feature(f16)] + /// # use serde::Serializer; + /// # + /// # serde::__private_serialize!(); + /// # + /// impl Serialize for f16 { + /// fn serialize(&self, serializer: S) -> Result + /// where + /// S: Serializer, + /// { + /// serializer.serialize_f16(*self) + /// } + /// } + /// ``` + /// The default behavior unconditionally returns an error. + #[cfg(feature = "unstable")] + fn serialize_f16(self, v: f16) -> Result { + let _ = v; + Err(Error::custom("f16 is not supported")) + } + /// Serialize an `f32` value. /// /// If the format does not differentiate between `f32` and `f64`, a @@ -665,6 +693,30 @@ pub trait Serializer: Sized { /// ``` fn serialize_f64(self, v: f64) -> Result; + /// Serialize an `f128` value. + /// + /// ```edition2021 + /// # #![feature(f128)] + /// # use serde::Serializer; + /// # + /// # serde::__private_serialize!(); + /// # + /// impl Serialize for f128 { + /// fn serialize(&self, serializer: S) -> Result + /// where + /// S: Serializer, + /// { + /// serializer.serialize_f128(*self) + /// } + /// } + /// ``` + /// The default behavior unconditionally returns an error. + #[cfg(feature = "unstable")] + fn serialize_f128(self, v: f128) -> Result { + let _ = v; + Err(Error::custom("f128 is not supported")) + } + /// Serialize a character. /// /// If the format does not support characters, it is reasonable to serialize diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 2e80fbaf9..58c28b9ed 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -8,7 +8,7 @@ clippy::uninlined_format_args, clippy::unreadable_literal )] -#![cfg_attr(feature = "unstable", feature(never_type))] +#![cfg_attr(feature = "unstable", feature(never_type, f16, f128))] use serde::de::value::{F32Deserializer, F64Deserializer}; use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer}; @@ -816,6 +816,16 @@ fn test_nonzero_usize() { test(10, &[Token::U64(10)]); } +#[test] +#[cfg(feature = "unstable")] +#[ignore = "serde_test lacks support for f16"] +fn test_f16() { + let test = test::; + + test(1.11, &[Token::F32(1.11)]); + test(1.11, &[Token::F64(1.11)]); +} + #[test] fn test_f32() { let test = test::; @@ -832,6 +842,16 @@ fn test_f64() { test(1.11, &[Token::F64(1.11)]); } +#[test] +#[cfg(feature = "unstable")] +#[ignore = "serde_test lacks support for f128"] +fn test_f128() { + let test = test::; + + test(1.11, &[Token::F32(1.11)]); + test(1.11, &[Token::F64(1.11)]); +} + #[test] fn test_nan() { let f32_deserializer = F32Deserializer::::new; diff --git a/test_suite/tests/test_ignored_any.rs b/test_suite/tests/test_ignored_any.rs index 955b7974e..a4f057bf5 100644 --- a/test_suite/tests/test_ignored_any.rs +++ b/test_suite/tests/test_ignored_any.rs @@ -33,6 +33,11 @@ impl<'de> Deserializer<'de> for Enum { bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } + + #[cfg(feature = "unstable")] + forward_to_deserialize_any! { + f16 f128 + } } impl<'de> EnumAccess<'de> for Enum {