瀏覽代碼

Record attempted conversion in error

When a conversion error occurs, it is quite useful to know exactly which
conversion failed. By storing both the current value and the target
value in the `AmlError::IncompatibleValueConversion` enum variant, this
information can be provided to the caller. Additionally, by using a
struct enum variant, there is no need to keep track of which value is
the current value, and which is the target value, as this is encoded in
the type.
Casper Verhaar 4 年之前
父節點
當前提交
ad1b6a8696
共有 4 個文件被更改,包括 25 次插入15 次删除
  1. 4 1
      aml/src/lib.rs
  2. 7 3
      aml/src/pci_routing.rs
  3. 5 2
      aml/src/resource.rs
  4. 9 9
      aml/src/value.rs

+ 4 - 1
aml/src/lib.rs

@@ -713,7 +713,10 @@ pub enum AmlError {
     InvalidNameSeg,
     InvalidPkgLength,
     InvalidFieldFlags,
-    IncompatibleValueConversion,
+    IncompatibleValueConversion {
+        current: AmlType,
+        target: AmlType,
+    },
     UnterminatedStringConstant,
     InvalidStringConstant,
     InvalidRegionSpace(u8),

+ 7 - 3
aml/src/pci_routing.rs

@@ -4,6 +4,7 @@ use crate::{
     value::Args,
     AmlContext,
     AmlError,
+    AmlType,
     AmlValue,
 };
 use alloc::vec::Vec;
@@ -129,13 +130,16 @@ impl PciRoutingTable {
                         _ => return Err(AmlError::PrtInvalidSource),
                     }
                 } else {
-                    return Err(AmlError::IncompatibleValueConversion);
+                    return Err(AmlError::IncompatibleValueConversion {
+                        current: value.type_of(),
+                        target: AmlType::Package,
+                    });
                 }
             }
 
             Ok(PciRoutingTable { entries })
         } else {
-            Err(AmlError::IncompatibleValueConversion)
+            Err(AmlError::IncompatibleValueConversion { current: prt.type_of(), target: AmlType::Package })
         }
     }
 
@@ -174,7 +178,7 @@ impl PciRoutingTable {
                 let resources = resource::resource_descriptor_list(link_crs)?;
                 match resources.as_slice() {
                     [Resource::Irq(descriptor)] => Ok(descriptor.clone()),
-                    _ => Err(AmlError::IncompatibleValueConversion),
+                    _ => Err(AmlError::IncompatibleValueConversion { current: todo!(), target: todo!() }),
                 }
             }
         }

+ 5 - 2
aml/src/resource.rs

@@ -1,6 +1,9 @@
 use core::mem;
 
-use crate::{value::AmlValue, AmlError};
+use crate::{
+    value::{AmlType, AmlValue},
+    AmlError,
+};
 use alloc::vec::Vec;
 use bit_field::BitField;
 use byteorder::{ByteOrder, LittleEndian};
@@ -34,7 +37,7 @@ pub fn resource_descriptor_list(descriptor: &AmlValue) -> Result<Vec<Resource>,
 
         Ok(descriptors)
     } else {
-        Err(AmlError::IncompatibleValueConversion)
+        Err(AmlError::IncompatibleValueConversion { current: descriptor.type_of(), target: AmlType::Buffer })
     }
 }
 

+ 9 - 9
aml/src/value.rs

@@ -243,7 +243,7 @@ impl AmlValue {
         match self {
             AmlValue::Boolean(value) => Ok(*value),
             AmlValue::Integer(value) => Ok(*value != 0),
-            _ => Err(AmlError::IncompatibleValueConversion),
+            _ => Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: AmlType::Integer }),
         }
     }
 
@@ -274,7 +274,7 @@ impl AmlValue {
              */
             AmlValue::Field { .. } => self.read_field(context)?.as_integer(context),
 
-            _ => Err(AmlError::IncompatibleValueConversion),
+            _ => Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: AmlType::Integer }),
         }
     }
 
@@ -283,7 +283,7 @@ impl AmlValue {
             AmlValue::Buffer(ref bytes) => Ok(bytes.clone()),
             // TODO: implement conversion of String and Integer to Buffer
             AmlValue::Field { .. } => self.read_field(context)?.as_buffer(context),
-            _ => Err(AmlError::IncompatibleValueConversion),
+            _ => Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: AmlType::Buffer }),
         }
     }
 
@@ -292,7 +292,7 @@ impl AmlValue {
             AmlValue::String(ref string) => Ok(string.clone()),
             // TODO: implement conversion of Buffer to String
             AmlValue::Field { .. } => self.read_field(context)?.as_string(context),
-            _ => Err(AmlError::IncompatibleValueConversion),
+            _ => Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: AmlType::String }),
         }
     }
 
@@ -345,7 +345,7 @@ impl AmlValue {
             AmlType::FieldUnit => panic!(
                 "Can't implicitly convert to FieldUnit. This must be special-cased by the caller for now :("
             ),
-            _ => Err(AmlError::IncompatibleValueConversion),
+            _ => Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: desired_type }),
         }
     }
 
@@ -389,7 +389,7 @@ impl AmlValue {
                 context.read_region(*region, *offset, access_size)?.get_bits(0..(*length as usize)),
             ))
         } else {
-            Err(AmlError::IncompatibleValueConversion)
+            Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: AmlType::FieldUnit })
         }
     }
 
@@ -402,7 +402,7 @@ impl AmlValue {
         let field_update_rule = if let AmlValue::Field { region, flags, offset, length } = self {
             flags.field_update_rule()?
         } else {
-            return Err(AmlError::IncompatibleValueConversion);
+            return Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: todo!() });
         };
         let mut field_value = match field_update_rule {
             FieldUpdateRule::Preserve => self.read_field(context)?.as_integer(context)?,
@@ -440,7 +440,7 @@ impl AmlValue {
             field_value.set_bits(0..(*length as usize), value.as_integer(context)?);
             context.write_region(*region, *offset, access_size, field_value)
         } else {
-            Err(AmlError::IncompatibleValueConversion)
+            Err(AmlError::IncompatibleValueConversion { current: self.type_of(), target: AmlType::FieldUnit })
         }
     }
 
@@ -525,7 +525,7 @@ mod tests {
 
         assert_eq!(
             AmlValue::Integer(4).cmp(AmlValue::Boolean(true), &mut context),
-            Err(AmlError::IncompatibleValueConversion)
+            Err(AmlError::IncompatibleValueConversion { current: AmlType::Integer, target: AmlType::Integer })
         );
 
         // TODO: test the other combinations too, as well as conversions to the correct types for the second operand