Phase 1.2-1.6: replace variables HashMap<String,String> with HashMap<String,Value>, rewrite str_to_dyn/dyn_to_str -> value_to_dynamic/dynamic_to_value, update resolve_string/evaluate_condition/is_truthy for Value
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use super::opcodes::*;
|
||||
use super::types::InterpError;
|
||||
use super::types::{InterpError, Value};
|
||||
use compact_str::CompactString;
|
||||
|
||||
pub struct Reader<'a> {
|
||||
pub data: &'a [u8],
|
||||
@@ -138,6 +139,77 @@ impl<'a> Reader<'a> {
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
pub fn read_value(&mut self, type_op: u8) -> Result<Option<Value>, InterpError> {
|
||||
let val = match type_op {
|
||||
OP_PROP_STR | OP_PROP_COLOR | OP_PROP_FSPATH | OP_PROP_IDENT => {
|
||||
Some(Value::Str(CompactString::new(self.read_string()?)))
|
||||
}
|
||||
OP_PROP_RHEI => {
|
||||
let raw = self.read_string()?;
|
||||
let mut s = String::with_capacity(super::rhei::RHEI_PREFIX.len() + raw.len());
|
||||
s.push_str(super::rhei::RHEI_PREFIX);
|
||||
s.push_str(&raw);
|
||||
Some(Value::Str(CompactString::new(s)))
|
||||
}
|
||||
OP_PROP_VAR => {
|
||||
let name = self.read_str_ref()?;
|
||||
let mut s = String::with_capacity(name.len() + 1);
|
||||
s.push('$');
|
||||
s.push_str(name);
|
||||
Some(Value::Str(CompactString::new(s)))
|
||||
}
|
||||
OP_PROP_INT => Some(Value::Int(self.read_i64()?)),
|
||||
OP_PROP_FLOAT => Some(Value::Float(self.read_f64()?)),
|
||||
OP_PROP_BOOL => Some(Value::Bool(self.read_byte()? != 0)),
|
||||
OP_PROP_NULL => None,
|
||||
OP_PROP_ARRAY => {
|
||||
let items = self.read_array_as_values()?;
|
||||
Some(Value::Array(items))
|
||||
}
|
||||
OP_PROP_UNIT => {
|
||||
let num = self.read_f64()?;
|
||||
let unit = self.read_str_ref()?;
|
||||
let s = if num.fract() == 0.0 {
|
||||
format!("{}{}", num as i64, unit)
|
||||
} else {
|
||||
format!("{}{}", num, unit)
|
||||
};
|
||||
Some(Value::Str(CompactString::new(s)))
|
||||
}
|
||||
OP_PROP_CALL => {
|
||||
let name = self.read_string()?;
|
||||
let arg_count = self.read_u32()? as usize;
|
||||
let mut args = Vec::with_capacity(arg_count);
|
||||
for _ in 0..arg_count {
|
||||
let op = self.read_byte()?;
|
||||
let val = self.read_value(op)?.unwrap_or(Value::None);
|
||||
args.push(match val {
|
||||
Value::Str(s) => s.to_string(),
|
||||
Value::Int(i) => i.to_string(),
|
||||
Value::Float(f) => f.to_string(),
|
||||
Value::Bool(b) => b.to_string(),
|
||||
_ => String::new(),
|
||||
});
|
||||
}
|
||||
Some(Value::Str(CompactString::new(format!("{}({})", name, args.join(",")))))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
pub fn read_array_as_values(&mut self) -> Result<Vec<Value>, InterpError> {
|
||||
let count = self.read_u32()? as usize;
|
||||
let mut items = Vec::with_capacity(count);
|
||||
for _ in 0..count {
|
||||
let elem_op = self.read_byte()?;
|
||||
if let Some(v) = self.read_value(elem_op)? {
|
||||
items.push(v);
|
||||
}
|
||||
}
|
||||
Ok(items)
|
||||
}
|
||||
|
||||
pub fn read_array_as_strings(&mut self) -> Result<Vec<String>, InterpError> {
|
||||
let count = self.read_u32()? as usize;
|
||||
let mut items = Vec::with_capacity(count);
|
||||
|
||||
Reference in New Issue
Block a user