Merge pull request #778 from SimonSapin/serialize_display_bounded_length

Avoid some string allocations.
This commit is contained in:
David Tolnay 2017-02-20 11:09:32 -08:00 committed by GitHub
commit f98e7f6ba0
2 changed files with 48 additions and 5 deletions

View File

@ -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)
}
}
}

View File

@ -623,7 +623,10 @@ impl Serialize for net::IpAddr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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)
}
}