use crate::*;
impl<const MIN: u8, const MAX: u8> PaddedNumber<MIN, MAX> {
pub fn checked_section<const START_INDEX: u8, const END_INDEX: u8>(
&self,
) -> Option<PaddedNumber<{ END_INDEX - START_INDEX }, { END_INDEX - START_INDEX }>>
where
[(); { MAX - END_INDEX } as usize]:,
{
if END_INDEX > self.len() {
return None;
}
let (leading_zeros, number) = section_impl(self.leading_zeros, self.number, START_INDEX, END_INDEX);
Some(PaddedNumber { leading_zeros, number })
}
pub fn relaxed_section<const START: u8, const END: u8, const NEW_MIN: u8>(
&self,
) -> Option<PaddedNumber<NEW_MIN, { END - START }>>
where
[(); { MAX - END } as usize]:,
[(); { (END - START) - NEW_MIN } as usize]:,
{
let remaining_length = self.len().saturating_sub(START);
if remaining_length < NEW_MIN {
return None;
}
if remaining_length == 0 {
return Some(PaddedNumber { leading_zeros: 0, number: 0 });
}
let (leading_zeros, number) = section_impl(self.leading_zeros, self.number, START, START + remaining_length);
Some(PaddedNumber { leading_zeros, number })
}
pub fn expected_section<const START_INDEX: u8, const END_INDEX: u8>(
&self,
) -> PaddedNumber<{ END_INDEX - START_INDEX }, { END_INDEX - START_INDEX }>
where
[(); { MIN - END_INDEX } as usize]:,
[(); { MAX - END_INDEX } as usize]:,
{
let (leading_zeros, number) = section_impl(self.leading_zeros, self.number, START_INDEX, END_INDEX);
PaddedNumber { leading_zeros, number }
}
}
fn section_impl(leading_zeros: u8, remaining_number: u64, start: u8, end: u8) -> (u8, u64) {
match (start.checked_sub(leading_zeros), end.checked_sub(leading_zeros)) {
(Some(translated_start), Some(translated_end)) => {
(0, number_subsection(remaining_number, translated_start, translated_end))
}
(None, Some(translated_end)) => (
leading_zeros - start,
number_subsection(remaining_number, 0, translated_end),
),
(None, None) => {
let leading_zero_start = leading_zeros - start;
let leading_zero_end = leading_zeros - end;
(leading_zero_start - leading_zero_end, 0)
}
(Some(_), None) => {
panic!("encountered start > end")
}
}
}
pub(crate) const fn number_subsection(number: u64, start: u8, end: u8) -> u64 {
let number_length = utils::number_len(number);
if number_length == 0 {
return 0;
}
let left_shifts = start;
let right_shifts = number_length - end;
let mut number = number;
number = left_shift_repeated(number, number_length, left_shifts);
number = right_shift_repeated(number, right_shifts);
return number;
const fn left_shift_repeated(number: u64, number_length: u8, repetitions: u8) -> u64 {
let mut current = number;
let mut current_length = number_length;
let mut repetitions_left = repetitions;
while repetitions_left > 0 {
current = left_shift(current, current_length);
current_length -= 1;
repetitions_left -= 1;
}
current
}
const fn left_shift(number: u64, number_length: u8) -> u64 {
let decimal = 10u64.pow((number_length - 1) as u32);
number - (number / decimal) * decimal
}
const fn right_shift_repeated(number: u64, repetitions: u8) -> u64 {
number / 10u64.pow(repetitions as u32)
}
}