surrealdb_sql/fnc/script/
from.rs1use super::classes;
2use crate::array::Array;
3use crate::datetime::Datetime;
4use crate::object::Object;
5use crate::value::Value;
6use crate::Id;
7use chrono::{TimeZone, Utc};
8use js::prelude::This;
9use js::Ctx;
10use js::Error;
11use js::Exception;
12use js::FromAtom;
13use js::FromJs;
14
15fn check_nul(s: &str) -> Result<(), Error> {
16 if s.contains('\0') {
17 Err(Error::InvalidString(std::ffi::CString::new(s).unwrap_err()))
18 } else {
19 Ok(())
20 }
21}
22
23impl<'js> FromJs<'js> for Value {
24 fn from_js(ctx: &Ctx<'js>, val: js::Value<'js>) -> Result<Self, Error> {
25 match val {
26 val if val.type_name() == "null" => Ok(Value::Null),
27 val if val.type_name() == "undefined" => Ok(Value::None),
28 val if val.is_bool() => Ok(val.as_bool().unwrap().into()),
29 val if val.is_string() => match val.into_string().unwrap().to_string() {
30 Ok(v) => {
31 check_nul(&v)?;
32 Ok(Value::from(v))
33 }
34 Err(e) => Err(e),
35 },
36 val if val.is_number() => Ok(val.as_number().unwrap().into()),
37 val if val.is_array() => {
38 let v = val.as_array().unwrap();
39 let mut x = Array::with_capacity(v.len());
40 for i in v.iter() {
41 let v = i?;
42 let v = Value::from_js(ctx, v)?;
43 x.push(v);
44 }
45 Ok(x.into())
46 }
47 val if val.is_object() => {
48 let v = val.into_object().unwrap();
50 if v.is_error() {
52 let e: String = v.get("message")?;
53 let (Ok(e) | Err(e)) =
54 Exception::from_message(ctx.clone(), &e).map(|x| x.throw());
55 return Err(e);
56 }
57 if (v).instance_of::<classes::record::Record>() {
59 let v = v.into_class::<classes::record::Record>().unwrap();
60 let borrow = v.borrow();
61 let v: &classes::record::Record = &borrow;
62 check_nul(&v.value.tb)?;
63 if let Id::String(s) = &v.value.id {
64 check_nul(s)?;
65 }
66 return Ok(v.value.clone().into());
67 }
68 if (v).instance_of::<classes::duration::Duration>() {
70 let v = v.into_class::<classes::duration::Duration>().unwrap();
71 let borrow = v.borrow();
72 let v: &classes::duration::Duration = &borrow;
73 return match &v.value {
74 Some(v) => Ok((*v).into()),
75 None => Ok(Value::None),
76 };
77 }
78 if (v).instance_of::<classes::uuid::Uuid>() {
80 let v = v.into_class::<classes::uuid::Uuid>().unwrap();
81 let borrow = v.borrow();
82 let v: &classes::uuid::Uuid = &borrow;
83 return match &v.value {
84 Some(v) => Ok((*v).into()),
85 None => Ok(Value::None),
86 };
87 }
88 let date: js::Object = ctx.globals().get("Date")?;
90 if (v).is_instance_of(&date) {
91 let f: js::Function = v.get("getTime")?;
92 let m: i64 = f.call((This(v),))?;
93 let d = Utc.timestamp_millis_opt(m).unwrap();
94 return Ok(Datetime::from(d).into());
95 }
96 if let Some(v) = v.as_array() {
98 let mut x = Array::with_capacity(v.len());
99 for i in v.iter() {
100 let v = i?;
101 let v = Value::from_js(ctx, v)?;
102 x.push(v);
103 }
104 return Ok(x.into());
105 }
106 if v.as_function().is_some() {
108 return Ok(Value::None);
109 }
110 let mut x = Object::default();
112 for i in v.props() {
113 let (k, v) = i?;
114 let k = String::from_atom(k)?;
115 check_nul(&k)?;
116 let v = Value::from_js(ctx, v)?;
117 x.insert(k, v);
118 }
119 Ok(x.into())
120 }
121 _ => Ok(Value::None),
122 }
123 }
124}