at_commands/parser/
common.rs1use {
16 pest::{
17 error::Error as PestError,
18 iterators::{Pair, Pairs},
19 RuleType,
20 },
21 std::num::ParseIntError,
22 thiserror::Error,
23};
24
25#[derive(Debug, Error)]
26pub enum ParseError<Rule: RuleType> {
27 #[error("Unable to use pest to parse {string:?}: {pest_error:?}")]
28 PestParseFailure { string: String, pest_error: PestError<Rule> },
29 #[error("Expected one of {expected_rules:?}, got nothing.")]
30 NextRuleMissing { expected_rules: Vec<Rule> },
31 #[error("Expected one of {expected_rules:?}, got {actual_rule:?}.")]
32 NextRuleUnexpected { expected_rules: Vec<Rule>, actual_rule: Rule },
33 #[error("Unable to parse \"{string:?}\" as an integer: {error:?}.")]
34 InvalidInteger { string: String, error: ParseIntError },
35 #[error("Unknown character after AT: \"{0}\"")]
36 UnknownExtensionCharacter(String),
37}
38
39pub type ParseResult<T, R> = std::result::Result<T, Box<ParseError<R>>>;
40
41pub fn next_match_one_of<'a, Rule: RuleType>(
44 pairs: &mut Pairs<'a, Rule>,
45 expected_rules: Vec<Rule>,
46) -> ParseResult<Pair<'a, Rule>, Rule> {
47 let pair_result = pairs.next();
48 let pair = pair_result
49 .ok_or_else(|| ParseError::NextRuleMissing { expected_rules: expected_rules.clone() })?;
50
51 let pair_rule = pair.as_rule();
52 if !expected_rules.contains(&pair_rule) {
53 return Err(Box::new(ParseError::NextRuleUnexpected {
54 expected_rules: expected_rules,
55 actual_rule: pair_rule,
56 }));
57 }
58
59 Ok(pair)
60}
61
62pub fn next_match<'a, Rule: RuleType>(
65 pairs: &mut Pairs<'a, Rule>,
66 expected_rule: Rule,
67) -> ParseResult<Pair<'a, Rule>, Rule> {
68 next_match_one_of(pairs, vec![expected_rule])
69}
70
71pub fn next_match_option<'a, Rule: RuleType>(
74 pairs: &mut Pairs<'a, Rule>,
75 expected_rule: Rule,
76) -> ParseResult<Option<Pair<'a, Rule>>, Rule> {
77 if !pairs.peek().is_some() {
78 Ok(None)
79 } else {
80 next_match(pairs, expected_rule).map(|pair| Some(pair))
81 }
82}
83
84pub fn next_match_rep<'a, Rule: RuleType>(
87 pairs: &mut Pairs<'a, Rule>,
88 expected_rule: Rule,
89) -> Vec<Pair<'a, Rule>> {
90 let is_correct_rule = |pair_option: Option<Pair<'a, Rule>>| match pair_option {
91 Some(pair) => pair.as_rule() == expected_rule,
92 None => false,
93 };
94
95 let mut vector = Vec::new();
96 while is_correct_rule(pairs.peek()) {
97 let pair = pairs.next().unwrap();
98 vector.push(pair);
99 }
100
101 vector
102}
103
104pub fn parse_string<Rule: RuleType>(string: Pair<'_, Rule>) -> ParseResult<String, Rule> {
107 Ok(string.as_span().as_str().to_string())
108}
109
110pub fn parse_integer<Rule: RuleType>(integer: Pair<'_, Rule>) -> ParseResult<i64, Rule> {
113 let str = integer.as_span().as_str();
114 str.parse()
115 .map_err(|err| Box::new(ParseError::InvalidInteger { string: str.to_string(), error: err }))
116}
117
118pub fn parse_name<Rule: RuleType>(name: Pair<'_, Rule>) -> ParseResult<String, Rule> {
121 Ok(name.as_span().as_str().to_string())
122}