Merge pull request #14 from glandium/master

Support no_std
This commit is contained in:
David Tolnay 2018-03-18 00:14:19 -07:00 committed by GitHub
commit c1c4f7320e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 17 deletions

View File

@ -13,5 +13,7 @@ matrix:
script: script:
- cargo build --verbose --features "$FEATURES" - cargo build --verbose --features "$FEATURES"
- cargo test --verbose --features "$FEATURES" - cargo test --verbose --features "$FEATURES"
- cargo build --verbose --no-default-features --features "$FEATURES"
- cargo test --verbose --no-default-features --features "$FEATURES"
- if [ "$BUILD_BENCH" == "true" ]; then cargo bench --verbose --no-run --features "$FEATURES"; fi - if [ "$BUILD_BENCH" == "true" ]; then cargo bench --verbose --no-run --features "$FEATURES"; fi

View File

@ -11,4 +11,6 @@ readme = "README.md"
exclude = ["performance.png"] exclude = ["performance.png"]
[features] [features]
default = ["std"]
i128 = [] i128 = []
std = []

View File

@ -5,7 +5,8 @@ itoa
[![Latest Version](https://img.shields.io/crates/v/itoa.svg)](https://crates.io/crates/itoa) [![Latest Version](https://img.shields.io/crates/v/itoa.svg)](https://crates.io/crates/itoa)
This crate provides fast functions for printing integer primitives to an This crate provides fast functions for printing integer primitives to an
[`io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html). The [`io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html) or a
[`fmt::Write`](https://doc.rust-lang.org/core/fmt/trait.Write.html). The
implementation comes straight from implementation comes straight from
[libcore](https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L201-L254) [libcore](https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L201-L254)
but avoids the performance penalty of going through but avoids the performance penalty of going through
@ -32,12 +33,19 @@ println!("{:?}", buf);
let mut bytes = [b'\0'; 20]; let mut bytes = [b'\0'; 20];
let n = itoa::write(&mut bytes[..], 128u64)?; let n = itoa::write(&mut bytes[..], 128u64)?;
println!("{:?}", &bytes[..n]); println!("{:?}", &bytes[..n]);
// write to a String
let mut s = String::new();
itoa::fmt(&mut s, 128u64)?;
println!("{}", s);
``` ```
The function signature is: The function signatures are:
```rust ```rust
fn write<W: io::Write, V: itoa::Integer>(writer: W, value: V) -> io::Result<usize> 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`, where `itoa::Integer` is implemented for `i8`, `u8`, `i16`, `u16`, `i32`, `u32`,
@ -45,6 +53,9 @@ where `itoa::Integer` is implemented for `i8`, `u8`, `i16`, `u16`, `i32`, `u32`,
only available with the nightly compiler when the `i128` feature is enabled for only available with the nightly compiler when the `i128` feature is enabled for
this crate. The return value gives the number of bytes written. this crate. The return value gives the number of bytes written.
The `write` function is only available when the `std` feature is enabled
(default is enabled).
## Dependency ## Dependency
Itoa is available on [crates.io](https://crates.io/crates/itoa). Use the Itoa is available on [crates.io](https://crates.io/crates/itoa). Use the

View File

@ -8,6 +8,8 @@
#![doc(html_root_url = "https://docs.rs/itoa/0.3.4")] #![doc(html_root_url = "https://docs.rs/itoa/0.3.4")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "i128", feature(i128_type, i128))] #![cfg_attr(feature = "i128", feature(i128_type, i128))]
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, unreadable_literal))] #![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, unreadable_literal))]
@ -15,15 +17,33 @@
#[cfg(feature = "i128")] #[cfg(feature = "i128")]
mod udiv128; mod udiv128;
use std::{io, mem, ptr, slice}; #[cfg(feature = "std")]
use std::{fmt, io, mem, ptr, slice, str};
#[cfg(not(feature = "std"))]
use core::{fmt, mem, ptr, slice, str};
#[cfg(feature = "std")]
#[inline] #[inline]
pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> { pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> {
value.write(wr) value.write(wr)
} }
pub trait Integer { #[inline]
pub fn fmt<W: fmt::Write, V: Integer>(wr: W, value: V) -> fmt::Result {
value.fmt(wr)
}
// Seal to prevent downstream implementations of the Integer trait.
mod private {
pub trait Sealed {}
}
pub trait Integer: private::Sealed {
#[cfg(feature = "std")]
fn write<W: io::Write>(self, W) -> io::Result<usize>; fn write<W: io::Write>(self, W) -> io::Result<usize>;
fn fmt<W: fmt::Write>(self, W) -> fmt::Result;
} }
trait IntegerPrivate { trait IntegerPrivate {
@ -41,16 +61,31 @@ const MAX_LEN: usize = 40; // i128::MIN (including minus sign)
// Adaptation of the original implementation at // Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266 // https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_Integer { macro_rules! impl_IntegerCommon {
($($t:ident),* as $conv_fn:ident) => {$( ($t:ident) => {
impl Integer for $t { impl Integer for $t {
#[cfg(feature = "std")]
fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> { fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
let mut buf = unsafe { mem::uninitialized() }; let mut buf = unsafe { mem::uninitialized() };
let bytes = self.write_to(&mut buf); let bytes = self.write_to(&mut buf);
try!(wr.write_all(bytes)); try!(wr.write_all(bytes));
Ok(bytes.len()) Ok(bytes.len())
} }
fn fmt<W: fmt::Write>(self, mut wr: W) -> fmt::Result {
let mut buf = unsafe { mem::uninitialized() };
let bytes = self.write_to(&mut buf);
wr.write_str(unsafe { str::from_utf8_unchecked(bytes) })
} }
}
impl private::Sealed for $t {}
};
}
macro_rules! impl_Integer {
($($t:ident),* as $conv_fn:ident) => {$(
impl_IntegerCommon!($t);
impl IntegerPrivate for $t { impl IntegerPrivate for $t {
#[allow(unused_comparisons)] #[allow(unused_comparisons)]
@ -128,14 +163,7 @@ impl_Integer!(isize, usize as u64);
#[cfg(all(feature = "i128"))] #[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 { macro_rules! impl_Integer128 {
($($t:ident),*) => {$( ($($t:ident),*) => {$(
impl Integer for $t { impl_IntegerCommon!($t);
fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
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 { impl IntegerPrivate for $t {
#[allow(unused_comparisons)] #[allow(unused_comparisons)]

View File

@ -17,10 +17,17 @@ macro_rules! test {
$(#[$attr])* $(#[$attr])*
#[test] #[test]
fn $name() { fn $name() {
#[cfg(feature = "std")]
{
let mut buf = [b'\0'; 40]; let mut buf = [b'\0'; 40];
let len = itoa::write(&mut buf[..], $value).unwrap(); let len = itoa::write(&mut buf[..], $value).unwrap();
assert_eq!(&buf[0..len], $expected.as_bytes()); assert_eq!(&buf[0..len], $expected.as_bytes());
} }
let mut s = String::new();
itoa::fmt(&mut s, $value).unwrap();
assert_eq!(s, $expected);
}
)* )*
} }
} }