Browse Source

Change the map combinator to take a Result as the return value

This allows for fallible mappings that are easily propagated as errors if
they fail.
Isaac Woods 5 years ago
parent
commit
8ddecb6fb9
4 changed files with 32 additions and 24 deletions
  1. 6 5
      aml_parser/src/name_object.rs
  2. 1 1
      aml_parser/src/opcode.rs
  3. 10 6
      aml_parser/src/parser.rs
  4. 15 12
      aml_parser/src/term_object.rs

+ 6 - 5
aml_parser/src/name_object.rs

@@ -15,8 +15,9 @@ where
      * NameString := <RootChar('\') NamePath> | <PrefixPath NamePath>
      * PrefixPath := Nothing | <'^' PrefixPath>
      */
-    let root_name_string =
-        opcode(ROOT_CHAR).then(name_path()).map(|((), name_path)| String::from("\\") + &name_path);
+    let root_name_string = opcode(ROOT_CHAR)
+        .then(name_path())
+        .map(|((), name_path)| Ok(String::from("\\") + &name_path));
 
     comment_scope_verbose("NameString", move |input: &'a [u8], context: &'c mut AmlContext| {
         let first_char = match input.first() {
@@ -46,7 +47,7 @@ where
         null_name(),
         dual_name_path(),
         multi_name_path(),
-        name_seg().map(|seg| String::from(seg.as_str()))
+        name_seg().map(|seg| Ok(String::from(seg.as_str())))
     )
 }
 
@@ -57,7 +58,7 @@ where
     /*
      * NullName := 0x00
      */
-    opcode(NULL_NAME).map(|_| String::from(""))
+    opcode(NULL_NAME).map(|_| Ok(String::from("")))
 }
 
 pub fn dual_name_path<'a, 'c>() -> impl Parser<'a, 'c, String>
@@ -70,7 +71,7 @@ where
     opcode(DUAL_NAME_PREFIX)
         .then(name_seg())
         .then(name_seg())
-        .map(|(((), first), second)| String::from(first.as_str()) + second.as_str())
+        .map(|(((), first), second)| Ok(String::from(first.as_str()) + second.as_str()))
 }
 
 pub fn multi_name_path<'a, 'c>() -> impl Parser<'a, 'c, String>

+ 1 - 1
aml_parser/src/opcode.rs

@@ -47,7 +47,7 @@ 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(|_| ())
+    opcode(EXT_OPCODE_PREFIX).then(opcode(ext_opcode)).discard_result()
 }
 
 #[cfg(test)]

+ 10 - 6
aml_parser/src/parser.rs

@@ -14,7 +14,7 @@ where
 
     fn map<F, A>(self, map_fn: F) -> Map<'a, 'c, Self, F, R, A>
     where
-        F: Fn(R) -> A,
+        F: Fn(R) -> Result<A, AmlError>,
     {
         Map { parser: self, map_fn, _phantom: PhantomData }
     }
@@ -269,7 +269,7 @@ pub struct Map<'a, 'c, P, F, R, A>
 where
     'c: 'a,
     P: Parser<'a, 'c, R>,
-    F: Fn(R) -> A,
+    F: Fn(R) -> Result<A, AmlError>,
 {
     parser: P,
     map_fn: F,
@@ -280,12 +280,16 @@ impl<'a, 'c, P, F, R, A> Parser<'a, 'c, A> for Map<'a, 'c, P, F, R, A>
 where
     'c: 'a,
     P: Parser<'a, 'c, R>,
-    F: Fn(R) -> A,
+    F: Fn(R) -> Result<A, AmlError>,
 {
     fn parse(&self, input: &'a [u8], context: &'c mut AmlContext) -> ParseResult<'a, 'c, A> {
-        self.parser
-            .parse(input, context)
-            .map(|(new_input, context, result)| (new_input, context, (self.map_fn)(result)))
+        match self.parser.parse(input, context) {
+            Ok((new_input, context, result)) => match (self.map_fn)(result) {
+                Ok(result_value) => Ok((new_input, context, result_value)),
+                Err(err) => Err((input, context, err)),
+            },
+            Err(result) => Err(result),
+        }
     }
 }
 

+ 15 - 12
aml_parser/src/term_object.rs

@@ -123,7 +123,7 @@ where
                 })
                 .feed(move |(pkg_length, name)| {
                     trace!("Scope with name: {}, length: {:?}", name, pkg_length);
-                    term_list(pkg_length).map(move |_| name.clone())
+                    term_list(pkg_length).map(move |_| Ok(name.clone()))
                 })
                 .map_with_context(|name, context| {
                     // TODO: remove scope
@@ -272,7 +272,8 @@ where
                 .then(name_string())
                 .then(take())
                 .feed(|((length, name), flags)| {
-                    take_to_end_of_pkglength(length).map(move |code| (name.clone(), flags, code))
+                    take_to_end_of_pkglength(length)
+                        .map(move |code| Ok((name.clone(), flags, code)))
                 })
                 .map_with_context(|(name, flags, code), context| {
                     // TODO: put it in the namespace
@@ -300,7 +301,9 @@ where
             "DefDevice",
             pkg_length()
                 .then(name_string())
-                .feed(|(length, name)| term_list(length).map(move |result| (name.clone(), result)))
+                .feed(|(length, name)| {
+                    term_list(length).map(move |result| Ok((name.clone(), result)))
+                })
                 .map_with_context(|(name, result), context| {
                     // TODO: add to namespace
                     trace!("Device with name: {}", name);
@@ -365,16 +368,16 @@ where
 
         match op {
             opcode::BYTE_CONST => {
-                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, context)
-            }
-            opcode::DWORD_CONST => {
-                take_u32().map(|value| AmlValue::Integer(value as u64)).parse(new_input, context)
+                take().map(|value| Ok(AmlValue::Integer(value as u64))).parse(new_input, context)
             }
+            opcode::WORD_CONST => take_u16()
+                .map(|value| Ok(AmlValue::Integer(value as u64)))
+                .parse(new_input, context),
+            opcode::DWORD_CONST => take_u32()
+                .map(|value| Ok(AmlValue::Integer(value as u64)))
+                .parse(new_input, context),
             opcode::QWORD_CONST => {
-                take_u64().map(|value| AmlValue::Integer(value)).parse(new_input, context)
+                take_u64().map(|value| Ok(AmlValue::Integer(value))).parse(new_input, context)
             }
             // TODO: implement String
             opcode::ZERO_OP => Ok((new_input, context, AmlValue::Integer(0))),
@@ -389,7 +392,7 @@ where
         "ComputationalData",
         choice!(
             ext_opcode(opcode::EXT_REVISION_OP)
-                .map(|_| AmlValue::Integer(crate::AML_INTERPRETER_REVISION)),
+                .map(|_| Ok(AmlValue::Integer(crate::AML_INTERPRETER_REVISION))),
             const_parser //TODO: parse DefBuffer here too
         ),
     )