napi-rs/crates/napi/src/bindgen_runtime/js_values/serde.rs

99 lines
2.9 KiB
Rust
Raw Normal View History

2021-09-28 01:01:19 +09:00
use serde_json::{Map, Value};
2021-11-15 19:56:06 +09:00
use crate::{
bindgen_runtime::Null, check_status, sys, type_of, Error, JsObject, Result, Status, ValueType,
};
2021-09-28 01:01:19 +09:00
use super::{FromNapiValue, Object, ToNapiValue};
impl ToNapiValue for Value {
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
match val {
2022-01-13 12:15:02 +09:00
Value::Null => unsafe { Null::to_napi_value(env, Null) },
Value::Bool(b) => unsafe { bool::to_napi_value(env, b) },
2021-09-28 01:01:19 +09:00
Value::Number(n) => {
if n.is_i64() {
2022-01-13 12:15:02 +09:00
unsafe { i64::to_napi_value(env, n.as_i64().unwrap()) }
2021-09-28 01:01:19 +09:00
} else if n.is_f64() {
2022-01-13 12:15:02 +09:00
unsafe { f64::to_napi_value(env, n.as_f64().unwrap()) }
2021-09-28 01:01:19 +09:00
} else {
let n = n.as_u64().unwrap();
if n > u32::MAX as u64 {
todo!("impl BigInt")
} else {
2022-01-13 12:15:02 +09:00
unsafe { u32::to_napi_value(env, n as u32) }
2021-09-28 01:01:19 +09:00
}
}
}
2022-01-13 12:15:02 +09:00
Value::String(s) => unsafe { String::to_napi_value(env, s) },
Value::Array(arr) => unsafe { Vec::<Value>::to_napi_value(env, arr) },
Value::Object(obj) => unsafe { Map::to_napi_value(env, obj) },
2021-09-28 01:01:19 +09:00
}
}
}
impl FromNapiValue for Value {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
let ty = type_of!(env, napi_val)?;
let val = match ty {
2022-01-13 12:15:02 +09:00
ValueType::Boolean => Value::Bool(unsafe { bool::from_napi_value(env, napi_val)? }),
2021-09-28 01:01:19 +09:00
ValueType::Number => {
return Err(Error::new(
Status::InvalidArg,
"Js Number is not be able to convert to rust.".to_owned(),
));
}
2022-01-13 12:15:02 +09:00
ValueType::String => Value::String(unsafe { String::from_napi_value(env, napi_val)? }),
2021-09-28 01:01:19 +09:00
ValueType::Object => {
let mut is_arr = false;
check_status!(
2022-01-13 12:15:02 +09:00
unsafe { sys::napi_is_array(env, napi_val, &mut is_arr) },
2021-09-28 01:01:19 +09:00
"Failed to detect whether given js is an array"
)?;
if is_arr {
2022-01-13 12:15:02 +09:00
Value::Array(unsafe { Vec::<Value>::from_napi_value(env, napi_val)? })
2021-09-28 01:01:19 +09:00
} else {
2022-01-13 12:15:02 +09:00
Value::Object(unsafe { Map::<String, Value>::from_napi_value(env, napi_val)? })
2021-09-28 01:01:19 +09:00
}
}
#[cfg(feature = "napi6")]
2021-11-11 01:33:51 +09:00
ValueType::BigInt => todo!(),
2021-09-28 01:01:19 +09:00
_ => Value::Null,
};
Ok(val)
}
}
impl ToNapiValue for Map<String, Value> {
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
let mut obj = Object::new(env)?;
for (k, v) in val.into_iter() {
obj.set(k, v)?;
}
2022-01-13 12:15:02 +09:00
unsafe { Object::to_napi_value(env, obj) }
2021-09-28 01:01:19 +09:00
}
}
impl FromNapiValue for Map<String, Value> {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
2021-11-15 19:56:06 +09:00
let obj = JsObject(crate::Value {
2021-09-28 01:01:19 +09:00
env,
2021-11-15 19:56:06 +09:00
value: napi_val,
value_type: ValueType::Object,
});
2021-09-28 01:01:19 +09:00
let mut map = Map::new();
for key in Object::keys(&obj)?.into_iter() {
if let Some(val) = obj.get(&key)? {
map.insert(key, val);
}
}
Ok(map)
}
}