From f2899a9e064b225d903307db25719324c3db0510 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 5 Sep 2024 10:38:00 +0200 Subject: [PATCH 1/2] Implement serialize/deserialize for core::net instead of std::net if running rust version newer than 1.77, where core::net was stabilized --- serde/build.rs | 7 +++++ serde/src/de/impls.rs | 34 ++++++++++----------- serde/src/lib.rs | 7 ++++- serde/src/ser/impls.rs | 69 +++++++++++++++++++++++++++++------------- 4 files changed, 78 insertions(+), 39 deletions(-) diff --git a/serde/build.rs b/serde/build.rs index c32872b95..604511587 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -15,6 +15,7 @@ fn main() { if minor >= 77 { println!("cargo:rustc-check-cfg=cfg(no_core_cstr)"); + println!("cargo:rustc-check-cfg=cfg(no_core_net)"); println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)"); println!("cargo:rustc-check-cfg=cfg(no_core_try_from)"); println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)"); @@ -86,6 +87,12 @@ fn main() { println!("cargo:rustc-cfg=no_core_num_saturating"); } + // Support for core::net stabilized in Rust 1.77. + // https://blog.rust-lang.org/2024/03/21/Rust-1.77.0.html + if minor < 77 { + println!("cargo:rustc-cfg=no_core_net"); + } + // Support for the `#[diagnostic]` tool attribute namespace // https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes if minor < 78 { diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 02591d982..c85aa30d0 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1604,7 +1604,7 @@ macro_rules! parse_ip_impl { }; } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] macro_rules! variant_identifier { ( $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*) @@ -1679,7 +1679,7 @@ macro_rules! variant_identifier { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] macro_rules! deserialize_enum { ( $name:ident $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*) @@ -1716,8 +1716,8 @@ macro_rules! deserialize_enum { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl<'de> Deserialize<'de> for net::IpAddr { fn deserialize(deserializer: D) -> Result where @@ -1737,14 +1737,14 @@ impl<'de> Deserialize<'de> for net::IpAddr { } parse_ip_impl! { - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg(any(feature = "std", not(no_core_net)))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::Ipv4Addr, "IPv4 address", 4 } parse_ip_impl! { - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg(any(feature = "std", not(no_core_net)))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::Ipv6Addr, "IPv6 address", 16 } @@ -1770,8 +1770,8 @@ macro_rules! parse_socket_impl { }; } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl<'de> Deserialize<'de> for net::SocketAddr { fn deserialize(deserializer: D) -> Result where @@ -1791,15 +1791,15 @@ impl<'de> Deserialize<'de> for net::SocketAddr { } parse_socket_impl! { - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg(any(feature = "std", not(no_core_net)))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::SocketAddrV4, "IPv4 socket address", |(ip, port)| net::SocketAddrV4::new(ip, port), } parse_socket_impl! { - #[cfg(feature = "std")] - #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + #[cfg(any(feature = "std", not(no_core_net)))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] net::SocketAddrV6, "IPv6 socket address", |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0), } @@ -3160,13 +3160,13 @@ atomic_impl! { AtomicU64 "64" } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] struct FromStrVisitor { expecting: &'static str, ty: PhantomData, } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] impl FromStrVisitor { fn new(expecting: &'static str) -> Self { FromStrVisitor { @@ -3176,7 +3176,7 @@ impl FromStrVisitor { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] impl<'de, T> Visitor<'de> for FromStrVisitor where T: str::FromStr, diff --git a/serde/src/lib.rs b/serde/src/lib.rs index e9fc96cba..32509ca85 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -238,8 +238,13 @@ mod lib { #[cfg(feature = "std")] pub use std::ffi::CString; + #[cfg(all(not(no_core_net), not(feature = "std")))] + pub use self::core::net; #[cfg(feature = "std")] - pub use std::{error, net}; + pub use std::net; + + #[cfg(feature = "std")] + pub use std::error; #[cfg(feature = "std")] pub use std::collections::{HashMap, HashSet}; diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 557b6aa12..aae7ec453 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -769,20 +769,47 @@ impl Serialize for SystemTime { //////////////////////////////////////////////////////////////////////////////// +#[cfg(any(feature = "std", not(no_core_net)))] +struct Wrapper<'a> { + pub buf: &'a mut [u8], + pub offset: usize, +} + +#[cfg(any(feature = "std", not(no_core_net)))] +impl<'a> fmt::Write for Wrapper<'a> { + fn write_str(&mut self, s: &str) -> fmt::Result { + if self.offset > self.buf.len() { + return Err(fmt::Error); + } + let remaining_buf = &mut self.buf[self.offset..]; + let raw_s = s.as_bytes(); + let write_num = core::cmp::min(raw_s.len(), remaining_buf.len()); + remaining_buf[..write_num].copy_from_slice(&raw_s[..write_num]); + self.offset += raw_s.len(); + if write_num < raw_s.len() { + Err(fmt::Error) + } else { + Ok(()) + } + } +} + /// Serialize a value that implements `Display` as a string, when that string is /// statically known to never have more than a constant `MAX_LEN` bytes. /// /// Panics if the `Display` impl tries to write more than `MAX_LEN` bytes. -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] macro_rules! serialize_display_bounded_length { ($value:expr, $max:expr, $serializer:expr) => {{ let mut buffer = [0u8; $max]; - let remaining_len = { - let mut remaining = &mut buffer[..]; - write!(remaining, "{}", $value).unwrap(); - remaining.len() + let written_len = { + let mut w = Wrapper { + buf: &mut buffer, + offset: 0, + }; + write!(&mut w, "{}", $value).unwrap(); + w.offset }; - let written_len = buffer.len() - remaining_len; let written = &buffer[..written_len]; // write! only provides fmt::Formatter to Display implementations, which @@ -793,8 +820,8 @@ macro_rules! serialize_display_bounded_length { }}; } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::IpAddr { fn serialize(&self, serializer: S) -> Result where @@ -818,7 +845,7 @@ impl Serialize for net::IpAddr { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] const DEC_DIGITS_LUT: &[u8] = b"\ 0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ @@ -826,7 +853,7 @@ const DEC_DIGITS_LUT: &[u8] = b"\ 6061626364656667686970717273747576777879\ 8081828384858687888990919293949596979899"; -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] #[inline] fn format_u8(mut n: u8, out: &mut [u8]) -> usize { if n >= 100 { @@ -847,7 +874,7 @@ fn format_u8(mut n: u8, out: &mut [u8]) -> usize { } } -#[cfg(feature = "std")] +#[cfg(any(feature = "std", not(no_core_net)))] #[test] fn test_format_u8() { let mut i = 0u8; @@ -864,8 +891,8 @@ fn test_format_u8() { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result where @@ -889,8 +916,8 @@ impl Serialize for net::Ipv4Addr { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::Ipv6Addr { fn serialize(&self, serializer: S) -> Result where @@ -906,8 +933,8 @@ impl Serialize for net::Ipv6Addr { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::SocketAddr { fn serialize(&self, serializer: S) -> Result where @@ -931,8 +958,8 @@ impl Serialize for net::SocketAddr { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::SocketAddrV4 { fn serialize(&self, serializer: S) -> Result where @@ -948,8 +975,8 @@ impl Serialize for net::SocketAddrV4 { } } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[cfg(any(feature = "std", not(no_core_net)))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "std", not(no_core_net)))))] impl Serialize for net::SocketAddrV6 { fn serialize(&self, serializer: S) -> Result where From d940fe1b4934f097b0333dcb87bec5ee308d39cd Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 5 Sep 2024 14:24:44 +0200 Subject: [PATCH 2/2] Reuse existing Buf wrapper as replacement for std::io::Write --- serde/src/de/mod.rs | 5 ++--- serde/src/{de => }/format.rs | 0 serde/src/lib.rs | 2 ++ serde/src/ser/impls.rs | 43 +++--------------------------------- 4 files changed, 7 insertions(+), 43 deletions(-) rename serde/src/{de => }/format.rs (100%) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index d6b9f5ab4..a87558ec5 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -118,7 +118,6 @@ use crate::lib::*; pub mod value; -mod format; mod ignored_any; mod impls; pub(crate) mod size_hint; @@ -1374,7 +1373,7 @@ pub trait Visitor<'de>: Sized { E: Error, { let mut buf = [0u8; 58]; - let mut writer = format::Buf::new(&mut buf); + let mut writer = crate::format::Buf::new(&mut buf); fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap(); Err(Error::invalid_type( Unexpected::Other(writer.as_str()), @@ -1436,7 +1435,7 @@ pub trait Visitor<'de>: Sized { E: Error, { let mut buf = [0u8; 57]; - let mut writer = format::Buf::new(&mut buf); + let mut writer = crate::format::Buf::new(&mut buf); fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap(); Err(Error::invalid_type( Unexpected::Other(writer.as_str()), diff --git a/serde/src/de/format.rs b/serde/src/format.rs similarity index 100% rename from serde/src/de/format.rs rename to serde/src/format.rs diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 32509ca85..f40f6a60e 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -310,6 +310,8 @@ mod integer128; pub mod de; pub mod ser; +mod format; + #[doc(inline)] pub use crate::de::{Deserialize, Deserializer}; #[doc(inline)] diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index aae7ec453..235c9cdeb 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -769,31 +769,6 @@ impl Serialize for SystemTime { //////////////////////////////////////////////////////////////////////////////// -#[cfg(any(feature = "std", not(no_core_net)))] -struct Wrapper<'a> { - pub buf: &'a mut [u8], - pub offset: usize, -} - -#[cfg(any(feature = "std", not(no_core_net)))] -impl<'a> fmt::Write for Wrapper<'a> { - fn write_str(&mut self, s: &str) -> fmt::Result { - if self.offset > self.buf.len() { - return Err(fmt::Error); - } - let remaining_buf = &mut self.buf[self.offset..]; - let raw_s = s.as_bytes(); - let write_num = core::cmp::min(raw_s.len(), remaining_buf.len()); - remaining_buf[..write_num].copy_from_slice(&raw_s[..write_num]); - self.offset += raw_s.len(); - if write_num < raw_s.len() { - Err(fmt::Error) - } else { - Ok(()) - } - } -} - /// Serialize a value that implements `Display` as a string, when that string is /// statically known to never have more than a constant `MAX_LEN` bytes. /// @@ -802,21 +777,9 @@ impl<'a> fmt::Write for Wrapper<'a> { macro_rules! serialize_display_bounded_length { ($value:expr, $max:expr, $serializer:expr) => {{ let mut buffer = [0u8; $max]; - let written_len = { - let mut w = Wrapper { - buf: &mut buffer, - offset: 0, - }; - write!(&mut w, "{}", $value).unwrap(); - w.offset - }; - let written = &buffer[..written_len]; - - // write! only provides fmt::Formatter to Display implementations, which - // has methods write_str and write_char but no method to write arbitrary - // bytes. Therefore `written` must be valid UTF-8. - let written_str = str::from_utf8(written).expect("must be valid UTF-8"); - $serializer.serialize_str(written_str) + let mut writer = crate::format::Buf::new(&mut buffer); + write!(&mut writer, "{}", $value).unwrap(); + $serializer.serialize_str(writer.as_str()) }}; }