aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:07:25 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:07:25 +0000
commit6b63833c08ffb40a313f12f17a004ce27812023b (patch)
tree7063856b00fcda978586fe349806ad14c4e22c9c
parentf8b2f8df732e74644161f87122580e7012caec0e (diff)
parentc42c4eaf61c61127a4c1907f0171b453780fade4 (diff)
downloaditoa-aml_per_341614000.tar.gz
Change-Id: Ife6ad57831ad65773f44ca3b1aa0a6fe95e01558
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--.clippy.toml2
-rw-r--r--.github/workflows/ci.yml74
-rw-r--r--Android.bp18
-rw-r--r--Cargo.toml25
-rw-r--r--Cargo.toml.orig20
-rw-r--r--METADATA16
-rw-r--r--README.md73
-rw-r--r--TEST_MAPPING31
-rw-r--r--benches/bench.rs62
-rw-r--r--patches/std.diff15
-rw-r--r--src/lib.rs212
-rw-r--r--src/udiv128.rs11
-rw-r--r--tests/test.rs44
14 files changed, 253 insertions, 357 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 8da2e20..4917a0e 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "de247d6ac25d2e62d4cbd195f064ed4af35fd4eb"
- }
-}
+ "sha1": "ef4faeda61024dfb38b3897e46aeda8140828dc6"
+ },
+ "path_in_vcs": ""
+} \ No newline at end of file
diff --git a/.clippy.toml b/.clippy.toml
index 8e17d80..0a54853 100644
--- a/.clippy.toml
+++ b/.clippy.toml
@@ -1 +1 @@
-msrv = "1.0.0"
+msrv = "1.36.0"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e0f8585..d16faca 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,6 +5,12 @@ on:
pull_request:
schedule: [cron: "40 1 * * *"]
+permissions:
+ contents: read
+
+env:
+ RUSTFLAGS: -Dwarnings
+
jobs:
test:
name: Rust ${{matrix.rust}}
@@ -12,42 +18,62 @@ jobs:
strategy:
fail-fast: false
matrix:
- rust: [nightly, beta, stable, 1.26.0]
+ rust: [nightly, beta, stable, 1.36.0]
+ timeout-minutes: 45
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
- run: cargo build
- - run: cargo build --features i128
- - run: cargo test --features i128
- - run: cargo test --features i128 --release
- - run: cargo build --no-default-features --features i128
- - run: cargo test --tests --no-default-features --features i128
- - run: cargo test --tests --no-default-features --features i128 --release
- - run: cargo bench --no-run --features i128
+ - run: cargo test
+ - run: cargo test --release
+ - run: cargo build --no-default-features
+ - run: cargo test --tests --no-default-features
+ - run: cargo test --tests --no-default-features --release
+ - run: cargo build --tests --features no-panic --release
+ if: matrix.rust == 'nightly'
+ - run: cargo bench --no-run
if: matrix.rust == 'nightly'
- mintest:
- name: Rust 1.20.0
+ miri:
+ name: Miri
runs-on: ubuntu-latest
+ timeout-minutes: 45
steps:
- - uses: actions/checkout@v2
- - uses: dtolnay/rust-toolchain@1.20.0
- - run: cargo test
-
- msrv:
- name: Rust 1.0.0
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - uses: dtolnay/rust-toolchain@1.0.0
- - run: cargo build
+ - uses: actions/checkout@v3
+ - uses: dtolnay/rust-toolchain@miri
+ - run: cargo miri test
+ env:
+ MIRIFLAGS: -Zmiri-strict-provenance
clippy:
name: Clippy
runs-on: ubuntu-latest
+ if: github.event_name != 'pull_request'
+ timeout-minutes: 45
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@clippy
- - run: cargo clippy -- -Dclippy::all -Dclippy::pedantic
+ - run: cargo clippy --tests --benches -- -Dclippy::all -Dclippy::pedantic
+
+ fuzz:
+ name: Fuzz
+ runs-on: ubuntu-latest
+ timeout-minutes: 45
+ steps:
+ - uses: actions/checkout@v3
+ - uses: dtolnay/rust-toolchain@nightly
+ - uses: dtolnay/install@cargo-fuzz
+ - run: cargo fuzz build -O
+
+ outdated:
+ name: Outdated
+ runs-on: ubuntu-latest
+ if: github.event_name != 'pull_request'
+ timeout-minutes: 45
+ steps:
+ - uses: actions/checkout@v3
+ - uses: dtolnay/install@cargo-outdated
+ - run: cargo outdated --workspace --exit-code 1
+ - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1
diff --git a/Android.bp b/Android.bp
index 6027693..da9aca2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,18 +43,14 @@ rust_test {
host_supported: true,
crate_name: "test",
cargo_env_compat: true,
- cargo_pkg_version: "0.4.8",
+ cargo_pkg_version: "1.0.5",
srcs: ["tests/test.rs"],
test_suites: ["general-tests"],
auto_gen_config: true,
test_options: {
unit_test: true,
},
- edition: "2015",
- features: [
- "default",
- "std",
- ],
+ edition: "2018",
rustlibs: [
"libitoa",
],
@@ -65,15 +61,13 @@ rust_library {
host_supported: true,
crate_name: "itoa",
cargo_env_compat: true,
- cargo_pkg_version: "0.4.8",
+ cargo_pkg_version: "1.0.5",
srcs: ["src/lib.rs"],
- edition: "2015",
- features: [
- "default",
- "std",
- ],
+ edition: "2018",
apex_available: [
"//apex_available:platform",
"com.android.virt",
],
+ product_available: true,
+ vendor_available: true,
}
diff --git a/Cargo.toml b/Cargo.toml
index 02b4382..86c10b6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,20 +10,29 @@
# See Cargo.toml.orig for the original contents.
[package]
+edition = "2018"
+rust-version = "1.36"
name = "itoa"
-version = "0.4.8"
+version = "1.0.5"
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"]
+keywords = ["integer"]
+categories = [
+ "value-formatting",
+ "no-std",
+]
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 = []
+[dependencies.no-panic]
+version = "0.1"
+optional = true
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 2781d7c..a24b8e4 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,19 +1,19 @@
[package]
name = "itoa"
-version = "0.4.8" # remember to update html_root_url
+version = "1.0.5" # remember to update html_root_url
authors = ["David Tolnay <dtolnay@gmail.com>"]
+categories = ["value-formatting", "no-std"]
+description = "Fast integer primitive to string conversion"
+documentation = "https://docs.rs/itoa"
+edition = "2018"
+exclude = ["performance.png", "chart/**"]
+keywords = ["integer"]
license = "MIT OR Apache-2.0"
-description = "Fast functions for printing integer primitives to an io::Write"
repository = "https://github.com/dtolnay/itoa"
-documentation = "https://docs.rs/itoa"
-categories = ["value-formatting"]
-readme = "README.md"
-exclude = ["performance.png"]
+rust-version = "1.36"
-[features]
-default = ["std"]
-i128 = []
-std = []
+[dependencies]
+no-panic = { version = "0.1", optional = true }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
diff --git a/METADATA b/METADATA
index e9cdb68..84449ae 100644
--- a/METADATA
+++ b/METADATA
@@ -1,5 +1,9 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/itoa
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
name: "itoa"
-description: "Fast functions for printing integer primitives to an io::Write"
+description: "Fast integer primitive to string conversion"
third_party {
url {
type: HOMEPAGE
@@ -7,13 +11,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/itoa/itoa-0.4.8.crate"
+ value: "https://static.crates.io/crates/itoa/itoa-1.0.5.crate"
}
- version: "0.4.8"
+ version: "1.0.5"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 9
- day: 22
+ year: 2023
+ month: 2
+ day: 2
}
}
diff --git a/README.md b/README.md
index cff3bb3..5728fb7 100644
--- a/README.md
+++ b/README.md
@@ -3,80 +3,43 @@ itoa
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/itoa-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/itoa)
[<img alt="crates.io" src="https://img.shields.io/crates/v/itoa.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/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)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-itoa-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/itoa)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/itoa/ci.yml?branch=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>
-## Performance (lower is better)
-
-![performance](https://raw.githubusercontent.com/dtolnay/itoa/master/performance.png)
-
-<br>
-
-## Examples
+## Example
```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(())
+fn main() {
+ let mut buffer = itoa::Buffer::new();
+ let printed = buffer.format(128u64);
+ assert_eq!(printed, "128");
}
```
-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;
-```
+<br>
-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.
+## Performance (lower is better)
-The `write` function is only available when the `std` feature is enabled
-(default is enabled). The return value gives the number of bytes written.
+![performance](https://raw.githubusercontent.com/dtolnay/itoa/master/performance.png)
<br>
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 9095ded..c57fb45 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -24,40 +24,31 @@
},
{
"path": "external/rust/crates/url"
- }
- ],
- "presubmit": [
+ },
{
- "name": "ZipFuseTest"
+ "path": "packages/modules/Virtualization/authfs"
},
{
- "name": "authfs_device_test_src_lib"
+ "path": "packages/modules/Virtualization/microdroid_manager"
},
{
- "name": "itoa_test_tests_test"
+ "path": "packages/modules/Virtualization/virtualizationmanager"
},
{
- "name": "microdroid_manager_test"
+ "path": "packages/modules/Virtualization/vm"
},
{
- "name": "virtualizationservice_device_test"
+ "path": "packages/modules/Virtualization/zipfuse"
}
],
- "presubmit-rust": [
- {
- "name": "ZipFuseTest"
- },
- {
- "name": "authfs_device_test_src_lib"
- },
+ "presubmit": [
{
"name": "itoa_test_tests_test"
- },
- {
- "name": "microdroid_manager_test"
- },
+ }
+ ],
+ "presubmit-rust": [
{
- "name": "virtualizationservice_device_test"
+ "name": "itoa_test_tests_test"
}
]
}
diff --git a/benches/bench.rs b/benches/bench.rs
index a9ed517..acd2a0c 100644
--- a/benches/bench.rs
+++ b/benches/bench.rs
@@ -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);
- 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);
+ let mut buffer = itoa::Buffer::new();
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())
}
diff --git a/patches/std.diff b/patches/std.diff
new file mode 100644
index 0000000..e335aef
--- /dev/null
+++ b/patches/std.diff
@@ -0,0 +1,15 @@
+diff --git a/src/lib.rs b/src/lib.rs
+index 7c3616e..cbcd374 100644
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -46,6 +46,10 @@ use core::{ptr, slice, str};
+ #[cfg(feature = "no-panic")]
+ use no_panic::no_panic;
+
++/// Local Android change: Use std to allow building as a dylib.
++#[cfg(android_dylib)]
++extern crate std;
++
+ /// A correctly sized stack allocation for the formatted integer to be written
+ /// into.
+ ///
diff --git a/src/lib.rs b/src/lib.rs
index 8d4582e..c03064f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,102 +2,56 @@
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
-//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
//!
//! <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>
-//!
-//! # 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]);
+//! # Example
//!
-//! Ok(())
+//! ```
+//! fn main() {
+//! let mut buffer = itoa::Buffer::new();
+//! let printed = buffer.format(128u64);
+//! assert_eq!(printed, "128");
//! }
+//! ```
//!
-//! fn demo_itoa_fmt() -> fmt::Result {
-//! // Write to a string.
-//! let mut s = String::new();
-//! itoa::fmt(&mut s, 128u64)?;
-//! println!("{}", s);
+//! # Performance (lower is better)
//!
-//! Ok(())
-//! }
-//! ```
+//! ![performance](https://raw.githubusercontent.com/dtolnay/itoa/master/performance.png)
-#![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.5")]
+#![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};
-
-#[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),
- }
-}
+use core::mem::{self, MaybeUninit};
+use core::{ptr, slice, str};
+#[cfg(feature = "no-panic")]
+use no_panic::no_panic;
-/// 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))
-}
+/// Local Android change: Use std to allow building as a dylib.
+#[cfg(android_dylib)]
+extern crate std;
-/// A safe API for formatting integers to text.
+/// A correctly sized stack allocation for the formatted integer to be written
+/// into.
///
/// # Example
///
@@ -106,9 +60,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 +82,37 @@ impl Buffer {
/// This is a cheap operation; you don't need to worry about reusing buffers
/// for efficiency.
#[inline]
- #[allow(deprecated)]
+ #[cfg_attr(feature = "no-panic", no_panic)]
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.
+ #[cfg_attr(feature = "no-panic", no_panic)]
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)
+ })
}
}
-// Seal to prevent downstream implementations of the Integer trait.
-mod private {
- pub trait Sealed {}
-}
-
-/// An integer that can be formatted by `itoa::write` and `itoa::fmt`.
+/// 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 {
- // Not public API.
- #[doc(hidden)]
- fn write(self, buf: &mut Buffer) -> &str;
-}
+pub trait Integer: private::Sealed {}
-trait IntegerPrivate<B> {
- fn write_to(self, buf: &mut B) -> &[u8];
+// Seal to prevent downstream implementations of the Integer trait.
+mod private {
+ pub trait Sealed: Copy {
+ type Buffer: 'static;
+ fn write(self, buf: &mut Self::Buffer) -> &str;
+ }
}
-const DEC_DIGITS_LUT: &'static [u8] = b"\
+const DEC_DIGITS_LUT: &[u8] = b"\
0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
@@ -170,34 +121,17 @@ 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] {
+ #[cfg_attr(feature = "no-panic", no_panic)]
+ 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 +140,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 +187,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 +223,17 @@ 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] {
+ #[cfg_attr(feature = "no-panic", no_panic)]
+ 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 +242,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 +258,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 +280,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);
diff --git a/src/udiv128.rs b/src/udiv128.rs
index 617c1c1..0587047 100644
--- a/src/udiv128.rs
+++ b/src/udiv128.rs
@@ -1,5 +1,9 @@
+#[cfg(feature = "no-panic")]
+use no_panic::no_panic;
+
/// Multiply unsigned 128 bit integers, return upper 128 bits of the result
#[inline]
+#[cfg_attr(feature = "no-panic", no_panic)]
fn u128_mulhi(x: u128, y: u128) -> u128 {
let x_lo = x as u64;
let x_hi = (x >> 64) as u64;
@@ -12,7 +16,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
}
@@ -26,15 +30,14 @@ fn u128_mulhi(x: u128, y: u128) -> u128 {
/// Implementation, 1994, pp. 61–72
///
#[inline]
+#[cfg_attr(feature = "no-panic", no_panic)]
pub fn udivmod_1e19(n: u128) -> (u128, u64) {
let d = 10_000_000_000_000_000_000_u64; // 10^19
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;
diff --git a/tests/test.rs b/tests/test.rs
index 5355868..1d7e8cb 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -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 {
- (
- $(
- $(#[$attr:meta])*
- $name:ident($value:expr, $expected:expr)
- ),*
- ) => {
+ ($($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")
}