فهرست منبع

Allow access to the AmlContext throughout the parse

This should make it super easy to e.g. add stuff to the namespace, or
change the current scope. In the future, it will mean we can set and access
args and locals when we actually execute AML methods.

It does make the combinators more ugly, which bleeds into the imperatively
written parsers (e.g. raw_pkg_length). In the future, I hope to rewrite
these parsers to make use of more powerful combinators, but I haven't worked
out how yet.
Isaac Woods 5 سال پیش
والد
کامیت
e2d469502a
7فایلهای تغییر یافته به همراه402 افزوده شده و 230 حذف شده
  1. 3 2
      aml_parser/src/lib.rs
  2. 60 31
      aml_parser/src/name_object.rs
  3. 38 13
      aml_parser/src/opcode.rs
  4. 178 113
      aml_parser/src/parser.rs
  5. 45 31
      aml_parser/src/pkg_length.rs
  6. 72 34
      aml_parser/src/term_object.rs
  7. 6 6
      aml_parser/src/test_utils.rs

+ 3 - 2
aml_parser/src/lib.rs

@@ -35,6 +35,7 @@ pub enum AmlError {
     InvalidFieldFlags,
 }
 
+#[derive(Debug)]
 pub struct AmlContext {
     namespace: BTreeMap<String, AmlValue>,
 }
