1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/***************************************************************************
*
* AT Command Parser
* Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <https://www.gnu.org/licenses/>.
*
***************************************************************************/
use crateAtContext;
use crate::;
/*
AT Command Forms:
- AT+CMD (execution)
- AT+CMD? (query)
- AT+CMD=? (test)
- AT+CMD=... (set with arguments)
*/
/// Represents the different forms an AT command can take
/// The main AT command parser
///
/// Generic over `T` which must implement the [`AtContext<SIZE>`](crate::context::AtContext) trait,
/// and over the const `SIZE` which determines the response buffer size.
///
/// # Generic Design
///
/// The parser is generic over the command handler type `T` and response size `SIZE` to allow
/// compile-time type checking when all handlers are of the same type. This provides:
///
/// - **Type safety**: Compile-time verification of handler types
/// - **Zero overhead**: No dynamic dispatch when using concrete types
/// - **Flexibility**: Can be used with trait objects (`dyn AtContext<SIZE>`) for mixed handler types
///
/// # Usage Patterns
///
/// ## With trait objects (recommended for mixed types):
/// ```rust,no_run
/// # use at_parser_rs::parser::AtParser;
/// # use at_parser_rs::context::AtContext;
/// # struct Dummy; impl AtContext<64> for Dummy {}
/// # let mut echo_handler = Dummy; let mut reset_handler = Dummy;
/// const SIZE: usize = 64;
/// let mut parser: AtParser<dyn AtContext<SIZE>, SIZE> = AtParser::new();
/// let commands: &mut [(&str, &mut dyn AtContext<SIZE>)] = &mut [
/// ("AT+ECHO", &mut echo_handler),
/// ("AT+RST", &mut reset_handler),
/// ];
/// parser.set_commands(commands);
/// ```
///
/// ## With concrete types (for homogeneous handlers):
/// ```rust,no_run
/// # use at_parser_rs::parser::AtParser;
/// # use at_parser_rs::context::AtContext;
/// # struct MyHandler; impl AtContext<64> for MyHandler {}
/// # let mut handler1 = MyHandler; let mut handler2 = MyHandler;
/// const SIZE: usize = 64;
/// let mut parser: AtParser<MyHandler, SIZE> = AtParser::new();
/// let commands: &mut [(&str, &mut MyHandler)] = &mut [
/// ("AT+CMD1", &mut handler1),
/// ("AT+CMD2", &mut handler2),
/// ];
/// parser.set_commands(commands);
/// ```
/// Parse an AT command string into its name and form.
///
/// Examines the suffix of `input` (after trimming whitespace) to determine
/// which AT command form was requested, then returns the bare command name
/// together with the detected [`AtForm`].
///
/// | Suffix | Resulting form |
/// |---|---|
/// | `=?` | [`AtForm::Test`] |
/// | `?` | [`AtForm::Query`] |
/// | `=<args>` | [`AtForm::Set`] with the text after `=` as raw args |
/// | *(none)* | [`AtForm::Exec`] |
///
/// This function never returns an error; every well-formed AT command string
/// maps to exactly one form.
///
/// # Arguments
///
/// * `input` — pre-trimmed AT command string (trimming is reapplied internally)
///
/// # Returns
///
/// `Ok((command_name, form))` where `command_name` is a slice of `input`
/// with the suffix removed.