diff options
Diffstat (limited to 'ext/ffi/lib.rs')
-rw-r--r-- | ext/ffi/lib.rs | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs index e1acd097a..ebf5572a7 100644 --- a/ext/ffi/lib.rs +++ b/ext/ffi/lib.rs @@ -11,6 +11,7 @@ use deno_core::Extension; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; +use deno_core::ZeroCopyBuf; use dlopen::raw::Library; use libffi::middle::Arg; use serde::Deserialize; @@ -131,6 +132,7 @@ enum NativeType { ISize, F32, F64, + Buffer, } impl From<NativeType> for libffi::middle::Type { @@ -149,6 +151,7 @@ impl From<NativeType> for libffi::middle::Type { NativeType::ISize => libffi::middle::Type::isize(), NativeType::F32 => libffi::middle::Type::f32(), NativeType::F64 => libffi::middle::Type::f64(), + NativeType::Buffer => libffi::middle::Type::pointer(), } } } @@ -168,6 +171,7 @@ union NativeValue { isize_value: isize, f32_value: f32, f64_value: f64, + buffer: *const u8, } impl NativeValue { @@ -210,9 +214,14 @@ impl NativeValue { NativeType::F64 => Self { f64_value: value_as_f64(value), }, + NativeType::Buffer => unreachable!(), } } + fn buffer(ptr: *const u8) -> Self { + Self { buffer: ptr } + } + unsafe fn as_arg(&self, native_type: NativeType) -> Arg { match native_type { NativeType::Void => Arg::new(&self.void_value), @@ -228,6 +237,7 @@ impl NativeValue { NativeType::ISize => Arg::new(&self.isize_value), NativeType::F32 => Arg::new(&self.f32_value), NativeType::F64 => Arg::new(&self.f64_value), + NativeType::Buffer => Arg::new(&self.buffer), } } } @@ -257,6 +267,7 @@ fn value_as_f64(value: Value) -> f64 { } #[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] struct ForeignFunction { parameters: Vec<NativeType>, result: NativeType, @@ -293,20 +304,32 @@ where Ok(state.resource_table.add(resource)) } -#[derive(Deserialize, Debug)] +#[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct FfiCallArgs { rid: ResourceId, symbol: String, parameters: Vec<Value>, + buffers: Vec<ZeroCopyBuf>, } fn ffi_call(args: FfiCallArgs, symbol: &Symbol) -> Result<Value, AnyError> { + let buffers: Vec<&[u8]> = + args.buffers.iter().map(|buffer| &buffer[..]).collect(); + let native_values = symbol .parameter_types .iter() .zip(args.parameters.into_iter()) - .map(|(&native_type, value)| NativeValue::new(native_type, value)) + .map(|(&native_type, value)| { + if let NativeType::Buffer = native_type { + let idx: usize = value_as_uint(value); + let ptr = buffers[idx].as_ptr(); + NativeValue::buffer(ptr) + } else { + NativeValue::new(native_type, value) + } + }) .collect::<Vec<_>>(); let call_args = symbol @@ -358,6 +381,7 @@ fn ffi_call(args: FfiCallArgs, symbol: &Symbol) -> Result<Value, AnyError> { NativeType::F64 => { json!(unsafe { symbol.cif.call::<f64>(symbol.ptr, &call_args) }) } + NativeType::Buffer => unreachable!(), }) } |