From 772b22b427e53ac38250152982acf4d12f2416e9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 20 Feb 2017 18:30:41 +0100 Subject: [PATCH] Avoid some string allocations. --- serde/src/macros.rs | 32 ++++++++++++++++++++++++++++++++ serde/src/ser/impls.rs | 21 ++++++++++++++++----- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/serde/src/macros.rs b/serde/src/macros.rs index 8050e8b5..126c7ec1 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -188,3 +188,35 @@ macro_rules! forward_to_deserialize { $(forward_to_deserialize_helper!{$func})* }; } + +/// Seralize the `$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")] +// Not exported +macro_rules! serialize_display_bounded_length { + ($value: expr, $MAX_LEN: expr, $serializer: expr) => { + { + use std::io::Write; + let mut buffer: [u8; $MAX_LEN] = unsafe { ::std::mem::uninitialized() }; + let remaining_len; + { + let mut remaining = &mut buffer[..]; + write!(remaining, "{}", $value).unwrap(); + remaining_len = remaining.len() + } + let written_len = buffer.len() - remaining_len; + let written = &buffer[..written_len]; + + // write! only provides std::fmt::Formatter to Display implementations, + // which has methods write_str and write_char but no method to write arbitrary bytes. + // Therefore, `written` is well-formed in UTF-8. + let written_str = unsafe { + ::std::str::from_utf8_unchecked(written) + }; + $serializer.serialize_str(written_str) + } + } +} diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 745903fa..a7ac780f 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -623,7 +623,10 @@ impl Serialize for net::IpAddr { fn serialize(&self, serializer: S) -> Result where S: Serializer { - self.to_string().serialize(serializer) + match *self { + net::IpAddr::V4(ref a) => a.serialize(serializer), + net::IpAddr::V6(ref a) => a.serialize(serializer), + } } } @@ -632,7 +635,9 @@ impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result where S: Serializer { - self.to_string().serialize(serializer) + /// "101.102.103.104".len() + const MAX_LEN: usize = 15; + serialize_display_bounded_length!(self, MAX_LEN, serializer) } } @@ -641,7 +646,9 @@ impl Serialize for net::Ipv6Addr { fn serialize(&self, serializer: S) -> Result where S: Serializer { - self.to_string().serialize(serializer) + /// "1000:1002:1003:1004:1005:1006:1007:1008".len() + const MAX_LEN: usize = 39; + serialize_display_bounded_length!(self, MAX_LEN, serializer) } } @@ -664,7 +671,9 @@ impl Serialize for net::SocketAddrV4 { fn serialize(&self, serializer: S) -> Result where S: Serializer { - self.to_string().serialize(serializer) + /// "101.102.103.104:65000".len() + const MAX_LEN: usize = 21; + serialize_display_bounded_length!(self, MAX_LEN, serializer) } } @@ -673,7 +682,9 @@ impl Serialize for net::SocketAddrV6 { fn serialize(&self, serializer: S) -> Result where S: Serializer { - self.to_string().serialize(serializer) + /// "[1000:1002:1003:1004:1005:1006:1007:1008]:65000".len() + const MAX_LEN: usize = 47; + serialize_display_bounded_length!(self, MAX_LEN, serializer) } }