impl To/FromNapiValue for HashMap

This commit is contained in:
forehalo 2021-09-24 17:01:54 +08:00 committed by LongYinan
parent e77d2e95ef
commit f4c0b0639b
16 changed files with 170 additions and 21 deletions
crates/napi/src/bindgen_runtime

View file

@ -4,6 +4,7 @@ use std::ptr;
mod array;
mod boolean;
mod buffer;
mod map;
mod nil;
mod number;
mod object;

View file

@ -0,0 +1,44 @@
use std::collections::HashMap;
use std::hash::Hash;
use crate::bindgen_prelude::{Env, Result, ToNapiValue, *};
impl<K, V> TypeName for HashMap<K, V> {
fn type_name() -> &'static str {
"HashMap"
}
}
impl<K, V> ToNapiValue for HashMap<K, V>
where
K: AsRef<str>,
V: ToNapiValue,
{
unsafe fn to_napi_value(raw_env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
let env = Env::from(raw_env);
let mut obj = env.create_object()?;
for (k, v) in val.into_iter() {
obj.set(k.as_ref(), v)?;
}
Object::to_napi_value(raw_env, obj)
}
}
impl<K, V> FromNapiValue for HashMap<K, V>
where
K: From<String> + Eq + Hash,
V: FromNapiValue,
{
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
let obj = Object::from_napi_value(env, napi_val)?;
let mut map = HashMap::new();
for key in Object::keys(&obj)?.into_iter() {
if let Some(val) = obj.get(&key)? {
map.insert(K::from(key), val);
}
}
Ok(map)
}
}

View file

@ -19,8 +19,8 @@ impl Object {
Ok(Object { env, inner: ptr })
}
pub fn get<T: FromNapiValue>(&self, field: String) -> Result<Option<T>> {
let c_field = CString::new(field)?;
pub fn get<K: AsRef<str>, V: FromNapiValue>(&self, field: K) -> Result<Option<V>> {
let c_field = CString::new(field.as_ref())?;
unsafe {
let mut ret = ptr::null_mut();
@ -36,16 +36,16 @@ impl Object {
Ok(if ty == ValueType::Undefined {
None
} else {
Some(T::from_napi_value(self.env, ret)?)
Some(V::from_napi_value(self.env, ret)?)
})
}
}
pub fn set<T: ToNapiValue>(&mut self, field: String, val: T) -> Result<()> {
let c_field = CString::new(field)?;
pub fn set<K: AsRef<str>, V: ToNapiValue>(&mut self, field: K, val: V) -> Result<()> {
let c_field = CString::new(field.as_ref())?;
unsafe {
let napi_val = T::to_napi_value(self.env, val)?;
let napi_val = V::to_napi_value(self.env, val)?;
check_status!(
sys::napi_set_named_property(self.env, self.inner, c_field.as_ptr(), napi_val),