#![cfg(feature = "compact")]
#![doc(hidden)]
use core::mem;
use lexical_util::algorithm::copy_to_dst;
use lexical_util::assert::debug_assert_radix;
use lexical_util::digit::digit_to_char;
use lexical_util::num::{AsCast, UnsignedInteger};
pub unsafe fn write_digits<T: UnsignedInteger>(
mut value: T,
radix: u32,
buffer: &mut [u8],
mut index: usize,
) -> usize {
debug_assert_radix(radix);
let radix = T::from_u32(radix);
while value >= radix {
let r = value % radix;
value /= radix;
index -= 1;
unsafe { index_unchecked_mut!(buffer[index]) = digit_to_char(u32::as_cast(r)) };
}
let r = value % radix;
index -= 1;
unsafe { index_unchecked_mut!(buffer[index]) = digit_to_char(u32::as_cast(r)) };
index
}
pub trait Compact: UnsignedInteger {
unsafe fn compact(self, radix: u32, buffer: &mut [u8]) -> usize {
debug_assert!(Self::BITS <= 128);
let mut digits: mem::MaybeUninit<[u8; 128]> = mem::MaybeUninit::uninit();
unsafe {
let digits = &mut *digits.as_mut_ptr();
let length = digits.len();
let index = write_digits(self, radix, digits, length);
copy_to_dst(buffer, &mut index_unchecked_mut!(digits[index..]))
}
}
}
macro_rules! compact_impl {
($($t:ty)*) => ($(
impl Compact for $t {}
)*)
}
compact_impl! { u8 u16 u32 u64 u128 usize }