diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 2f6d0442c..2ddf939c1 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -139,7 +139,6 @@ ) )] // Rustc lints. -#![forbid(unsafe_code)] #![deny(missing_docs, unused_imports)] //////////////////////////////////////////////////////////////////////////////// diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 431a478cc..ffbcb7f3e 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -674,6 +674,42 @@ impl Serialize for net::IpAddr { } } +const DEC_DIGITS_LUT: &'static [u8] = b"\ + 0001020304050607080910111213141516171819\ + 2021222324252627282930313233343536373839\ + 4041424344454647484950515253545556575859\ + 6061626364656667686970717273747576777879\ + 8081828384858687888990919293949596979899"; + +#[inline] +fn format_u8(mut n: u8, out: &mut [u8]) -> usize { + if n >= 100 { + let d1 = ((n % 100) << 1) as usize; + n /= 100; + out[0] = b'0' + n; + out[1] = DEC_DIGITS_LUT[d1]; + out[2] = DEC_DIGITS_LUT[d1 + 1]; + 3 + } else if n >= 10 { + let d1 = (n << 1) as usize; + out[0] = DEC_DIGITS_LUT[d1]; + out[1] = DEC_DIGITS_LUT[d1 + 1]; + 2 + } else { + out[0] = b'0' + n; + 1 + } +} + +#[test] +fn test_format_u8() { + for i in 0..(u8::MAX as u16) { + let mut buf = [0u8; 3]; + let written = format_u8(i as u8, &mut buf); + assert_eq!(i.to_string().as_bytes(), &buf[..written]); + } +} + #[cfg(feature = "std")] impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result @@ -683,7 +719,14 @@ impl Serialize for net::Ipv4Addr { if serializer.is_human_readable() { const MAX_LEN: usize = 15; debug_assert_eq!(MAX_LEN, "101.102.103.104".len()); - serialize_display_bounded_length!(self, MAX_LEN, serializer) + let mut buf = [b'.'; MAX_LEN]; + let mut written = format_u8(self.octets()[0], &mut buf); + for oct in &self.octets()[1..] { + // Skip over delimiters that we initialized buf with + written += format_u8(*oct, &mut buf[written + 1..]) + 1; + } + // We've only written ASCII bytes to the buffer, so it is valid UTF-8 + serializer.serialize_str(unsafe { str::from_utf8_unchecked(&buf[..written]) }) } else { self.octets().serialize(serializer) }