Expose some internals & make const
This commit is contained in:
parent
547c143d50
commit
3ef6de9039
34
src/lib.rs
34
src/lib.rs
|
@ -40,6 +40,11 @@
|
||||||
clippy::needless_doctest_main,
|
clippy::needless_doctest_main,
|
||||||
clippy::unreadable_literal
|
clippy::unreadable_literal
|
||||||
)]
|
)]
|
||||||
|
#![feature(const_intrinsic_copy)]
|
||||||
|
#![feature(const_mut_refs)]
|
||||||
|
#![feature(const_ptr_write)]
|
||||||
|
#![feature(const_trait_impl)]
|
||||||
|
#![feature(effects)]
|
||||||
|
|
||||||
mod udiv128;
|
mod udiv128;
|
||||||
|
|
||||||
|
@ -84,7 +89,7 @@ impl Buffer {
|
||||||
/// for efficiency.
|
/// for efficiency.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||||
pub fn new() -> Buffer {
|
pub const fn new() -> Buffer {
|
||||||
let bytes = [MaybeUninit::<u8>::uninit(); I128_MAX_LEN];
|
let bytes = [MaybeUninit::<u8>::uninit(); I128_MAX_LEN];
|
||||||
Buffer { bytes }
|
Buffer { bytes }
|
||||||
}
|
}
|
||||||
|
@ -92,10 +97,10 @@ impl Buffer {
|
||||||
/// Print an integer into this buffer and return a reference to its string
|
/// Print an integer into this buffer and return a reference to its string
|
||||||
/// representation within the buffer.
|
/// representation within the buffer.
|
||||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||||
pub fn format<I: Integer>(&mut self, i: I) -> &str {
|
pub const fn format<I: ~const Integer>(&mut self, i: I) -> &str {
|
||||||
i.write(unsafe {
|
i.write(unsafe {
|
||||||
&mut *(&mut self.bytes as *mut [MaybeUninit<u8>; I128_MAX_LEN]
|
&mut *(&mut self.bytes as *mut [MaybeUninit<u8>; I128_MAX_LEN]
|
||||||
as *mut <I as private::Sealed>::Buffer)
|
as *mut I::Buffer)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,13 +108,18 @@ impl Buffer {
|
||||||
/// An integer that can be written into an [`itoa::Buffer`][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.
|
/// This trait is sealed and cannot be implemented for types outside of itoa.
|
||||||
pub trait Integer: private::Sealed {}
|
#[const_trait]
|
||||||
|
pub trait Integer: private::Sealed {
|
||||||
|
#[doc(hidden)]
|
||||||
|
type Buffer: 'static;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn write(self, buf: &mut Self::Buffer) -> &str;
|
||||||
|
}
|
||||||
|
|
||||||
// Seal to prevent downstream implementations of the Integer trait.
|
// Seal to prevent downstream implementations of the Integer trait.
|
||||||
mod private {
|
mod private {
|
||||||
pub trait Sealed: Copy {
|
pub trait Sealed: Copy {
|
||||||
type Buffer: 'static;
|
|
||||||
fn write(self, buf: &mut Self::Buffer) -> &str;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,9 +134,7 @@ const DEC_DIGITS_LUT: &[u8] = b"\
|
||||||
// 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_Integer {
|
||||||
($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$(
|
($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$(
|
||||||
impl Integer for $t {}
|
impl const Integer for $t {
|
||||||
|
|
||||||
impl private::Sealed for $t {
|
|
||||||
type Buffer = [MaybeUninit<u8>; $max_len];
|
type Buffer = [MaybeUninit<u8>; $max_len];
|
||||||
|
|
||||||
#[allow(unused_comparisons)]
|
#[allow(unused_comparisons)]
|
||||||
|
@ -192,6 +200,8 @@ macro_rules! impl_Integer {
|
||||||
unsafe { str::from_utf8_unchecked(bytes) }
|
unsafe { str::from_utf8_unchecked(bytes) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl private::Sealed for $t {}
|
||||||
)*};
|
)*};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,9 +236,7 @@ impl_Integer!(I64_MAX_LEN => isize, U64_MAX_LEN => usize as u64);
|
||||||
|
|
||||||
macro_rules! impl_Integer128 {
|
macro_rules! impl_Integer128 {
|
||||||
($($max_len:expr => $t:ident),*) => {$(
|
($($max_len:expr => $t:ident),*) => {$(
|
||||||
impl Integer for $t {}
|
impl const Integer for $t {
|
||||||
|
|
||||||
impl private::Sealed for $t {
|
|
||||||
type Buffer = [MaybeUninit<u8>; $max_len];
|
type Buffer = [MaybeUninit<u8>; $max_len];
|
||||||
|
|
||||||
#[allow(unused_comparisons)]
|
#[allow(unused_comparisons)]
|
||||||
|
@ -286,6 +294,8 @@ macro_rules! impl_Integer128 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl private::Sealed for $t {}
|
||||||
)*};
|
)*};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use no_panic::no_panic;
|
||||||
/// Multiply unsigned 128 bit integers, return upper 128 bits of the result
|
/// Multiply unsigned 128 bit integers, return upper 128 bits of the result
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||||
fn u128_mulhi(x: u128, y: u128) -> u128 {
|
const fn u128_mulhi(x: u128, y: u128) -> u128 {
|
||||||
let x_lo = x as u64;
|
let x_lo = x as u64;
|
||||||
let x_hi = (x >> 64) as u64;
|
let x_hi = (x >> 64) as u64;
|
||||||
let y_lo = y as u64;
|
let y_lo = y as u64;
|
||||||
|
@ -31,7 +31,7 @@ fn u128_mulhi(x: u128, y: u128) -> u128 {
|
||||||
///
|
///
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg_attr(feature = "no-panic", no_panic)]
|
#[cfg_attr(feature = "no-panic", no_panic)]
|
||||||
pub fn udivmod_1e19(n: u128) -> (u128, u64) {
|
pub const fn udivmod_1e19(n: u128) -> (u128, u64) {
|
||||||
let d = 10_000_000_000_000_000_000_u64; // 10^19
|
let d = 10_000_000_000_000_000_000_u64; // 10^19
|
||||||
|
|
||||||
let quot = if n < 1 << 83 {
|
let quot = if n < 1 << 83 {
|
||||||
|
@ -41,8 +41,8 @@ pub fn udivmod_1e19(n: u128) -> (u128, u64) {
|
||||||
};
|
};
|
||||||
|
|
||||||
let rem = (n - quot * d as u128) as u64;
|
let rem = (n - quot * d as u128) as u64;
|
||||||
debug_assert_eq!(quot, n / d as u128);
|
debug_assert!(quot == n / d as u128);
|
||||||
debug_assert_eq!(rem as u128, n % d as u128);
|
debug_assert!(rem as u128 == n % d as u128);
|
||||||
|
|
||||||
(quot, rem)
|
(quot, rem)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue