From 890a310159e46c84c9d1d0df40ef7689f7de3e83 Mon Sep 17 00:00:00 2001 From: zhangyuang Date: Sat, 13 Apr 2024 23:25:39 +0800 Subject: [PATCH] feat: support static array in c struct field --- build.rs | 19 ------ cpp/sum.cpp | 8 +++ cpp/sum.h | 23 ++----- scripts/type.js | 2 +- scripts/types.d.ts | 1 + src/datatype/function.rs | 12 +++- src/datatype/object_calculate.rs | 113 ++++++++++++++++++++++++++----- src/datatype/object_generate.rs | 71 ++++++++++++++----- src/define.rs | 9 +++ src/lib.rs | 1 - src/utils/dataprocess.rs | 80 ++++++++++++++++------ src/utils/mod.rs | 1 + src/utils/object_utils.rs | 38 +++++++++++ test.ts | 45 +++++++++--- 14 files changed, 315 insertions(+), 108 deletions(-) create mode 100644 src/utils/object_utils.rs diff --git a/build.rs b/build.rs index 5c5924b..3bb5d75 100644 --- a/build.rs +++ b/build.rs @@ -1,25 +1,6 @@ extern crate napi_build; -macro_rules! p { - ($($tokens: tt)*) => { - println!("cargo:warning={}", format!($($tokens)*)) - } -} fn main() { - let env = std::env::var("env").unwrap_or_else(|_| String::from("production")); println!("cargo:rustc-link-search=native=."); - if env == "development" { - let bindings = bindgen::Builder::default() - .header("./cpp/sum.h") - .parse_callbacks(Box::new(bindgen::CargoCallbacks)) - .allowlist_function(".*") - .raw_line("#[link(name = \"sum\")]") - .generate() - .expect("Unable to generate bindings"); - bindings - .write_to_file("./src/bindings.rs") - .expect("Couldn't write bindings!"); - } - napi_build::setup(); } diff --git a/cpp/sum.cpp b/cpp/sum.cpp index bbc1b76..1f685c1 100644 --- a/cpp/sum.cpp +++ b/cpp/sum.cpp @@ -53,6 +53,7 @@ typedef struct Person { const char *name; char **stringArray; int *i32Array; + uint8_t staticBytes[16]; bool boolTrue; bool boolFalse; int64_t longVal; @@ -74,6 +75,10 @@ extern "C" Person *createPerson() { person->age = 23; person->doubleProps = 1.1; person->byte = 'A'; + uint8_t bytes[16]; + memset(bytes, 99, sizeof(bytes)); + + memcpy(person->staticBytes, bytes, sizeof(bytes)); // Allocate and initialize name person->name = strdup("tom"); @@ -105,6 +110,9 @@ extern "C" Person *createPerson() { person->parent->age = 43; person->parent->doubleProps = 3.3; person->parent->name = strdup("tom father"); + uint8_t pbytes[16]; + memset(pbytes, 88, sizeof(bytes)); + memcpy(person->parent->staticBytes, pbytes, sizeof(pbytes)); char *pstringArray[] = {strdup("tom"), strdup("father")}; person->parent->stringArray = (char **)malloc(sizeof(pstringArray)); diff --git a/cpp/sum.h b/cpp/sum.h index 52b3e27..6c66ec0 100644 --- a/cpp/sum.h +++ b/cpp/sum.h @@ -13,26 +13,11 @@ extern void noRet(); extern int *createArrayi32(const int *arr, int size); extern double *createArrayDouble(const double *arr, int size); extern char **createArrayString(char **arr, int size); -typedef struct Parent { - const char *name; - int age; -} Parent; -class MyClass { -public: - MyClass(); - void method(); -}; -typedef void (*FunctionPointer)(double a); - -extern void callFunction(FunctionPointer func); - -typedef struct Person { - const char *name; - int age; - Parent parent; -} Person; -extern const Person *getStruct(const Person *p); +typedef struct { + int bytes[2]; +} cpu_svn_t; +extern int pck_cert_select(const cpu_svn_t *platform_svn, int bytes[2]); #ifdef __cplusplus } #endif diff --git a/scripts/type.js b/scripts/type.js index 05fdb8f..a06a0dc 100644 --- a/scripts/type.js +++ b/scripts/type.js @@ -11,11 +11,11 @@ const { resolve } = require("path"); ` ${entryContent} module.exports.arrayConstructor = (options) => ({ + dynamicArray: true, ...options, ffiTypeTag: 'array' }) module.exports.funcConstructor = (options) => (() => ({ - permanent: false, ffiTypeTag: 'function', ...options, })) diff --git a/scripts/types.d.ts b/scripts/types.d.ts index df09a85..14ff037 100644 --- a/scripts/types.d.ts +++ b/scripts/types.d.ts @@ -53,6 +53,7 @@ export type ArrayConstructorOptions = { type: T; length: number; ffiTypeTag?: string; + dynamicArray?: boolean }; export type FuncConstructorOptions = { diff --git a/src/datatype/function.rs b/src/datatype/function.rs index c670ff4..bfc582a 100644 --- a/src/datatype/function.rs +++ b/src/datatype/function.rs @@ -44,7 +44,11 @@ pub unsafe fn get_js_function_call_value_from_ptr( RsArgsValue::Object(obj) => { let array_desc = get_array_desc(obj); if array_desc.is_some() { - let (array_len, array_type) = array_desc.unwrap(); + let FFIARRARYDESC { + array_type, + array_len, + .. + } = array_desc.unwrap(); match array_type { RefDataType::StringArray => { let arr = @@ -119,7 +123,11 @@ pub unsafe fn get_js_function_call_value( RsArgsValue::Object(obj) => { let array_desc = get_array_desc(obj); if array_desc.is_some() { - let (array_len, array_type) = array_desc.unwrap(); + let FFIARRARYDESC { + array_type, + array_len, + .. + } = array_desc.unwrap(); match array_type { RefDataType::StringArray => { let arr = create_array_from_pointer(func_val_ptr as *mut *mut c_char, array_len); diff --git a/src/datatype/object_calculate.rs b/src/datatype/object_calculate.rs index e732a2f..d3443ff 100644 --- a/src/datatype/object_calculate.rs +++ b/src/datatype/object_calculate.rs @@ -1,5 +1,7 @@ -use crate::define::RsArgsValue; -use crate::utils::dataprocess::get_js_external_wrap_data; +use crate::define::{RsArgsValue, FFIARRARYDESC}; +use crate::utils::dataprocess::{get_array_desc, get_js_external_wrap_data}; +use crate::utils::object_utils::get_size_align; +use crate::{FFIError, RefDataType}; use indexmap::IndexMap; use libc::{c_ulonglong, c_void}; use napi::{Env, Result}; @@ -7,10 +9,6 @@ use std::alloc::{alloc, Layout}; use std::ffi::CString; use std::ffi::{c_char, c_double, c_int, c_longlong, c_uchar}; -pub fn get_size_align() -> (usize, usize) { - (std::mem::size_of::(), std::mem::align_of::()) -} - macro_rules! calculate_layout_for { ($variant:ident, $type:ty) => { fn $variant(size: usize, align: usize, offset: usize) -> (usize, usize, usize) { @@ -44,8 +42,34 @@ pub fn calculate_struct_size(map: &IndexMap) -> (usize, usi RsArgsValue::String(_) => calculate_string(size, align, offset), RsArgsValue::Boolean(_) => calculate_boolean(size, align, offset), RsArgsValue::Void(_) => calculate_void(size, align, offset), - RsArgsValue::Object(_) - | RsArgsValue::StringArray(_) + RsArgsValue::Object(obj) => { + let array_desc = get_array_desc(obj); + if array_desc.is_some() { + let FFIARRARYDESC { + array_type, + array_len, + .. + } = array_desc.unwrap(); + let (mut type_size, type_align) = match array_type { + RefDataType::U8Array => get_size_align::(), + RefDataType::I32Array => get_size_align::(), + RefDataType::DoubleArray => get_size_align::(), + _ => panic!( + "write {:?} static array in struct is unsupported", + array_type + ), + }; + type_size = type_size * array_len; + let align = align.max(type_align); + let padding = (type_align - (offset % type_align)) % type_align; + let size = size + padding + type_size; + let offset = offset + padding + type_size; + (size, align, offset) + } else { + calculate_pointer(size, align, offset) + } + } + RsArgsValue::StringArray(_) | RsArgsValue::DoubleArray(_) | RsArgsValue::I32Array(_) | RsArgsValue::U8Array(_, _) @@ -147,7 +171,7 @@ pub unsafe fn generate_c_struct( let c_string = CString::new(str).unwrap(); let ptr = c_string.as_ptr(); std::mem::forget(c_string); - return ptr; + ptr }) .collect(); (field_ptr as *mut *const *const c_char).write(c_char_vec.as_ptr()); @@ -173,7 +197,7 @@ pub unsafe fn generate_c_struct( offset += size + padding; size } - RsArgsValue::U8Array(buffer, arr) => { + RsArgsValue::U8Array(buffer, _) => { let buffer = buffer.unwrap(); let (size, align) = get_size_align::<*mut c_void>(); let padding = (align - (offset % align)) % align; @@ -184,13 +208,68 @@ pub unsafe fn generate_c_struct( size } RsArgsValue::Object(val) => { - let (size, align) = get_size_align::<*mut c_void>(); - let padding = (align - (offset % align)) % align; - field_ptr = field_ptr.offset(padding as isize); - let obj_ptr = generate_c_struct(env, val)?; - (field_ptr as *mut *const c_void).write(obj_ptr); - offset += size + padding; - size + let array_desc = get_array_desc(&val); + if array_desc.is_some() { + // write static array data to struct + let FFIARRARYDESC { + array_type, + array_len, + array_value, + dynamic_array, + .. + } = array_desc.unwrap(); + if dynamic_array { + panic!("generate struct field unsupport use object describe array") + } + match array_type { + RefDataType::U8Array => { + let (size, align) = get_size_align::(); + let field_size = size * array_len; + let padding = (align - (offset % align)) % align; + field_ptr = field_ptr.offset(padding as isize); + if let RsArgsValue::U8Array(buffer, _) = array_value.unwrap() { + let buffer = buffer.as_ref().unwrap(); + std::ptr::copy(buffer.as_ptr(), field_ptr as *mut u8, array_len); + offset += field_size + padding; + } + field_size + } + RefDataType::I32Array => { + let (size, align) = get_size_align::(); + let field_size = size * array_len; + let padding = (align - (offset % align)) % align; + field_ptr = field_ptr.offset(padding as isize); + if let RsArgsValue::I32Array(arr) = array_value.unwrap() { + std::ptr::copy(arr.as_ptr(), field_ptr as *mut i32, array_len); + offset += field_size + padding; + } + field_size + } + RefDataType::DoubleArray => { + let (size, align) = get_size_align::(); + let field_size = size * array_len; + let padding = (align - (offset % align)) % align; + field_ptr = field_ptr.offset(padding as isize); + if let RsArgsValue::DoubleArray(arr) = array_value.unwrap() { + std::ptr::copy(arr.as_ptr(), field_ptr as *mut f64, array_len); + offset += field_size + padding; + } + field_size + } + _ => panic!( + "write {:?} static array in struct is unsupported", + array_type + ), + } + } else { + let (size, align) = get_size_align::<*mut c_void>(); + let padding = (align - (offset % align)) % align; + field_ptr = field_ptr.offset(padding as isize); + let obj_ptr = generate_c_struct(env, val)?; + (field_ptr as *mut *const c_void).write(obj_ptr); + offset += size + padding; + size + } } RsArgsValue::External(val) => { let (size, align) = get_size_align::<*mut c_void>(); diff --git a/src/datatype/object_generate.rs b/src/datatype/object_generate.rs index 64d35ea..0454382 100644 --- a/src/datatype/object_generate.rs +++ b/src/datatype/object_generate.rs @@ -1,8 +1,8 @@ use super::array::*; use super::buffer::*; -use super::object_calculate::get_size_align; use super::pointer::*; use crate::utils::dataprocess::get_array_desc; +use crate::utils::object_utils::{create_static_array_from_pointer, get_size_align}; use crate::define::*; use indexmap::IndexMap; @@ -118,50 +118,87 @@ pub unsafe fn create_rs_struct_from_pointer( let array_desc = get_array_desc(obj); if array_desc.is_some() { // array - let (array_len, array_type) = array_desc.unwrap(); - let size = match array_type { + let array_desc = array_desc.unwrap(); + let FFIARRARYDESC { + array_type, + array_len, + dynamic_array, + .. + } = &array_desc; + match array_type { RefDataType::StringArray => { let (size, align) = get_size_align::<*const c_void>(); let padding = (align - (offset % align)) % align; field_ptr = field_ptr.offset(padding as isize); let type_field_ptr = field_ptr as *mut *mut *mut c_char; - let arr = create_array_from_pointer(*type_field_ptr, array_len); + let arr = create_array_from_pointer(*type_field_ptr, *array_len); rs_struct.insert(field, RsArgsValue::StringArray(arr)); offset += size + padding; field_size = size } RefDataType::DoubleArray => { - let (size, align) = get_size_align::<*const c_void>(); + let (size, align) = if *dynamic_array { + get_size_align::<*const c_void>() + } else { + let (size, align) = get_size_align::(); + (size * array_len, align) + }; let padding = (align - (offset % align)) % align; field_ptr = field_ptr.offset(padding as isize); - let type_field_ptr = field_ptr as *mut *mut c_double; - let arr = create_array_from_pointer(*type_field_ptr, array_len); - rs_struct.insert(field, RsArgsValue::DoubleArray(arr)); + if *dynamic_array { + let type_field_ptr = field_ptr as *mut *mut c_double; + let arr = create_array_from_pointer(*type_field_ptr, *array_len); + rs_struct.insert(field, RsArgsValue::DoubleArray(arr)); + } else { + let arr = create_static_array_from_pointer(field_ptr as *mut c_void, &array_desc); + rs_struct.insert(field, arr); + } offset += size + padding; field_size = size } RefDataType::I32Array => { - let (size, align) = get_size_align::<*const c_void>(); + let (size, align) = if *dynamic_array { + get_size_align::<*const c_void>() + } else { + let (size, align) = get_size_align::(); + (size * array_len, align) + }; let padding = (align - (offset % align)) % align; field_ptr = field_ptr.offset(padding as isize); - let type_field_ptr = field_ptr as *mut *mut c_int; - let arr = create_array_from_pointer(*type_field_ptr, array_len); - rs_struct.insert(field, RsArgsValue::I32Array(arr)); + if *dynamic_array { + let type_field_ptr = field_ptr as *mut *mut c_int; + let arr = create_array_from_pointer(*type_field_ptr, *array_len); + rs_struct.insert(field, RsArgsValue::I32Array(arr)); + } else { + let arr = create_static_array_from_pointer(field_ptr as *mut c_void, &array_desc); + rs_struct.insert(field, arr); + } offset += size + padding; field_size = size } RefDataType::U8Array => { - let (size, align) = get_size_align::<*const c_void>(); + let (size, align) = if *dynamic_array { + get_size_align::<*const c_void>() + } else { + let (size, align) = get_size_align::(); + (size * array_len, align) + }; let padding = (align - (offset % align)) % align; field_ptr = field_ptr.offset(padding as isize); - let type_field_ptr = field_ptr as *mut *mut c_uchar; - let arr = create_array_from_pointer(*type_field_ptr, array_len); - rs_struct.insert(field, get_safe_buffer(env, arr, need_thread_safe)); + if *dynamic_array { + let type_field_ptr = field_ptr as *mut *mut c_uchar; + let arr = create_array_from_pointer(*type_field_ptr, array_desc.array_len); + rs_struct.insert(field, get_safe_buffer(env, arr, need_thread_safe)); + } else { + let arr = create_static_array_from_pointer(field_ptr as *mut c_void, &array_desc); + if let RsArgsValue::U8Array(_, arr) = arr { + rs_struct.insert(field, get_safe_buffer(env, arr.unwrap(), need_thread_safe)); + } + } offset += size + padding; field_size = size } }; - size } else { // function | raw object let (size, align) = get_size_align::<*const c_void>(); diff --git a/src/define.rs b/src/define.rs index 53fdb78..bb9b369 100644 --- a/src/define.rs +++ b/src/define.rs @@ -71,6 +71,13 @@ where unsafe { JsObject::to_napi_value(raw_env, obj) } } } + +pub struct FFIARRARYDESC<'a> { + pub dynamic_array: bool, + pub array_type: RefDataType, + pub array_len: usize, + pub array_value: Option<&'a RsArgsValue>, +} #[napi] #[derive(Debug)] pub enum DataType { @@ -246,3 +253,5 @@ pub struct OpenParams { pub const ARRAY_LENGTH_TAG: &str = "length"; pub const ARRAY_TYPE_TAG: &str = "type"; +pub const ARRAY_DYNAMIC_TAG: &str = "dynamicArray"; +pub const ARRAY_VALUE_TAG: &str = "value"; diff --git a/src/lib.rs b/src/lib.rs index 4da9e14..7a8e6c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -155,7 +155,6 @@ unsafe fn load(env: Env, params: FFIParams) -> napi::Result { let params_type_len = params_type.len(); let (mut arg_types, arg_values) = get_arg_types_values(&env, params_type, params_value)?; let mut arg_values_c_void = get_value_pointer(&env, arg_values)?; - let ret_type_rs = type_define_to_rs_args(ret_type)?; let r_type: *mut ffi_type = match ret_type_rs { RsArgsValue::I32(number) => { diff --git a/src/utils/dataprocess.rs b/src/utils/dataprocess.rs index 8657899..4cfeb7b 100644 --- a/src/utils/dataprocess.rs +++ b/src/utils/dataprocess.rs @@ -23,19 +23,28 @@ pub unsafe fn get_js_external_wrap_data(env: &Env, js_external: JsExternal) -> R Ok(*external) } -pub fn get_array_desc(obj: &IndexMap) -> Option<(usize, RefDataType)> { +pub fn get_array_desc(obj: &IndexMap) -> Option { if obj.get(ARRAY_LENGTH_TAG).is_none() { return None; } - let (mut array_len, mut array_type) = (0, 0); + let (mut array_len, mut array_type, mut array_dynamic) = (0, 0, true); if let RsArgsValue::I32(number) = obj.get(ARRAY_LENGTH_TAG).unwrap() { array_len = *number as usize } if let RsArgsValue::I32(number) = obj.get(ARRAY_TYPE_TAG).unwrap() { array_type = *number } + if let RsArgsValue::Boolean(val) = obj.get(ARRAY_DYNAMIC_TAG).unwrap() { + array_dynamic = *val + } let array_type = number_to_ref_data_type(array_type); - Some((array_len, array_type)) + + Some(FFIARRARYDESC { + array_len, + dynamic_array: array_dynamic, + array_type, + array_value: obj.get(ARRAY_VALUE_TAG), + }) } pub fn js_string_to_string(js_string: JsString) -> String { @@ -355,7 +364,7 @@ pub fn get_params_value_rs_struct( params_value_object: &JsObject, ) -> Result> { let mut index_map = IndexMap::new(); - let _: Result<()> = JsObject::keys(¶ms_value_object)? + let parse_result: Result<()> = JsObject::keys(¶ms_value_object)? .into_iter() .try_for_each(|field| { let field_type: JsUnknown = params_type_object.get_named_property(&field)?; @@ -429,13 +438,29 @@ pub fn get_params_value_rs_struct( ValueType::Object => { let params_type = field_type.coerce_to_object()?; let params_value: JsObject = params_value_object.get_named_property(&field)?; - let map = get_params_value_rs_struct(env, ¶ms_type, ¶ms_value); - index_map.insert(field, RsArgsValue::Object(map?)); + let mut params_type_rs_value = type_object_to_rs_struct(¶ms_type)?; + let array_desc = get_array_desc(¶ms_type_rs_value); + if array_desc.is_some() { + let FFIARRARYDESC { array_type, .. } = array_desc.unwrap(); + let array_value = match array_type { + RefDataType::U8Array => { + let js_buffer: JsBuffer = params_value_object.get_named_property(&field)?; + RsArgsValue::U8Array(Some(js_buffer.into_value()?), None) + } + _ => panic!("111"), + }; + params_type_rs_value.insert("value".to_string(), array_value); + index_map.insert(field, RsArgsValue::Object(params_type_rs_value)); + } else { + let map = get_params_value_rs_struct(env, ¶ms_type, ¶ms_value); + index_map.insert(field, RsArgsValue::Object(map?)); + } } _ => { return Err( FFIError::UnsupportedValueType(format!( - "Received {:?} but params type only supported number or object ", + "Get field {:?} received {:?} but params type only supported number or object ", + field, field_type.get_type().unwrap() )) .into(), @@ -444,31 +469,37 @@ pub fn get_params_value_rs_struct( }; Ok(()) }); - Ok(index_map) + match parse_result { + Ok(_) => Ok(index_map), + Err(e) => Err(e), + } } -pub fn type_object_to_rs_struct(params_type: &JsObject) -> IndexMap { +pub fn type_object_to_rs_struct(params_type: &JsObject) -> Result> { let mut index_map = IndexMap::new(); - let _: Result<()> = JsObject::keys(params_type) + let parse_result: Result<()> = JsObject::keys(params_type) .unwrap() .into_iter() .try_for_each(|field| { let field_type: JsUnknown = params_type.get_named_property(&field).unwrap(); match field_type.get_type().unwrap() { ValueType::Number => { - let number: JsNumber = field_type.try_into().unwrap(); - let val: i32 = number.try_into().unwrap(); + let number: JsNumber = field_type.try_into()?; + let val: i32 = number.try_into()?; index_map.insert(field, RsArgsValue::I32(val)); } - + ValueType::Boolean => { + let val: JsBoolean = field_type.try_into()?; + index_map.insert(field, RsArgsValue::Boolean(val.try_into()?)); + } ValueType::Object => { // maybe jsobject or jsarray - let args_type = field_type.coerce_to_object().unwrap(); - let map = type_object_to_rs_struct(&args_type); + let args_type = field_type.coerce_to_object()?; + let map = type_object_to_rs_struct(&args_type)?; index_map.insert(field, RsArgsValue::Object(map)); } ValueType::String => { - let str: JsString = field_type.try_into().unwrap(); + let str: JsString = field_type.try_into()?; let str = js_string_to_string(str); index_map.insert(field, RsArgsValue::String(str)); } @@ -479,12 +510,15 @@ pub fn type_object_to_rs_struct(params_type: &JsObject) -> IndexMap Ok(index_map), + Err(e) => Err(e), + } } pub fn type_object_to_rs_vector(params_type: &JsObject) -> Result> { @@ -503,7 +537,7 @@ pub fn type_object_to_rs_vector(params_type: &JsObject) -> Result { // maybe jsobject or jsarray let args_type = field_type.coerce_to_object().unwrap(); - let map = type_object_to_rs_struct(&args_type); + let map = type_object_to_rs_struct(&args_type)?; RsArgsValue::Object(map) } ValueType::String => { @@ -531,7 +565,7 @@ pub fn type_define_to_rs_args(type_define: JsUnknown) -> Result { let ret_value = match ret_value_type { ValueType::Number => RsArgsValue::I32(js_number_to_i32(type_define.coerce_to_number()?)), ValueType::Object => { - RsArgsValue::Object(type_object_to_rs_struct(&type_define.coerce_to_object()?)) + RsArgsValue::Object(type_object_to_rs_struct(&type_define.coerce_to_object()?)?) } _ => { return Err( @@ -582,7 +616,11 @@ pub unsafe fn get_js_unknown_from_pointer( let array_desc = get_array_desc(&obj); if array_desc.is_some() { // array - let (array_len, array_type) = array_desc.ok_or(FFIError::UnExpectedError)?; + let FFIARRARYDESC { + array_type, + array_len, + .. + } = array_desc.ok_or(FFIError::UnExpectedError)?; match array_type { RefDataType::U8Array => { let arr = create_array_from_pointer(*(ptr as *mut *mut c_uchar), array_len); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 6a74e68..f94776f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1 +1,2 @@ pub mod dataprocess; +pub mod object_utils; diff --git a/src/utils/object_utils.rs b/src/utils/object_utils.rs new file mode 100644 index 0000000..24e4f46 --- /dev/null +++ b/src/utils/object_utils.rs @@ -0,0 +1,38 @@ +use crate::{RefDataType, RsArgsValue, FFIARRARYDESC}; +use libc::{c_char, c_void}; + +pub fn get_size_align() -> (usize, usize) { + (std::mem::size_of::(), std::mem::align_of::()) +} + +pub unsafe fn create_static_array_from_pointer( + ptr: *mut c_void, + array_desc: &FFIARRARYDESC, +) -> RsArgsValue { + let FFIARRARYDESC { + array_type, + array_len, + .. + } = array_desc; + match array_type { + RefDataType::U8Array => { + let ptr = ptr as *mut u8; + let arr = (0..*array_len).map(|n| *(ptr.offset(n as isize))).collect(); + RsArgsValue::U8Array(None, Some(arr)) + } + RefDataType::I32Array => { + let ptr = ptr as *mut i32; + let arr = (0..*array_len).map(|n| *(ptr.offset(n as isize))).collect(); + RsArgsValue::I32Array(arr) + } + RefDataType::DoubleArray => { + let ptr = ptr as *mut f64; + let arr = (0..*array_len).map(|n| *(ptr.offset(n as isize))).collect(); + RsArgsValue::DoubleArray(arr) + } + _ => panic!( + "{:?} type transform to static array is unsupported at now", + array_type + ), + } +} diff --git a/test.ts b/test.ts index b2cd8f4..2a2ab0c 100644 --- a/test.ts +++ b/test.ts @@ -202,6 +202,7 @@ const parent = { name: "tom father", stringArray: ["tom", "father"], i32Array: [5, 6, 7], + staticBytes: Buffer.from(new Array(16).fill(88)), boolTrue: true, boolFalse: false, longVal: 5294967296, @@ -216,6 +217,7 @@ const person = { name: "tom", stringArray: ["tom"], i32Array: [1, 2, 3, 4], + staticBytes: Buffer.from(new Array(16).fill(99)), boolTrue: true, boolFalse: false, longVal: 4294967296, @@ -239,6 +241,11 @@ const parentType = { type: DataType.I32Array, length: parent.i32Array.length, }), + staticBytes: arrayConstructor({ + type: DataType.U8Array, + length: parent.staticBytes.length, + dynamicArray: false + }), boolTrue: DataType.Boolean, boolFalse: DataType.Boolean, longVal: DataType.I64, @@ -265,6 +272,11 @@ const personType = { type: DataType.I32Array, length: person.i32Array.length, }), + staticBytes: arrayConstructor({ + type: DataType.U8Array, + length: person.staticBytes.length, + dynamicArray: false + }), boolTrue: DataType.Boolean, boolFalse: DataType.Boolean, longVal: DataType.I64, @@ -286,9 +298,14 @@ const testObject = () => { stringArray: DataType.StringArray, doubleArray: DataType.DoubleArray, i32Array: DataType.I32Array, + staticBytes: arrayConstructor({ + type: DataType.U8Array, + length: parent.staticBytes.length, + dynamicArray: false + }), boolTrue: DataType.Boolean, boolFalse: DataType.Boolean, - longVal: DataType.I64, + longVal: DataType.U64, byte: DataType.U8, byteArray: DataType.U8Array, }, @@ -296,12 +313,26 @@ const testObject = () => { name: DataType.String, stringArray: DataType.StringArray, i32Array: DataType.I32Array, + staticBytes: arrayConstructor({ + type: DataType.U8Array, + length: person.staticBytes.length, + dynamicArray: false + }), boolTrue: DataType.Boolean, boolFalse: DataType.Boolean, - longVal: DataType.I64, + longVal: DataType.U64, byte: DataType.U8, byteArray: DataType.U8Array, } + const createdPerson = load({ + library: "libsum", + funcName: "createPerson", + retType: personType, + paramsType: [], + paramsValue: [], + }); + deepStrictEqual(createdPerson, person); + logGreen('test createdPerson succeed') const personObj = load({ library: "libsum", funcName: "getStruct", @@ -337,14 +368,7 @@ const testObject = () => { retType: [personType] }) deepStrictEqual(person, restorePersonObjByPointer[0]) - const createdPerson = load({ - library: "libsum", - funcName: "createPerson", - retType: personType, - paramsType: [], - paramsValue: [], - }); - deepStrictEqual(createdPerson, person); + } const testFunction = () => { @@ -464,7 +488,6 @@ const unitTest = () => { logGreen('test main program succeed') testFunction() logGreen('test function succeed') - }; unitTest();