use core::mem::{self, MaybeUninit}; use core::{ptr, slice, str}; #[cfg(feature = "no-panic")] use no_panic::no_panic;
/// A correctly sized stack allocation for the formatted integer to be written /// into. /// /// # Example /// /// ``` /// let mut buffer = itoa::Buffer::new(); /// let printed = buffer.format(1234); /// assert_eq!(printed, "1234"); /// ``` pubstruct Buffer {
bytes: [MaybeUninit<u8>; I128_MAX_LEN],
}
impl Buffer { /// This is a cheap operation; you don't need to worry about reusing buffers /// for efficiency. #[inline] #[cfg_attr(feature = "no-panic", no_panic)] pubfn new() -> Buffer { 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. #[cfg_attr(feature = "no-panic", no_panic)] pubfn format<I: Integer>(&mutself, i: I) -> &str {
i.write(unsafe {
&mut *(&mutself.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. pubtrait Integer: private::Sealed {}
// Seal to prevent downstream implementations of the Integer trait. mod private { pubtrait Sealed: Copy { type Buffer: 'static; fn write(self, buf: &mutSelf::Buffer) -> &str;
}
}
impl private::Sealed for $t { type Buffer = [MaybeUninit<u8>; $max_len];
#[allow(unused_comparisons)] #[inline] #[cfg_attr(feature = "no-panic", no_panic)] fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str { let is_nonnegative = self >= 0; letmut n = if is_nonnegative { selfas $conv_fn
} else { // convert the negative num to positive by summing 1 to it's 2 complement
(!(selfas $conv_fn)).wrapping_add(1)
}; letmut curr = buf.len() as isize; let buf_ptr = buf.as_mut_ptr() as *mut u8; let lut_ptr = DEC_DIGITS_LUT.as_ptr();
unsafe { // need at least 16 bits for the 4-characters-at-a-time to work. if mem::size_of::<$t>() >= 2 { // eagerly decode 4 characters at a time while n >= 10000 { let rem = (n % 10000) as isize;
n /= 10000;
impl private::Sealed for $t { type Buffer = [MaybeUninit<u8>; $max_len];
#[allow(unused_comparisons)] #[inline] #[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 { selfas u128
} else { // convert the negative num to positive by summing 1 to it's 2 complement
(!(selfas u128)).wrapping_add(1)
}; letmut curr = buf.len() as isize; 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 [MaybeUninit<u8>; U64_MAX_LEN];
curr -= rem.write(&mut *buf1).len() as isize;
if n != 0 { // Memset the base10 leading zeros of rem. let target = buf.len() as isize - 19;
ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
curr = target;
// 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 [MaybeUninit<u8>; U64_MAX_LEN];
curr -= rem.write(&mut *buf2).len() as isize;
if n != 0 { // Memset the leading zeros. let target = buf.len() as isize - 38;
ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
curr = target;
// There is at most one digit left // because u128::max / 10^19 / 10^19 is 3.
curr -= 1;
*buf_ptr.offset(curr) = (n as u8) + b'0';
}
}
if !is_nonnegative {
curr -= 1;
*buf_ptr.offset(curr) = b'-';
}
let len = buf.len() - curr as usize; let bytes = slice::from_raw_parts(buf_ptr.offset(curr), len);
str::from_utf8_unchecked(bytes)
}
}
}
)*};
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.