use crate::error::ParseError;
use crate::identifier::Identifier;
use crate::letter::Letter;
use crate::state::State;
pub(crate) const fn parse(input: &str) -> Result<Identifier, ParseError> {
parse_bytes(input.as_bytes())
}
pub(crate) const fn parse_bytes(bytes: &[u8]) -> Result<Identifier, ParseError> {
match bytes {
[] => Err(ParseError::Empty),
[b0] => parse_bare(*b0),
[b0, b1] => parse_pair(*b0, *b1),
[b0, b1, b2] => parse_triple(*b0, *b1, *b2),
_ => Err(ParseError::TooLong),
}
}
const fn parse_bare(byte: u8) -> Result<Identifier, ParseError> {
match Letter::from_ascii(byte) {
Some((letter, side)) => Ok(Identifier::new(letter, side, State::Normal, false)),
None => Err(ParseError::InvalidLetter),
}
}
const fn parse_pair(first: u8, second: u8) -> Result<Identifier, ParseError> {
if let Some((letter, side)) = Letter::from_ascii(first) {
return match second {
b'^' => Ok(Identifier::new(letter, side, State::Normal, true)),
_ => Err(ParseError::InvalidTerminalMarker),
};
}
if let Some(state) = modifier_state(first) {
return match Letter::from_ascii(second) {
Some((letter, side)) => Ok(Identifier::new(letter, side, state, false)),
None => Err(ParseError::InvalidLetter),
};
}
Err(ParseError::InvalidStateModifier)
}
const fn parse_triple(first: u8, second: u8, third: u8) -> Result<Identifier, ParseError> {
let Some(state) = modifier_state(first) else {
return Err(ParseError::InvalidStateModifier);
};
let Some((letter, side)) = Letter::from_ascii(second) else {
return Err(ParseError::InvalidLetter);
};
match third {
b'^' => Ok(Identifier::new(letter, side, state, true)),
_ => Err(ParseError::InvalidTerminalMarker),
}
}
const fn modifier_state(byte: u8) -> Option<State> {
match byte {
b'+' => Some(State::Enhanced),
b'-' => Some(State::Diminished),
_ => None,
}
}