use crate::behavior::BehaviorError;
use crate::value::Value;
#[derive(Debug, Clone)]
pub enum RawValue {
Null,
Bool(bool),
Int(i64),
Float(f64),
Str(String),
Arr(Vec<RawValue>),
Row(RawRow),
}
impl RawValue {
pub fn type_name(&self) -> &'static str {
match self {
RawValue::Null => "null",
RawValue::Bool(_) => "bool",
RawValue::Int(_) => "int",
RawValue::Float(_) => "float",
RawValue::Str(_) => "string",
RawValue::Arr(_) => "arr",
RawValue::Row(_) => "obj",
}
}
}
#[derive(Debug, Clone, Default)]
pub struct RawRow {
fields: Vec<(String, RawValue)>,
}
impl RawRow {
pub fn new() -> Self {
RawRow { fields: Vec::new() }
}
pub fn set(&mut self, key: impl Into<String>, val: RawValue) {
let key = key.into();
if let Some(slot) = self.fields.iter_mut().find(|(k, _)| *k == key) {
slot.1 = val;
} else {
self.fields.push((key, val));
}
}
pub fn field(&self, key: &str) -> Option<&RawValue> {
self.fields.iter().find(|(k, _)| k == key).map(|(_, v)| v)
}
pub fn pairs(&self) -> &[(String, RawValue)] {
&self.fields
}
}
#[derive(Debug, Clone)]
pub enum RawOutcome {
Ok(RawValue),
Error(String),
}
pub trait RawComponentExec {
fn exec_raw(
&mut self,
component: &str,
ports: &[(String, Value)],
bound: Option<&Value>,
) -> Option<RawOutcome>;
fn exec_raw_ctx(
&mut self,
node_id: &str,
component: &str,
ports: &[(String, Value)],
bound: Option<&Value>,
) -> Option<RawOutcome> {
let _ = node_id;
self.exec_raw(component, ports, bound)
}
}
impl RawComponentExec for &mut dyn RawComponentExec {
fn exec_raw(
&mut self,
component: &str,
ports: &[(String, Value)],
bound: Option<&Value>,
) -> Option<RawOutcome> {
(**self).exec_raw(component, ports, bound)
}
fn exec_raw_ctx(
&mut self,
node_id: &str,
component: &str,
ports: &[(String, Value)],
bound: Option<&Value>,
) -> Option<RawOutcome> {
(**self).exec_raw_ctx(node_id, component, ports, bound)
}
}
pub fn raw_from_value(v: &Value) -> RawValue {
match v {
Value::Null => RawValue::Null,
Value::Bool(b) => RawValue::Bool(*b),
Value::Int(i) => RawValue::Int(*i),
Value::Float(f) => RawValue::Float(*f),
Value::Str(s) => RawValue::Str(s.clone()),
Value::Arr(xs) => RawValue::Arr(xs.iter().map(raw_from_value).collect()),
Value::Obj(pairs) => {
let mut row = RawRow::new();
for (k, val) in pairs {
row.set(k.clone(), raw_from_value(val));
}
RawValue::Row(row)
}
}
}
pub fn raw_missing_prop(struct_name: &str, key: &str) -> BehaviorError {
crate::expr::ExprFailure {
code: crate::expr::ExprFailureCode::MissingProp,
message: format!("typed raw marshal {struct_name}: missing property .{key}"),
}
.into()
}
pub fn raw_type_mismatch(expected: &str, got: &str) -> BehaviorError {
crate::expr::ExprFailure {
code: crate::expr::ExprFailureCode::TypeMismatch,
message: format!("typed raw marshal: expected {expected}, got {got}"),
}
.into()
}