Bug 1769902 - Update the itoa crate to 1.0.x. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D146662
This commit is contained in:
Mike Hommey 2022-05-18 21:04:31 +00:00
parent 83c74198fa
commit beaa7521c7
11 changed files with 178 additions and 294 deletions

23
Cargo.lock generated
View file

@ -1081,7 +1081,7 @@ checksum = "031d29b6d1ea84f63436e45fb6f3c1a3d62dc1650018c53fa7165e108d35d88f"
dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa",
"itoa 0.4.999",
"matches",
"phf",
"proc-macro2",
@ -2388,7 +2388,7 @@ checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
dependencies = [
"bytes 1.1.0",
"fnv",
"itoa",
"itoa 0.4.999",
]
[[package]]
@ -2460,7 +2460,7 @@ dependencies = [
"http",
"http-body",
"httparse",
"itoa",
"itoa 0.4.999",
"log",
"pin-project",
"socket2",
@ -2601,9 +2601,16 @@ dependencies = [
[[package]]
name = "itoa"
version = "0.4.8"
version = "0.4.999"
dependencies = [
"itoa 1.0.2",
]
[[package]]
name = "itoa"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
[[package]]
name = "jobserver"
@ -4608,7 +4615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527"
dependencies = [
"indexmap",
"itoa",
"itoa 0.4.999",
"ryu",
"serde",
]
@ -4631,7 +4638,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
dependencies = [
"dtoa",
"itoa",
"itoa 0.4.999",
"serde",
"url",
]
@ -4878,7 +4885,7 @@ dependencies = [
"gecko-profiler",
"indexmap",
"itertools 0.8.2",
"itoa",
"itoa 0.4.999",
"lazy_static",
"log",
"malloc_size_of",

View file

@ -90,6 +90,9 @@ vcpkg = { path = "build/rust/vcpkg" }
# Helper crate for integration in the gecko build system.
mozbuild = { path = "build/rust/mozbuild" }
# Patch itoa 0.4 to 1.0.
itoa = { path = "build/rust/itoa" }
# Patch autocfg to hide rustc output. Workaround for https://github.com/cuviper/autocfg/issues/30
autocfg = { path = "third_party/rust/autocfg" }

View file

@ -0,0 +1,11 @@
[package]
name = "itoa"
version = "0.4.999"
edition = "2018"
license = "MIT OR Apache-2.0"
[lib]
path = "lib.rs"
[dependencies]
itoa = "1.0"

21
build/rust/itoa/lib.rs Normal file
View file

@ -0,0 +1,21 @@
pub use itoa::*;
use std::{io, fmt};
// APIs that were in itoa 0.4 but aren't in 1.0.
#[inline]
pub fn write<W: io::Write, V: Integer>(mut wr: W, value: V) -> io::Result<usize> {
let mut buf = Buffer::new();
let s = buf.format(value);
match wr.write_all(s.as_bytes()) {
Ok(()) => Ok(s.len()),
Err(e) => Err(e),
}
}
/// Write integer to an `fmt::Write`.
#[inline]
pub fn fmt<W: fmt::Write, V: Integer>(mut wr: W, value: V) -> fmt::Result {
let mut buf = Buffer::new();
wr.write_str(buf.format(value))
}

View file

@ -1 +1 @@
{"files":{"Cargo.toml":"46f2cf3006d59c73bed95c276f43ddab1a9a9fa177ea0142777b7471c753f558","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"5eac563c0123003363f4706f36927cf4d3b118965e35b51bc515343ce6a711ae","benches/bench.rs":"fc009678431563bfb1b51698fb5b83f5309a3cdab90dc7365800f4e32bc287be","src/lib.rs":"a7b37eab3872193cf666c1d7d4db8d7e82c6dc6d8121fc762b5f69ddb4df3b01","src/udiv128.rs":"1c9c374680162e12c734d369d1494ee8c91e11eb4b05500e96e6303155bdc623","tests/test.rs":"c9b124462b75078e2407e0239222edd7859c3112d65a114742dbb8c47dafc07c"},"package":"b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"}
{"files":{"Cargo.toml":"3c81fd59c059ee454f7812e8a9e90078880a4c101964ac4ce63537cec7d36c1e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"8e9d4e6ac0c740793958bf57c3dbd62827340cf77a282633c388aff70a7c1a22","benches/bench.rs":"636f3093bd461210ad3063289d455f90669c4a1be3273bcd30898de39f02c641","src/lib.rs":"f3b4bd0934f41b8f8a8828a22a9f5ad2af1ac1e7b632743ec2de46fbb4cb0b59","src/udiv128.rs":"16394f767854452756372d74f8025f7329fd8b61a676d81edf489681a6332ee9","tests/test.rs":"f7404fc5f7cd1bdaf74a3b64a70d5b30586241ddc1ce2c82bd1b564999fcce0e"},"package":"112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"}

View file

@ -10,20 +10,21 @@
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
rust-version = "1.36"
name = "itoa"
version = "0.4.8"
version = "1.0.2"
authors = ["David Tolnay <dtolnay@gmail.com>"]
exclude = ["performance.png"]
description = "Fast functions for printing integer primitives to an io::Write"
exclude = [
"performance.png",
"chart/**",
]
description = "Fast integer primitive to string conversion"
documentation = "https://docs.rs/itoa"
readme = "README.md"
categories = ["value-formatting"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/dtolnay/itoa"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[features]
default = ["std"]
i128 = []
std = []

View file

@ -6,24 +6,33 @@ itoa
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-itoa-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/itoa)
[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/itoa/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/itoa/actions?query=branch%3Amaster)
This crate provides fast functions for printing integer primitives to an
[`io::Write`] or a [`fmt::Write`]. The implementation comes straight from
[libcore] but avoids the performance penalty of going through
[`fmt::Formatter`].
This crate provides a fast conversion of integer primitives to decimal strings.
The implementation comes straight from [libcore] but avoids the performance
penalty of going through [`core::fmt::Formatter`].
See also [`dtoa`] for printing floating point primitives.
See also [`ryu`] for printing floating point primitives.
*Version requirement: rustc 1.0+*
*Version requirement: rustc 1.36+*
[`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
[`fmt::Write`]: https://doc.rust-lang.org/core/fmt/trait.Write.html
[libcore]: https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L201-L254
[`fmt::Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html
[`dtoa`]: https://github.com/dtolnay/dtoa
[`core::fmt::Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html
[`ryu`]: https://github.com/dtolnay/ryu
```toml
[dependencies]
itoa = "0.4"
itoa = "1.0"
```
<br>
## Example
```rust
fn main() {
let mut buffer = itoa::Buffer::new();
let printed = buffer.format(128u64);
assert_eq!(printed, "128");
}
```
<br>
@ -34,52 +43,6 @@ itoa = "0.4"
<br>
## Examples
```rust
use std::{fmt, io};
fn demo_itoa_write() -> io::Result<()> {
// Write to a vector or other io::Write.
let mut buf = Vec::new();
itoa::write(&mut buf, 128u64)?;
println!("{:?}", buf);
// Write to a stack buffer.
let mut bytes = [0u8; 20];
let n = itoa::write(&mut bytes[..], 128u64)?;
println!("{:?}", &bytes[..n]);
Ok(())
}
fn demo_itoa_fmt() -> fmt::Result {
// Write to a string.
let mut s = String::new();
itoa::fmt(&mut s, 128u64)?;
println!("{}", s);
Ok(())
}
```
The function signatures are:
```rust
fn write<W: io::Write, V: itoa::Integer>(writer: W, value: V) -> io::Result<usize>;
fn fmt<W: fmt::Write, V: itoa::Integer>(writer: W, value: V) -> fmt::Result;
```
where `itoa::Integer` is implemented for i8, u8, i16, u16, i32, u32, i64, u64,
i128, u128, isize and usize. 128-bit integer support requires rustc 1.26+ and
the `i128` feature of this crate enabled.
The `write` function is only available when the `std` feature is enabled
(default is enabled). The return value gives the number of bytes written.
<br>
#### License
<sup>

View file

@ -1,66 +1,40 @@
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
#![feature(test)]
#![allow(non_snake_case)]
#![allow(clippy::cast_lossless)]
extern crate itoa;
extern crate test;
macro_rules! benches {
(
$(
$(#[$attr:meta])*
$name:ident($value:expr)
),*
) => {
mod bench_itoa_write {
($($name:ident($value:expr))*) => {
mod bench_itoa_format {
use test::{Bencher, black_box};
$(
$(#[$attr])*
#[bench]
fn $name(b: &mut Bencher) {
use itoa;
let mut buf = Vec::with_capacity(40);
let mut buffer = itoa::Buffer::new();
b.iter(|| {
buf.clear();
itoa::write(&mut buf, black_box($value)).unwrap()
});
}
)*
}
mod bench_itoa_fmt {
use test::{Bencher, black_box};
$(
$(#[$attr])*
#[bench]
fn $name(b: &mut Bencher) {
use itoa;
let mut buf = String::with_capacity(40);
b.iter(|| {
buf.clear();
itoa::fmt(&mut buf, black_box($value)).unwrap()
let printed = buffer.format(black_box($value));
black_box(printed);
});
}
)*
}
mod bench_std_fmt {
use std::io::Write;
use test::{Bencher, black_box};
$(
$(#[$attr])*
#[bench]
fn $name(b: &mut Bencher) {
use std::io::Write;
let mut buf = Vec::with_capacity(40);
b.iter(|| {
buf.clear();
write!(&mut buf, "{}", black_box($value)).unwrap()
write!(&mut buf, "{}", black_box($value)).unwrap();
black_box(&buf);
});
}
)*
@ -69,15 +43,13 @@ macro_rules! benches {
}
benches! {
bench_u64_0(0u64),
bench_u64_half(<u32>::max_value() as u64),
bench_u64_max(<u64>::max_value()),
bench_u64_0(0u64)
bench_u64_half(u32::max_value() as u64)
bench_u64_max(u64::max_value())
bench_i16_0(0i16),
bench_i16_min(<i16>::min_value()),
bench_i16_0(0i16)
bench_i16_min(i16::min_value())
#[cfg(feature = "i128")]
bench_u128_0(0u128),
#[cfg(feature = "i128")]
bench_u128_max(<u128>::max_value())
bench_u128_0(0u128)
bench_u128_max(u128::max_value())
}

View file

@ -6,98 +6,46 @@
//!
//! <br>
//!
//! This crate provides fast functions for printing integer primitives to an
//! [`io::Write`] or a [`fmt::Write`]. The implementation comes straight from
//! [libcore] but avoids the performance penalty of going through
//! [`fmt::Formatter`].
//! This crate provides a fast conversion of integer primitives to decimal
//! strings. The implementation comes straight from [libcore] but avoids the
//! performance penalty of going through [`core::fmt::Formatter`].
//!
//! See also [`dtoa`] for printing floating point primitives.
//! See also [`ryu`] for printing floating point primitives.
//!
//! [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
//! [`fmt::Write`]: https://doc.rust-lang.org/core/fmt/trait.Write.html
//! [libcore]: https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L201-L254
//! [`fmt::Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html
//! [`dtoa`]: https://github.com/dtolnay/dtoa
//! [`core::fmt::Formatter`]: https://doc.rust-lang.org/std/fmt/struct.Formatter.html
//! [`ryu`]: https://github.com/dtolnay/ryu
//!
//! <br>
//! # Example
//!
//! ```
//! fn main() {
//! let mut buffer = itoa::Buffer::new();
//! let printed = buffer.format(128u64);
//! assert_eq!(printed, "128");
//! }
//! ```
//!
//! # Performance (lower is better)
//!
//! ![performance](https://raw.githubusercontent.com/dtolnay/itoa/master/performance.png)
//!
//! <br>
//!
//! # Examples
//!
//! ```edition2018
//! use std::{fmt, io};
//!
//! fn demo_itoa_write() -> io::Result<()> {
//! // Write to a vector or other io::Write.
//! let mut buf = Vec::new();
//! itoa::write(&mut buf, 128u64)?;
//! println!("{:?}", buf);
//!
//! // Write to a stack buffer.
//! let mut bytes = [0u8; 20];
//! let n = itoa::write(&mut bytes[..], 128u64)?;
//! println!("{:?}", &bytes[..n]);
//!
//! Ok(())
//! }
//!
//! fn demo_itoa_fmt() -> fmt::Result {
//! // Write to a string.
//! let mut s = String::new();
//! itoa::fmt(&mut s, 128u64)?;
//! println!("{}", s);
//!
//! Ok(())
//! }
//! ```
#![doc(html_root_url = "https://docs.rs/itoa/0.4.8")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(
feature = "cargo-clippy",
allow(
expl_impl_clone_on_copy,
missing_errors_doc,
must_use_candidate,
transmute_ptr_to_ptr
)
#![doc(html_root_url = "https://docs.rs/itoa/1.0.2")]
#![no_std]
#![allow(
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::must_use_candidate,
clippy::unreadable_literal
)]
#[cfg(feature = "i128")]
mod udiv128;
#[cfg(feature = "std")]
use std::{fmt, io, mem, ptr, slice, str};
use core::mem::{self, MaybeUninit};
use core::{ptr, slice, str};
#[cfg(not(feature = "std"))]
use core::{fmt, mem, ptr, slice, str};
/// Write integer to an `io::Write`.
#[cfg(feature = "std")]
#[inline]
pub fn write<W: io::Write, V: Integer>(mut wr: W, value: V) -> io::Result<usize> {
let mut buf = Buffer::new();
let s = buf.format(value);
match wr.write_all(s.as_bytes()) {
Ok(()) => Ok(s.len()),
Err(e) => Err(e),
}
}
/// Write integer to an `fmt::Write`.
#[inline]
pub fn fmt<W: fmt::Write, V: Integer>(mut wr: W, value: V) -> fmt::Result {
let mut buf = Buffer::new();
wr.write_str(buf.format(value))
}
/// A safe API for formatting integers to text.
/// A correctly sized stack allocation for the formatted integer to be written
/// into.
///
/// # Example
///
@ -106,9 +54,8 @@ pub fn fmt<W: fmt::Write, V: Integer>(mut wr: W, value: V) -> fmt::Result {
/// let printed = buffer.format(1234);
/// assert_eq!(printed, "1234");
/// ```
#[derive(Copy)]
pub struct Buffer {
bytes: [u8; I128_MAX_LEN],
bytes: [MaybeUninit<u8>; I128_MAX_LEN],
}
impl Default for Buffer {
@ -129,39 +76,35 @@ impl Buffer {
/// This is a cheap operation; you don't need to worry about reusing buffers
/// for efficiency.
#[inline]
#[allow(deprecated)]
pub fn new() -> Buffer {
Buffer {
bytes: unsafe { mem::uninitialized() },
}
let bytes = [MaybeUninit::<u8>::uninit(); I128_MAX_LEN];
Buffer { bytes }
}
/// Print an integer into this buffer and return a reference to its string representation
/// within the buffer.
/// Print an integer into this buffer and return a reference to its string
/// representation within the buffer.
pub fn format<I: Integer>(&mut self, i: I) -> &str {
i.write(self)
i.write(unsafe {
&mut *(&mut self.bytes as *mut [MaybeUninit<u8>; I128_MAX_LEN]
as *mut <I as private::Sealed>::Buffer)
})
}
}
/// An integer that can be written into an [`itoa::Buffer`][Buffer].
///
/// This trait is sealed and cannot be implemented for types outside of itoa.
pub trait Integer: private::Sealed {}
// Seal to prevent downstream implementations of the Integer trait.
mod private {
pub trait Sealed {}
pub trait Sealed: Copy {
type Buffer: 'static;
fn write(self, buf: &mut Self::Buffer) -> &str;
}
}
/// An integer that can be formatted by `itoa::write` and `itoa::fmt`.
///
/// This trait is sealed and cannot be implemented for types outside of itoa.
pub trait Integer: private::Sealed {
// Not public API.
#[doc(hidden)]
fn write(self, buf: &mut Buffer) -> &str;
}
trait IntegerPrivate<B> {
fn write_to(self, buf: &mut B) -> &[u8];
}
const DEC_DIGITS_LUT: &'static [u8] = b"\
const DEC_DIGITS_LUT: &[u8] = b"\
0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
@ -170,34 +113,16 @@ const DEC_DIGITS_LUT: &'static [u8] = b"\
// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_IntegerCommon {
($max_len:expr, $t:ident) => {
impl Integer for $t {
#[inline]
fn write(self, buf: &mut Buffer) -> &str {
unsafe {
debug_assert!($max_len <= I128_MAX_LEN);
let buf = mem::transmute::<&mut [u8; I128_MAX_LEN], &mut [u8; $max_len]>(
&mut buf.bytes,
);
let bytes = self.write_to(buf);
str::from_utf8_unchecked(bytes)
}
}
}
impl private::Sealed for $t {}
};
}
macro_rules! impl_Integer {
($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$(
impl_IntegerCommon!($max_len, $t);
impl Integer for $t {}
impl private::Sealed for $t {
type Buffer = [MaybeUninit<u8>; $max_len];
impl IntegerPrivate<[u8; $max_len]> for $t {
#[allow(unused_comparisons)]
#[inline]
fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
let is_nonnegative = self >= 0;
let mut n = if is_nonnegative {
self as $conv_fn
@ -206,7 +131,7 @@ macro_rules! impl_Integer {
(!(self as $conv_fn)).wrapping_add(1)
};
let mut curr = buf.len() as isize;
let buf_ptr = buf.as_mut_ptr();
let buf_ptr = buf.as_mut_ptr() as *mut u8;
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
unsafe {
@ -253,7 +178,8 @@ macro_rules! impl_Integer {
}
let len = buf.len() - curr as usize;
unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
let bytes = unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) };
unsafe { str::from_utf8_unchecked(bytes) }
}
}
)*};
@ -288,15 +214,16 @@ impl_Integer!(I32_MAX_LEN => isize, U32_MAX_LEN => usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(I64_MAX_LEN => isize, U64_MAX_LEN => usize as u64);
#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
($($max_len:expr => $t:ident),*) => {$(
impl_IntegerCommon!($max_len, $t);
impl Integer for $t {}
impl private::Sealed for $t {
type Buffer = [MaybeUninit<u8>; $max_len];
impl IntegerPrivate<[u8; $max_len]> for $t {
#[allow(unused_comparisons)]
#[inline]
fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
let is_nonnegative = self >= 0;
let n = if is_nonnegative {
self as u128
@ -305,13 +232,13 @@ macro_rules! impl_Integer128 {
(!(self as u128)).wrapping_add(1)
};
let mut curr = buf.len() as isize;
let buf_ptr = buf.as_mut_ptr();
let buf_ptr = buf.as_mut_ptr() as *mut u8;
unsafe {
// Divide by 10^19 which is the highest power less than 2^64.
let (n, rem) = udiv128::udivmod_1e19(n);
let buf1 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
curr -= rem.write_to(&mut *buf1).len() as isize;
let buf1 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [MaybeUninit<u8>; U64_MAX_LEN];
curr -= rem.write(&mut *buf1).len() as isize;
if n != 0 {
// Memset the base10 leading zeros of rem.
@ -321,8 +248,8 @@ macro_rules! impl_Integer128 {
// Divide by 10^19 again.
let (n, rem) = udiv128::udivmod_1e19(n);
let buf2 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
curr -= rem.write_to(&mut *buf2).len() as isize;
let buf2 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [MaybeUninit<u8>; U64_MAX_LEN];
curr -= rem.write(&mut *buf2).len() as isize;
if n != 0 {
// Memset the leading zeros.
@ -343,16 +270,15 @@ macro_rules! impl_Integer128 {
}
let len = buf.len() - curr as usize;
slice::from_raw_parts(buf_ptr.offset(curr), len)
let bytes = slice::from_raw_parts(buf_ptr.offset(curr), len);
str::from_utf8_unchecked(bytes)
}
}
}
)*};
}
#[cfg(all(feature = "i128"))]
const U128_MAX_LEN: usize = 39;
const I128_MAX_LEN: usize = 40;
#[cfg(all(feature = "i128"))]
impl_Integer128!(I128_MAX_LEN => i128, U128_MAX_LEN => u128);

View file

@ -12,7 +12,7 @@ fn u128_mulhi(x: u128, y: u128) -> u128 {
let high1 = m >> 64;
let m_lo = m as u64;
let high2 = x_hi as u128 * y_lo as u128 + m_lo as u128 >> 64;
let high2 = (x_hi as u128 * y_lo as u128 + m_lo as u128) >> 64;
x_hi as u128 * y_hi as u128 + high1 + high2
}
@ -32,9 +32,7 @@ pub fn udivmod_1e19(n: u128) -> (u128, u64) {
let quot = if n < 1 << 83 {
((n >> 19) as u64 / (d >> 19)) as u128
} else {
let factor =
(8507059173023461586_u64 as u128) << 64 | 10779635027931437427 as u128;
u128_mulhi(n, factor) >> 62
u128_mulhi(n, 156927543384667019095894735580191660403) >> 62
};
let rem = (n - quot * d as u128) as u64;

View file

@ -1,28 +1,13 @@
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, string_lit_as_bytes))]
#![allow(non_snake_case)]
extern crate itoa;
#![allow(clippy::cast_lossless)]
macro_rules! test {
(
($($name:ident($value:expr, $expected:expr))*) => {
$(
$(#[$attr:meta])*
$name:ident($value:expr, $expected:expr)
),*
) => {
$(
$(#[$attr])*
#[test]
fn $name() {
#[cfg(feature = "std")]
{
let mut buf = [b'\0'; 40];
let len = itoa::write(&mut buf[..], $value).unwrap();
assert_eq!(&buf[0..len], $expected.as_bytes());
}
let mut s = String::new();
itoa::fmt(&mut s, $value).unwrap();
let mut buffer = itoa::Buffer::new();
let s = buffer.format($value);
assert_eq!(s, $expected);
}
)*
@ -30,18 +15,15 @@ macro_rules! test {
}
test! {
test_u64_0(0u64, "0"),
test_u64_half(<u32>::max_value() as u64, "4294967295"),
test_u64_max(<u64>::max_value(), "18446744073709551615"),
test_i64_min(<i64>::min_value(), "-9223372036854775808"),
test_u64_0(0u64, "0")
test_u64_half(u32::max_value() as u64, "4294967295")
test_u64_max(u64::max_value(), "18446744073709551615")
test_i64_min(i64::min_value(), "-9223372036854775808")
test_i16_0(0i16, "0"),
test_i16_min(<i16>::min_value(), "-32768"),
test_i16_0(0i16, "0")
test_i16_min(i16::min_value(), "-32768")
#[cfg(feature = "i128")]
test_u128_0(0u128, "0"),
#[cfg(feature = "i128")]
test_u128_max(<u128>::max_value(), "340282366920938463463374607431768211455"),
#[cfg(feature = "i128")]
test_i128_min(<i128>::min_value(), "-170141183460469231731687303715884105728")
test_u128_0(0u128, "0")
test_u128_max(u128::max_value(), "340282366920938463463374607431768211455")
test_i128_min(i128::min_value(), "-170141183460469231731687303715884105728")
}