Fix read/writeString and add test (#243)

This commit is contained in:
qwreey 2024-11-12 06:34:22 +00:00
parent e8cc2dcda3
commit 7a51bc9aa4
No known key found for this signature in database
GPG key ID: D28DB79297A214BD
6 changed files with 83 additions and 34 deletions

View file

@ -14,6 +14,7 @@ pub mod method_provider {
// Implement tostring // Implement tostring
pub fn provide_to_string<'lua, Target, M>(methods: &mut M) pub fn provide_to_string<'lua, Target, M>(methods: &mut M)
where where
Target: 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| { methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| {
@ -24,6 +25,7 @@ pub mod method_provider {
// Implement ptr method // Implement ptr method
pub fn provide_ptr<'lua, Target, M>(methods: &mut M) pub fn provide_ptr<'lua, Target, M>(methods: &mut M)
where where
Target: 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_function("ptr", |lua, this: LuaAnyUserData| { methods.add_function("ptr", |lua, this: LuaAnyUserData| {
@ -34,6 +36,7 @@ pub mod method_provider {
// Implement arr method // Implement arr method
pub fn provide_arr<'lua, Target, M>(methods: &mut M) pub fn provide_arr<'lua, Target, M>(methods: &mut M)
where where
Target: 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| { methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
@ -44,7 +47,7 @@ pub mod method_provider {
// Implement readData method // Implement readData method
pub fn provide_read_data<'lua, Target, M>(methods: &mut M) pub fn provide_read_data<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert + 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method( methods.add_method(
@ -68,7 +71,7 @@ pub mod method_provider {
// Implement writeData method // Implement writeData method
pub fn provide_write_data<'lua, Target, M>(methods: &mut M) pub fn provide_write_data<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert + 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method( methods.add_method(
@ -93,7 +96,7 @@ pub mod method_provider {
// Implement copyData method // Implement copyData method
pub fn provide_copy_data<'lua, Target, M>(methods: &mut M) pub fn provide_copy_data<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert + 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method( methods.add_method(
@ -134,7 +137,7 @@ pub mod method_provider {
// Implement stringifyData method // Implement stringifyData method
pub fn provide_stringify_data<'lua, Target, M>(methods: &mut M) pub fn provide_stringify_data<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert + 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method( methods.add_method(
@ -148,7 +151,7 @@ pub mod method_provider {
// Implement box method // Implement box method
pub fn provide_box<'lua, Target, M>(methods: &mut M) pub fn provide_box<'lua, Target, M>(methods: &mut M)
where where
Target: FfiSize + FfiConvert, Target: FfiSize + FfiConvert + 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method("box", |lua, this, value: LuaValue| { methods.add_method("box", |lua, this, value: LuaValue| {

View file

@ -8,19 +8,20 @@ pub mod method_provider {
// Implement copyFrom method // Implement copyFrom method
pub fn provide_copy_from<'lua, Target, M>(methods: &mut M) pub fn provide_copy_from<'lua, Target, M>(methods: &mut M)
where where
Target: FfiData, Target: FfiData + 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method( methods.add_function(
"copyFrom", "copyFrom",
|_lua, |_lua,
this, (this_userdata, src, length, dst_offset, src_offset): (
(src, length, dst_offset, src_offset): ( LuaAnyUserData,
LuaAnyUserData, LuaAnyUserData,
usize, usize,
Option<isize>, Option<isize>,
Option<isize>, Option<isize>,
)| unsafe { )| unsafe {
let this = this_userdata.borrow::<Target>()?;
let dst_offset = dst_offset.unwrap_or(0); let dst_offset = dst_offset.unwrap_or(0);
let src_offset = src_offset.unwrap_or(0); let src_offset = src_offset.unwrap_or(0);
let src = src.get_ffi_data()?; let src = src.get_ffi_data()?;
@ -34,7 +35,7 @@ pub mod method_provider {
this.copy_from(&src, length, dst_offset, src_offset); this.copy_from(&src, length, dst_offset, src_offset);
Ok(()) Ok(this_userdata.clone())
}, },
); );
} }
@ -42,7 +43,7 @@ pub mod method_provider {
// Implement readString method // Implement readString method
pub fn provide_read_string<'lua, Target, M>(methods: &mut M) pub fn provide_read_string<'lua, Target, M>(methods: &mut M)
where where
Target: FfiData, Target: FfiData + 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method( methods.add_method(
@ -62,24 +63,27 @@ pub mod method_provider {
// Implement writeString method // Implement writeString method
pub fn provide_write_string<'lua, Target, M>(methods: &mut M) pub fn provide_write_string<'lua, Target, M>(methods: &mut M)
where where
Target: FfiData, Target: FfiData + 'static,
M: LuaUserDataMethods<'lua, Target>, M: LuaUserDataMethods<'lua, Target>,
{ {
methods.add_method( methods.add_function(
"writeString", "writeString",
|_lua, |_lua,
this, (this_userdata, string, length, dst_offset, src_offset): (
(string, length, dst_offset, src_offset): ( LuaAnyUserData,
LuaString, LuaString,
usize, Option<usize>,
Option<isize>, Option<isize>,
Option<usize>, Option<usize>,
)| unsafe { )| unsafe {
let string_len = string.as_bytes().len();
let dst_offset = dst_offset.unwrap_or(0); let dst_offset = dst_offset.unwrap_or(0);
let src_offset = src_offset.unwrap_or(0); let src_offset = src_offset.unwrap_or(0);
let length = length.unwrap_or_else(|| string_len - src_offset);
let this = this_userdata.borrow::<Target>()?;
// Source string boundary check // Source string boundary check
if string.as_bytes().len() < src_offset + length { if string_len < src_offset + length {
return Err(LuaError::external("Source out of bounds")); return Err(LuaError::external("Source out of bounds"));
} }
@ -89,7 +93,7 @@ pub mod method_provider {
} }
this.write_string(string, length, dst_offset, src_offset); this.write_string(string, length, dst_offset, src_offset);
Ok(()) Ok(this_userdata.clone())
}, },
); );
} }

View file

@ -97,7 +97,10 @@ pub trait FfiData {
self.get_inner_pointer() self.get_inner_pointer()
.cast::<u8>() .cast::<u8>()
.byte_offset(dst_offset) .byte_offset(dst_offset)
.copy_from(src.to_pointer().cast::<u8>().byte_add(src_offset), length); .copy_from(
src.as_bytes().as_ptr().cast::<u8>().byte_add(src_offset),
length,
);
} }
} }

View file

@ -123,6 +123,7 @@ create_tests! {
ffi_free: "ffi/free", ffi_free: "ffi/free",
ffi_is_integer: "ffi/isInteger", ffi_is_integer: "ffi/isInteger",
ffi_read_boundary: "ffi/readBoundary", ffi_read_boundary: "ffi/readBoundary",
ffi_read_write_string: "ffi/stringReadWrite",
ffi_write_boundary: "ffi/writeBoundary", ffi_write_boundary: "ffi/writeBoundary",
} }

View file

@ -0,0 +1,34 @@
local ffi = require("@lune/ffi")
local ok
local str = "hello world"
local strbox = ffi.box(#str):writeString(str)
assert(strbox:readString(#str) == str, "String read write assersion failed")
-- Case1: Fail
ok = pcall(function()
local box = ffi.box(2)
box:readString(10)
end)
assert(not ok, "assersion failed, Case1 should fail")
-- Case2: Fail
ok = pcall(function()
local box = ffi.box(2)
box:writeString("hello world")
end)
assert(not ok, "assersion failed, Case2 should fail")
-- Case3: Fail
ok = pcall(function()
local box = ffi.box(2):ref()
box:readString(10)
end)
assert(not ok, "assersion failed, Case3 should fail")
-- Case4: Fail
ok = pcall(function()
local box = ffi.box(2):ref()
box:writeString("hello world")
end)
assert(not ok, "assersion failed, Case4 should fail")

View file

@ -128,6 +128,7 @@ export type RefData = {
@param length The amount of data to copy, in bytes @param length The amount of data to copy, in bytes
@param dstOffset The offset in the destination where the content will be pasted @param dstOffset The offset in the destination where the content will be pasted
@param srcOffset The offset in the source data from where the content will be copied @param srcOffset The offset in the source data from where the content will be copied
@return `RefData` itself for convenience
]=] ]=]
copyFrom: ( copyFrom: (
self: RefData, self: RefData,
@ -135,13 +136,13 @@ export type RefData = {
length: number, length: number,
dstOffset: number, dstOffset: number,
srcOffset: number srcOffset: number
) -> (), ) -> RefData,
--[=[ --[=[
@within RefData @within RefData
@tag Method @tag Method
@method readString @method readString
Read string from data with specific length. Read string from data with specific length without null termination.
@param length The amount of data to read, in bytes @param length The amount of data to read, in bytes
@param offset Offset to read string from @param offset Offset to read string from
@ -153,20 +154,21 @@ export type RefData = {
@tag Method @tag Method
@method writeString @method writeString
Write string into data. Write string into data without null termination.
@param src The source string @param src The source string
@param length The amount of data to write, in bytes @param length The amount of data to write, in bytes
@param dstOffset The offset in the destination where the content will be pasted @param dstOffset The offset in the destination where the content will be pasted
@param srcOffset The offset in the source string from where the content will be copied @param srcOffset The offset in the source string from where the content will be copied
@return `RefData` itself for convenience
]=] ]=]
writeString: ( writeString: (
self: RefData, self: RefData,
src: string, src: string,
length: number, length: number?,
dstOffset: number, dstOffset: number?,
srcOffset: number srcOffset: number?
) -> (), ) -> RefData,
} }
--[=[ --[=[
@ -191,7 +193,7 @@ export type BoxData = {
Fill the box with zero. Fill the box with zero.
@return `Box` itself for convenience @return `BoxData` itself for convenience
]=] ]=]
zero: (self: BoxData) -> BoxData, zero: (self: BoxData) -> BoxData,
--[=[ --[=[
@ -231,6 +233,7 @@ export type BoxData = {
@param length The amount of data to copy, in bytes @param length The amount of data to copy, in bytes
@param dstOffset The offset in the destination where the content will be pasted @param dstOffset The offset in the destination where the content will be pasted
@param srcOffset The offset in the source data from where the content will be copied @param srcOffset The offset in the source data from where the content will be copied
@return `BoxData` itself for convenience
]=] ]=]
copyFrom: ( copyFrom: (
self: BoxData, self: BoxData,
@ -238,13 +241,13 @@ export type BoxData = {
length: number, length: number,
dstOffset: number, dstOffset: number,
srcOffset: number srcOffset: number
) -> (), ) -> BoxData,
--[=[ --[=[
@within BoxData @within BoxData
@tag Method @tag Method
@method readString @method readString
Read string from data with specific length. Read string from data with specific length without null termination.
@param length The amount of data to read, in bytes @param length The amount of data to read, in bytes
@param offset Offset to read string from @param offset Offset to read string from
@ -256,20 +259,21 @@ export type BoxData = {
@tag Method @tag Method
@method writeString @method writeString
Write string into data. Write string into data without null termination.
@param src The source string @param src The source string
@param length The amount of data to write, in bytes @param length The amount of data to write, in bytes
@param dstOffset The offset in the destination where the content will be pasted @param dstOffset The offset in the destination where the content will be pasted
@param srcOffset The offset in the source string from where the content will be copied @param srcOffset The offset in the source string from where the content will be copied
@return `BoxData` itself for convenience
]=] ]=]
writeString: ( writeString: (
self: BoxData, self: BoxData,
src: string, src: string,
length: number, length: number?,
dstOffset: number, dstOffset: number?,
srcOffset: number srcOffset: number?
) -> (), ) -> BoxData,
} }
--[=[ --[=[