use super::*;
use crate::{AsciiLut, is};
impl Digits<u16> {
pub const MAX_DIGITS_10: u8 = 5;
pub const MAX_DIGITS_16: u8 = 4;
#[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 {
match self.0 {
0 => 1,
0x1..=0xF => 1,
0x10..=0xFF => 2,
0x100..=0xFFF => 3,
_ => 4,
}
}
#[must_use]
#[inline(always)]
pub const fn digit_at_index10(self, index: u8) -> u8 {
is![index >= self.count_digits10(), return b'0'];
let power = AsciiLut::POWERS10[index as usize] as u16;
(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 = AsciiLut::POWERS10[index as usize] as u16;
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;
AsciiLut::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(AsciiLut::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 = AsciiLut::POWERS10[index as usize] as u16;
(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 = AsciiLut::POWERS10[index as usize] as u16;
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: u16) -> u8 {
(self.0 / divisor % 10) as u8 + b'0'
}
#[doc = _DOC_DIGIT_AT_POWER_16!()]
#[must_use]
pub(crate) const fn digit_at_power16(self, divisor: u16) -> u8 {
let digit = match divisor {
0x1 => self.0 & 0xF,
0x10 => (self.0 >> 4) & 0xF,
0x100 => (self.0 >> 8) & 0xF,
0x1000 => (self.0 >> 12) & 0xF,
_ => (self.0 / divisor) % 16,
};
AsciiLut::DIGITS_BASE36[digit as usize]
}
#[must_use]
pub const fn digits10(self) -> [u8; Self::MAX_DIGITS_10 as usize] {
[
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),
]
}
pub const fn digits16(self) -> [u8; Self::MAX_DIGITS_16 as usize] {
[
self.digit_at_power16(0x1000), self.digit_at_power16(0x100),
self.digit_at_power16(0x10),
self.digit_at_power16(0x1),
]
}
#[inline(always)]
const fn write_digits10_inner(self, buf: &mut [u8], offset: usize) -> usize {
let n = self.0;
if n < 10 {
buf[offset] = n as u8 + b'0';
1
} else if n < 100 {
buf[offset] = (n / 10) as u8 + b'0';
buf[offset + 1] = (n % 10) as u8 + b'0';
2
} else if n < 1000 {
buf[offset] = (n / 100) as u8 + b'0';
buf[offset + 1] = ((n / 10) % 10) as u8 + b'0';
buf[offset + 2] = (n % 10) as u8 + b'0';
3
} else if n < 10000 {
buf[offset] = (n / 1000) as u8 + b'0';
buf[offset + 1] = ((n / 100) % 10) as u8 + b'0';
buf[offset + 2] = ((n / 10) % 10) as u8 + b'0';
buf[offset + 3] = (n % 10) as u8 + b'0';
4
} else {
buf[offset] = (n / 10000) as u8 + b'0';
buf[offset + 1] = ((n / 1000) % 10) as u8 + b'0';
buf[offset + 2] = ((n / 100) % 10) as u8 + b'0';
buf[offset + 3] = ((n / 10) % 10) as u8 + b'0';
buf[offset + 4] = (n % 10) as u8 + b'0';
5
}
}
#[doc = _DOC_WRITE_DIGITS_10!(5)]
pub const fn write_digits10(self, buf: &mut [u8], offset: usize) -> usize {
let len = self.count_digits10() as usize;
is![len > buf.len().saturating_sub(offset), return 0];
self.write_digits10_inner(buf, offset)
}
#[doc = _DOC_WRITE_DIGITS_10_NONZERO!(5)]
pub const fn write_digits10_nonzero(self, buf: &mut [u8], offset: usize) -> usize {
is![self.0 == 0, return 0];
self.write_digits10(buf, offset)
}
#[doc = _DOC_WRITE_DIGITS_10_FAST!(5)]
pub const fn write_digits10_fast(self, buf: &mut [u8], offset: usize) -> usize {
const MAX: usize = Digits::<u16>::MAX_DIGITS_10 as usize;
is![MAX > buf.len().saturating_sub(offset), return 0];
self.write_digits10_inner(buf, offset)
}
#[doc = _DOC_WRITE_DIGITS_10_FAST_NONZERO!(5)]
pub const fn write_digits10_fast_nonzero(self, buf: &mut [u8], offset: usize) -> usize {
is![self.0 == 0, return 0];
self.write_digits10_fast(buf, offset)
}
#[must_use]
pub const fn digits10_2(self) -> [u8; 2] {
debug_assert![self.0 <= 99];
[self.digit_at_power10(10), self.digit_at_power10(1)]
}
#[must_use]
pub const fn digits10_3(self) -> [u8; 3] {
debug_assert![self.0 <= 999];
[self.digit_at_power10(100), self.digit_at_power10(10), self.digit_at_power10(1)]
}
#[must_use]
pub const fn digits10_4(self) -> [u8; 4] {
debug_assert![self.0 <= 9999];
[
self.digit_at_power10(1000),
self.digit_at_power10(100),
self.digit_at_power10(10),
self.digit_at_power10(1),
]
}
}