1use crate::{pkg_length::PkgLength, AmlContext, AmlError, AmlValue, DebugVerbosity};
2use alloc::vec::Vec;
3use core::{convert::TryInto, marker::PhantomData};
4use log::trace;
5
6pub const INDENT_PER_SCOPE: usize = 2;
8
9impl AmlContext {
10 pub(crate) fn comment(&self, verbosity: DebugVerbosity, message: &str) {
14 if verbosity <= self.debug_verbosity {
15 log::trace!("{:indent$}{}", "", message, indent = self.scope_indent);
16 }
17 }
18}
19
20#[derive(Debug)]
21pub enum Propagate {
22 Err(AmlError),
23 Return(AmlValue),
24 Break,
25 Continue,
26}
27
28impl From<AmlError> for Propagate {
29 fn from(error: AmlError) -> Self {
30 Self::Err(error)
31 }
32}
33
34pub type ParseResult<'a, 'c, R> =
35 Result<(&'a [u8], &'c mut AmlContext, R), (&'a [u8], &'c mut AmlContext, Propagate)>;
36
37pub trait Parser<'a, 'c, R>: Sized
38where
39 'c: 'a,
40{
41 fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, R>;
42
43 fn map<F, A>(self, map_fn: F) -> Map<'a, 'c, Self, F, R, A>
44 where
45 F: Fn(R) -> Result<A, Propagate>,
46 {
47 Map {
48 parser: self,
49 map_fn,
50 _phantom: PhantomData,
51 }
52 }
53
54 fn map_with_context<F, A>(self, map_fn: F) -> MapWithContext<'a, 'c, Self, F, R, A>
55 where
56 F: Fn(R, &'c mut AmlContext) -> (Result<A, Propagate>, &'c mut AmlContext),
57 {
58 MapWithContext {
59 parser: self,
60 map_fn,
61 _phantom: PhantomData,
62 }
63 }
64
65 fn discard_result(self) -> DiscardResult<'a, 'c, Self, R> {
66 DiscardResult {
67 parser: self,
68 _phantom: PhantomData,
69 }
70 }
71
72 fn _or<OtherParser>(self, other: OtherParser) -> Or<'a, 'c, Self, OtherParser, R>
77 where
78 OtherParser: Parser<'a, 'c, R>,
79 {
80 Or {
81 p1: self,
82 p2: other,
83 _phantom: PhantomData,
84 }
85 }
86
87 fn then<NextParser, NextR>(self, next: NextParser) -> Then<'a, 'c, Self, NextParser, R, NextR>
88 where
89 NextParser: Parser<'a, 'c, NextR>,
90 {
91 Then {
92 p1: self,
93 p2: next,
94 _phantom: PhantomData,
95 }
96 }
97
98 fn feed<F, P2, R2>(self, producer_fn: F) -> Feed<'a, 'c, Self, P2, F, R, R2>
104 where
105 P2: Parser<'a, 'c, R2>,
106 F: Fn(R) -> P2,
107 {
108 Feed {
109 parser: self,
110 producer_fn,
111 _phantom: PhantomData,
112 }
113 }
114}
115
116impl<'a, 'c, F, R> Parser<'a, 'c, R> for F
117where
118 'c: 'a,
119 F: Fn(&'a [u8], &'c mut AmlContext) -> ParseResult<'a, 'c, R>,
120{
121 fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, R> {
122 self(input, context)
123 }
124}
125
126pub fn id<'a, 'c>() -> impl Parser<'a, 'c, ()>
129where
130 'c: 'a,
131{
132 move |input: &'a [u8], context: &'c mut AmlContext| Ok((input, context, ()))
133}
134
135pub fn take<'a, 'c>() -> impl Parser<'a, 'c, u8>
136where
137 'c: 'a,
138{
139 move |input: &'a [u8], context: &'c mut AmlContext| match input.first() {
140 Some(&byte) => Ok((&input[1..], context, byte)),
141 None => Err((
142 input,
143 context,
144 Propagate::Err(AmlError::UnexpectedEndOfStream),
145 )),
146 }
147}
148
149pub fn take_u16<'a, 'c>() -> impl Parser<'a, 'c, u16>
150where
151 'c: 'a,
152{
153 move |input: &'a [u8], context: &'c mut AmlContext| {
154 if input.len() < 2 {
155 return Err((
156 input,
157 context,
158 Propagate::Err(AmlError::UnexpectedEndOfStream),
159 ));
160 }
161
162 Ok((
163 &input[2..],
164 context,
165 u16::from_le_bytes(input[0..2].try_into().unwrap()),
166 ))
167 }
168}
169
170pub fn take_u32<'a, 'c>() -> impl Parser<'a, 'c, u32>
171where
172 'c: 'a,
173{
174 move |input: &'a [u8], context: &'c mut AmlContext| {
175 if input.len() < 4 {
176 return Err((
177 input,
178 context,
179 Propagate::Err(AmlError::UnexpectedEndOfStream),
180 ));
181 }
182
183 Ok((
184 &input[4..],
185 context,
186 u32::from_le_bytes(input[0..4].try_into().unwrap()),
187 ))
188 }
189}
190
191pub fn take_u64<'a, 'c>() -> impl Parser<'a, 'c, u64>
192where
193 'c: 'a,
194{
195 move |input: &'a [u8], context: &'c mut AmlContext| {
196 if input.len() < 8 {
197 return Err((
198 input,
199 context,
200 Propagate::Err(AmlError::UnexpectedEndOfStream),
201 ));
202 }
203
204 Ok((
205 &input[8..],
206 context,
207 u64::from_le_bytes(input[0..8].try_into().unwrap()),
208 ))
209 }
210}
211
212pub fn take_n<'a, 'c>(n: u32) -> impl Parser<'a, 'c, &'a [u8]>
213where
214 'c: 'a,
215{
216 move |input: &'a [u8], context| {
217 if (input.len() as u32) < n {
218 return Err((
219 input,
220 context,
221 Propagate::Err(AmlError::UnexpectedEndOfStream),
222 ));
223 }
224
225 let (result, new_input) = input.split_at(n as usize);
226 Ok((new_input, context, result))
227 }
228}
229
230pub fn take_to_end_of_pkglength<'a, 'c>(length: PkgLength) -> impl Parser<'a, 'c, &'a [u8]>
231where
232 'c: 'a,
233{
234 move |input: &'a [u8], context| {
235 let bytes_to_take = match (input.len() as u32).checked_sub(length.end_offset) {
240 Some(bytes_to_take) => bytes_to_take,
241 None => return Err((input, context, Propagate::Err(AmlError::InvalidPkgLength))),
242 };
243 take_n(bytes_to_take).parse(input, context)
244 }
245}
246
247pub fn n_of<'a, 'c, P, R>(parser: P, n: usize) -> impl Parser<'a, 'c, Vec<R>>
248where
249 'c: 'a,
250 P: Parser<'a, 'c, R>,
251{
252 move |mut input, mut context| {
254 let mut results = Vec::with_capacity(n);
255
256 for _ in 0..n {
257 let (new_input, new_context, result) = match parser.parse(input, context) {
258 Ok((input, context, result)) => (input, context, result),
259 Err((_, context, propagate)) => return Err((input, context, propagate)),
260 };
261 results.push(result);
262 input = new_input;
263 context = new_context;
264 }
265
266 Ok((input, context, results))
267 }
268}
269
270pub fn take_while<'a, 'c, P, R>(parser: P) -> impl Parser<'a, 'c, usize>
271where
272 'c: 'a,
273 P: Parser<'a, 'c, R>,
274{
275 move |mut input: &'a [u8], mut context: &'c mut AmlContext| {
276 let mut num_passed = 0;
277 loop {
278 match parser.parse(input, context) {
279 Ok((new_input, new_context, _)) => {
280 input = new_input;
281 context = new_context;
282 num_passed += 1;
283 }
284 Err((_, context, Propagate::Err(AmlError::WrongParser))) => {
285 return Ok((input, context, num_passed))
286 }
287 Err((_, context, err)) => return Err((input, context, err)),
288 }
289 }
290 }
291}
292
293pub fn consume<'a, 'c, F>(condition: F) -> impl Parser<'a, 'c, u8>
294where
295 'c: 'a,
296 F: Fn(u8) -> bool,
297{
298 move |input: &'a [u8], context: &'c mut AmlContext| match input.first() {
299 Some(&byte) if condition(byte) => Ok((&input[1..], context, byte)),
300 Some(&byte) => Err((
301 input,
302 context,
303 Propagate::Err(AmlError::UnexpectedByte(byte)),
304 )),
305 None => Err((
306 input,
307 context,
308 Propagate::Err(AmlError::UnexpectedEndOfStream),
309 )),
310 }
311}
312
313pub fn comment_scope<'a, 'c, P, R>(
314 verbosity: DebugVerbosity,
315 scope_name: &'a str,
316 parser: P,
317) -> impl Parser<'a, 'c, R>
318where
319 'c: 'a,
320 R: core::fmt::Debug,
321 P: Parser<'a, 'c, R>,
322{
323 move |input, context: &'c mut AmlContext| {
324 if verbosity <= context.debug_verbosity {
325 trace!(
326 "{:indent$}--> {}",
327 "",
328 scope_name,
329 indent = context.scope_indent
330 );
331 context.scope_indent += INDENT_PER_SCOPE;
332 }
333
334 let (new_input, context, result) = parser.parse(input, context)?;
336
337 if verbosity <= context.debug_verbosity {
338 context.scope_indent -= INDENT_PER_SCOPE;
339 trace!(
340 "{:indent$}<-- {}",
341 "",
342 scope_name,
343 indent = context.scope_indent
344 );
345 }
346
347 Ok((new_input, context, result))
348 }
349}
350
351pub fn extract<'a, 'c, P, R>(parser: P) -> impl Parser<'a, 'c, (R, &'a [u8])>
357where
358 'c: 'a,
359 P: Parser<'a, 'c, R>,
360{
361 move |input, context: &'c mut AmlContext| {
362 let before = input;
363 let (after, context, result) = parser.parse(input, context)?;
364 let bytes_parsed = before.len() - after.len();
365 let parsed = &before[..bytes_parsed];
366
367 Ok((after, context, (result, parsed)))
368 }
369}
370
371#[allow(dead_code)]
372pub struct Or<'a, 'c, P1, P2, R>
373where
374 'c: 'a,
375 P1: Parser<'a, 'c, R>,
376 P2: Parser<'a, 'c, R>,
377{
378 p1: P1,
379 p2: P2,
380 _phantom: PhantomData<(&'a R, &'c ())>,
381}
382
383impl<'a, 'c, P1, P2, R> Parser<'a, 'c, R> for Or<'a, 'c, P1, P2, R>
384where
385 'c: 'a,
386 P1: Parser<'a, 'c, R>,
387 P2: Parser<'a, 'c, R>,
388{
389 fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, R> {
390 match self.p1.parse(input, context) {
391 Ok(parse_result) => Ok(parse_result),
392 Err((_, context, Propagate::Err(AmlError::WrongParser))) => {
393 self.p2.parse(input, context)
394 }
395 Err((_, context, err)) => Err((input, context, err)),
396 }
397 }
398}
399
400pub struct Map<'a, 'c, P, F, R, A>
401where
402 'c: 'a,
403 P: Parser<'a, 'c, R>,
404 F: Fn(R) -> Result<A, Propagate>,
405{
406 parser: P,
407 map_fn: F,
408 _phantom: PhantomData<(&'a (R, A), &'c ())>,
409}
410
411impl<'a, 'c, P, F, R, A> Parser<'a, 'c, A> for Map<'a, 'c, P, F, R, A>
412where
413 'c: 'a,
414 P: Parser<'a, 'c, R>,
415 F: Fn(R) -> Result<A, Propagate>,
416{
417 fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, A> {
418 match self.parser.parse(input, context) {
419 Ok((new_input, context, result)) => match (self.map_fn)(result) {
420 Ok(result_value) => Ok((new_input, context, result_value)),
421 Err(err) => Err((input, context, err)),
422 },
423 Err(result) => Err(result),
424 }
425 }
426}
427
428pub struct MapWithContext<'a, 'c, P, F, R, A>
429where
430 'c: 'a,
431 P: Parser<'a, 'c, R>,
432 F: Fn(R, &'c mut AmlContext) -> (Result<A, Propagate>, &'c mut AmlContext),
433{
434 parser: P,
435 map_fn: F,
436 _phantom: PhantomData<(&'a (R, A), &'c ())>,
437}
438
439impl<'a, 'c, P, F, R, A> Parser<'a, 'c, A> for MapWithContext<'a, 'c, P, F, R, A>
440where
441 'c: 'a,
442 P: Parser<'a, 'c, R>,
443 F: Fn(R, &'c mut AmlContext) -> (Result<A, Propagate>, &'c mut AmlContext),
444{
445 fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, A> {
446 match self.parser.parse(input, context) {
447 Ok((new_input, context, result)) => match (self.map_fn)(result, context) {
448 (Ok(result_value), context) => Ok((new_input, context, result_value)),
449 (Err(err), context) => Err((input, context, err)),
450 },
451 Err(result) => Err(result),
452 }
453 }
454}
455
456pub struct DiscardResult<'a, 'c, P, R>
457where
458 'c: 'a,
459 P: Parser<'a, 'c, R>,
460{
461 parser: P,
462 _phantom: PhantomData<(&'a R, &'c ())>,
463}
464
465impl<'a, 'c, P, R> Parser<'a, 'c, ()> for DiscardResult<'a, 'c, P, R>
466where
467 'c: 'a,
468 P: Parser<'a, 'c, R>,
469{
470 fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, ()> {
471 self.parser
472 .parse(input, context)
473 .map(|(new_input, new_context, _)| (new_input, new_context, ()))
474 }
475}
476
477pub struct Then<'a, 'c, P1, P2, R1, R2>
478where
479 'c: 'a,
480 P1: Parser<'a, 'c, R1>,
481 P2: Parser<'a, 'c, R2>,
482{
483 p1: P1,
484 p2: P2,
485 _phantom: PhantomData<(&'a (R1, R2), &'c ())>,
486}
487
488impl<'a, 'c, P1, P2, R1, R2> Parser<'a, 'c, (R1, R2)> for Then<'a, 'c, P1, P2, R1, R2>
489where
490 'c: 'a,
491 P1: Parser<'a, 'c, R1>,
492 P2: Parser<'a, 'c, R2>,
493{
494 fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, (R1, R2)> {
495 self.p1
496 .parse(input, context)
497 .and_then(|(next_input, context, result_a)| {
498 self.p2
499 .parse(next_input, context)
500 .map(|(final_input, context, result_b)| {
501 (final_input, context, (result_a, result_b))
502 })
503 })
504 }
505}
506
507pub struct Feed<'a, 'c, P1, P2, F, R1, R2>
508where
509 'c: 'a,
510 P1: Parser<'a, 'c, R1>,
511 P2: Parser<'a, 'c, R2>,
512 F: Fn(R1) -> P2,
513{
514 parser: P1,
515 producer_fn: F,
516 _phantom: PhantomData<(&'a (R1, R2), &'c ())>,
517}
518
519impl<'a, 'c, P1, P2, F, R1, R2> Parser<'a, 'c, R2> for Feed<'a, 'c, P1, P2, F, R1, R2>
520where
521 'c: 'a,
522 P1: Parser<'a, 'c, R1>,
523 P2: Parser<'a, 'c, R2>,
524 F: Fn(R1) -> P2,
525{
526 fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, R2> {
527 let (input, context, first_result) = self.parser.parse(input, context)?;
528
529 let second_parser = (self.producer_fn)(first_result);
531 second_parser.parse(input, context)
532 }
533}
534
535#[macro_export]
538macro_rules! choice {
539 () => {
540 id().map(|()| Err(AmlError::WrongParser))
541 };
542
543 ($($parser: expr),+) => {
560 move |input, context| {
561 $(
562 let context = match ($parser).parse(input, context) {
563 Ok(parse_result) => return Ok(parse_result),
564 Err((_, new_context, crate::Propagate::Err(crate::AmlError::WrongParser))) => new_context,
565 Err((_, context, propagate)) => return Err((input, context, propagate)),
566 };
567 )+
568 Err((input, context, crate::Propagate::Err(crate::AmlError::WrongParser)))
569 }
570 }
571}
572
573#[macro_export]
579macro_rules! try_with_context {
580 ($context:expr, $expr:expr) => {
581 match $expr {
582 Ok(result) => result,
583 Err(err) => return (Err(Propagate::Err(err)), $context),
584 }
585 };
586}