use crate::field::ast::CommonSwitches;
use crate::field::error::FieldParseError;
use crate::field::parse::Token;
pub(crate) fn extract_common_switches(
tokens: &[Token],
) -> Result<(CommonSwitches, Vec<Token>), FieldParseError> {
let mut switches = CommonSwitches::default();
let mut remaining = Vec::new();
let mut i = 0;
while i < tokens.len() {
match &tokens[i] {
Token::Switch(ch, pos) if *ch == '*' => {
i += 1;
let value = take_switch_value(tokens, &mut i, "\\*", *pos)?;
switches.format = Some(value);
}
Token::Switch(ch, pos) if *ch == '#' => {
i += 1;
let value = take_switch_value(tokens, &mut i, "\\#", *pos)?;
switches.numeric_format = Some(value);
}
Token::Switch(ch, pos) if *ch == '@' => {
i += 1;
let value = take_switch_value(tokens, &mut i, "\\@", *pos)?;
switches.date_format = Some(value);
}
_ => {
remaining.push(tokens[i].clone());
i += 1;
}
}
}
Ok((switches, remaining))
}
fn take_switch_value(
tokens: &[Token],
i: &mut usize,
switch_name: &str,
_pos: usize,
) -> Result<String, FieldParseError> {
if *i < tokens.len() {
match &tokens[*i] {
Token::Quoted(s, _) | Token::Word(s, _) => {
let val = s.clone();
*i += 1;
Ok(val)
}
_ => Err(FieldParseError::MissingSwitchValue {
switch: switch_name.to_string(),
}),
}
} else {
Err(FieldParseError::MissingSwitchValue {
switch: switch_name.to_string(),
})
}
}
pub(crate) fn has_flag(tokens: &[Token], ch: char) -> bool {
tokens
.iter()
.any(|t| matches!(t, Token::Switch(c, _) if *c == ch))
}
pub(crate) fn take_switch_with_value(
tokens: &mut Vec<Token>,
ch: char,
) -> Result<Option<String>, FieldParseError> {
let pos = tokens
.iter()
.position(|t| matches!(t, Token::Switch(c, _) if *c == ch));
let Some(idx) = pos else {
return Ok(None);
};
let switch_pos = match &tokens[idx] {
Token::Switch(_, p) => *p,
_ => unreachable!(),
};
tokens.remove(idx);
if idx < tokens.len() {
match &tokens[idx] {
Token::Quoted(s, _) | Token::Word(s, _) => {
let val = s.clone();
tokens.remove(idx);
Ok(Some(val))
}
_ => Err(FieldParseError::MissingSwitchValue {
switch: format!("\\{ch}"),
}),
}
} else {
Err(FieldParseError::MissingSwitchValue {
switch: format!("\\{ch} at position {switch_pos}"),
})
}
}
#[allow(dead_code)]
pub(crate) fn remove_flags(tokens: &mut Vec<Token>, ch: char) {
tokens.retain(|t| !matches!(t, Token::Switch(c, _) if *c == ch));
}