use crate::iterhelp::ByteSliceIter;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ParsedComponent {
pub letter: bool,
pub char_cnt: u8,
pub value: i16,
}
impl ParsedComponent {
pub fn is_year_comp(&self) -> bool {
self.is_gregorian_year() || self.is_sac13_year()
}
pub fn is_gregorian_year(&self) -> bool {
!self.letter && (self.value <= 0 || self.char_cnt >= 3)
}
pub fn is_sac13_year(&self) -> bool {
self.letter && self.char_cnt == 4
}
pub fn parse(i: &mut ByteSliceIter) -> Option<Self> {
let mut num_comp = ParsedComponent {
letter: false,
value: 0,
char_cnt: 0,
};
let mut peeked = i.peek()?;
let invert = peeked == b'-';
if invert {
_ = i.next();
peeked = i.peek()?;
}
if peeked.is_ascii_uppercase() {
if invert {
return None;
}
_ = i.next();
num_comp.value = (peeked - b'A') as i16;
num_comp.letter = true;
num_comp.char_cnt += 1;
}
loop {
let Some(peeked) = i.peek() else {
break;
};
if !peeked.is_ascii_digit() {
break;
}
_ = i.next();
let digit_value = (peeked - b'0') as i16;
num_comp.char_cnt += 1;
num_comp.value = num_comp.value.checked_mul(10)?;
num_comp.value = num_comp.value.checked_add(digit_value)?;
}
if invert {
num_comp.value *= -1;
}
Some(num_comp)
}
}