Expose some internals & make const

This commit is contained in:
Michael Pfaff 2024-05-20 18:58:32 -04:00
parent 547c143d50
commit 3ef6de9039
2 changed files with 26 additions and 16 deletions

View File

@ -40,6 +40,11 @@
clippy::needless_doctest_main,
clippy::unreadable_literal
)]
#![feature(const_intrinsic_copy)]
#![feature(const_mut_refs)]
#![feature(const_ptr_write)]
#![feature(const_trait_impl)]
#![feature(effects)]
mod udiv128;
@ -84,7 +89,7 @@ impl Buffer {
/// for efficiency.
#[inline]
#[cfg_attr(feature = "no-panic", no_panic)]
pub fn new() -> Buffer {
pub const fn new() -> Buffer {
let bytes = [MaybeUninit::<u8>::uninit(); I128_MAX_LEN];
Buffer { bytes }
}
@ -92,10 +97,10 @@ impl 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 {
pub const fn format<I: ~const Integer>(&mut self, i: I) -> &str {
i.write(unsafe {
&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].
///
/// 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.
mod private {
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
macro_rules! impl_Integer {
($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$(
impl Integer for $t {}
impl private::Sealed for $t {
impl const Integer for $t {
type Buffer = [MaybeUninit<u8>; $max_len];
#[allow(unused_comparisons)]
@ -192,6 +200,8 @@ macro_rules! impl_Integer {
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 {
($($max_len:expr => $t:ident),*) => {$(
impl Integer for $t {}
impl private::Sealed for $t {
impl const Integer for $t {
type Buffer = [MaybeUninit<u8>; $max_len];
#[allow(unused_comparisons)]
@ -286,6 +294,8 @@ macro_rules! impl_Integer128 {
}
}
}
impl private::Sealed for $t {}
)*};
}

View File

@ -4,7 +4,7 @@ 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 {
const fn u128_mulhi(x: u128, y: u128) -> u128 {
let x_lo = x as u64;
let x_hi = (x >> 64) as u64;
let y_lo = y as u64;
@ -31,7 +31,7 @@ fn u128_mulhi(x: u128, y: u128) -> u128 {
///
#[inline]
#[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 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;
debug_assert_eq!(quot, n / d as u128);
debug_assert_eq!(rem as u128, n % d as u128);
debug_assert!(quot == n / d as u128);
debug_assert!(rem as u128 == n % d as u128);
(quot, rem)
}