refactor(napi-rs): make api calls more safety

This commit is contained in:
LongYinan 2020-04-17 11:54:17 +08:00 committed by LongYinan
parent ddb3813b9a
commit fa8e1be7b9
No known key found for this signature in database
GPG key ID: C3666B7FC82ADAD7
5 changed files with 178 additions and 179 deletions

View file

@ -115,12 +115,12 @@ npm test
| [Enum types](https://nodejs.org/api/n-api.html#n_api_enum_types) | 6 | v13.7.0 | ⛔️ |
| [napi_create_array](https://nodejs.org/api/n-api.html#n_api_napi_create_array) | 1 | v8.0.0 | ✅ |
| [napi_create_array_with_length](https://nodejs.org/api/n-api.html#n_api_napi_create_array_with_length) | 1 | v8.0.0 | ✅ |
| [napi_create_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_create_arraybuffer) | 1 | v8.0.0 | ⛔️ |
| [napi_create_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_create_arraybuffer) | 1 | v8.0.0 | |
| [napi_create_buffer](https://nodejs.org/api/n-api.html#n_api_napi_create_buffer) | 1 | v8.0.0 | ✅ |
| [napi_create_buffer_copy](https://nodejs.org/api/n-api.html#n_api_napi_create_buffer_copy) | 1 | v8.0.0 | ⛔️ |
| [napi_create_date](https://nodejs.org/api/n-api.html#n_api_napi_create_date) | 5 | v11.11.0 | ⛔️ |
| [napi_create_external](https://nodejs.org/api/n-api.html#n_api_napi_create_external) | 1 | v8.0.0 | ⛔️ |
| [napi_create_external_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_create_external_arraybuffer) | 1 | v8.0.0 | ⛔️ |
| [napi_create_external_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_create_external_arraybuffer) | 1 | v8.0.0 | |
| [napi_create_external_buffer](https://nodejs.org/api/n-api.html#n_api_napi_create_external_buffer) | 1 | v8.0.0 | ✅ |
| [napi_create_object](https://nodejs.org/api/n-api.html#n_api_napi_create_object) | 1 | v8.0.0 | ✅ |
| [napi_create_symbol](https://nodejs.org/api/n-api.html#n_api_napi_create_symbol) | 1 | v8.0.0 | ⛔️ |
@ -142,7 +142,7 @@ npm test
| NAPI | NAPI Version | Minimal Node Version | Status |
| ---- | ------------ | -------------------- | ------ |
|[napi_get_array_length](https://nodejs.org/api/n-api.html#n_api_napi_get_array_length)| 1 | v8.0.0 | ✅ |
|[napi_get_arraybuffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_arraybuffer_info)| 1 | v8.0.0 | ⛔️ |
|[napi_get_arraybuffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_arraybuffer_info)| 1 | v8.0.0 | |
|[napi_get_buffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_buffer_info)| 1 | v8.0.0 | ✅ |
|[napi_get_prototype](https://nodejs.org/api/n-api.html#n_api_napi_get_prototype)| 1 | v8.0.0 | ⛔️ |
|[napi_get_typedarray_info](https://nodejs.org/api/n-api.html#n_api_napi_get_typedarray_info)| 1 | v8.0.0 | ⛔️ |

View file

@ -12,10 +12,9 @@ keywords = ["NodeJS", "FFI"]
futures = { version = "0.3", features = ["default", "thread-pool"] }
serde = { version = "1", optional = true }
serde_json = { version = "1", optional = true }
rayon = { version = "1", optional = true }
[features]
serde-json = ["serde", "serde_json", "rayon"]
serde-json = ["serde", "serde_json"]
default = ["serde-json"]

View file

@ -1,10 +1,7 @@
#[cfg(feature = "serde-json")]
extern crate rayon;
#[cfg(feature = "serde-json")]
extern crate serde_json;
extern crate futures;
pub extern crate futures;
use std::any::TypeId;
use std::convert::TryInto;
use std::ffi::CString;
use std::marker::PhantomData;
use std::mem;
@ -14,9 +11,6 @@ use std::ptr;
use std::slice;
use std::string::String as RustString;
#[cfg(feature = "serde-json")]
use serde_json::value::Value as SerdeValue;
mod executor;
pub mod sys;
@ -142,7 +136,7 @@ macro_rules! register_module {
raw_exports: sys::napi_value,
) -> sys::napi_value {
let env = Env::from_raw(raw_env);
let mut exports: Value<Object> = Value::from_raw(&env, raw_exports);
let mut exports: Value<Object> = Value::from_raw(&env, raw_exports).unwrap();
let result = $init(&env, &mut exports);
@ -195,10 +189,10 @@ macro_rules! callback {
}
let env = Env::from_raw(raw_env);
let this = Value::from_raw(&env, raw_this);
let this = Value::from_raw(&env, raw_this).unwrap();
let mut args = unsafe { mem::MaybeUninit::<[Value<Any>; 8]>::uninit().assume_init() };
for (i, raw_arg) in raw_args.iter().enumerate() {
args[i] = Value::from_raw(&env, *raw_arg)
args[i] = Value::from_raw(&env, *raw_arg).unwrap()
}
let callback = $callback_expr;
@ -257,11 +251,11 @@ impl Env {
Ok(Value::from_raw_value(self, raw_value, Null))
}
pub fn get_boolean(&self, value: bool) -> Value<Boolean> {
pub fn get_boolean(&self, value: bool) -> Result<Value<Boolean>> {
let mut raw_value = ptr::null_mut();
let status = unsafe { sys::napi_get_boolean(self.0, value, &mut raw_value) };
debug_assert!(Status::from(status) == Status::Ok);
Value::from_raw_value(self, raw_value, Boolean { value })
check_status(status)?;
Ok(Value::from_raw_value(self, raw_value, Boolean { value }))
}
pub fn create_int64<'a>(&'a self, int: i64) -> Result<Value<'a, Number>> {
@ -298,88 +292,46 @@ impl Env {
Ok(Value::from_raw_value(self, raw_value, String))
}
pub fn create_string_utf16<'a, 'b>(&'a self, chars: &[u16]) -> Value<'a, String> {
pub fn create_string_utf16<'a, 'b>(&'a self, chars: &[u16]) -> Result<Value<'a, String>> {
let mut raw_value = ptr::null_mut();
let status = unsafe {
sys::napi_create_string_utf16(self.0, chars.as_ptr(), chars.len() as u64, &mut raw_value)
};
debug_assert!(Status::from(status) == Status::Ok);
Value::from_raw_value(self, raw_value, String)
check_status(status)?;
Ok(Value::from_raw_value(self, raw_value, String))
}
pub fn create_object<'a>(&'a self) -> Value<'a, Object> {
pub fn create_object<'a>(&'a self) -> Result<Value<'a, Object>> {
let mut raw_value = ptr::null_mut();
let status = unsafe { sys::napi_create_object(self.0, &mut raw_value) };
debug_assert!(Status::from(status) == Status::Ok);
Value::from_raw_value(self, raw_value, Object)
check_status(status)?;
Ok(Value::from_raw_value(self, raw_value, Object))
}
#[cfg(feature = "serde-json")]
pub fn from_serde_value<'a>(&'a self, serde_value: &'a SerdeValue) -> Result<Value<'a, Any>> {
match serde_value {
SerdeValue::Array(v) => {
let result = self.create_array_with_length(v.len());
v.iter().enumerate().try_for_each(|(index, value)| unsafe {
let status = sys::napi_set_element(
self.0,
result.into_raw(),
index as u32,
self.from_serde_value(value)?.into_raw(),
);
check_status(status)
})?;
Ok(result.into_any())
}
SerdeValue::Bool(v) => Ok(self.get_boolean(*v).into_any()),
SerdeValue::Number(v) => {
if v.is_f64() {
self
.create_double(v.as_f64().unwrap())
.map(|v| v.into_any())
} else if v.is_i64() {
self.create_int64(v.as_i64().unwrap()).map(|v| v.into_any())
} else {
self
.create_int64(v.as_u64().unwrap() as i64)
.map(|v| v.into_any())
}
}
SerdeValue::Null => self.get_null().map(|v| v.into_any()),
SerdeValue::String(s) => self.create_string(s).map(|v| v.into_any()),
SerdeValue::Object(map) => {
let mut result = self.create_object();
map.iter().try_for_each(|(key, value)| {
result.set_named_property(key, self.from_serde_value(value)?)
})?;
Ok(result.into_any())
}
}
}
pub fn create_array_with_length(&self, length: usize) -> Value<Object> {
pub fn create_array_with_length(&self, length: usize) -> Result<Value<Object>> {
let mut raw_value = ptr::null_mut();
let status =
unsafe { sys::napi_create_array_with_length(self.0, length as u64, &mut raw_value) };
debug_assert!(Status::from(status) == Status::Ok);
Value::from_raw_value(self, raw_value, Object)
check_status(status)?;
Ok(Value::from_raw_value(self, raw_value, Object))
}
pub fn create_buffer(&self, length: u64) -> Value<Buffer> {
pub fn create_buffer(&self, length: u64) -> Result<Value<Buffer>> {
let mut raw_value = ptr::null_mut();
let mut data = ptr::null_mut();
let status = unsafe { sys::napi_create_buffer(self.0, length, &mut data, &mut raw_value) };
debug_assert!(Status::from(status) == Status::Ok);
Value::from_raw_value(
check_status(status)?;
Ok(Value::from_raw_value(
self,
raw_value,
Buffer {
data: data as *const u8,
size: length,
},
)
))
}
pub fn create_buffer_with_data(&self, data: Vec<u8>) -> Value<Buffer> {
pub fn create_buffer_with_data(&self, data: Vec<u8>) -> Result<Value<Buffer>> {
let length = data.len() as u64;
let mut raw_value = ptr::null_mut();
let data_ptr = data.as_ptr();
@ -393,27 +345,72 @@ impl Env {
&mut raw_value,
)
};
debug_assert!(Status::from(status) == Status::Ok);
check_status(status)?;
let mut changed = 0;
let ajust_external_memory_status =
unsafe { sys::napi_adjust_external_memory(self.0, length as i64, &mut changed) };
debug_assert!(Status::from(ajust_external_memory_status) == Status::Ok);
check_status(ajust_external_memory_status)?;
mem::forget(data);
Value::from_raw_value(
Ok(Value::from_raw_value(
self,
raw_value,
Buffer {
data: data_ptr,
size: length,
},
)
))
}
pub fn create_arraybuffer(&self, length: u64) -> Result<Value<ArrayBuffer>> {
let mut raw_value = ptr::null_mut();
let mut data = ptr::null_mut();
let status = unsafe { sys::napi_create_arraybuffer(self.0, length, &mut data, &mut raw_value) };
check_status(status)?;
Ok(Value::from_raw_value(
self,
raw_value,
ArrayBuffer {
data: data as *const u8,
size: length,
},
))
}
pub fn create_arraybuffer_with_data(&self, data: Vec<u8>) -> Result<Value<ArrayBuffer>> {
let length = data.len() as u64;
let mut raw_value = ptr::null_mut();
let data_ptr = data.as_ptr();
let status = unsafe {
sys::napi_create_external_arraybuffer(
self.0,
data_ptr as *mut c_void,
length,
Some(drop_buffer),
Box::into_raw(Box::from(length)) as *mut c_void,
&mut raw_value,
)
};
check_status(status)?;
let mut changed = 0;
let ajust_external_memory_status =
unsafe { sys::napi_adjust_external_memory(self.0, length as i64, &mut changed) };
check_status(ajust_external_memory_status)?;
mem::forget(data);
Ok(Value::from_raw_value(
self,
raw_value,
ArrayBuffer {
data: data_ptr,
size: length,
},
))
}
pub fn create_function<'a, 'b>(
&'a self,
name: &'b str,
callback: Callback,
) -> Value<'a, Function> {
) -> Result<Value<'a, Function>> {
let mut raw_result = ptr::null_mut();
let status = unsafe {
sys::napi_create_function(
@ -426,30 +423,30 @@ impl Env {
)
};
debug_assert!(Status::from(status) == Status::Ok);
check_status(status)?;
Value::from_raw_value(self, raw_result, Function)
Ok(Value::from_raw_value(self, raw_result, Function))
}
pub fn create_reference<T>(&self, value: &Value<T>) -> Ref<T> {
pub fn create_reference<T>(&self, value: &Value<T>) -> Result<Ref<T>> {
let mut raw_ref = ptr::null_mut();
unsafe {
let status = sys::napi_create_reference(self.0, value.raw_value, 1, &mut raw_ref);
debug_assert!(Status::from(status) == Status::Ok);
check_status(status)?;
};
Ref {
Ok(Ref {
raw_env: self.0,
raw_ref,
_marker: PhantomData,
}
})
}
pub fn get_reference_value<T: ValueType>(&self, reference: &Ref<T>) -> Value<T> {
pub fn get_reference_value<T: ValueType>(&self, reference: &Ref<T>) -> Result<Value<T>> {
let mut raw_value = ptr::null_mut();
unsafe {
let status = sys::napi_get_reference_value(self.0, reference.raw_ref, &mut raw_value);
debug_assert!(Status::from(status) == Status::Ok);
check_status(status)?;
};
Value::from_raw(self, raw_value)
@ -541,8 +538,8 @@ impl Env {
pub fn async_init(&self, resource: Option<Value<Object>>, name: &str) -> Result<AsyncContext> {
let raw_resource = resource
.map(|r| r.into_raw())
.unwrap_or_else(|| self.create_object().into_raw());
.map(|r| Ok(r.into_raw()))
.unwrap_or_else(|| self.create_object().map(|o| o.into_raw()))?;
let raw_name = self.create_string(name)?.into_raw();
let mut raw_context = ptr::null_mut();
@ -591,13 +588,13 @@ impl Env {
}
pub trait ValueType: Copy {
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Self;
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result<Self>;
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool;
}
impl ValueType for Any {
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
Any
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result<Self> {
Ok(Any)
}
fn matches_raw_type(_env: sys::napi_env, _raw: sys::napi_value) -> bool {
@ -606,8 +603,8 @@ impl ValueType for Any {
}
impl ValueType for Undefined {
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
Undefined
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result<Self> {
Ok(Undefined)
}
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
@ -616,8 +613,8 @@ impl ValueType for Undefined {
}
impl ValueType for Null {
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
Null
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result<Self> {
Ok(Null)
}
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
@ -626,11 +623,11 @@ impl ValueType for Null {
}
impl ValueType for Boolean {
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Self {
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result<Self> {
let mut value = true;
let status = unsafe { sys::napi_get_value_bool(env, raw, &mut value) };
debug_assert!(Status::from(status) == Status::Ok);
Boolean { value }
check_status(status)?;
Ok(Boolean { value })
}
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
@ -639,11 +636,11 @@ impl ValueType for Boolean {
}
impl ValueType for Number {
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Self {
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result<Self> {
let mut double: f64 = 0.0;
let status = unsafe { sys::napi_get_value_double(env, raw, &mut double) };
debug_assert!(Status::from(status) == Status::Ok);
Number::Double(double)
check_status(status)?;
Ok(Number::Double(double))
}
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
@ -652,8 +649,8 @@ impl ValueType for Number {
}
impl ValueType for String {
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
String {}
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result<Self> {
Ok(String {})
}
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
@ -662,8 +659,8 @@ impl ValueType for String {
}
impl ValueType for Object {
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
Object {}
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result<Self> {
Ok(Object {})
}
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
@ -672,15 +669,15 @@ impl ValueType for Object {
}
impl ValueType for Buffer {
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Self {
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result<Self> {
let mut data = ptr::null_mut();
let mut size: u64 = 0;
let status = unsafe { sys::napi_get_buffer_info(env, raw, &mut data, &mut size) };
debug_assert!(Status::from(status) == Status::Ok);
Buffer {
check_status(status)?;
Ok(Buffer {
data: data as *const u8,
size,
}
})
}
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
@ -694,15 +691,15 @@ impl ValueType for Buffer {
}
impl ValueType for ArrayBuffer {
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Self {
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result<Self> {
let mut data = ptr::null_mut();
let mut size: u64 = 0;
let status = unsafe { sys::napi_get_arraybuffer_info(env, raw, &mut data, &mut size) };
debug_assert!(Status::from(status) == Status::Ok);
ArrayBuffer {
check_status(status)?;
Ok(ArrayBuffer {
data: data as *const u8,
size,
}
})
}
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
@ -717,18 +714,18 @@ impl ValueType for ArrayBuffer {
impl<'env> Value<'env, Buffer> {
#[inline]
pub fn from_value(env: &'env Env, value: &Value<'env, Any>) -> Value<'env, Buffer> {
Value {
pub fn from_value(env: &'env Env, value: &Value<'env, Any>) -> Result<Value<'env, Buffer>> {
Ok(Value {
env,
raw_value: value.raw_value,
value: Buffer::from_raw(env.0, value.into_raw()),
}
value: Buffer::from_raw(env.0, value.into_raw())?,
})
}
}
impl ValueType for Function {
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
Function {}
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Result<Self> {
Ok(Function {})
}
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
@ -745,28 +742,18 @@ impl<'env, T: ValueType> Value<'env, T> {
}
}
pub fn from_raw(env: &'env Env, raw_value: sys::napi_value) -> Self {
Self {
pub fn from_raw(env: &'env Env, raw_value: sys::napi_value) -> Result<Self> {
Ok(Self {
env,
raw_value,
value: T::from_raw(env.0, raw_value),
}
value: T::from_raw(env.0, raw_value)?,
})
}
pub fn into_raw(self) -> sys::napi_value {
self.raw_value
}
pub fn try_into<S: ValueType>(self) -> Result<Value<'env, S>> {
if S::matches_raw_type(self.env.0, self.raw_value) {
Ok(Value::from_raw(self.env, self.raw_value))
} else {
Err(Error {
status: Status::GenericFailure,
})
}
}
pub fn coerce_to_number(self) -> Result<Value<'env, Number>> {
let mut new_raw_value = ptr::null_mut();
let status =
@ -775,7 +762,7 @@ impl<'env, T: ValueType> Value<'env, T> {
Ok(Value {
env: self.env,
raw_value: self.raw_value,
value: Number::from_raw(self.env.0, self.raw_value),
value: Number::from_raw(self.env.0, self.raw_value)?,
})
}
@ -829,7 +816,7 @@ fn get_raw_type(env: sys::napi_env, raw_value: sys::napi_value) -> sys::napi_val
}
impl<'env> Value<'env, String> {
pub fn len(&self) -> usize {
pub fn len(&self) -> Result<usize> {
let mut raw_length = ptr::null_mut();
unsafe {
let status = sys::napi_get_named_property(
@ -838,19 +825,17 @@ impl<'env> Value<'env, String> {
"length\0".as_ptr() as *const c_char,
&mut raw_length,
);
debug_assert!(Status::from(status) == Status::Ok);
check_status(status)?;
}
let length: Value<Number> = Value::from_raw(self.env, raw_length);
length.into()
let length: Value<Number> = Value::from_raw(self.env, raw_length)?;
length.try_into()
}
}
impl<'env> Deref for Value<'env, String> {
type Target = [u8];
fn deref(&self) -> &[u8] {
impl<'env> Value<'env, String> {
pub fn get_ref(&self) -> Result<&[u8]> {
let mut written_char_count: u64 = 0;
let len = self.len() + 1;
let len = self.len()? + 1;
let mut result = Vec::with_capacity(len);
unsafe {
let status = sys::napi_get_value_string_utf8(
@ -861,18 +846,19 @@ impl<'env> Deref for Value<'env, String> {
&mut written_char_count,
);
debug_assert!(Status::from(status) == Status::Ok);
check_status(status)?;
let ptr = result.as_ptr();
mem::forget(result);
slice::from_raw_parts(ptr as *const u8, written_char_count as usize)
Ok(slice::from_raw_parts(
ptr as *const u8,
written_char_count as usize,
))
}
}
}
impl<'env> DerefMut for Value<'env, String> {
fn deref_mut(&mut self) -> &mut [u8] {
pub fn get_ref_mut(&mut self) -> Result<&mut [u8]> {
let mut written_char_count: u64 = 0;
let len = self.len() + 1;
let len = self.len()? + 1;
let mut result = Vec::with_capacity(len);
unsafe {
let status = sys::napi_get_value_string_utf8(
@ -883,17 +869,22 @@ impl<'env> DerefMut for Value<'env, String> {
&mut written_char_count,
);
debug_assert!(Status::from(status) == Status::Ok);
check_status(status)?;
let ptr = result.as_ptr();
mem::forget(result);
slice::from_raw_parts_mut(ptr as *mut _, written_char_count as usize)
Ok(slice::from_raw_parts_mut(
ptr as *mut _,
written_char_count as usize,
))
}
}
}
impl<'env> Into<Vec<u16>> for Value<'env, String> {
fn into(self) -> Vec<u16> {
let mut result = Vec::with_capacity(self.len() + 1); // Leave room for trailing null byte
impl<'env> TryInto<Vec<u16>> for Value<'env, String> {
type Error = Error;
fn try_into(self) -> Result<Vec<u16>> {
let mut result = Vec::with_capacity(self.len()? + 1); // Leave room for trailing null byte
unsafe {
let mut written_char_count = 0;
@ -904,38 +895,44 @@ impl<'env> Into<Vec<u16>> for Value<'env, String> {
result.capacity() as u64,
&mut written_char_count,
);
debug_assert!(Status::from(status) == Status::Ok);
check_status(status)?;
result.set_len(written_char_count as usize);
}
result
Ok(result)
}
}
impl<'env> Into<usize> for Value<'env, Number> {
fn into(self) -> usize {
impl<'env> TryInto<usize> for Value<'env, Number> {
type Error = Error;
fn try_into(self) -> Result<usize> {
let mut result = 0;
let status = unsafe { sys::napi_get_value_int64(self.env.0, self.raw_value, &mut result) };
debug_assert!(Status::from(status) == Status::Ok);
result as usize
check_status(status)?;
Ok(result as usize)
}
}
impl<'env> Into<i64> for Value<'env, Number> {
fn into(self) -> i64 {
impl<'env> TryInto<i64> for Value<'env, Number> {
type Error = Error;
fn try_into(self) -> Result<i64> {
let mut result = 0;
let status = unsafe { sys::napi_get_value_int64(self.env.0, self.raw_value, &mut result) };
debug_assert!(Status::from(status) == Status::Ok);
result
check_status(status)?;
Ok(result)
}
}
impl<'env> Into<f64> for Value<'env, Number> {
fn into(self) -> f64 {
impl<'env> TryInto<f64> for Value<'env, Number> {
type Error = Error;
fn try_into(self) -> Result<f64> {
let mut result = 0_f64;
let status = unsafe { sys::napi_get_value_double(self.env.0, self.raw_value, &mut result) };
debug_assert!(Status::from(status) == Status::Ok);
result
check_status(status)?;
Ok(result)
}
}
@ -983,7 +980,7 @@ impl<'env> Value<'env, Object> {
)
};
check_status(status)?;
Value::<Any>::from_raw(self.env, raw_value).try_into()
Value::<T>::from_raw(self.env, raw_value)
}
pub fn get_property_names<T: ValueType>(&self) -> Result<Value<T>> {
@ -991,7 +988,7 @@ impl<'env> Value<'env, Object> {
let status =
unsafe { sys::napi_get_property_names(self.raw_env(), self.raw_value(), &mut raw_value) };
check_status(status)?;
Value::<Any>::from_raw(self.env, raw_value).try_into()
Value::<T>::from_raw(self.env, raw_value)
}
pub fn set_index<'a, T>(&mut self, index: usize, value: Value<T>) -> Result<()> {
@ -1003,7 +1000,7 @@ impl<'env> Value<'env, Object> {
let status =
unsafe { sys::napi_get_element(self.raw_env(), self.raw_value(), index, &mut raw_value) };
check_status(status)?;
Value::<Any>::from_raw(self.env, raw_value).try_into()
Value::<T>::from_raw(self.env, raw_value)
}
pub fn is_array(&self) -> Result<bool> {
@ -1020,7 +1017,7 @@ impl<'env> Value<'env, Object> {
Ok(is_buffer)
}
pub fn to_buffer(&self) -> Value<'env, Buffer> {
pub fn to_buffer(&self) -> Result<Value<'env, Buffer>> {
Value::from_raw(self.env, self.raw_value)
}
@ -1101,7 +1098,7 @@ impl<'env> Value<'env, Function> {
};
check_status(status)?;
Ok(Value::from_raw(self.env, return_value))
Value::from_raw(self.env, return_value)
}
}

View file

@ -8,6 +8,7 @@ edition = "2018"
crate-type = ["cdylib"]
[dependencies]
futures = "0.3"
napi-rs = {path = "../napi"}
[build-dependencies]

View file

@ -1,7 +1,9 @@
#[macro_use]
extern crate napi_rs as napi;
use napi::{futures, Any, Env, Error, Object, Result, Status, Value};
extern crate futures;
use napi::{Any, Env, Error, Object, Result, Status, Value};
register_module!(test_module, init);
@ -11,11 +13,11 @@ fn init<'env>(
) -> Result<Option<Value<'env, Object>>> {
exports.set_named_property(
"testSpawn",
env.create_function("testSpawn", callback!(test_spawn)),
env.create_function("testSpawn", callback!(test_spawn))?,
)?;
exports.set_named_property(
"testThrow",
env.create_function("testThrow", callback!(test_throw)),
env.create_function("testThrow", callback!(test_throw))?,
)?;
Ok(None)
}
@ -53,7 +55,7 @@ fn test_spawn<'a>(
env.create_executor().execute(fut_values);
Ok(Some(promise.try_into().unwrap()))
Ok(Some(promise.into_any()))
}
fn test_throw<'a>(