use super::VmValue;
impl From<harn_kernel::DataValue> for VmValue {
fn from(value: harn_kernel::DataValue) -> Self {
use harn_kernel::DataValue;
use std::sync::Arc;
match value {
DataValue::Nil => Self::Nil,
DataValue::Bool(value) => Self::Bool(value),
DataValue::Int(value) => Self::Int(value),
DataValue::Float(value) => Self::Float(value),
DataValue::String(value) => Self::String(value.into()),
DataValue::Bytes(value) => Self::Bytes(Arc::new(value)),
DataValue::List(values) => {
Self::List(Arc::new(values.into_iter().map(Self::from).collect()))
}
DataValue::Record(entries) => Self::dict(
entries
.into_iter()
.map(|(key, value)| (key, Self::from(value))),
),
}
}
}
pub(crate) const BYTES_B64_TAG: &str = "$bytes_b64";
pub(crate) fn tagged_bytes_json(bytes: &[u8]) -> serde_json::Value {
use base64::Engine;
serde_json::json!({
BYTES_B64_TAG: base64::engine::general_purpose::STANDARD.encode(bytes),
})
}
pub fn json_to_vm_value(jv: &serde_json::Value) -> VmValue {
match jv {
serde_json::Value::Null => VmValue::Nil,
serde_json::Value::Bool(b) => VmValue::Bool(*b),
serde_json::Value::Number(n) => {
if let Some(i) = n.as_i64() {
VmValue::Int(i)
} else {
VmValue::Float(n.as_f64().unwrap_or(0.0))
}
}
serde_json::Value::String(s) => VmValue::String(arcstr::ArcStr::from(s.as_str())),
serde_json::Value::Array(arr) => VmValue::List(std::sync::Arc::new(
arr.iter().map(json_to_vm_value).collect(),
)),
serde_json::Value::Object(map) => {
let mut m = super::DictMap::new();
for (k, v) in map {
m.insert(super::intern_key(k), json_to_vm_value(v));
}
VmValue::dict(m)
}
}
}
pub(crate) fn vm_value_dict_to_json(dict: &super::DictMap) -> serde_json::Value {
let mut map = serde_json::Map::new();
for (k, v) in dict {
map.insert(k.to_string(), vm_value_to_json(v));
}
serde_json::Value::Object(map)
}
pub fn vm_value_to_json(val: &VmValue) -> serde_json::Value {
match val {
VmValue::Int(i) => serde_json::json!(i),
VmValue::Float(f) => serde_json::json!(f),
VmValue::Decimal(d) => serde_json::json!(d.to_string()),
VmValue::String(s) => serde_json::json!(s.as_str()),
VmValue::Bytes(bytes) => tagged_bytes_json(bytes),
VmValue::Bool(b) => serde_json::json!(b),
VmValue::Nil => serde_json::Value::Null,
VmValue::List(list) => {
serde_json::Value::Array(list.iter().map(vm_value_to_json).collect())
}
VmValue::Dict(d) => vm_value_dict_to_json(d),
VmValue::StructInstance(_) => {
vm_value_dict_to_json(&val.struct_fields_map().unwrap_or_default())
}
_ => serde_json::json!(val.display()),
}
}