Skip to content

Commit

Permalink
Added cStringVecToStringArray conversion, and made stringified …
Browse files Browse the repository at this point in the history
…types use the C names rather than the Rust ones.
  • Loading branch information
danielhenrymantilla committed Mar 24, 2021
1 parent 8bd0a4a commit e556a94
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 76 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ headers = [
csharp-headers = ["headers"]

node-js = [
"headers",
"inventory",
"napi",
"napi-derive",
Expand Down
2 changes: 1 addition & 1 deletion nodejs_tests/tests/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ assertCheckPointIsCalled((checkPoint) => {

assertCheckPointIsCalled((checkPoint) => {
let error = null;
let v = ffi.withOutVecOfPtrs("u8", (p) => {
let v = ffi.withOutVecOfPtrs("Vec_uint8_t", "uint8_t", (p) => {
try {
checkPoint();
ffi.takes_out_vec(p);
Expand Down
28 changes: 20 additions & 8 deletions src/layout/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,13 @@ macro_rules! CType {(
where
Self : 'static,
$(
$field_ty : $crate::node_js::ReprNapi,
$field_ty : $crate::layout::ReprC,
<$field_ty as $crate::layout::ReprC>::CLayout : $crate::node_js::ReprNapi,
)*
$(
$($(
$generics : $crate::node_js::ReprNapi,
$generics : $crate::layout::ReprC,
<$generics as $crate::layout::ReprC>::CLayout : $crate::node_js::ReprNapi,
)+)?
$($($bounds)*)?
)?
Expand All @@ -146,8 +148,12 @@ macro_rules! CType {(
$(
_obj.set_named_property(
$crate::core::stringify!($field_name),
<$field_ty as $crate::node_js::ReprNapi>::to_napi_value(
self.$field_name,
<
<$field_ty as $crate::layout::ReprC>::CLayout
as
$crate::node_js::ReprNapi
>::to_napi_value(
unsafe { $crate::layout::into_raw(self.$field_name) },
env,
)?,
)?;
Expand Down Expand Up @@ -198,10 +204,16 @@ macro_rules! CType {(
let obj = $crate::node_js::JsObject::try_from(obj)?;
$crate::node_js::Result::Ok(Self {
$(
$field_name: <$field_ty as $crate::node_js::ReprNapi>::from_napi_value(
env,
obj.get_named_property($crate::core::stringify!($field_name))?,
)?,
$field_name: unsafe { $crate::layout::from_raw_unchecked(
<
<$field_ty as $crate::layout::ReprC>::CLayout
as
$crate::node_js::ReprNapi
>::from_napi_value(
env,
obj.get_named_property($crate::core::stringify!($field_name))?,
)?
)},
)*
})
}
Expand Down
126 changes: 66 additions & 60 deletions src/node_js/ffi_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn with_js_string_as_utf8 (ctx: CallContext<'_>)
let cb: JsFunction = ctx.get(1)?;
let mut bytes;
let ptr: *const crate::c_char = match fst.get_type() {
| Ok(Js::Null) => crate::NULL!(),
| Ok(Js::Null) => NULL!(),
| Ok(Js::String) => {
let s = unsafe { fst.cast::<JsString>() };
bytes = s.into_utf8()?.take();
Expand Down Expand Up @@ -65,7 +65,7 @@ fn with_js_buffer_as_slice_uint8_t_ref (ctx: CallContext<'_>)
cb.call(None, &[
ReprNapi::to_napi_value(
crate::slice::slice_raw_Layout::<u8> {
ptr: crate::NULL!(),
ptr: NULL!(),
len: 0xbad000,
},
ctx.env,
Expand Down Expand Up @@ -180,32 +180,34 @@ fn with_out_u64 (ctx: CallContext<'_>)
.into_unknown()
})}

fn wrap_ptr (env: &'_ Env, p: *mut (), ty: &'_ str)
-> Result<JsUnknown>
{
let mut obj = env.create_object()?;
obj.set_named_property(
"addr",
ReprNapi::to_napi_value(p as isize, env)?,
)?;
obj.set_named_property(
"type",
env.create_string(ty)?,
)?;
Ok(obj.into_unknown())
}

#[js_function(2)]
pub
fn with_out_ptr (ctx: CallContext<'_>)
-> Result<JsUnknown>
{Ok({
let ref ty: String = ctx.get::<JsString>(0)?.into_utf8()?.into_owned()?;
let ty = &format!("*mut {}", ty);
let wrap_ptr = |p: *mut (), ty: &str| Ok::<_, Error>({
let mut obj = ctx.env.create_object()?;
obj.set_named_property(
"addr",
ReprNapi::to_napi_value(p as isize, ctx.env)?,
)?;
obj.set_named_property(
"type",
ctx.env.create_string(ty)?,
)?;
obj.into_unknown()
});
let cb: JsFunction = ctx.get(1)?;
let mut p: *mut () = crate::NULL!();
let mut p: *mut () = NULL!();
let out_p = &mut p;
cb.call(None, &[
wrap_ptr(<*mut _>::cast(out_p), &format!("*mut {}", ty))?
wrap_ptr(ctx.env, <*mut _>::cast(out_p), &format!("{} *", ty))?
])?;
wrap_ptr(p, ty)?
wrap_ptr(ctx.env, p, ty)?
.into_unknown()
})}

Expand All @@ -214,19 +216,7 @@ pub
fn with_out_byte_slice (ctx: CallContext<'_>)
-> Result<JsUnknown>
{Ok({
let ty = &"safer_ffi::slice::__slice_boxed_safer_ffi_mod::slice_boxed<u8>";
let wrap_ptr = |p: *mut (), ty: &str| Ok::<_, Error>({
let mut obj = ctx.env.create_object()?;
obj.set_named_property(
"addr",
ReprNapi::to_napi_value(p as isize, ctx.env)?,
)?;
obj.set_named_property(
"type",
ctx.env.create_string(ty)?,
)?;
obj.into_unknown()
});
let ty = &"slice_boxed_uint8_t";
let cb: JsFunction = ctx.get(0)?;
let mut v = crate::slice::slice_ref_Layout::<()> {
ptr: NULL!(),
Expand All @@ -235,65 +225,80 @@ fn with_out_byte_slice (ctx: CallContext<'_>)
};
let out_v = &mut v;
cb.call(None, &[
wrap_ptr(<*mut _>::cast(out_v), &format!("*mut {}", ty))?
wrap_ptr(ctx.env, <*mut _>::cast(out_v), &format!("{} *", ty))?
])?;
let mut v_js = ctx.env.create_object()?;
v_js.set_named_property(
"ptr",
wrap_ptr(v.ptr as _, ty)?,
"ptr", wrap_ptr(ctx.env, v.ptr as _, "uint8_t *")?,
)?;
v_js.set_named_property(
"len",
ReprNapi::to_napi_value(v.len as usize, ctx.env)?,
"len", ReprNapi::to_napi_value(v.len as usize, ctx.env)?,
)?;
v_js.into_unknown()
})}

#[js_function(2)]
#[js_function(3)]
pub
fn with_out_vec_of_ptrs (ctx: CallContext<'_>)
-> Result<JsUnknown>
{Ok({
let ref ty: String = ctx.get::<JsString>(0)?.into_utf8()?.into_owned()?;
let ty = &format!("safer_ffi::vec::__Vec_safer_ffi_mod::Vec<{}>", ty);
let wrap_ptr = |p: *mut (), ty: &str| Ok::<_, Error>({
let mut obj = ctx.env.create_object()?;
obj.set_named_property(
"addr",
ReprNapi::to_napi_value(p as isize, ctx.env)?,
)?;
obj.set_named_property(
"type",
ctx.env.create_string(ty)?,
)?;
obj.into_unknown()
});
let cb: JsFunction = ctx.get(1)?;
let ref vec_ty: String = ctx.get::<JsString>(0)?.into_utf8()?.into_owned()?;
let ref ty: String = ctx.get::<JsString>(1)?.into_utf8()?.into_owned()?;
let cb: JsFunction = ctx.get(2)?;
let mut v = crate::vec::Vec_Layout::<()> {
ptr: NULL!(),
len: 0,
cap: 0,
};
let out_v = &mut v;
cb.call(None, &[
wrap_ptr(<*mut _>::cast(out_v), &format!("*mut {}", ty))?
wrap_ptr(
ctx.env,
<*mut _>::cast(out_v),
&format!("{} *", vec_ty),
)?
])?;
let mut v_js = ctx.env.create_object()?;
v_js.set_named_property(
"ptr",
wrap_ptr(v.ptr.cast(), ty)?,
"ptr", wrap_ptr(ctx.env, v.ptr.cast(), &format!("{} *", ty))?,
)?;
v_js.set_named_property(
"len",
ReprNapi::to_napi_value(v.len as usize, ctx.env)?,
"len", ReprNapi::to_napi_value(v.len as usize, ctx.env)?,
)?;
v_js.set_named_property(
"cap",
ReprNapi::to_napi_value(v.cap as usize, ctx.env)?,
"cap", ReprNapi::to_napi_value(v.cap as usize, ctx.env)?,
)?;
v_js.into_unknown()
})}

#[js_function(1)]
pub
fn vec_char_ptr_to_js_string_array (ctx: CallContext<'_>)
-> Result<JsObject>
{Ok({
use crate::prelude::*;
let arg = super::extract_arg::<crate::vec::Vec_Layout::<char_p::Box>>(&ctx, 0)?;
let v: repr_c::Vec<char_p::Box> = unsafe { crate::layout::from_raw_unchecked(arg) };
let v: Vec<char_p::Box> = v.into();
let ret = ctx.env.create_array()?;
let push = {
let ret = &ret;
let push_method = ret.get_property::<_, JsFunction>(&ctx.env.create_string("push")?)?;
move |elem| push_method.call(
Some(ret),
&[elem],
)
};
for p in v {
push(
ctx .env
.create_string(p.to_str())?
.into_unknown()
)?;
}
ret
})}

match_! {(
"withCString": with_js_string_as_utf8,
"boxCStringIntoString": char_p_boxed_to_js_string,
Expand All @@ -303,8 +308,9 @@ match_! {(
"withOutPtr": with_out_ptr,
"withOutBoolean": with_out_bool,
"withOutU64": with_out_u64,
"withOutVecOfPtrs": with_out_vec_of_ptrs,
"withOutBoxCBytes": with_out_byte_slice,
"withOutVecOfPtrs": with_out_vec_of_ptrs,
"cStringVecToStringArray": vec_char_ptr_to_js_string_array,
) {[ $( $name:literal : $fun:ident ),* $(,)? ] => (
#[macro_export]
macro_rules! node_js_export_ffi_helpers {() => (const _: () = {
Expand Down
14 changes: 7 additions & 7 deletions src/node_js/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ match_! {( const, mut ) {
;
let ty: JsString =
env.create_string_from_std(format!(
"*{mut} {pointee}",
mut = stringify!($mut),
pointee = ::core::any::type_name::<T>(),
"{pointee} {mut}*",
mut = if stringify!($mut) == "const" { "const " } else { "" },
pointee = <T as crate::layout::CType>::c_var(""),
))?
;

Expand Down Expand Up @@ -151,15 +151,15 @@ match_! {( const, mut ) {
let addr: JsNumber = obj.get_named_property("addr")?;
let ty: JsString = obj.get_named_property("type")?;
let expected_ty: &str = &format!(
"*{mut} {pointee}",
mut = stringify!($mut),
pointee = ::core::any::type_name::<T>(),
"{pointee} {mut}*",
mut = if stringify!($mut) == "const" { "const " } else { "" },
pointee = <T as crate::layout::CType>::c_var(""),
);
let actual_ty = ty.into_utf8()?;
let mut actual_ty = actual_ty.as_str()?;
let storage;
if stringify!($mut) == "const" {
storage = actual_ty.replace("mut", "const");
storage = actual_ty.replace("const *", "*").replace(" *", " const *");
actual_ty = &storage;
}
if actual_ty != expected_ty {
Expand Down

0 comments on commit e556a94

Please sign in to comment.