at_parser_rs/
parser.rs

1use crate::context::AtContext;
2use crate::{AtError, AtResult, Args};
3
4/*
5AT Command Forms:
6- AT+CMD     (execution)
7- AT+CMD?    (query)
8- AT+CMD=?   (test)
9- AT+CMD=... (set with arguments)
10 */
11
12/// Represents the different forms an AT command can take
13enum AtForm<'a> {
14    /// Execute command without parameters (AT+CMD)
15    Exec,
16    /// Query the current state (AT+CMD?)
17    Query,
18    /// Test command availability or get valid ranges (AT+CMD=?)
19    Test,
20    /// Set command with arguments (AT+CMD=args)
21    Set(Args<'a>),
22}
23
24/// The main AT command parser
25/// Generic over T which must implement AtContext trait
26pub struct AtParser<'a, T>
27where
28    T: AtContext {
29    /// Array of registered commands with their name and handler
30    pub commands: &'a mut [(&'static str, &'a mut T)],
31}
32
33impl<'a, T> AtParser<'a, T>
34where
35    T: AtContext {
36
37    /// Create a new empty parser
38    pub fn new() -> Self {
39        Self { commands: & mut [] }
40    }
41
42    /// Register commands that this parser will handle
43    pub fn set_commands(&mut self, commands: &'a mut [(&'static str, &'a mut T)]) {
44        self.commands = commands;
45    }
46
47    /// Parse and execute an AT command string
48    /// 
49    /// # Arguments
50    /// * `input` - The raw AT command string (e.g., "AT+CMD?")
51    /// 
52    /// # Returns
53    /// * `Ok(&str)` - Success response from the command handler
54    /// * `Err(AtError)` - Error if parsing fails or command is not found
55    pub fn execute(&mut self, input: &str) -> AtResult<'static> {
56        let input = input.trim();
57        let (name, form) = parse(input)?;
58
59        // Find the command handler
60        let (_, module) = self.commands
61            .iter_mut()
62            .find(|(n, _)| *n == name)
63            .ok_or(AtError::UnknownCommand)?;
64
65        // Dispatch to the appropriate handler method
66        match form {
67            AtForm::Exec => module.exec(),
68            AtForm::Query => module.query(),
69            AtForm::Test => module.test(),
70            AtForm::Set(args) => module.set(args),
71        }
72    }
73}
74
75/// Parse an AT command string into its name and form
76/// 
77/// # Arguments
78/// * `input` - The command string to parse
79/// 
80/// # Returns
81/// A tuple of (command_name, command_form)
82fn parse<'a>(input: &'a str) -> Result<(&'a str, AtForm<'a>), AtError> {
83    let input = input.trim();
84
85    // Check suffixes to determine command form
86    if let Some(cmd) = input.strip_suffix("=?") {
87        Ok((cmd, AtForm::Test))
88    } else if let Some(cmd) = input.strip_suffix('?') {
89        Ok((cmd, AtForm::Query))
90    } else if let Some((cmd, args)) = input.split_once('=') {
91        Ok((cmd, AtForm::Set(Args { raw: args })))
92    } else {
93        Ok((input, AtForm::Exec))
94    }
95}