From bc1f58860dd789908cd2b0414a8433e3512087f0 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 29 Aug 2017 16:48:37 +0200 Subject: [PATCH 1/3] Use a byte literal ASCII 0 instead of its decimal value. --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 0e240c1..2a2e8ec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,7 +75,7 @@ macro_rules! impl_Integer { // decode last 1 or 2 chars if n < 10 { curr -= 1; - *buf_ptr.offset(curr) = (n as u8) + 48; + *buf_ptr.offset(curr) = (n as u8) + b'0'; } else { let d1 = n << 1; curr -= 2; From 294d84272fda036bc9f632e4174c4625b6325f35 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 29 Aug 2017 16:55:32 +0200 Subject: [PATCH 2/3] Include the minus sign in the same buffer, to only make a single write_all call. --- Cargo.toml | 2 +- src/lib.rs | 13 +++++++------ tests/test.rs | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a1113ef..db6516d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "itoa" -version = "0.3.2" # remember to update html_root_url +version = "0.3.3" # remember to update html_root_url authors = ["David Tolnay "] license = "MIT/Apache-2.0" description = "Fast functions for printing integer primitives to an io::Write" diff --git a/src/lib.rs b/src/lib.rs index 2a2e8ec..3f57e52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![doc(html_root_url = "https://docs.rs/itoa/0.3.2")] +#![doc(html_root_url = "https://docs.rs/itoa/0.3.3")] use std::{io, mem, ptr, slice}; @@ -37,7 +37,6 @@ macro_rules! impl_Integer { let mut n = if is_nonnegative { self as $conv_fn } else { - try!(wr.write_all(b"-")); // convert the negative num to positive by summing 1 to it's 2 complement (!(self as $conv_fn)).wrapping_add(1) }; @@ -81,13 +80,15 @@ macro_rules! impl_Integer { curr -= 2; ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); } + + if !is_nonnegative { + curr -= 1; + *buf_ptr.offset(curr) = b'-'; + } } - let mut len = buf.len() - curr as usize; + let len = buf.len() - curr as usize; try!(wr.write_all(unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) })); - if !is_nonnegative { - len += 1; - } Ok(len) } })*); diff --git a/tests/test.rs b/tests/test.rs index 7615c19..0a33f80 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -19,6 +19,7 @@ test!( test_0u64(0u64, "0"), test_HALFu64(::max_value() as u64, "4294967295"), test_MAXu64(::max_value(), "18446744073709551615"), + test_MINi64(::min_value(), "-9223372036854775808"), test_0i16(0i16, "0"), test_MINi16(::min_value(), "-32768"), From 7128b4bef1d37c474602c8e5e383902fd5d44a53 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 29 Aug 2017 17:34:17 +0200 Subject: [PATCH 3/3] Reduce the amount of code generic on W: io::Write --- src/lib.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3f57e52..9f8b030 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,10 @@ pub trait Integer { fn write(self, W) -> io::Result; } +trait IntegerPrivate { + fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8]; +} + const DEC_DIGITS_LUT: &'static[u8] = b"0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ @@ -26,13 +30,24 @@ const DEC_DIGITS_LUT: &'static[u8] = 6061626364656667686970717273747576777879\ 8081828384858687888990919293949596979899"; +const MAX_LEN: usize = 20; // Tie between i64::MIN (including minus sign) and u64::MAX + // Adaptation of the original implementation at // https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266 macro_rules! impl_Integer { ($($t:ident),* as $conv_fn:ident) => ($( impl Integer for $t { - #[allow(unused_comparisons)] fn write(self, mut wr: W) -> io::Result { + let mut buf = unsafe { mem::uninitialized() }; + let bytes = self.write_to(&mut buf); + try!(wr.write_all(bytes)); + Ok(bytes.len()) + } + } + + impl IntegerPrivate for $t { + #[allow(unused_comparisons)] + fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] { let is_nonnegative = self >= 0; let mut n = if is_nonnegative { self as $conv_fn @@ -40,7 +55,6 @@ macro_rules! impl_Integer { // convert the negative num to positive by summing 1 to it's 2 complement (!(self as $conv_fn)).wrapping_add(1) }; - let mut buf: [u8; 20] = unsafe { mem::uninitialized() }; let mut curr = buf.len() as isize; let buf_ptr = buf.as_mut_ptr(); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); @@ -88,8 +102,7 @@ macro_rules! impl_Integer { } let len = buf.len() - curr as usize; - try!(wr.write_all(unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) })); - Ok(len) + unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) } } })*); }