87 lines
2.8 KiB
Rust
Raw Normal View History

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;
2017-08-01 14:44:33 +03:00
use interpreter::{Error, CustomUserError};
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.
2017-08-01 14:44:33 +03:00
pub struct TableInstance<E: CustomUserError> {
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-08-01 14:44:33 +03:00
buffer: RwLock<Vec<TableElement<E>>>,
2017-07-31 11:58:24 +03:00
}
/// Table element. Cloneable wrapper around VariableInstance.
2017-08-01 14:44:33 +03:00
struct TableElement<E: CustomUserError> {
pub var: VariableInstance<E>,
2017-04-21 14:35:12 +03:00
}
2017-08-01 14:44:33 +03:00
impl<E> TableInstance<E> where E: CustomUserError {
2017-05-22 19:54:56 +03:00
/// New instance of the table
2017-08-01 14:44:33 +03:00
pub fn new(table_type: &TableType) -> Result<Arc<Self>, Error<E>> {
2017-06-08 10:49:32 +03:00
check_limits(table_type.limits())?;
2017-06-21 11:35:09 +03:00
let variable_type = table_type.elem_type().into();
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(
2017-07-31 11:58:24 +03:00
vec![TableElement::new(VariableInstance::new(true, variable_type, RuntimeValue::Null)?); table_type.limits().initial() as usize]
2017-04-26 15:41:22 +03:00
),
2017-04-21 14:35:12 +03:00
}))
}
/// Get variable type for this table.
pub fn variable_type(&self) -> VariableType {
self.variable_type
}
2017-05-22 19:54:56 +03:00
/// Get the specific value in the table
2017-08-01 14:44:33 +03:00
pub fn get(&self, offset: u32) -> Result<RuntimeValue, Error<E>> {
2017-04-26 15:41:22 +03:00
let buffer = self.buffer.read();
let buffer_len = buffer.len();
buffer.get(offset as usize)
2017-07-31 11:58:24 +03:00
.map(|v| v.var.get())
2017-04-26 15:41:22 +03:00
.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-08-01 14:44:33 +03:00
pub fn set_raw(&self, mut offset: u32, module_name: String, value: &[u32]) -> Result<(), Error<E>> {
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-08-01 14:44:33 +03:00
pub fn set(&self, offset: u32, value: RuntimeValue) -> Result<(), Error<E>> {
2017-04-26 15:41:22 +03:00
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)))
2017-07-31 11:58:24 +03:00
.and_then(|v| v.var.set(value))
}
}
2017-08-01 14:44:33 +03:00
impl<E> TableElement<E> where E: CustomUserError {
pub fn new(var: VariableInstance<E>) -> Self {
2017-07-31 11:58:24 +03:00
TableElement {
var: var,
}
}
}
2017-08-01 14:44:33 +03:00
impl<E> Clone for TableElement<E> where E: CustomUserError {
2017-07-31 11:58:24 +03:00
fn clone(&self) -> Self {
TableElement::new(VariableInstance::new(self.var.is_mutable(), self.var.variable_type(), self.var.get())
.expect("it only fails when variable_type() != passed variable value; both are read from already constructed var; qed"))
2017-04-21 14:35:12 +03:00
}
}