Skip to content

Commit

Permalink
Add readString, writeString method (#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
qwreey committed Nov 12, 2024
1 parent 627c2c9 commit e8cc2dc
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 25 deletions.
3 changes: 3 additions & 0 deletions crates/lune-std-ffi/src/data/box_data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ impl LuaUserData for BoxData {
}
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
method_provider::provide_copy_from(methods);
method_provider::provide_read_string(methods);
method_provider::provide_write_string(methods);

// For convenience, :zero returns box itself.
methods.add_function_mut("zero", |_lua, this: LuaAnyUserData| {
this.borrow_mut::<BoxData>()?.zero();
Expand Down
61 changes: 58 additions & 3 deletions crates/lune-std-ffi/src/data/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ pub mod method_provider {
let src = src.get_ffi_data()?;

if !src.check_inner_boundary(src_offset, length) {
return Err(LuaError::external("Source boundary check failed"));
return Err(LuaError::external("Source out of bounds"));
}
if !this.check_inner_boundary(dst_offset, length) {
return Err(LuaError::external("Self boundary check failed"));
return Err(LuaError::external("Self out of bounds"));
}

this.copy_from(&src, length, dst_offset, src_offset);
Expand All @@ -39,6 +39,61 @@ pub mod method_provider {
);
}

// TODO: writeString, readString, writeBase64 and readBase64 methods
// Implement readString method
pub fn provide_read_string<'lua, Target, M>(methods: &mut M)
where
Target: FfiData,
M: LuaUserDataMethods<'lua, Target>,
{
methods.add_method(
"readString",
|lua, this, (length, offset): (usize, Option<isize>)| unsafe {
let offset = offset.unwrap_or(0);

if !this.check_inner_boundary(offset, length) {
return Err(LuaError::external("Source out of bounds"));
}

lua.create_string(this.read_string(length, offset))
},
);
}

// Implement writeString method
pub fn provide_write_string<'lua, Target, M>(methods: &mut M)
where
Target: FfiData,
M: LuaUserDataMethods<'lua, Target>,
{
methods.add_method(
"writeString",
|_lua,
this,
(string, length, dst_offset, src_offset): (
LuaString,
usize,
Option<isize>,
Option<usize>,
)| unsafe {
let dst_offset = dst_offset.unwrap_or(0);
let src_offset = src_offset.unwrap_or(0);

// Source string boundary check
if string.as_bytes().len() < src_offset + length {
return Err(LuaError::external("Source out of bounds"));
}

// Self boundary check
if !this.check_inner_boundary(dst_offset, length) {
return Err(LuaError::external("Self out of bounds"));
}

this.write_string(string, length, dst_offset, src_offset);
Ok(())
},
);
}

// TODO: Bit operation support
// TODO: writeBase64 and readBase64 methods
}
2 changes: 2 additions & 0 deletions crates/lune-std-ffi/src/data/ref_data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ impl FfiData for RefData {
impl LuaUserData for RefData {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
method_provider::provide_copy_from(methods);
method_provider::provide_read_string(methods);
method_provider::provide_write_string(methods);

methods.add_method("deref", |_lua, this, ()| unsafe { this.dereference() });
methods.add_function("offset", |lua, (this, offset): (LuaAnyUserData, isize)| {
Expand Down
27 changes: 26 additions & 1 deletion crates/lune-std-ffi/src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,33 @@ pub trait FfiData {
src_offset: isize,
) {
self.get_inner_pointer()
.cast::<u8>()
.byte_offset(dst_offset)
.copy_from(src.get_inner_pointer().byte_offset(src_offset), length);
.copy_from(
src.get_inner_pointer().cast::<u8>().byte_offset(src_offset),
length,
);
}
unsafe fn read_string(&self, length: usize, offset: isize) -> Vec<u8> {
let mut string = Vec::<u8>::with_capacity(length);
string.as_mut_ptr().copy_from(
self.get_inner_pointer().cast::<u8>().byte_offset(offset),
length,
);
string.set_len(length);
string
}
unsafe fn write_string(
&self,
src: LuaString,
length: usize,
dst_offset: isize,
src_offset: usize,
) {
self.get_inner_pointer()
.cast::<u8>()
.byte_offset(dst_offset)
.copy_from(src.to_pointer().cast::<u8>().byte_add(src_offset), length);
}
}

Expand Down
104 changes: 83 additions & 21 deletions types/ffi.luau
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ export type RefData = {
Copy content from another data with specific length.
@param src The source data
@param len The amount of data to copy, in bytes
@param dstOffset The offset in the destination where the data will be pasted
@param srcOffset The offset in the source data from where the data will be copied
@param length The amount of data to copy, in bytes
@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
]=]
copyFrom: (
self: RefData,
Expand All @@ -136,6 +136,37 @@ export type RefData = {
dstOffset: number,
srcOffset: number
) -> (),
--[=[
@within RefData
@tag Method
@method readString
Read string from data with specific length.
@param length The amount of data to read, in bytes
@param offset Offset to read string from
@return A string
]=]
readString: (self: RefData, length: number, offset: number?) -> string,
--[=[
@within RefData
@tag Method
@method writeString
Write string into data.
@param src The source string
@param length The amount of data to write, in bytes
@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
]=]
writeString: (
self: RefData,
src: string,
length: number,
dstOffset: number,
srcOffset: number
) -> (),
}

--[=[
Expand Down Expand Up @@ -197,9 +228,9 @@ export type BoxData = {
Copy content from another data with specific length.
@param src The source data
@param len The amount of data to copy, in bytes
@param dstOffset The offset in the destination where the data will be pasted
@param srcOffset The offset in the source data from where the data will be copied
@param length The amount of data to copy, in bytes
@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
]=]
copyFrom: (
self: BoxData,
Expand All @@ -208,6 +239,37 @@ export type BoxData = {
dstOffset: number,
srcOffset: number
) -> (),
--[=[
@within BoxData
@tag Method
@method readString
Read string from data with specific length.
@param length The amount of data to read, in bytes
@param offset Offset to read string from
@return A string
]=]
readString: (self: BoxData, length: number, offset: number?) -> string,
--[=[
@within BoxData
@tag Method
@method writeString
Write string into data.
@param src The source string
@param length The amount of data to write, in bytes
@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
]=]
writeString: (
self: BoxData,
src: string,
length: number,
dstOffset: number,
srcOffset: number
) -> (),
}

--[=[
Expand Down Expand Up @@ -305,10 +367,10 @@ export type CTypeInfo<T, R> = {
Create an array subtype with specific length.
@param len The length of the array
@param length The length of the array
@return An array subtype
]=]
arr: (self: CTypeInfo<T, R>, len: number) -> CArrInfo<CTypeInfo<T, R>, R>,
arr: (self: CTypeInfo<T, R>, length: number) -> CArrInfo<CTypeInfo<T, R>, R>,

-- Create/Read/Write/Copy
--[=[
Expand Down Expand Up @@ -353,10 +415,10 @@ export type CTypeInfo<T, R> = {
Copy values ​​from the source and paste them into the target.
@param dst Where the data will be pasted
@param dst Where the content will be pasted
@param src The source data
@param dstOffset The offset in the destination where the data will be pasted
@param srcOffset The offset in the source data from where the data will be copied
@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
]=]
copyData: (
self: CTypeInfo<T, R>,
Expand Down Expand Up @@ -434,10 +496,10 @@ export type CPtrInfo<T> = {
Create an array subtype with specific length.
@param len The length of the array
@param length The length of the array
@return An array subtype
]=]
arr: (self: CPtrInfo<T>, len: number) -> any,
arr: (self: CPtrInfo<T>, length: number) -> any,
-- FIXME: recursive types; result 'any' should be CPtrInfo<CPtrInfo<T>>
--[=[
@within CPtrInfo
Expand Down Expand Up @@ -585,10 +647,10 @@ export type CArrInfo<T, R> = {
Copy values ​​from the source and paste them into the target.
@param dst Where the data will be pasted
@param dst Where the content will be pasted
@param src The source data
@param dstOffset The offset in the dst where the data will be pasted
@param srcOffset The offset in the source data from where the data will be copied
@param dstOffset The offset in the dst where the content will be pasted
@param srcOffset The offset in the source data from where the content will be copied
]=]
copyData: (
self: CArrInfo<T, R>,
Expand Down Expand Up @@ -677,10 +739,10 @@ export type CStructInfo = {
Create a struct array type.
@param len The length of the array
@param length The length of the array
@return A struct array type
]=]
arr: (self: CStructInfo, len: number) -> CArrInfo<CStructInfo, { any }>,
arr: (self: CStructInfo, length: number) -> CArrInfo<CStructInfo, { any }>,
--[=[
@within CSturctInfo
@tag Method
Expand Down Expand Up @@ -740,10 +802,10 @@ export type CStructInfo = {
Copy values from the source and paste them into the target.
@param dst Where the data will be pasted
@param dst Where the content will be pasted
@param src The source data
@param dstOffset The offset in the destination where the data will be pasted
@param srcOffset The offset in the source data from where the data will be copied
@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
]=]
copyData: (
self: CStructInfo,
Expand Down

0 comments on commit e8cc2dc

Please sign in to comment.