at_commands/parser/
common.rsuse {
pest::{
error::Error as PestError,
iterators::{Pair, Pairs},
RuleType,
},
std::num::ParseIntError,
thiserror::Error,
};
#[derive(Debug, Error)]
pub enum ParseError<Rule: RuleType> {
#[error("Unable to use pest to parse {string:?}: {pest_error:?}")]
PestParseFailure { string: String, pest_error: PestError<Rule> },
#[error("Expected one of {expected_rules:?}, got nothing.")]
NextRuleMissing { expected_rules: Vec<Rule> },
#[error("Expected one of {expected_rules:?}, got {actual_rule:?}.")]
NextRuleUnexpected { expected_rules: Vec<Rule>, actual_rule: Rule },
#[error("Unable to parse \"{string:?}\" as an integer: {error:?}.")]
InvalidInteger { string: String, error: ParseIntError },
#[error("Unknown character after AT: \"{0}\"")]
UnknownExtensionCharacter(String),
}
pub type ParseResult<T, R> = std::result::Result<T, ParseError<R>>;
pub fn next_match_one_of<'a, Rule: RuleType>(
pairs: &mut Pairs<'a, Rule>,
expected_rules: Vec<Rule>,
) -> ParseResult<Pair<'a, Rule>, Rule> {
let pair_result = pairs.next();
let pair = pair_result
.ok_or_else(|| ParseError::NextRuleMissing { expected_rules: expected_rules.clone() })?;
let pair_rule = pair.as_rule();
if !expected_rules.contains(&pair_rule) {
return Err(ParseError::NextRuleUnexpected {
expected_rules: expected_rules,
actual_rule: pair_rule,
});
}
Ok(pair)
}
pub fn next_match<'a, Rule: RuleType>(
pairs: &mut Pairs<'a, Rule>,
expected_rule: Rule,
) -> ParseResult<Pair<'a, Rule>, Rule> {
next_match_one_of(pairs, vec![expected_rule])
}
pub fn next_match_option<'a, Rule: RuleType>(
pairs: &mut Pairs<'a, Rule>,
expected_rule: Rule,
) -> ParseResult<Option<Pair<'a, Rule>>, Rule> {
if !pairs.peek().is_some() {
Ok(None)
} else {
next_match(pairs, expected_rule).map(|pair| Some(pair))
}
}
pub fn next_match_rep<'a, Rule: RuleType>(
pairs: &mut Pairs<'a, Rule>,
expected_rule: Rule,
) -> Vec<Pair<'a, Rule>> {
let is_correct_rule = |pair_option: Option<Pair<'a, Rule>>| match pair_option {
Some(pair) => pair.as_rule() == expected_rule,
None => false,
};
let mut vector = Vec::new();
while is_correct_rule(pairs.peek()) {
let pair = pairs.next().unwrap();
vector.push(pair);
}
vector
}
pub fn parse_string<Rule: RuleType>(string: Pair<'_, Rule>) -> ParseResult<String, Rule> {
Ok(string.as_span().as_str().to_string())
}
pub fn parse_integer<Rule: RuleType>(integer: Pair<'_, Rule>) -> ParseResult<i64, Rule> {
let str = integer.as_span().as_str();
str.parse().map_err(|err| ParseError::InvalidInteger { string: str.to_string(), error: err })
}
pub fn parse_name<Rule: RuleType>(name: Pair<'_, Rule>) -> ParseResult<String, Rule> {
Ok(name.as_span().as_str().to_string())
}