use sashite_sin::Identifier;
use crate::error::ParseError;
pub(crate) fn validate(field: &[u8]) -> Result<(Identifier, Identifier), ParseError> {
let mut delimiter = None;
let mut slashes = 0usize;
for (idx, &b) in field.iter().enumerate() {
if b == b'/' {
slashes += 1;
delimiter = Some(idx);
}
}
let (1, Some(at)) = (slashes, delimiter) else {
return Err(ParseError::InvalidStyleTurnDelimiter);
};
let active = parse_style(&field[..at])?;
let inactive = parse_style(&field[at + 1..])?;
if active.side() == inactive.side() {
return Err(ParseError::StylesSameCase);
}
Ok((active, inactive))
}
fn parse_style(bytes: &[u8]) -> Result<Identifier, ParseError> {
Identifier::try_from(bytes).map_err(|_| ParseError::InvalidStyleToken)
}
#[cfg(test)]
mod tests {
use super::*;
use sashite_sin::Side;
fn ok(field: &str) -> (Side, char, char) {
let (active, inactive) = validate(field.as_bytes()).expect("valid style-turn");
(active.side(), active.to_char(), inactive.to_char())
}
fn err(field: &str) -> ParseError {
validate(field.as_bytes()).unwrap_err()
}
#[test]
fn first_active() {
assert_eq!(ok("C/c"), (Side::First, 'C', 'c'));
}
#[test]
fn second_active() {
assert_eq!(ok("c/C"), (Side::Second, 'c', 'C'));
}
#[test]
fn cross_style() {
assert_eq!(ok("W/c"), (Side::First, 'W', 'c'));
}
#[test]
fn cross_style_second_active() {
assert_eq!(ok("w/C"), (Side::Second, 'w', 'C'));
}
#[test]
fn same_case_rejected() {
assert_eq!(err("C/C"), ParseError::StylesSameCase);
}
#[test]
fn same_case_lower() {
assert_eq!(err("c/c"), ParseError::StylesSameCase);
}
#[test]
fn no_delimiter() {
assert_eq!(err("C"), ParseError::InvalidStyleTurnDelimiter);
}
#[test]
fn two_delimiters() {
assert_eq!(err("C/c/W"), ParseError::InvalidStyleTurnDelimiter);
}
#[test]
fn left_too_long() {
assert_eq!(err("CC/c"), ParseError::InvalidStyleToken);
}
#[test]
fn right_empty() {
assert_eq!(err("C/"), ParseError::InvalidStyleToken);
}
#[test]
fn left_empty() {
assert_eq!(err("/c"), ParseError::InvalidStyleToken);
}
#[test]
fn non_letter_token() {
assert_eq!(err("1/c"), ParseError::InvalidStyleToken);
}
}