at_commands/parser/
response_parser.rs1use {
11 crate::lowlevel::{HardcodedError, Response},
12 crate::parser::{
13 arguments_parser::ArgumentsParser,
14 common::{
15 ParseError, ParseResult, next_match, next_match_one_of, parse_integer, parse_name,
16 parse_string,
17 },
18 response_grammar::{Grammar, Rule},
19 },
20 pest::{Parser, iterators::Pair},
21};
22
23static ARGUMENTS_PARSER: ArgumentsParser<Rule> = ArgumentsParser {
24 argument_list: Rule::argument_list,
25 argument: Rule::argument,
26 arguments: Rule::arguments,
27 key_value_argument: Rule::key_value_argument,
28 optional_argument_delimiter: Rule::optional_argument_delimiter,
29 optional_argument_terminator: Rule::optional_argument_terminator,
30 parenthesized_argument_lists: Rule::parenthesized_argument_lists,
31 primitive_argument: Rule::primitive_argument,
32};
33
34pub fn parse(string: &str) -> ParseResult<Response, Rule> {
35 let mut parsed = Grammar::parse(Rule::input, string).map_err(|pest_error| {
36 ParseError::PestParseFailure { string: string.into(), pest_error: Box::new(pest_error) }
37 })?;
38
39 let input = next_match(&mut parsed, Rule::input)?;
40 let mut input_elements = input.into_inner();
41 let response = next_match(&mut input_elements, Rule::response)?;
42
43 parse_response(response)
44}
45
46fn parse_response(response: Pair<'_, Rule>) -> ParseResult<Response, Rule> {
47 let mut response_elements = response.into_inner();
48 let response_variant = next_match_one_of(
49 &mut response_elements,
50 vec![Rule::ok, Rule::error, Rule::hardcoded_error, Rule::cme_error, Rule::success],
51 )?;
52
53 let parsed_response = match response_variant.as_rule() {
54 Rule::ok => Response::Ok,
55 Rule::error => Response::Error,
56 Rule::hardcoded_error => parse_hardcoded_error(response_variant)?,
57 Rule::cme_error => parse_cme_error(response_variant)?,
58 Rule::success => parse_success(response_variant)?,
59 _ => unreachable!(),
63 };
64
65 Ok(parsed_response)
66}
67
68fn parse_hardcoded_error(hardcoded_error: Pair<'_, Rule>) -> ParseResult<Response, Rule> {
69 let error_string = parse_string(hardcoded_error)?;
70
71 let parsed_error = match error_string.as_str() {
72 "NO CARRIER" => HardcodedError::NoCarrier,
73 "BUSY" => HardcodedError::Busy,
74 "NO ANSWER" => HardcodedError::NoAnswer,
75 "DELAYED" => HardcodedError::Delayed,
76 "BLACKLIST" => HardcodedError::Blacklist,
77 _ => unreachable!(),
81 };
82
83 Ok(Response::HardcodedError(parsed_error))
84}
85
86fn parse_cme_error(cme_error: Pair<'_, Rule>) -> ParseResult<Response, Rule> {
87 let mut cme_error_elements = cme_error.into_inner();
88
89 let error_code = next_match(&mut cme_error_elements, Rule::integer)?;
90 let parsed_error_code = parse_integer(error_code)?;
91
92 Ok(Response::CmeError(parsed_error_code))
93}
94
95fn parse_success(success: Pair<'_, Rule>) -> ParseResult<Response, Rule> {
96 let mut success_elements = success.into_inner();
97
98 let optional_extension = next_match(&mut success_elements, Rule::optional_extension)?;
99 let parsed_optional_extension = parse_optional_extension(optional_extension)?;
100
101 let name = next_match(&mut success_elements, Rule::command_name)?;
102 let parsed_name = parse_name(name)?;
103
104 let delimited_arguments = next_match(&mut success_elements, Rule::delimited_arguments)?;
105 let parsed_delimited_arguments =
106 ARGUMENTS_PARSER.parse_delimited_arguments(delimited_arguments)?;
107
108 Ok(Response::Success {
109 name: parsed_name,
110 is_extension: parsed_optional_extension,
111 arguments: parsed_delimited_arguments,
112 })
113}
114
115fn parse_optional_extension(optional_extension: Pair<'_, Rule>) -> ParseResult<bool, Rule> {
116 let extension_str = optional_extension.as_span().as_str();
117
118 match extension_str {
119 "" => Ok(false),
120 "+" => Ok(true),
121 c => Err(ParseError::UnknownExtensionCharacter(c.to_string()).into()),
122 }
123}