mirror of
https://github.com/gorules/zen.git
synced 2026-10-04 16:02:18 +00:00
116 lines
4.0 KiB
Rust
116 lines
4.0 KiB
Rust
use crate::variable::Variable;
|
|
use crate::vm::helpers::date_time;
|
|
use crate::vm::VMError;
|
|
use chrono::NaiveDateTime;
|
|
use rust_decimal::prelude::ToPrimitive;
|
|
use rust_decimal::Decimal;
|
|
use serde_json::{Number, Value};
|
|
use std::rc::Rc;
|
|
|
|
impl From<Value> for Variable {
|
|
fn from(value: Value) -> Self {
|
|
match value {
|
|
Value::Null => Variable::Null,
|
|
Value::Bool(b) => Variable::Bool(b),
|
|
Value::Number(n) => Variable::Number(
|
|
Decimal::from_str_exact(n.as_str())
|
|
.or_else(|_| Decimal::from_scientific(n.as_str()))
|
|
.expect("Allowed number"),
|
|
),
|
|
Value::String(s) => Variable::String(Rc::from(s.as_str())),
|
|
Value::Array(arr) => {
|
|
Variable::from_array(arr.into_iter().map(Variable::from).collect())
|
|
}
|
|
Value::Object(obj) => Variable::from_object(
|
|
obj.into_iter()
|
|
.map(|(k, v)| (Rc::from(k.as_str()), Variable::from(v)))
|
|
.collect(),
|
|
),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<&Value> for Variable {
|
|
fn from(value: &Value) -> Self {
|
|
match value {
|
|
Value::Null => Variable::Null,
|
|
Value::Bool(b) => Variable::Bool(*b),
|
|
Value::Number(n) => Variable::Number(
|
|
Decimal::from_str_exact(n.as_str())
|
|
.or_else(|_| Decimal::from_scientific(n.as_str()))
|
|
.expect("Allowed number"),
|
|
),
|
|
Value::String(s) => Variable::String(Rc::from(s.as_str())),
|
|
Value::Array(arr) => Variable::from_array(arr.iter().map(Variable::from).collect()),
|
|
Value::Object(obj) => Variable::from_object(
|
|
obj.iter()
|
|
.map(|(k, v)| (Rc::from(k.as_str()), Variable::from(v)))
|
|
.collect(),
|
|
),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<Variable> for Value {
|
|
fn from(value: Variable) -> Self {
|
|
match value {
|
|
Variable::Null => Value::Null,
|
|
Variable::Bool(b) => Value::Bool(b),
|
|
Variable::Number(n) => {
|
|
Value::Number(Number::from_string_unchecked(n.normalize().to_string()))
|
|
}
|
|
Variable::String(s) => Value::String(s.to_string()),
|
|
Variable::Array(arr) => {
|
|
let vec = Rc::try_unwrap(arr)
|
|
.map(|a| a.into_inner())
|
|
.unwrap_or_else(|s| {
|
|
let borrowed = s.borrow();
|
|
borrowed.clone()
|
|
});
|
|
|
|
Value::Array(vec.into_iter().map(Value::from).collect())
|
|
}
|
|
Variable::Object(obj) => {
|
|
let hmap = Rc::try_unwrap(obj)
|
|
.map(|a| a.into_inner())
|
|
.unwrap_or_else(|s| {
|
|
let borrowed = s.borrow();
|
|
borrowed.clone()
|
|
});
|
|
|
|
Value::Object(
|
|
hmap.into_iter()
|
|
.map(|(k, v)| (k.to_string(), Value::from(v)))
|
|
.collect(),
|
|
)
|
|
}
|
|
Variable::Dynamic(d) => d.to_value(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&Variable> for NaiveDateTime {
|
|
type Error = VMError;
|
|
|
|
fn try_from(value: &Variable) -> Result<Self, Self::Error> {
|
|
match value {
|
|
Variable::String(a) => date_time(a),
|
|
#[allow(deprecated)]
|
|
Variable::Number(a) => NaiveDateTime::from_timestamp_opt(
|
|
a.to_i64().ok_or_else(|| VMError::OpcodeErr {
|
|
opcode: "DateManipulation".into(),
|
|
message: "Failed to extract date".into(),
|
|
})?,
|
|
0,
|
|
)
|
|
.ok_or_else(|| VMError::ParseDateTimeErr {
|
|
timestamp: a.to_string(),
|
|
}),
|
|
_ => Err(VMError::OpcodeErr {
|
|
opcode: "DateManipulation".into(),
|
|
message: "Unsupported type".into(),
|
|
}),
|
|
}
|
|
}
|
|
}
|