Implement buffer
This commit is contained in:
parent
211ce1e523
commit
7bae4cbb4a
6 changed files with 208 additions and 84 deletions
55
build.rs
55
build.rs
|
@ -9,37 +9,39 @@ use std::path::{Path, PathBuf};
|
|||
use std::process::Command;
|
||||
|
||||
fn find_it<P>(exe_name: P) -> Option<PathBuf>
|
||||
where P: AsRef<Path>,
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
env::var_os("PATH").and_then(|paths| {
|
||||
env::split_paths(&paths).filter_map(|dir| {
|
||||
let full_path = dir.join(&exe_name);
|
||||
if full_path.is_file() {
|
||||
Some(full_path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).next()
|
||||
env::split_paths(&paths)
|
||||
.filter_map(|dir| {
|
||||
let full_path = dir.join(&exe_name);
|
||||
if full_path.is_file() {
|
||||
Some(full_path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.next()
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let node_include_path = find_it("node")
|
||||
.expect("can not find executable node")
|
||||
.parent().unwrap()
|
||||
.parent().unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join("include/node");
|
||||
let node_version = semver::Version::parse(
|
||||
String::from_utf8(Command::new("node")
|
||||
.arg("-v")
|
||||
.output()
|
||||
.unwrap().stdout
|
||||
)
|
||||
String::from_utf8(Command::new("node").arg("-v").output().unwrap().stdout)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.get(1..)
|
||||
.unwrap()
|
||||
).unwrap();
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let node_major_version = node_version.major;
|
||||
|
||||
|
@ -53,13 +55,16 @@ fn main() {
|
|||
|
||||
// Activate the "node8" or "nodestable" feature for compatibility with
|
||||
// different versions of Node.js/N-API.
|
||||
println!("cargo:rustc-cfg=node{}", if node_major_version > 8 {
|
||||
"stable"
|
||||
} else if node_major_version == 8 {
|
||||
"8"
|
||||
} else {
|
||||
panic!("node version is too low")
|
||||
});
|
||||
println!(
|
||||
"cargo:rustc-cfg=node{}",
|
||||
if node_major_version > 8 {
|
||||
"stable"
|
||||
} else if node_major_version == 8 {
|
||||
"8"
|
||||
} else {
|
||||
panic!("node version is too low")
|
||||
}
|
||||
);
|
||||
|
||||
bindgen::Builder::default()
|
||||
.header("src/sys/bindings.h")
|
||||
|
|
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
|
@ -0,0 +1 @@
|
|||
tab_spaces = 2
|
|
@ -27,7 +27,7 @@ const nodeIncludePath = path.join(
|
|||
'node',
|
||||
)
|
||||
|
||||
const moduleName = path.basename(process.cwd()).replace('-', '_')
|
||||
const moduleName = path.basename(process.cwd()).replace(/-/g, '_')
|
||||
process.env.NODE_INCLUDE_PATH = nodeIncludePath
|
||||
process.env.NODE_MAJOR_VERSION = nodeMajorVersion > 8 ? 'stable' : 8
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ impl<T: 'static + Future> Task<T> {
|
|||
fn poll_future(&mut self) -> bool {
|
||||
match self.spawn.poll_future_notify(&self.notify_handle, 0) {
|
||||
Ok(Async::Ready(_)) => {
|
||||
let mut handle = self.notify_handle.0.write().unwrap().take().unwrap();
|
||||
let handle = self.notify_handle.0.write().unwrap().take().unwrap();
|
||||
handle.close();
|
||||
true
|
||||
}
|
||||
|
|
230
src/lib.rs
230
src/lib.rs
|
@ -33,10 +33,14 @@ pub struct Any;
|
|||
pub struct Undefined;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Boolean;
|
||||
pub struct Boolean {
|
||||
value: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Number;
|
||||
pub struct Number {
|
||||
int: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct String;
|
||||
|
@ -48,13 +52,16 @@ pub struct Object;
|
|||
pub struct Function;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Buffer;
|
||||
pub struct Buffer {
|
||||
data: *const u8,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Value<'env, T> {
|
||||
env: &'env Env,
|
||||
raw_value: sys::napi_value,
|
||||
_marker: PhantomData<T>,
|
||||
value: T,
|
||||
}
|
||||
|
||||
pub struct Ref<T> {
|
||||
|
@ -219,14 +226,14 @@ impl Env {
|
|||
let mut raw_value = ptr::null_mut();
|
||||
let status = unsafe { sys::napi_get_undefined(self.0, &mut raw_value) };
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
Value::from_raw(self, raw_value)
|
||||
Value::from_raw_value(self, raw_value, Undefined)
|
||||
}
|
||||
|
||||
pub fn get_boolean(&self, value: bool) -> 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(self, raw_value)
|
||||
Value::from_raw_value(self, raw_value, Boolean { value })
|
||||
}
|
||||
|
||||
pub fn create_int64<'a>(&'a self, int: i64) -> Value<'a, Number> {
|
||||
|
@ -234,7 +241,7 @@ impl Env {
|
|||
let status =
|
||||
unsafe { sys::napi_create_int64(self.0, int, (&mut raw_value) as *mut sys::napi_value) };
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
Value::from_raw(self, raw_value)
|
||||
Value::from_raw_value(self, raw_value, Number { int })
|
||||
}
|
||||
|
||||
pub fn create_string<'a, 'b>(&'a self, s: &'b str) -> Value<'a, String> {
|
||||
|
@ -243,7 +250,7 @@ impl Env {
|
|||
sys::napi_create_string_utf8(self.0, s.as_ptr() as *const c_char, s.len(), &mut raw_value)
|
||||
};
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
Value::from_raw(self, raw_value)
|
||||
Value::from_raw_value(self, raw_value, String)
|
||||
}
|
||||
|
||||
pub fn create_string_utf16<'a, 'b>(&'a self, chars: &[u16]) -> Value<'a, String> {
|
||||
|
@ -251,29 +258,52 @@ impl Env {
|
|||
let status =
|
||||
unsafe { sys::napi_create_string_utf16(self.0, chars.as_ptr(), chars.len(), &mut raw_value) };
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
Value::from_raw(self, raw_value)
|
||||
Value::from_raw_value(self, raw_value, String)
|
||||
}
|
||||
|
||||
pub fn create_object<'a>(&'a self) -> 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(self, raw_value)
|
||||
Value::from_raw_value(self, raw_value, Object)
|
||||
}
|
||||
|
||||
pub fn create_array_with_length(&self, length: usize) -> Value<Object> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let status = unsafe { sys::napi_create_array_with_length(self.0, length, &mut raw_value) };
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
Value::from_raw(self, raw_value)
|
||||
Value::from_raw_value(self, raw_value, Object)
|
||||
}
|
||||
|
||||
pub fn create_buffer(&self, length: usize) -> 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, _data, &mut raw_value) };
|
||||
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(self, raw_value)
|
||||
Value::from_raw_value(
|
||||
self,
|
||||
raw_value,
|
||||
Buffer {
|
||||
data: data as *const u8,
|
||||
size: length,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn create_buffer_with_data(&self, data_ptr: *const u8, length: usize) -> Value<Buffer> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let mut data_raw_ptr = data_ptr as *mut c_void;
|
||||
let status =
|
||||
unsafe { sys::napi_create_buffer(self.0, length, &mut data_raw_ptr, &mut raw_value) };
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
Value::from_raw_value(
|
||||
self,
|
||||
raw_value,
|
||||
Buffer {
|
||||
data: data_ptr,
|
||||
size: length,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn create_function<'a, 'b>(
|
||||
|
@ -295,7 +325,7 @@ impl Env {
|
|||
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
|
||||
Value::from_raw(self, raw_result)
|
||||
Value::from_raw_value(self, raw_result, Function)
|
||||
}
|
||||
|
||||
pub fn create_reference<T>(&self, value: &Value<T>) -> Ref<T> {
|
||||
|
@ -349,7 +379,7 @@ impl Env {
|
|||
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
|
||||
Value::from_raw(self, raw_result)
|
||||
Value::from_raw_value(self, raw_result, Function)
|
||||
}
|
||||
|
||||
pub fn wrap<T: 'static>(&self, js_object: &mut Value<Object>, native_object: T) -> Result<()> {
|
||||
|
@ -437,7 +467,10 @@ impl Env {
|
|||
sys::napi_create_promise(self.0, &mut raw_deferred, &mut raw_promise);
|
||||
}
|
||||
|
||||
(Value::from_raw(self, raw_promise), Deferred(raw_deferred))
|
||||
(
|
||||
Value::from_raw_value(self, raw_promise, Object),
|
||||
Deferred(raw_deferred),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_deferred<T: ValueType>(&self, deferred: Deferred, value: Value<T>) {
|
||||
|
@ -453,63 +486,122 @@ impl Env {
|
|||
}
|
||||
|
||||
pub trait ValueType: Copy {
|
||||
fn matches_raw_type(raw_type: sys::napi_valuetype) -> bool;
|
||||
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Self;
|
||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool;
|
||||
}
|
||||
|
||||
impl ValueType for Any {
|
||||
fn matches_raw_type(_raw_type: sys::napi_valuetype) -> bool {
|
||||
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
|
||||
Any
|
||||
}
|
||||
|
||||
fn matches_raw_type(_env: sys::napi_env, _raw: sys::napi_value) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueType for Undefined {
|
||||
fn matches_raw_type(raw_type: sys::napi_valuetype) -> bool {
|
||||
raw_type == sys::napi_valuetype::napi_undefined
|
||||
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
|
||||
Undefined
|
||||
}
|
||||
|
||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_undefined
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueType for Boolean {
|
||||
fn matches_raw_type(raw_type: sys::napi_valuetype) -> bool {
|
||||
raw_type == sys::napi_valuetype::napi_boolean
|
||||
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> 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 }
|
||||
}
|
||||
|
||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_boolean
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueType for Number {
|
||||
fn matches_raw_type(raw_type: sys::napi_valuetype) -> bool {
|
||||
raw_type == sys::napi_valuetype::napi_number
|
||||
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Self {
|
||||
let mut int: i64 = 0;
|
||||
let status = unsafe { sys::napi_get_value_int64(env, raw, &mut int) };
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
Number { int }
|
||||
}
|
||||
|
||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_number
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueType for String {
|
||||
fn matches_raw_type(raw_type: sys::napi_valuetype) -> bool {
|
||||
raw_type == sys::napi_valuetype::napi_string
|
||||
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
|
||||
String {}
|
||||
}
|
||||
|
||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_string
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueType for Object {
|
||||
fn matches_raw_type(raw_type: sys::napi_valuetype) -> bool {
|
||||
raw_type == sys::napi_valuetype::napi_object
|
||||
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
|
||||
Object {}
|
||||
}
|
||||
|
||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_object
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueType for Buffer {
|
||||
fn matches_raw_type(raw_type: sys::napi_valuetype) -> bool {
|
||||
raw_type == sys::napi_valuetype::napi_external
|
||||
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Self {
|
||||
let mut data = ptr::null_mut();
|
||||
let mut size: usize = 0;
|
||||
let status = unsafe { sys::napi_get_buffer_info(env, raw, &mut data, &mut size) };
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
Buffer {
|
||||
data: data as *const u8,
|
||||
size,
|
||||
}
|
||||
}
|
||||
|
||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
||||
let mut result = false;
|
||||
unsafe {
|
||||
let status = sys::napi_is_buffer(env, raw, &mut result);
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueType for Function {
|
||||
fn matches_raw_type(raw_type: sys::napi_valuetype) -> bool {
|
||||
raw_type == sys::napi_valuetype::napi_function
|
||||
fn from_raw(_env: sys::napi_env, _raw: sys::napi_value) -> Self {
|
||||
Function {}
|
||||
}
|
||||
|
||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_function
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env, T: ValueType> Value<'env, T> {
|
||||
pub fn from_raw_value(env: &'env Env, raw_value: sys::napi_value, value: T) -> Self {
|
||||
Self {
|
||||
env,
|
||||
raw_value,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_raw(env: &'env Env, raw_value: sys::napi_value) -> Self {
|
||||
Self {
|
||||
env,
|
||||
raw_value,
|
||||
_marker: PhantomData,
|
||||
value: T::from_raw(env.0, raw_value),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -518,17 +610,12 @@ impl<'env, T: ValueType> Value<'env, T> {
|
|||
}
|
||||
|
||||
pub fn try_into<S: ValueType>(self) -> Result<Value<'env, S>> {
|
||||
unsafe {
|
||||
let mut value_type: sys::napi_valuetype = mem::uninitialized();
|
||||
let status = sys::napi_typeof(self.env.0, self.raw_value, &mut value_type);
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
if S::matches_raw_type(value_type) {
|
||||
Ok(mem::transmute(self))
|
||||
} else {
|
||||
Err(Error {
|
||||
status: Status::GenericFailure,
|
||||
})
|
||||
}
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,7 +627,7 @@ impl<'env, T: ValueType> Value<'env, T> {
|
|||
Ok(Value {
|
||||
env: self.env,
|
||||
raw_value: self.raw_value,
|
||||
_marker: PhantomData,
|
||||
value: Number::from_raw(self.env.0, self.raw_value),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -552,7 +639,7 @@ impl<'env, T: ValueType> Value<'env, T> {
|
|||
Ok(Value {
|
||||
env: self.env,
|
||||
raw_value: self.raw_value,
|
||||
_marker: PhantomData,
|
||||
value: String,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -569,11 +656,21 @@ impl<'env, T: ValueType> Value<'env, T> {
|
|||
Ok(Value {
|
||||
env: self.env,
|
||||
raw_value: self.raw_value,
|
||||
_marker: PhantomData,
|
||||
value: Object,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_raw_type(env: sys::napi_env, raw_value: sys::napi_value) -> sys::napi_valuetype {
|
||||
unsafe {
|
||||
let mut value_type: sys::napi_valuetype = mem::uninitialized();
|
||||
let status = sys::napi_typeof(env, raw_value, &mut value_type);
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
value_type
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env> Value<'env, String> {
|
||||
pub fn len(&self) -> usize {
|
||||
let mut raw_length = ptr::null_mut();
|
||||
|
@ -591,6 +688,30 @@ impl<'env> Value<'env, String> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'env> Deref for Value<'env, String> {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &[u8] {
|
||||
let mut written_char_count: usize = 0;
|
||||
let len = self.len() + 1;
|
||||
let mut result = Vec::with_capacity(len);
|
||||
unsafe {
|
||||
let status = sys::napi_get_value_string_utf8(
|
||||
self.env.0,
|
||||
self.raw_value,
|
||||
result.as_mut_ptr(),
|
||||
len,
|
||||
&mut written_char_count as *mut usize,
|
||||
);
|
||||
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
let ptr = result.as_ptr();
|
||||
mem::forget(result);
|
||||
slice::from_raw_parts(ptr as *const u8, written_char_count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -739,21 +860,18 @@ impl<'env> Deref for Value<'env, Buffer> {
|
|||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &[u8] {
|
||||
let mut data = ptr::null_mut();
|
||||
let size = ptr::null_mut();
|
||||
let status = unsafe { sys::napi_get_buffer_info(self.env.0, self.raw_value, &mut data, size) };
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
unsafe { slice::from_raw_parts(data as *const _, *size) }
|
||||
unsafe { slice::from_raw_parts(self.value.data, self.value.size) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env> DerefMut for Value<'env, Buffer> {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
let mut data = ptr::null_mut();
|
||||
let size = ptr::null_mut();
|
||||
let status = unsafe { sys::napi_get_buffer_info(self.env.0, self.raw_value, &mut data, size) };
|
||||
let mut size = 0;
|
||||
let status =
|
||||
unsafe { sys::napi_get_buffer_info(self.env.0, self.raw_value, &mut data, &mut size) };
|
||||
debug_assert!(Status::from(status) == Status::Ok);
|
||||
unsafe { slice::from_raw_parts_mut(data as *mut _, *size) }
|
||||
unsafe { slice::from_raw_parts_mut(data as *mut _, size) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ pub enum Status {
|
|||
EscapeCalledTwice,
|
||||
HandleScopeMismatch,
|
||||
StringContainsNull,
|
||||
CallbackScopeMismatch
|
||||
CallbackScopeMismatch,
|
||||
}
|
||||
|
||||
impl From<napi_status> for Status {
|
||||
|
|
Loading…
Reference in a new issue