From 60edb9da68a16ea947ee1fb07a58da8c7669fe6a Mon Sep 17 00:00:00 2001
From: Connor Wood <connorwood71@gmail.com>
Date: Tue, 29 Aug 2017 10:11:01 +0100
Subject: [PATCH] Implemented type checking and coersion upon store

---
 src/acpi/aml/namespace.rs | 38 +++++++++++++++++++++++++++++++++++++-
 src/acpi/aml/parser.rs    | 14 ++++++++++++--
 2 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/src/acpi/aml/namespace.rs b/src/acpi/aml/namespace.rs
index 3dcdb250..64ebb058 100644
--- a/src/acpi/aml/namespace.rs
+++ b/src/acpi/aml/namespace.rs
@@ -123,7 +123,43 @@ impl Debug for AmlValue {
     fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { Ok(()) }
 }
 
-impl AmlValue {    
+impl AmlValue {
+    pub fn get_as_type(&self, t: AmlValue) -> Result<AmlValue, AmlError> {
+        match t {
+            AmlValue::None => Ok(AmlValue::None),
+            AmlValue::Uninitialized => Ok(self.clone()),
+            AmlValue::Alias(_) => match *self {
+                AmlValue::Alias(_) => Ok(self.clone()),
+                _ => Err(AmlError::AmlValueError)
+            },
+            AmlValue::Buffer(_) => Ok(AmlValue::Buffer(self.get_as_buffer()?)),
+            AmlValue::BufferField(_) => Ok(AmlValue::BufferField(self.get_as_buffer_field()?)),
+            AmlValue::DDBHandle(_) => Ok(AmlValue::DDBHandle(self.get_as_ddb_handle()?)),
+            AmlValue::DebugObject => match *self {
+                AmlValue::DebugObject => Ok(self.clone()),
+                _ => Err(AmlError::AmlValueError)
+            },
+            AmlValue::Device(_) => Ok(AmlValue::Device(self.get_as_device()?)),
+            AmlValue::Event(_) => Ok(AmlValue::Event(self.get_as_event()?)),
+            AmlValue::FieldUnit(_) => Ok(AmlValue::FieldUnit(self.get_as_field_unit()?)),
+            AmlValue::Integer(_) => Ok(AmlValue::Integer(self.get_as_integer()?)),
+            AmlValue::IntegerConstant(_) => Ok(AmlValue::IntegerConstant(self.get_as_integer_constant()?)),
+            AmlValue::Method(_) => Ok(AmlValue::Method(self.get_as_method()?)),
+            AmlValue::Mutex(_) => Ok(AmlValue::Mutex(self.get_as_mutex()?)),
+            AmlValue::ObjectReference(_) => Ok(AmlValue::ObjectReference(self.get_as_object_reference()?)),
+            AmlValue::OperationRegion(_) => match *self {
+                AmlValue::OperationRegion(_) => Ok(self.clone()),
+                _ => Err(AmlError::AmlValueError)
+            },
+            AmlValue::Package(_) => Ok(AmlValue::Package(self.get_as_package()?)),
+            AmlValue::String(_) => Ok(AmlValue::String(self.get_as_string()?)),
+            AmlValue::PowerResource(_) => Ok(AmlValue::PowerResource(self.get_as_power_resource()?)),
+            AmlValue::Processor(_) => Ok(AmlValue::Processor(self.get_as_processor()?)),
+            AmlValue::RawDataBuffer(_) => Ok(AmlValue::RawDataBuffer(self.get_as_raw_data_buffer()?)),
+            AmlValue::ThermalZone(_) => Ok(AmlValue::ThermalZone(self.get_as_thermal_zone()?))
+        }
+    }
+
     pub fn get_as_buffer(&self) -> Result<Vec<u8>, AmlError> {
         match *self {
             AmlValue::Buffer(ref b) => Ok(b.clone()),
diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs
index 7ef78e79..3b382d41 100644
--- a/src/acpi/aml/parser.rs
+++ b/src/acpi/aml/parser.rs
@@ -285,13 +285,23 @@ impl AmlExecutionContext {
     }
 
     fn modify_local_obj(&mut self, local: usize, value: AmlValue) -> Result<(), AmlError> {
-        self.local_vars[local] = value;
+        self.local_vars[local] = value.get_as_type(self.local_vars[local].clone())?;
         Ok(())
     }
 
     fn modify_object(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> {
         if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
-            namespace.insert(name, value);
+            let coercion_obj = {
+                let obj = namespace.get(&name);
+
+                if let Some(o) = obj {
+                    o.clone()
+                } else {
+                    AmlValue::Uninitialized
+                }
+            };
+
+            namespace.insert(name, value.get_as_type(coercion_obj)?);
             Ok(())
         } else {
             Err(AmlError::AmlHardFatal)
-- 
GitLab