use super::*;
use crate::{Cmp, StringU8, TextLut, is};
impl Digits<u128> {
pub const MAX_DIGITS_10: u8 = 39;
pub const MAX_DIGITS_16: u8 = 32;
#[doc = DOC_COUNT_DIGITS_10!()]
#[must_use]
pub const fn count_digits10(self) -> u8 {
is![self.0 == 0, 1, self.0.ilog10() as u8 + 1]
}
#[doc = DOC_COUNT_DIGITS_16!()]
pub const fn count_digits16(self) -> u8 {
is![self.0 == 0, 1, ((self.0.ilog2() + 4) / 4) as u8]
}
#[must_use]
#[inline(always)]
pub const fn digit_at_index10(self, index: u8) -> u8 {
is![index >= self.count_digits10(), return b'0'];
let power = TextLut::POWERS10[index as usize];
(self.0 / power % 10) as u8 + b'0'
}
#[must_use]
pub const fn digit_at_index10_checked(self, index: u8) -> Option<u8> {
is![index >= self.count_digits10(), return None];
let power = TextLut::POWERS10[index as usize];
Some((self.0 / power % 10) as u8 + b'0')
}
#[must_use]
pub const fn digit_at_index16(self, index: u8) -> u8 {
let shift = index as u32 * 4;
let digit = (self.0.unbounded_shr(shift) & 0xF) as usize;
TextLut::DIGITS_BASE36[digit]
}
#[must_use]
pub const fn digit_at_index16_checked(self, index: u8) -> Option<u8> {
is![index >= self.count_digits16(), return None];
let shift = index as u32 * 4;
let digit = (self.0.unbounded_shr(shift) & 0xF) as usize;
Some(TextLut::DIGITS_BASE36[digit])
}
#[must_use]
pub const fn digit_value_at_index10(self, index: u8) -> u8 {
is![index >= self.count_digits10(), return 0];
let power = TextLut::POWERS10[index as usize];
(self.0 / power % 10) as u8
}
#[must_use]
pub const fn digit_value_at_index10_checked(self, index: u8) -> Option<u8> {
is![index >= self.count_digits10(), return None];
let power = TextLut::POWERS10[index as usize];
Some((self.0 / power % 10) as u8)
}
#[must_use]
#[inline(always)]
pub const fn digit_value_at_index16(self, index: u8) -> u8 {
let shift = index as u32 * 4;
(self.0.unbounded_shr(shift) & 0xF) as u8
}
#[must_use]
pub const fn digit_value_at_index16_checked(self, index: u8) -> Option<u8> {
is![index < self.count_digits16(), Some(self.digit_value_at_index16(index)), None]
}
#[doc = DOC_DIGIT_AT_POWER_10!()]
#[must_use]
pub(crate) const fn digit_at_power10(self, divisor: u128) -> u8 {
(self.0 / divisor % 10) as u8 + b'0'
}
#[doc = DOC_DIGIT_AT_POWER_16!()]
#[must_use]
#[allow(clippy::unreadable_literal)]
pub(crate) const fn digit_at_power16(self, divisor: u128) -> u8 {
let digit = match divisor {
0x1 => self.0 & 0xF,
0x10 => (self.0 >> 4) & 0xF,
0x100 => (self.0 >> 8) & 0xF,
0x1000 => (self.0 >> 12) & 0xF,
0x10000 => (self.0 >> 16) & 0xF,
0x100000 => (self.0 >> 20) & 0xF,
0x1000000 => (self.0 >> 24) & 0xF,
0x10000000 => (self.0 >> 28) & 0xF,
_ => (self.0 / divisor) % 16,
};
TextLut::DIGITS_BASE36[digit as usize]
}
#[must_use]
#[allow(clippy::unreadable_literal)]
pub const fn digits10(self) -> [u8; Self::MAX_DIGITS_10 as usize] {
[
self.digit_at_power10(100000000000000000000000000000000000000), self.digit_at_power10(10000000000000000000000000000000000000),
self.digit_at_power10(1000000000000000000000000000000000000),
self.digit_at_power10(100000000000000000000000000000000000),
self.digit_at_power10(10000000000000000000000000000000000),
self.digit_at_power10(1000000000000000000000000000000000),
self.digit_at_power10(100000000000000000000000000000000),
self.digit_at_power10(10000000000000000000000000000000),
self.digit_at_power10(1000000000000000000000000000000),
self.digit_at_power10(100000000000000000000000000000), self.digit_at_power10(10000000000000000000000000000),
self.digit_at_power10(1000000000000000000000000000),
self.digit_at_power10(100000000000000000000000000),
self.digit_at_power10(10000000000000000000000000),
self.digit_at_power10(1000000000000000000000000),
self.digit_at_power10(100000000000000000000000),
self.digit_at_power10(10000000000000000000000),
self.digit_at_power10(1000000000000000000000),
self.digit_at_power10(100000000000000000000),
self.digit_at_power10(10000000000000000000), self.digit_at_power10(1000000000000000000),
self.digit_at_power10(100000000000000000),
self.digit_at_power10(10000000000000000),
self.digit_at_power10(1000000000000000),
self.digit_at_power10(100000000000000),
self.digit_at_power10(10000000000000),
self.digit_at_power10(1000000000000),
self.digit_at_power10(100000000000),
self.digit_at_power10(10000000000),
self.digit_at_power10(1000000000), self.digit_at_power10(100000000),
self.digit_at_power10(10000000),
self.digit_at_power10(1000000),
self.digit_at_power10(100000),
self.digit_at_power10(10000),
self.digit_at_power10(1000),
self.digit_at_power10(100),
self.digit_at_power10(10),
self.digit_at_power10(1),
]
}
#[allow(clippy::unreadable_literal)]
pub const fn digits16(self) -> [u8; Self::MAX_DIGITS_16 as usize] {
[
self.digit_at_power16(0x10000000000000000000000000000000), self.digit_at_power16(0x1000000000000000000000000000000),
self.digit_at_power16(0x100000000000000000000000000000),
self.digit_at_power16(0x10000000000000000000000000000),
self.digit_at_power16(0x1000000000000000000000000000),
self.digit_at_power16(0x100000000000000000000000000),
self.digit_at_power16(0x10000000000000000000000000),
self.digit_at_power16(0x1000000000000000000000000),
self.digit_at_power16(0x100000000000000000000000),
self.digit_at_power16(0x10000000000000000000000),
self.digit_at_power16(0x1000000000000000000000),
self.digit_at_power16(0x100000000000000000000),
self.digit_at_power16(0x10000000000000000000),
self.digit_at_power16(0x1000000000000000000),
self.digit_at_power16(0x100000000000000000),
self.digit_at_power16(0x10000000000000000),
self.digit_at_power16(0x1000000000000000),
self.digit_at_power16(0x100000000000000),
self.digit_at_power16(0x10000000000000),
self.digit_at_power16(0x1000000000000),
self.digit_at_power16(0x100000000000),
self.digit_at_power16(0x10000000000),
self.digit_at_power16(0x1000000000),
self.digit_at_power16(0x100000000),
self.digit_at_power16(0x10000000),
self.digit_at_power16(0x1000000),
self.digit_at_power16(0x100000),
self.digit_at_power16(0x10000),
self.digit_at_power16(0x1000),
self.digit_at_power16(0x100),
self.digit_at_power16(0x10),
self.digit_at_power16(0x1),
]
}
#[doc = DOC_WRITE_DIGITS_10!(39)]
pub const fn write_digits10(self, buf: &mut [u8], offset: usize) -> usize {
let mut n = self.0;
if n == 0 {
is![offset < buf.len(), {
buf[offset] = b'0';
return 1;
}];
return 0;
}
let digits = n.ilog10() as usize + 1;
is![offset + digits > buf.len(), return 0];
let mut pos = offset + digits;
while n >= 100 {
pos -= 2;
let idx = ((n % 100) * 2) as usize;
buf[pos] = TextLut::DECIMAL_PAIRS[idx];
buf[pos + 1] = TextLut::DECIMAL_PAIRS[idx + 1];
n /= 100;
}
if n < 10 {
pos -= 1;
buf[pos] = n as u8 + b'0';
} else {
pos -= 2;
let idx = (n * 2) as usize;
buf[pos] = TextLut::DECIMAL_PAIRS[idx];
buf[pos + 1] = TextLut::DECIMAL_PAIRS[idx + 1];
}
digits
}
#[doc = DOC_WRITE_DIGITS_10_FAST!(39)]
pub fn write_digits10_fast(self, buf: &mut [u8], offset: usize) -> usize {
const MAX: usize = Digits::<u128>::MAX_DIGITS_10 as usize;
debug_assert!(offset + MAX <= buf.len(), "buffer < 39 bytes");
let mut n = self.0;
is![n == 0, {
buf[offset] = b'0';
return 1;
}];
let mut pos = offset + MAX;
while n >= 100 {
pos -= 2;
let idx = ((n % 100) * 2) as usize;
buf[pos] = TextLut::DECIMAL_PAIRS[idx];
buf[pos + 1] = TextLut::DECIMAL_PAIRS[idx + 1];
n /= 100;
}
if n < 10 {
pos -= 1;
buf[pos] = n as u8 + b'0';
} else {
pos -= 2;
let idx = (n * 2) as usize;
buf[pos] = TextLut::DECIMAL_PAIRS[idx];
buf[pos + 1] = TextLut::DECIMAL_PAIRS[idx + 1];
}
let written_len = (offset + MAX) - pos;
buf.copy_within(pos..(offset + MAX), offset); written_len
}
#[doc = DOC_DIGITS_STR!()] #[rustfmt::skip]
pub const fn digits10_str(self, width: u8) -> StringU8<{Self::MAX_DIGITS_10 as usize}> {
let width = Cmp(width).clamp(self.count_digits10(), Self::MAX_DIGITS_10);
#[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
return crate::unwrap![ok StringU8::<{Self::MAX_DIGITS_10 as usize}>
::from_array_nright(self.digits10(), width)];
#[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
unsafe { StringU8::<{Self::MAX_DIGITS_10 as usize}>
::from_array_nright_unchecked(self.digits10(), width) }
}
#[doc = DOC_DIGITS_STR!()] #[rustfmt::skip]
pub const fn digits16_str(self, width: u8) -> StringU8<{Self::MAX_DIGITS_16 as usize}> {
let width = Cmp(width).clamp(self.count_digits16(), Self::MAX_DIGITS_16);
#[cfg(any(feature = "safe_text", not(feature = "unsafe_str")))]
return crate::unwrap![ok StringU8::<{Self::MAX_DIGITS_16 as usize}>
::from_array_nright(self.digits16(), width)];
#[cfg(all(not(feature = "safe_text"), feature = "unsafe_str"))]
unsafe { StringU8::<{Self::MAX_DIGITS_16 as usize}>
::from_array_nright_unchecked(self.digits16(), width)
}
}
}