Skip to content

Commit

Permalink
Implement serialize/deserialize for core::net instead of std::net if …
Browse files Browse the repository at this point in the history
…running rust version newer than 1.77, where core::net was stabilized
  • Loading branch information
MathiasKoch committed Sep 5, 2024
1 parent 3aca38d commit f2899a9
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 39 deletions.
7 changes: 7 additions & 0 deletions serde/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)");
Expand Down Expand Up @@ -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 {
Expand Down
34 changes: 17 additions & 17 deletions serde/src/de/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),*)
Expand Down Expand Up @@ -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),*)
Expand Down Expand Up @@ -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<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand All @@ -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
}

Expand All @@ -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<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand All @@ -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),
}
Expand Down Expand Up @@ -3160,13 +3160,13 @@ atomic_impl! {
AtomicU64 "64"
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(no_core_net)))]
struct FromStrVisitor<T> {
expecting: &'static str,
ty: PhantomData<T>,
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(no_core_net)))]
impl<T> FromStrVisitor<T> {
fn new(expecting: &'static str) -> Self {
FromStrVisitor {
Expand All @@ -3176,7 +3176,7 @@ impl<T> FromStrVisitor<T> {
}
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(no_core_net)))]
impl<'de, T> Visitor<'de> for FromStrVisitor<T>
where
T: str::FromStr,
Expand Down
7 changes: 6 additions & 1 deletion serde/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
69 changes: 48 additions & 21 deletions serde/src/ser/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -818,15 +845,15 @@ impl Serialize for net::IpAddr {
}
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(no_core_net)))]
const DEC_DIGITS_LUT: &[u8] = b"\
0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
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 {
Expand All @@ -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;
Expand All @@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down

0 comments on commit f2899a9

Please sign in to comment.