2017-04-21 14:35:12 +03:00
|
|
|
use std::u32;
|
|
|
|
use std::sync::Arc;
|
2017-04-26 15:41:22 +03:00
|
|
|
use parking_lot::RwLock;
|
2017-04-21 14:35:12 +03:00
|
|
|
use elements::TableType;
|
|
|
|
use interpreter::Error;
|
2017-06-08 10:49:32 +03:00
|
|
|
use interpreter::module::check_limits;
|
2017-04-26 15:41:22 +03:00
|
|
|
use interpreter::variable::{VariableInstance, VariableType};
|
2017-04-21 14:35:12 +03:00
|
|
|
use interpreter::value::RuntimeValue;
|
|
|
|
|
|
|
|
/// Table instance.
|
|
|
|
pub struct TableInstance {
|
2017-04-26 15:41:22 +03:00
|
|
|
/// Table variables type.
|
|
|
|
variable_type: VariableType,
|
2017-04-21 14:35:12 +03:00
|
|
|
/// Table memory buffer.
|
2017-04-26 15:41:22 +03:00
|
|
|
buffer: RwLock<Vec<VariableInstance>>,
|
2017-04-21 14:35:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TableInstance {
|
2017-05-22 19:54:56 +03:00
|
|
|
/// New instance of the table
|
2017-04-26 15:41:22 +03:00
|
|
|
pub fn new(variable_type: VariableType, table_type: &TableType) -> Result<Arc<Self>, Error> {
|
2017-06-08 10:49:32 +03:00
|
|
|
check_limits(table_type.limits())?;
|
|
|
|
|
2017-04-21 14:35:12 +03:00
|
|
|
Ok(Arc::new(TableInstance {
|
2017-04-26 15:41:22 +03:00
|
|
|
variable_type: variable_type,
|
|
|
|
buffer: RwLock::new(
|
|
|
|
vec![VariableInstance::new(true, variable_type, RuntimeValue::Null)?; table_type.limits().initial() as usize]
|
|
|
|
),
|
2017-04-21 14:35:12 +03:00
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2017-05-22 19:54:56 +03:00
|
|
|
/// Get the specific value in the table
|
2017-04-26 15:41:22 +03:00
|
|
|
pub fn get(&self, offset: u32) -> Result<RuntimeValue, Error> {
|
|
|
|
let buffer = self.buffer.read();
|
|
|
|
let buffer_len = buffer.len();
|
|
|
|
buffer.get(offset as usize)
|
|
|
|
.map(|v| v.get())
|
|
|
|
.ok_or(Error::Table(format!("trying to read table item with index {} when there are only {} items", offset, buffer_len)))
|
|
|
|
}
|
|
|
|
|
2017-05-22 19:54:56 +03:00
|
|
|
/// Set the table value from raw slice
|
2017-06-13 12:01:59 +03:00
|
|
|
pub fn set_raw(&self, mut offset: u32, module_name: String, value: &[u32]) -> Result<(), Error> {
|
2017-04-26 15:41:22 +03:00
|
|
|
for val in value {
|
|
|
|
match self.variable_type {
|
2017-06-13 12:01:59 +03:00
|
|
|
VariableType::AnyFunc => self.set(offset, RuntimeValue::AnyFunc(module_name.clone(), *val))?,
|
2017-05-03 10:41:01 +03:00
|
|
|
_ => return Err(Error::Table(format!("table of type {:?} is not supported", self.variable_type))),
|
2017-04-26 15:41:22 +03:00
|
|
|
}
|
|
|
|
offset += 1;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2017-05-22 19:54:56 +03:00
|
|
|
/// Set the table from runtime variable value
|
2017-04-26 15:41:22 +03:00
|
|
|
pub fn set(&self, offset: u32, value: RuntimeValue) -> Result<(), Error> {
|
|
|
|
let mut buffer = self.buffer.write();
|
|
|
|
let buffer_len = buffer.len();
|
|
|
|
buffer.get_mut(offset as usize)
|
|
|
|
.ok_or(Error::Table(format!("trying to update table item with index {} when there are only {} items", offset, buffer_len)))
|
|
|
|
.and_then(|v| v.set(value))
|
2017-04-21 14:35:12 +03:00
|
|
|
}
|
|
|
|
}
|