@@ -52,10 +53,10 @@ impl AmlContext {
         match term_object::term_list(
             PkgLength::from_raw_length(stream, stream.len() as u32) as PkgLength
         )
-        .parse(stream)
+        .parse(stream, self)
         {
             Ok(_) => Ok(()),
-            Err((remaining, err)) => {
+            Err((remaining, _context, err)) => {
                 error!("Failed to parse AML stream. Err = {:?}", err);
                 trace!("Remaining AML: {:02x?}", remaining);
                 Err(err)

+ 60 - 31
aml_parser/src/name_object.rs

@@ -1,12 +1,16 @@
 use crate::{
     opcode::{opcode, DUAL_NAME_PREFIX, MULTI_NAME_PREFIX, NULL_NAME, PREFIX_CHAR, ROOT_CHAR},
     parser::{choice, comment_scope, consume, n_of, take, Parser},
+    AmlContext,
     AmlError,
 };
 use alloc::string::String;
 use core::str;
 
-pub fn name_string<'a>() -> impl Parser<'a, String> {
+pub fn name_string<'a, 'c>() -> impl Parser<'a, 'c, String>
+where
+    'c: 'a,
+{
     /*
      * NameString := <RootChar('\') NamePath> | <PrefixPath NamePath>
      * PrefixPath := Nothing | <'^' PrefixPath>
@@ -14,21 +18,27 @@ pub fn name_string<'a>() -> impl Parser<'a, String> {
     let root_name_string =
         opcode(ROOT_CHAR).then(name_path()).map(|((), name_path)| String::from("\\") + &name_path);
 
-    comment_scope("NameString", move |input: &'a [u8]| {
-        let first_char = *input.first().ok_or((input, AmlError::UnexpectedEndOfStream))?;
+    comment_scope("NameString", move |input: &'a [u8], context: &'c mut AmlContext| {
+        let first_char = match input.first() {
+            Some(&c) => c,
+            None => return Err((input, context, AmlError::UnexpectedEndOfStream)),
+        };
 
         match first_char {
-            ROOT_CHAR => root_name_string.parse(input),
+            ROOT_CHAR => root_name_string.parse(input, context),
             PREFIX_CHAR => {
                 // TODO: parse <PrefixPath NamePath> where there are actually PrefixChars
                 unimplemented!();
             }
-            _ => name_path().parse(input),
+            _ => name_path().parse(input, context),
         }
     })
 }
 
-pub fn name_path<'a>() -> impl Parser<'a, String> {
+pub fn name_path<'a, 'c>() -> impl Parser<'a, 'c, String>
+where
+    'c: 'a,
+{
     /*
      * NamePath := NullName | DualNamePath | MultiNamePath | NameSeg
      */
@@ -40,14 +50,20 @@ pub fn name_path<'a>() -> impl Parser<'a, String> {
     )
 }
 
-pub fn null_name<'a>() -> impl Parser<'a, String> {
+pub fn null_name<'a, 'c>() -> impl Parser<'a, 'c, String>
+where
+    'c: 'a,
+{
     /*
      * NullName := 0x00
      */
     opcode(NULL_NAME).map(|_| String::from(""))
 }
 
-pub fn dual_name_path<'a>() -> impl Parser<'a, String> {
+pub fn dual_name_path<'a, 'c>() -> impl Parser<'a, 'c, String>
+where
+    'c: 'a,
+{
     /*
      * DualNamePath := 0x2e NameSeg NameSeg
      */
@@ -57,19 +73,24 @@ pub fn dual_name_path<'a>() -> impl Parser<'a, String> {
         .map(|(((), first), second)| String::from(first.as_str()) + second.as_str())
 }
 
-pub fn multi_name_path<'a>() -> impl Parser<'a, String> {
+pub fn multi_name_path<'a, 'c>() -> impl Parser<'a, 'c, String>
+where
+    'c: 'a,
+{
     /*
      * MultiNamePath := 0x2f ByteData{SegCount} NameSeg(SegCount)
      */
-    move |input| {
-        let (new_input, ((), seg_count)) = opcode(MULTI_NAME_PREFIX).then(take()).parse(input)?;
-        match n_of(name_seg(), usize::from(seg_count)).parse(new_input) {
-            Ok((new_input, name_segs)) => Ok((
+    move |input, context| {
+        let (new_input, context, ((), seg_count)) =
+            opcode(MULTI_NAME_PREFIX).then(take()).parse(input, context)?;
+        match n_of(name_seg(), usize::from(seg_count)).parse(new_input, context) {
+            Ok((new_input, context, name_segs)) => Ok((
                 new_input,
+                context,
                 name_segs.iter().fold(String::new(), |name, name_seg| name + name_seg.as_str()),
             )),
             // Correct returned input to the one we haven't touched
-            Err((_, err)) => Err((input, err)),
+            Err((_, context, err)) => Err((input, context, err)),
         }
     }
 }
@@ -89,17 +110,20 @@ impl NameSeg {
     }
 }
 
-pub fn name_seg<'a>() -> impl Parser<'a, NameSeg> {
+pub fn name_seg<'a, 'c>() -> impl Parser<'a, 'c, NameSeg>
+where
+    'c: 'a,
+{
     /*
      * NameSeg := <LeadNameChar NameChar NameChar NameChar>
      */
     // TODO: can we write this better?
-    move |input| {
-        let (input, char_1) = consume(is_lead_name_char).parse(input)?;
-        let (input, char_2) = consume(is_name_char).parse(input)?;
-        let (input, char_3) = consume(is_name_char).parse(input)?;
-        let (input, char_4) = consume(is_name_char).parse(input)?;
-        Ok((input, NameSeg([char_1, char_2, char_3, char_4])))
+    move |input, context: &'c mut AmlContext| {
+        let (input, context, char_1) = consume(is_lead_name_char).parse(input, context)?;
+        let (input, context, char_2) = consume(is_name_char).parse(input, context)?;
+        let (input, context, char_3) = consume(is_name_char).parse(input, context)?;
+        let (input, context, char_4) = consume(is_name_char).parse(input, context)?;
+        Ok((input, context, NameSeg([char_1, char_2, char_3, char_4])))
     }
 }
 
@@ -118,33 +142,37 @@ fn is_name_char(byte: u8) -> bool {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::{parser::Parser, test_utils::*, AmlError};
+    use crate::{parser::Parser, test_utils::*, AmlContext, AmlError};
 
     #[test]
     fn test_name_seg() {
+        let mut context = AmlContext::new();
+
         check_ok!(
-            name_seg().parse(&[b'A', b'F', b'3', b'Z']),
+            name_seg().parse(&[b'A', b'F', b'3', b'Z'], &mut context),
             NameSeg([b'A', b'F', b'3', b'Z']),
             &[]
         );
         check_ok!(
-            name_seg().parse(&[b'A', b'F', b'3', b'Z', 0xff]),
+            name_seg().parse(&[b'A', b'F', b'3', b'Z', 0xff], &mut context),
             NameSeg([b'A', b'F', b'3', b'Z']),
             &[0xff]
         );
         check_err!(
-            name_seg().parse(&[0xff, b'E', b'A', b'7']),
+            name_seg().parse(&[0xff, b'E', b'A', b'7'], &mut context),
             AmlError::UnexpectedByte(0xff),
             &[0xff, b'E', b'A', b'7']
         );
-        check_err!(name_seg().parse(&[]), AmlError::UnexpectedEndOfStream, &[]);
+        check_err!(name_seg().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
     }
 
     #[test]
     fn test_name_path() {
-        check_err!(name_path().parse(&[]), AmlError::UnexpectedEndOfStream, &[]);
-        check_ok!(name_path().parse(&[0x00]), String::from(""), &[]);
-        check_ok!(name_path().parse(&[0x00, 0x00]), String::from(""), &[0x00]);
+        let mut context = AmlContext::new();
+
+        check_err!(name_path().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
+        check_ok!(name_path().parse(&[0x00], &mut context), String::from(""), &[]);
+        check_ok!(name_path().parse(&[0x00, 0x00], &mut context), String::from(""), &[0x00]);
         // TODO: this failure is actually a symptom of `choice!` not working quite correctly. When
         // the dual_name_path parser fails (this is one, but is too short), it carries on and then
         // returns a confusing error: `UnexpectedByte(0x2e)`. Not sure how the best way to go about
@@ -152,14 +180,15 @@ mod tests {
         //
         // For now, we know about this corner case, so altering the unit-test for now.
         check_err!(
-            name_path().parse(&[0x2e, b'A']),
+            name_path().parse(&[0x2e, b'A'], &mut context),
             AmlError::UnexpectedByte(0x2e),
             // TODO: this is the correct error
             // AmlError::UnexpectedEndOfStream,
             &[0x2e, b'A']
         );
         check_ok!(
-            name_path().parse(&[0x2e, b'A', b'B', b'C', b'D', b'E', b'_', b'F', b'G']),
+            name_path()
+                .parse(&[0x2e, b'A', b'B', b'C', b'D', b'E', b'_', b'F', b'G'], &mut context),
             String::from("ABCDE_FG"),
             &[]
         );

+ 38 - 13
aml_parser/src/opcode.rs

@@ -1,4 +1,4 @@
-use crate::{parser::*, AmlError};
+use crate::{parser::*, AmlContext, AmlError};
 
 pub const NULL_NAME: u8 = 0x00;
 pub const DUAL_NAME_PREFIX: u8 = 0x2E;
@@ -32,15 +32,21 @@ pub const EXT_DEVICE_OP: u8 = 0x82;
 
 pub const EXT_OPCODE_PREFIX: u8 = 0x5b;
 
-pub(crate) fn opcode<'a>(opcode: u8) -> impl Parser<'a, ()> {
-    move |stream: &'a [u8]| match stream.first() {
-        None => Err((stream, AmlError::UnexpectedEndOfStream)),
-        Some(&byte) if byte == opcode => Ok((&stream[1..], ())),
-        Some(&byte) => Err((stream, AmlError::UnexpectedByte(byte))),
+pub(crate) fn opcode<'a, 'c>(opcode: u8) -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
+    move |input: &'a [u8], context: &'c mut AmlContext| match input.first() {
+        None => Err((input, context, AmlError::UnexpectedEndOfStream)),
+        Some(&byte) if byte == opcode => Ok((&input[1..], context, ())),
+        Some(&byte) => Err((input, context, AmlError::UnexpectedByte(byte))),
     }
 }
 
-pub(crate) fn ext_opcode<'a>(ext_opcode: u8) -> impl Parser<'a, ()> {
+pub(crate) fn ext_opcode<'a, 'c>(ext_opcode: u8) -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
     opcode(EXT_OPCODE_PREFIX).then(opcode(ext_opcode)).map(|_| ())
 }
 
@@ -51,23 +57,42 @@ mod tests {
 
     #[test]
     fn empty() {
-        check_err!(opcode(NULL_NAME).parse(&[]), AmlError::UnexpectedEndOfStream, &[]);
-        check_err!(ext_opcode(EXT_FIELD_OP).parse(&[]), AmlError::UnexpectedEndOfStream, &[]);
+        let mut context = AmlContext::new();
+        check_err!(
+            opcode(NULL_NAME).parse(&[], &mut context),
+            AmlError::UnexpectedEndOfStream,
+            &[]
+        );
+        check_err!(
+            ext_opcode(EXT_FIELD_OP).parse(&[], &mut context),
+            AmlError::UnexpectedEndOfStream,
+            &[]
+        );
     }
 
     #[test]
     fn simple_opcodes() {
-        check_ok!(opcode(SCOPE_OP).parse(&[SCOPE_OP]), (), &[]);
-        check_ok!(opcode(NAME_OP).parse(&[NAME_OP, 0x31, 0x55, 0xf3]), (), &[0x31, 0x55, 0xf3]);
+        let mut context = AmlContext::new();
+        check_ok!(opcode(SCOPE_OP).parse(&[SCOPE_OP], &mut context), (), &[]);
+        check_ok!(
+            opcode(NAME_OP).parse(&[NAME_OP, 0x31, 0x55, 0xf3], &mut context),
+            (),
+            &[0x31, 0x55, 0xf3]
+        );
     }
 
     #[test]
     fn extended_opcodes() {
+        let mut context = AmlContext::new();
         check_err!(
-            ext_opcode(EXT_FIELD_OP).parse(&[EXT_FIELD_OP, EXT_FIELD_OP]),
+            ext_opcode(EXT_FIELD_OP).parse(&[EXT_FIELD_OP, EXT_FIELD_OP], &mut context),
             AmlError::UnexpectedByte(EXT_FIELD_OP),
             &[EXT_FIELD_OP, EXT_FIELD_OP]
         );
-        check_ok!(ext_opcode(EXT_FIELD_OP).parse(&[EXT_OPCODE_PREFIX, EXT_FIELD_OP]), (), &[]);
+        check_ok!(
+            ext_opcode(EXT_FIELD_OP).parse(&[EXT_OPCODE_PREFIX, EXT_FIELD_OP], &mut context),
+            (),
+            &[]
+        );
     }
 }

+ 178 - 113
aml_parser/src/parser.rs

@@ -1,37 +1,41 @@
-use crate::AmlError;
+use crate::{AmlContext, AmlError};
 use alloc::vec::Vec;
 use core::marker::PhantomData;
 use log::trace;
 
-pub type ParseResult<'a, R> = Result<(&'a [u8], R), (&'a [u8], AmlError)>;
+pub type ParseResult<'a, 'c, R> =
+    Result<(&'a [u8], &'c mut AmlContext, R), (&'a [u8], &'c mut AmlContext, AmlError)>;
 
-pub trait Parser<'a, R>: Sized {
-    fn parse(&self, input: &'a [u8]) -> ParseResult<'a, R>;
+pub trait Parser<'a, 'c, R>: Sized
+where
+    'c: 'a,
+{
+    fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, R>;
 
-    fn map<F, A>(self, map_fn: F) -> Map<'a, Self, F, R, A>
+    fn map<F, A>(self, map_fn: F) -> Map<'a, 'c, Self, F, R, A>
     where
         F: Fn(R) -> A,
     {
         Map { parser: self, map_fn, _phantom: PhantomData }
     }
 
-    fn discard_result(self) -> DiscardResult<'a, Self, R> {
+    fn discard_result(self) -> DiscardResult<'a, 'c, Self, R> {
         DiscardResult { parser: self, _phantom: PhantomData }
     }
 
     /// Try parsing with `self`. If it fails, try parsing with `other`, returning the result of the
     /// first of the two parsers to succeed. To `or` multiple parsers ergonomically, see the
     /// `choice!` macro.
-    fn or<OtherParser>(self, other: OtherParser) -> Or<'a, Self, OtherParser, R>
+    fn or<OtherParser>(self, other: OtherParser) -> Or<'a, 'c, Self, OtherParser, R>
     where
-        OtherParser: Parser<'a, R>,
+        OtherParser: Parser<'a, 'c, R>,
     {
         Or { p1: self, p2: other, _phantom: PhantomData }
     }
 
-    fn then<NextParser, NextR>(self, next: NextParser) -> Then<'a, Self, NextParser, R, NextR>
+    fn then<NextParser, NextR>(self, next: NextParser) -> Then<'a, 'c, Self, NextParser, R, NextR>
     where
-        NextParser: Parser<'a, NextR>,
+        NextParser: Parser<'a, 'c, NextR>,
     {
         Then { p1: self, p2: next, _phantom: PhantomData }
     }
@@ -41,49 +45,60 @@ pub trait Parser<'a, R>: Sized {
     /// but is useful for when the next parser's behaviour depends on a property of the result of
     /// the first (e.g. the first parser might parse a length `n`, and the second parser then
     /// consumes `n` bytes).
-    fn feed<F, P2, R2>(self, producer_fn: F) -> Feed<'a, Self, P2, F, R, R2>
+    fn feed<F, P2, R2>(self, producer_fn: F) -> Feed<'a, 'c, Self, P2, F, R, R2>
     where
-        P2: Parser<'a, R2>,
+        P2: Parser<'a, 'c, R2>,
         F: Fn(R) -> P2,
     {
         Feed { parser: self, producer_fn, _phantom: PhantomData }
     }
 }
 
-impl<'a, F, R> Parser<'a, R> for F
+impl<'a, 'c, F, R> Parser<'a, 'c, R> for F
 where
-    F: Fn(&'a [u8]) -> ParseResult<'a, R>,
+    'c: 'a,
+    F: Fn(&'a [u8], &'c mut AmlContext) -> ParseResult<'a, 'c, R>,
 {
-    fn parse(&self, input: &'a [u8]) -> ParseResult<'a, R> {
-        self(input)
+    fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, R> {
+        self(input, context)
     }
 }
 
-pub fn take<'a>() -> impl Parser<'a, u8> {
-    move |input: &'a [u8]| match input.first() {
-        Some(&byte) => Ok((&input[1..], byte)),
-        None => Err((input, AmlError::UnexpectedEndOfStream)),
+pub fn take<'a, 'c>() -> impl Parser<'a, 'c, u8>
+where
+    'c: 'a,
+{
+    move |input: &'a [u8], context: &'c mut AmlContext| match input.first() {
+        Some(&byte) => Ok((&input[1..], context, byte)),
+        None => Err((input, context, AmlError::UnexpectedEndOfStream)),
     }
 }
 
-pub fn take_u16<'a>() -> impl Parser<'a, u16> {
-    move |input: &'a [u8]| {
+pub fn take_u16<'a, 'c>() -> impl Parser<'a, 'c, u16>
+where
+    'c: 'a,
+{
+    move |input: &'a [u8], context: &'c mut AmlContext| {
         if input.len() < 2 {
-            return Err((input, AmlError::UnexpectedEndOfStream));
+            return Err((input, context, AmlError::UnexpectedEndOfStream));
         }
 
-        Ok((&input[2..], input[0] as u16 + ((input[1] as u16) << 8)))
+        Ok((&input[2..], context, input[0] as u16 + ((input[1] as u16) << 8)))
     }
 }
 
-pub fn take_u32<'a>() -> impl Parser<'a, u32> {
-    move |input: &'a [u8]| {
+pub fn take_u32<'a, 'c>() -> impl Parser<'a, 'c, u32>
+where
+    'c: 'a,
+{
+    move |input: &'a [u8], context: &'c mut AmlContext| {
         if input.len() < 4 {
-            return Err((input, AmlError::UnexpectedEndOfStream));
+            return Err((input, context, AmlError::UnexpectedEndOfStream));
         }
 
         Ok((
             &input[4..],
+            context,
             input[0] as u32
                 + ((input[1] as u32) << 8)
                 + ((input[2] as u32) << 16)
@@ -92,14 +107,18 @@ pub fn take_u32<'a>() -> impl Parser<'a, u32> {
     }
 }
 
-pub fn take_u64<'a>() -> impl Parser<'a, u64> {
-    move |input: &'a [u8]| {
+pub fn take_u64<'a, 'c>() -> impl Parser<'a, 'c, u64>
+where
+    'c: 'a,
+{
+    move |input: &'a [u8], context: &'c mut AmlContext| {
         if input.len() < 8 {
-            return Err((input, AmlError::UnexpectedEndOfStream));
+            return Err((input, context, AmlError::UnexpectedEndOfStream));
         }
 
         Ok((
             &input[8..],
+            context,
             input[0] as u64
                 + ((input[1] as u64) << 8)
                 + ((input[2] as u64) << 16)
@@ -112,178 +131,201 @@ pub fn take_u64<'a>() -> impl Parser<'a, u64> {
     }
 }
 
-pub fn take_n<'a>(n: usize) -> impl Parser<'a, &'a [u8]> {
-    move |input: &'a [u8]| {
+pub fn take_n<'a, 'c>(n: usize) -> impl Parser<'a, 'c, &'a [u8]>
+where
+    'c: 'a,
+{
+    move |input: &'a [u8], context| {
         if input.len() < n {
-            return Err((input, AmlError::UnexpectedEndOfStream));
+            return Err((input, context, AmlError::UnexpectedEndOfStream));
         }
 
         let (result, new_input) = input.split_at(n);
-        Ok((new_input, result))
+        Ok((new_input, context, result))
     }
 }
 
 // TODO: can we use const generics (e.g. [R; N]) to avoid allocating?
-pub fn n_of<'a, P, R>(parser: P, n: usize) -> impl Parser<'a, Vec<R>>
+pub fn n_of<'a, 'c, P, R>(parser: P, n: usize) -> impl Parser<'a, 'c, Vec<R>>
 where
-    P: Parser<'a, R>,
+    'c: 'a,
+    P: Parser<'a, 'c, R>,
 {
-    move |input| {
+    // TODO: can we write this more nicely?
+    move |mut input, mut context| {
         let mut results = Vec::with_capacity(n);
-        let mut new_input = input;
 
         for _ in 0..n {
-            let (after_input, result) = match parser.parse(new_input) {
-                Ok((input, result)) => (input, result),
-                Err((_, err)) => return Err((input, err)),
+            let (new_input, new_context, result) = match parser.parse(input, context) {
+                Ok((input, context, result)) => (input, context, result),
+                Err((_, context, err)) => return Err((input, context, err)),
             };
             results.push(result);
-            new_input = after_input;
+            input = new_input;
+            context = new_context;
         }
 
-        Ok((new_input, results))
+        Ok((input, context, results))
     }
 }
 
-pub fn consume<'a, F>(condition: F) -> impl Parser<'a, u8>
+pub fn consume<'a, 'c, F>(condition: F) -> impl Parser<'a, 'c, u8>
 where
+    'c: 'a,
     F: Fn(u8) -> bool,
 {
-    move |input: &'a [u8]| match input.first() {
-        Some(&byte) if condition(byte) => Ok((&input[1..], byte)),
-        Some(&byte) => Err((input, AmlError::UnexpectedByte(byte))),
-        None => Err((input, AmlError::UnexpectedEndOfStream)),
+    move |input: &'a [u8], context: &'c mut AmlContext| match input.first() {
+        Some(&byte) if condition(byte) => Ok((&input[1..], context, byte)),
+        Some(&byte) => Err((input, context, AmlError::UnexpectedByte(byte))),
+        None => Err((input, context, AmlError::UnexpectedEndOfStream)),
     }
 }
 
-pub fn comment_scope<'a, P, R>(scope_name: &'a str, parser: P) -> impl Parser<'a, R>
+pub fn comment_scope<'a, 'c, P, R>(scope_name: &'a str, parser: P) -> impl Parser<'a, 'c, R>
 where
+    'c: 'a,
     R: core::fmt::Debug,
-    P: Parser<'a, R>,
+    P: Parser<'a, 'c, R>,
 {
-    move |input| {
+    move |input, context| {
         trace!("--> {}", scope_name);
         // Return if the parse fails, so we don't print the tail. Makes it easier to debug.
-        let (new_input, result) = parser.parse(input)?;
+        let (new_input, context, result) = parser.parse(input, context)?;
         trace!("<-- {}({:?})", scope_name, result);
-        Ok((new_input, result))
+        Ok((new_input, context, result))
     }
 }
 
-pub struct Or<'a, P1, P2, R>
+pub struct Or<'a, 'c, P1, P2, R>
 where
-    P1: Parser<'a, R>,
-    P2: Parser<'a, R>,
+    'c: 'a,
+    P1: Parser<'a, 'c, R>,
+    P2: Parser<'a, 'c, R>,
 {
     p1: P1,
     p2: P2,
-    _phantom: PhantomData<&'a R>,
+    _phantom: PhantomData<(&'a R, &'c ())>,
 }
 
-impl<'a, P1, P2, R> Parser<'a, R> for Or<'a, P1, P2, R>
+impl<'a, 'c, P1, P2, R> Parser<'a, 'c, R> for Or<'a, 'c, P1, P2, R>
 where
-    P1: Parser<'a, R>,
-    P2: Parser<'a, R>,
+    'c: 'a,
+    P1: Parser<'a, 'c, R>,
+    P2: Parser<'a, 'c, R>,
 {
-    fn parse(&self, input: &'a [u8]) -> ParseResult<'a, R> {
-        match self.p1.parse(input) {
-            Ok(result) => return Ok(result),
-            Err(_) => (),
-        }
+    fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, R> {
+        let context = match self.p1.parse(input, context) {
+            Ok(parse_result) => return Ok(parse_result),
+            Err((_, context, _)) => context,
+        };
 
-        self.p2.parse(input)
+        self.p2.parse(input, context)
     }
 }
 
-pub struct Map<'a, P, F, R, A>
+pub struct Map<'a, 'c, P, F, R, A>
 where
-    P: Parser<'a, R>,
+    'c: 'a,
+    P: Parser<'a, 'c, R>,
     F: Fn(R) -> A,
 {
     parser: P,
     map_fn: F,
-    _phantom: PhantomData<&'a (R, A)>,
+    _phantom: PhantomData<(&'a (R, A), &'c ())>,
 }
 
-impl<'a, P, F, R, A> Parser<'a, A> for Map<'a, P, F, R, A>
+impl<'a, 'c, P, F, R, A> Parser<'a, 'c, A> for Map<'a, 'c, P, F, R, A>
 where
-    P: Parser<'a, R>,
+    'c: 'a,
+    P: Parser<'a, 'c, R>,
     F: Fn(R) -> A,
 {
-    fn parse(&self, input: &'a [u8]) -> ParseResult<'a, A> {
-        self.parser.parse(input).map(|(new_input, result)| (new_input, (self.map_fn)(result)))
+    fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, A> {
+        self.parser
+            .parse(input, context)
+            .map(|(new_input, new_context, result)| (new_input, new_context, (self.map_fn)(result)))
     }
 }
 
-pub struct DiscardResult<'a, P, R>
+pub struct DiscardResult<'a, 'c, P, R>
 where
-    P: Parser<'a, R>,
+    'c: 'a,
+    P: Parser<'a, 'c, R>,
 {
     parser: P,
-    _phantom: PhantomData<&'a R>,
+    _phantom: PhantomData<(&'a R, &'c ())>,
 }
 
-impl<'a, P, R> Parser<'a, ()> for DiscardResult<'a, P, R>
+impl<'a, 'c, P, R> Parser<'a, 'c, ()> for DiscardResult<'a, 'c, P, R>
 where
-    P: Parser<'a, R>,
+    'c: 'a,
+    P: Parser<'a, 'c, R>,
 {
-    fn parse(&self, input: &'a [u8]) -> ParseResult<'a, ()> {
-        self.parser.parse(input).map(|(new_input, _)| (new_input, ()))
+    fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, ()> {
+        self.parser
+            .parse(input, context)
+            .map(|(new_input, new_context, _)| (new_input, new_context, ()))
     }
 }
 
-pub struct Then<'a, P1, P2, R1, R2>
+pub struct Then<'a, 'c, P1, P2, R1, R2>
 where
-    P1: Parser<'a, R1>,
-    P2: Parser<'a, R2>,
+    'c: 'a,
+    P1: Parser<'a, 'c, R1>,
+    P2: Parser<'a, 'c, R2>,
 {
     p1: P1,
     p2: P2,
-    _phantom: PhantomData<&'a (R1, R2)>,
+    _phantom: PhantomData<(&'a (R1, R2), &'c ())>,
 }
 
-impl<'a, P1, P2, R1, R2> Parser<'a, (R1, R2)> for Then<'a, P1, P2, R1, R2>
+impl<'a, 'c, P1, P2, R1, R2> Parser<'a, 'c, (R1, R2)> for Then<'a, 'c, P1, P2, R1, R2>
 where
-    P1: Parser<'a, R1>,
-    P2: Parser<'a, R2>,
+    'c: 'a,
+    P1: Parser<'a, 'c, R1>,
+    P2: Parser<'a, 'c, R2>,
 {
-    fn parse(&self, input: &'a [u8]) -> ParseResult<'a, (R1, R2)> {
-        self.p1.parse(input).and_then(|(next_input, result_a)| {
-            self.p2
-                .parse(next_input)
-                .map(|(final_input, result_b)| (final_input, (result_a, result_b)))
+    fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, (R1, R2)> {
+        self.p1.parse(input, context).and_then(|(next_input, context, result_a)| {
+            self.p2.parse(next_input, context).map(|(final_input, context, result_b)| {
+                (final_input, context, (result_a, result_b))
+            })
         })
     }
 }
 
-pub struct Feed<'a, P1, P2, F, R1, R2>
+pub struct Feed<'a, 'c, P1, P2, F, R1, R2>
 where
-    P1: Parser<'a, R1>,
-    P2: Parser<'a, R2>,
+    'c: 'a,
+    P1: Parser<'a, 'c, R1>,
+    P2: Parser<'a, 'c, R2>,
     F: Fn(R1) -> P2,
 {
     parser: P1,
     producer_fn: F,
-    _phantom: PhantomData<&'a (R1, R2)>,
+    _phantom: PhantomData<(&'a (R1, R2), &'c ())>,
 }
 
-impl<'a, P1, P2, F, R1, R2> Parser<'a, R2> for Feed<'a, P1, P2, F, R1, R2>
+impl<'a, 'c, P1, P2, F, R1, R2> Parser<'a, 'c, R2> for Feed<'a, 'c, P1, P2, F, R1, R2>
 where
-    P1: Parser<'a, R1>,
-    P2: Parser<'a, R2>,
+    'c: 'a,
+    P1: Parser<'a, 'c, R1>,
+    P2: Parser<'a, 'c, R2>,
     F: Fn(R1) -> P2,
 {
-    fn parse(&self, input: &'a [u8]) -> ParseResult<'a, R2> {
-        let (input, first_result) = self.parser.parse(input)?;
+    fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, R2> {
+        let (input, context, first_result) = self.parser.parse(input, context)?;
 
         // We can now produce the second parser, and parse using that.
         let second_parser = (self.producer_fn)(first_result);
-        second_parser.parse(input)
+        second_parser.parse(input, context)
     }
 }
 
 /// Takes a number of parsers, and tries to apply each one to the input in order. Returns the
 /// result of the first one that succeeds, or fails if all of them fail.
+// TODO: maybe this should emit a custom error at the end? "None of these parsers could parse
+// this?" Or maybe just a specific UnexpectedByte?
 pub macro choice {
     ($first_parser: expr) => {
         $first_parser
@@ -304,25 +346,48 @@ mod tests {
 
     #[test]
     fn test_take_n() {
-        check_err!(take_n(1).parse(&[]), AmlError::UnexpectedEndOfStream, &[]);
-        check_err!(take_n(2).parse(&[0xf5]), AmlError::UnexpectedEndOfStream, &[0xf5]);
+        let mut context = AmlContext::new();
+        check_err!(take_n(1).parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
+        check_err!(
+            take_n(2).parse(&[0xf5], &mut context),
+            AmlError::UnexpectedEndOfStream,
+            &[0xf5]
+        );
 
-        check_ok!(take_n(1).parse(&[0xff]), &[0xff], &[]);
-        check_ok!(take_n(1).parse(&[0xff, 0xf8]), &[0xff], &[0xf8]);
-        check_ok!(take_n(2).parse(&[0xff, 0xf8]), &[0xff, 0xf8], &[]);
+        check_ok!(take_n(1).parse(&[0xff], &mut context), &[0xff], &[]);
+        check_ok!(take_n(1).parse(&[0xff, 0xf8], &mut context), &[0xff], &[0xf8]);
+        check_ok!(take_n(2).parse(&[0xff, 0xf8], &mut context), &[0xff, 0xf8], &[]);
     }
 
     #[test]
     fn test_take_ux() {
-        check_err!(take_u16().parse(&[0x34]), AmlError::UnexpectedEndOfStream, &[0x34]);
-        check_ok!(take_u16().parse(&[0x34, 0x12]), 0x1234, &[]);
+        let mut context = AmlContext::new();
+        check_err!(
+            take_u16().parse(&[0x34], &mut context),
+            AmlError::UnexpectedEndOfStream,
+            &[0x34]
+        );
+        check_ok!(take_u16().parse(&[0x34, 0x12], &mut context), 0x1234, &[]);
 
-        check_err!(take_u32().parse(&[0x34, 0x12]), AmlError::UnexpectedEndOfStream, &[0x34, 0x12]);
-        check_ok!(take_u32().parse(&[0x34, 0x12, 0xf4, 0xc3, 0x3e]), 0xc3f41234, &[0x3e]);
+        check_err!(
+            take_u32().parse(&[0x34, 0x12], &mut context),
+            AmlError::UnexpectedEndOfStream,
+            &[0x34, 0x12]
+        );
+        check_ok!(
+            take_u32().parse(&[0x34, 0x12, 0xf4, 0xc3, 0x3e], &mut context),
+            0xc3f41234,
+            &[0x3e]
+        );
 
-        check_err!(take_u64().parse(&[0x34]), AmlError::UnexpectedEndOfStream, &[0x34]);
+        check_err!(
+            take_u64().parse(&[0x34], &mut context),
+            AmlError::UnexpectedEndOfStream,
+            &[0x34]
+        );
         check_ok!(
-            take_u64().parse(&[0x34, 0x12, 0x35, 0x76, 0xd4, 0x43, 0xa3, 0xb6, 0xff, 0x00]),
+            take_u64()
+                .parse(&[0x34, 0x12, 0x35, 0x76, 0xd4, 0x43, 0xa3, 0xb6, 0xff, 0x00], &mut context),
             0xb6a343d476351234,
             &[0xff, 0x00]
         );

+ 45 - 31
aml_parser/src/pkg_length.rs

@@ -1,5 +1,6 @@
 use crate::{
     parser::{take, take_n, Parser},
+    AmlContext,
     AmlError,
 };
 use bit_field::BitField;
@@ -24,21 +25,27 @@ impl PkgLength {
     }
 }
 
-pub fn pkg_length<'a>() -> impl Parser<'a, PkgLength> {
-    move |input: &'a [u8]| {
-        let (new_input, raw_length) = raw_pkg_length().parse(input)?;
+pub fn pkg_length<'a, 'c>() -> impl Parser<'a, 'c, PkgLength>
+where
+    'c: 'a,
+{
+    move |input: &'a [u8], context: &'c mut AmlContext| {
+        let (new_input, context, raw_length) = raw_pkg_length().parse(input, context)?;
 
         /*
          * NOTE: we use the original input here, because `raw_length` includes the length of the
          * `PkgLength`.
          */
-        Ok((new_input, PkgLength::from_raw_length(input, raw_length)))
+        Ok((new_input, context, PkgLength::from_raw_length(input, raw_length)))
     }
 }
 
 /// Parses a `PkgLength` and returns the *raw length*. If you want an instance of `PkgLength`, use
 /// `pkg_length` instead.
-pub fn raw_pkg_length<'a>() -> impl Parser<'a, u32> {
+pub fn raw_pkg_length<'a, 'c>() -> impl Parser<'a, 'c, u32>
+where
+    'c: 'a,
+{
     /*
      * PkgLength := PkgLeadByte |
      * <PkgLeadByte ByteData> |
@@ -47,34 +54,38 @@ pub fn raw_pkg_length<'a>() -> impl Parser<'a, u32> {
      *
      * The length encoded by the PkgLength includes the number of bytes used to encode it.
      */
-    move |input: &'a [u8]| {
-        let (new_input, lead_byte) = take().parse(input)?;
+    move |input: &'a [u8], context: &'c mut AmlContext| {
+        let (new_input, context, lead_byte) = take().parse(input, context)?;
         let byte_count = lead_byte.get_bits(6..8);
 
         if byte_count == 0 {
             let length = u32::from(lead_byte.get_bits(0..6));
-            return Ok((new_input, length));
+            return Ok((new_input, context, length));
         }
 
-        let (new_input, length): (&[u8], u32) = match take_n(byte_count as usize).parse(new_input) {
-            Ok((new_input, bytes)) => {
-                let initial_length = u32::from(lead_byte.get_bits(0..4));
-                (
-                    new_input,
-                    bytes.iter().enumerate().fold(initial_length, |length, (i, &byte)| {
-                        length + (u32::from(byte) << (4 + i * 8))
-                    }),
-                )
-            }
+        let (new_input, context, length): (&[u8], &mut AmlContext, u32) =
+            match take_n(byte_count as usize).parse(new_input, context) {
+                Ok((new_input, context, bytes)) => {
+                    let initial_length = u32::from(lead_byte.get_bits(0..4));
+                    (
+                        new_input,
+                        context,
+                        bytes.iter().enumerate().fold(initial_length, |length, (i, &byte)| {
+                            length + (u32::from(byte) << (4 + i * 8))
+                        }),
+                    )
+                }
 
-            /*
-             * The stream was too short. We return an error, making sure to return the
-             * *original* stream (that we haven't consumed any of).
-             */
-            Err(_) => return Err((input, AmlError::UnexpectedEndOfStream)),
-        };
+                /*
+                 * The stream was too short. We return an error, making sure to return the
+                 * *original* stream (that we haven't consumed any of).
+                 */
+                Err((_, context, _)) => {
+                    return Err((input, context, AmlError::UnexpectedEndOfStream))
+                }
+            };
 
-        Ok((new_input, length))
+        Ok((new_input, context, length))
     }
 }
 
@@ -84,8 +95,9 @@ mod tests {
     use crate::{test_utils::*, AmlError};
 
     fn test_correct_pkglength(stream: &[u8], expected_raw_length: u32, expected_leftover: &[u8]) {
+        let mut context = AmlContext::new();
         check_ok!(
-            pkg_length().parse(stream),
+            pkg_length().parse(stream, &mut context),
             PkgLength::from_raw_length(stream, expected_raw_length),
             &expected_leftover
         );
@@ -93,14 +105,16 @@ mod tests {
 
     #[test]
     fn test_raw_pkg_length() {
-        check_ok!(raw_pkg_length().parse(&[0b01000101, 0x14]), 325, &[]);
-        check_ok!(raw_pkg_length().parse(&[0b01000111, 0x14, 0x46]), 327, &[0x46]);
-        check_ok!(raw_pkg_length().parse(&[0b10000111, 0x14, 0x46]), 287047, &[]);
+        let mut context = AmlContext::new();
+        check_ok!(raw_pkg_length().parse(&[0b01000101, 0x14], &mut context), 325, &[]);
+        check_ok!(raw_pkg_length().parse(&[0b01000111, 0x14, 0x46], &mut context), 327, &[0x46]);
+        check_ok!(raw_pkg_length().parse(&[0b10000111, 0x14, 0x46], &mut context), 287047, &[]);
     }
 
     #[test]
     fn test_pkg_length() {
-        check_err!(pkg_length().parse(&[]), AmlError::UnexpectedEndOfStream, &[]);
+        let mut context = AmlContext::new();
+        check_err!(pkg_length().parse(&[], &mut context), AmlError::UnexpectedEndOfStream, &[]);
         test_correct_pkglength(&[0x00], 0, &[]);
         test_correct_pkglength(
             &[0x05, 0xf5, 0x7f, 0x3e, 0x54, 0x03],
@@ -108,7 +122,7 @@ mod tests {
             &[0xf5, 0x7f, 0x3e, 0x54, 0x03],
         );
         check_err!(
-            pkg_length().parse(&[0b11000000, 0xff, 0x4f]),
+            pkg_length().parse(&[0b11000000, 0xff, 0x4f], &mut context),
             AmlError::UnexpectedEndOfStream,
             &[0b11000000, 0xff, 0x4f]
         );

+ 72 - 34
aml_parser/src/term_object.rs

@@ -4,6 +4,7 @@ use crate::{
     parser::{choice, comment_scope, take, take_u16, take_u32, take_u64, ParseResult, Parser},
     pkg_length::{pkg_length, PkgLength},
     value::{AmlValue, FieldFlags},
+    AmlContext,
     AmlError,
 };
 use alloc::string::String;
@@ -11,22 +12,29 @@ use log::{debug, trace};
 
 /// `TermList`s are usually found within explicit-length objects (so they have a `PkgLength`
 /// elsewhere in the structure), so this takes a number of bytes to parse.
-pub fn term_list<'a>(list_length: PkgLength) -> impl Parser<'a, ()> {
+pub fn term_list<'a, 'c>(list_length: PkgLength) -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
     /*
      * TermList := Nothing | <TermObj TermList>
      */
-    move |mut input: &'a [u8]| -> ParseResult<'a, ()> {
+    move |mut input: &'a [u8], mut context: &'c mut AmlContext| {
         while list_length.still_parsing(input) {
-            let (new_input, ()) = term_object().parse(input)?;
+            let (new_input, new_context, ()) = term_object().parse(input, context)?;
             input = new_input;
+            context = new_context;
         }
 
-        Ok((input, ()))
+        Ok((input, context, ()))
     }
 }
 
 // TODO: maybe return `AmlValue` on success
-pub fn term_object<'a>() -> impl Parser<'a, ()> {
+pub fn term_object<'a, 'c>() -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
     /*
      * TermObj := NamespaceModifierObj | NamedObj | Type1Opcode | Type2Opcode
      * NamespaceModifierObj := DefAlias | DefName | DefScope
@@ -34,7 +42,10 @@ pub fn term_object<'a>() -> impl Parser<'a, ()> {
     comment_scope("TermObj", choice!(def_scope(), def_op_region(), def_field()))
 }
 
-pub fn def_scope<'a>() -> impl Parser<'a, ()> {
+pub fn def_scope<'a, 'c>() -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
     /*
      * DefScope := 0x10 PkgLength NameString TermList
      */
@@ -49,7 +60,10 @@ pub fn def_scope<'a>() -> impl Parser<'a, ()> {
         .discard_result()
 }
 
-pub fn def_op_region<'a>() -> impl Parser<'a, ()> {
+pub fn def_op_region<'a, 'c>() -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
     /*
      * DefOpRegion := ExtOpPrefix 0x80 NameString RegionSpace RegionOffset RegionLen
      * RegionSpace := ByteData (where 0x00      = SystemMemory
@@ -80,7 +94,10 @@ pub fn def_op_region<'a>() -> impl Parser<'a, ()> {
         .discard_result()
 }
 
-pub fn def_field<'a>() -> impl Parser<'a, ()> {
+pub fn def_field<'a, 'c>() -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
     /*
      * DefField = ExtOpPrefix 0x81 PkgLength NameString FieldFlags FieldList
      * FieldFlags := ByteData
@@ -90,18 +107,22 @@ pub fn def_field<'a>() -> impl Parser<'a, ()> {
             "DefField",
             pkg_length().then(name_string()).then(take()).feed(
                 |((list_length, region_name), flags)| {
-                    move |mut input: &'a [u8]| -> ParseResult<'a, ()> {
+                    move |mut input: &'a [u8],
+                          mut context: &'c mut AmlContext|
+                          -> ParseResult<'a, 'c, ()> {
                         /*
                          * FieldList := Nothing | <FieldElement FieldList>
                          */
                         // TODO: can this pattern be expressed as a combinator
                         while list_length.still_parsing(input) {
-                            let (new_input, ()) =
-                                field_element(&region_name, FieldFlags::new(flags)).parse(input)?;
+                            let (new_input, new_context, ()) =
+                                field_element(&region_name, FieldFlags::new(flags))
+                                    .parse(input, context)?;
                             input = new_input;
+                            context = new_context;
                         }
 
-                        Ok((input, ()))
+                        Ok((input, context, ()))
                     }
                 },
             ),
@@ -109,7 +130,10 @@ pub fn def_field<'a>() -> impl Parser<'a, ()> {
         .discard_result()
 }
 
-pub fn field_element<'a>(region_name: &String, flags: FieldFlags) -> impl Parser<'a, ()> {
+pub fn field_element<'a, 'c>(region_name: &String, flags: FieldFlags) -> impl Parser<'a, 'c, ()>
+where
+    'c: 'a,
+{
     /*
      * FieldElement := NamedField | ReservedField | AccessField | ExtendedAccessField |
      *                 ConnectField
@@ -150,7 +174,10 @@ pub fn field_element<'a>(region_name: &String, flags: FieldFlags) -> impl Parser
     choice!(reserved_field, access_field, named_field)
 }
 
-pub fn term_arg<'a>() -> impl Parser<'a, AmlValue> {
+pub fn term_arg<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
+where
+    'c: 'a,
+{
     /*
      * TermArg := Type2Opcode | DataObject | ArgObj | LocalObj
      */
@@ -158,7 +185,10 @@ pub fn term_arg<'a>() -> impl Parser<'a, AmlValue> {
     comment_scope("TermArg", choice!(data_object()))
 }
 
-pub fn data_object<'a>() -> impl Parser<'a, AmlValue> {
+pub fn data_object<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
+where
+    'c: 'a,
+{
     /*
      * DataObject := DefPackage | DefVarPackage | ComputationalData
      *
@@ -169,7 +199,10 @@ pub fn data_object<'a>() -> impl Parser<'a, AmlValue> {
     comment_scope("DataObject", choice!(computational_data()))
 }
 
-pub fn computational_data<'a>() -> impl Parser<'a, AmlValue> {
+pub fn computational_data<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
+where
+    'c: 'a,
+{
     /*
      * ComputationalData := ByteConst | WordConst | DWordConst | QWordConst | String |
      *                      ConstObj | RevisionOp | DefBuffer
@@ -181,28 +214,28 @@ pub fn computational_data<'a>() -> impl Parser<'a, AmlValue> {
      * ConstObj := ZeroOp(0x00) | OneOp(0x01) | OnesOp(0xff)
      * RevisionOp := ExtOpPrefix(0x5b) 0x30
      */
-    let const_parser = |input: &'a [u8]| {
-        let (new_input, op) = take().parse(input)?;
+    let const_parser = |input: &'a [u8], context: &'c mut AmlContext| {
+        let (new_input, context, op) = take().parse(input, context)?;
 
         match op {
             opcode::BYTE_CONST => {
-                take().map(|value| AmlValue::Integer(value as u64)).parse(new_input)
+                take().map(|value| AmlValue::Integer(value as u64)).parse(new_input, context)
             }
             opcode::WORD_CONST => {
-                take_u16().map(|value| AmlValue::Integer(value as u64)).parse(new_input)
+                take_u16().map(|value| AmlValue::Integer(value as u64)).parse(new_input, context)
             }
             opcode::DWORD_CONST => {
-                take_u32().map(|value| AmlValue::Integer(value as u64)).parse(new_input)
+                take_u32().map(|value| AmlValue::Integer(value as u64)).parse(new_input, context)
             }
             opcode::QWORD_CONST => {
-                take_u64().map(|value| AmlValue::Integer(value)).parse(new_input)
+                take_u64().map(|value| AmlValue::Integer(value)).parse(new_input, context)
             }
             // TODO: implement String
-            opcode::ZERO_OP => Ok((new_input, AmlValue::Integer(0))),
-            opcode::ONE_OP => Ok((new_input, AmlValue::Integer(1))),
-            opcode::ONES_OP => Ok((new_input, AmlValue::Integer(u64::max_value()))),
+            opcode::ZERO_OP => Ok((new_input, context, AmlValue::Integer(0))),
+            opcode::ONE_OP => Ok((new_input, context, AmlValue::Integer(1))),
+            opcode::ONES_OP => Ok((new_input, context, AmlValue::Integer(u64::max_value()))),
 
-            _ => Err((input, AmlError::UnexpectedByte(op))),
+            _ => Err((input, context, AmlError::UnexpectedByte(op))),
         }
     };
 
@@ -223,40 +256,45 @@ mod test {
 
     #[test]
     fn test_computational_data() {
+        let mut context = AmlContext::new();
         check_ok!(
-            computational_data().parse(&[0x00, 0x34, 0x12]),
+            computational_data().parse(&[0x00, 0x34, 0x12], &mut context),
             AmlValue::Integer(0),
             &[0x34, 0x12]
         );
         check_ok!(
-            computational_data().parse(&[0x01, 0x18, 0xf3]),
+            computational_data().parse(&[0x01, 0x18, 0xf3], &mut context),
             AmlValue::Integer(1),
             &[0x18, 0xf3]
         );
         check_ok!(
-            computational_data().parse(&[0xff, 0x98, 0xc3]),
+            computational_data().parse(&[0xff, 0x98, 0xc3], &mut context),
             AmlValue::Integer(u64::max_value()),
             &[0x98, 0xc3]
         );
         check_ok!(
-            computational_data().parse(&[0x5b, 0x30]),
+            computational_data().parse(&[0x5b, 0x30], &mut context),
             AmlValue::Integer(crate::AML_INTERPRETER_REVISION),
             &[]
         );
         check_ok!(
-            computational_data().parse(&[0x0a, 0xf3, 0x35]),
+            computational_data().parse(&[0x0a, 0xf3, 0x35], &mut context),
             AmlValue::Integer(0xf3),
             &[0x35]
         );
-        check_ok!(computational_data().parse(&[0x0b, 0xf3, 0x35]), AmlValue::Integer(0x35f3), &[]);
         check_ok!(
-            computational_data().parse(&[0x0c, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00]),
+            computational_data().parse(&[0x0b, 0xf3, 0x35], &mut context),
+            AmlValue::Integer(0x35f3),
+            &[]
+        );
+        check_ok!(
+            computational_data().parse(&[0x0c, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00], &mut context),
             AmlValue::Integer(0x651235f3),
             &[0xff, 0x00]
         );
         check_ok!(
             computational_data()
-                .parse(&[0x0e, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00, 0x67, 0xde, 0x28]),
+                .parse(&[0x0e, 0xf3, 0x35, 0x12, 0x65, 0xff, 0x00, 0x67, 0xde, 0x28], &mut context),
             AmlValue::Integer(0xde6700ff651235f3),
             &[0x28]
         );

+ 6 - 6
aml_parser/src/test_utils.rs

@@ -1,21 +1,21 @@
 pub(crate) macro check_err($parse: expr, $error: pat, $remains: expr) {
     match $parse {
         Ok(result) => panic!("Expected Err, got {:#?}", result),
-        Err((remains, $error)) if *remains == *$remains => (),
-        Err((remains, $error)) => {
+        Err((remains, _, $error)) if *remains == *$remains => (),
+        Err((remains, _, $error)) => {
             panic!("Correct error, incorrect stream returned: {:x?}", remains)
         }
-        Err((_, err)) => panic!("Got wrong error: {:?}", err),
+        Err((_, _, err)) => panic!("Got wrong error: {:?}", err),
     }
 }
 
 pub(crate) macro check_ok($parse: expr, $expected: expr, $remains: expr) {
     match $parse {
-        Ok((remains, ref result)) if remains == *$remains && result == &$expected => (),
-        Ok((remains, ref result)) if result == &$expected => {
+        Ok((remains, _, ref result)) if remains == *$remains && result == &$expected => (),
+        Ok((remains, _, ref result)) if result == &$expected => {
             panic!("Correct result, incorrect slice returned: {:x?}", remains)
         }
         Ok(result) => panic!("Successfully parsed Ok, but it was wrong: {:#?}", result),
-        Err((_, err)) => panic!("Expected Ok, got {:#?}", err),
+        Err((_, _, err)) => panic!("Expected Ok, got {:#?}", err),
     }
 }