surrealpatch/lib/src/fnc/script/from.rs
2022-08-19 16:08:30 +01:00

96 lines
3.1 KiB
Rust

use super::classes;
use crate::sql::array::Array;
use crate::sql::datetime::Datetime;
use crate::sql::duration::Duration;
use crate::sql::object::Object;
use crate::sql::thing::Thing;
use crate::sql::uuid::Uuid;
use crate::sql::value::Value;
use chrono::{TimeZone, Utc};
use js::Ctx;
use js::Error;
use js::FromAtom;
use js::FromJs;
impl<'js> FromJs<'js> for Value {
fn from_js(ctx: Ctx<'js>, val: js::Value<'js>) -> Result<Self, Error> {
match val {
val if val.type_name() == "null" => Ok(Value::Null),
val if val.type_name() == "undefined" => Ok(Value::None),
val if val.is_bool() => Ok(val.as_bool().unwrap().into()),
val if val.is_string() => match val.into_string().unwrap().to_string() {
Ok(v) => Ok(Value::from(v)),
Err(e) => Err(e),
},
val if val.is_int() => Ok(val.as_int().unwrap().into()),
val if val.is_float() => Ok(val.as_float().unwrap().into()),
val if val.is_array() => {
let v = val.as_array().unwrap();
let mut x = Array::with_capacity(v.len());
for i in v.iter() {
let v = i?;
let v = Value::from_js(ctx, v)?;
x.push(v);
}
Ok(x.into())
}
val if val.is_object() => {
// Extract the value as an object
let v = val.into_object().unwrap();
// Check to see if this object is a duration
if (&v).instance_of::<classes::duration::duration::Duration>() {
let v = v.into_instance::<classes::duration::duration::Duration>().unwrap();
let v: &classes::duration::duration::Duration = v.as_ref();
let v = v.value.clone();
return Ok(Duration::from(v).into());
}
// Check to see if this object is a record
if (&v).instance_of::<classes::record::record::Record>() {
let v = v.into_instance::<classes::record::record::Record>().unwrap();
let v: &classes::record::record::Record = v.as_ref();
let v = (v.tb.clone(), v.id.clone());
return Ok(Thing::from(v).into());
}
// Check to see if this object is a uuid
if (&v).instance_of::<classes::uuid::uuid::Uuid>() {
let v = v.into_instance::<classes::uuid::uuid::Uuid>().unwrap();
let v: &classes::uuid::uuid::Uuid = v.as_ref();
let v = v.value.clone();
return Ok(Uuid::from(v).into());
}
// Check to see if this object is a date
let date: js::Object = ctx.globals().get("Date")?;
if (&v).is_instance_of(&date) {
let f: js::Function = v.get("getTime")?;
let m: i64 = f.call((js::This(v),))?;
let d = Utc.timestamp_millis(m);
return Ok(Datetime::from(d).into());
}
// Check to see if this object is an array
if let Some(v) = v.as_array() {
let mut x = Array::with_capacity(v.len());
for i in v.iter() {
let v = i?;
let v = Value::from_js(ctx, v)?;
x.push(v);
}
return Ok(x.into());
}
// Check to see if this object is a function
if v.as_function().is_some() {
return Ok(Value::None);
}
// This object is a normal object
let mut x = Object::default();
for i in v.props() {
let (k, v) = i?;
let k = String::from_atom(k)?;
let v = Value::from_js(ctx, v)?;
x.insert(k, v);
}
Ok(x.into())
}
_ => Ok(Value::None),
}
}
}