use wasmtime::Caller;
use crate::{ScriptManager, WasmScriptState};
use super::{system::_get_memory, LIBRARY_NAME};
fn memory_search(mut caller: Caller<'_, WasmScriptState>, ptr: u32, ch: u32, len: u32) -> u32 {
let (_, mem_ptr) = _get_memory(&mut caller);
let len = len as usize;
let ptr = ptr as usize;
let ch = ch as u8;
if (len + ptr) > mem_ptr.len() {
return 4;
}
for i in 0..len {
if mem_ptr[ptr + i] == ch {
return (ptr + i) as u32;
}
}
0
}
fn memory_search_last(mut caller: Caller<'_, WasmScriptState>, ptr: u32, ch: u32, len: u32) -> u32 {
let (_, mem_ptr) = _get_memory(&mut caller);
let len = len as usize;
let ptr = ptr as usize;
let ch = ch as u8;
if (len + ptr) > mem_ptr.len() {
return 4;
}
for i in 0..len {
let index = ptr + len - i - 1;
if mem_ptr[index] == ch {
return index as u32;
}
}
0
}
fn memory_compare(
mut caller: Caller<'_, WasmScriptState>,
lhs: u32,
rhs: u32,
len: u32,
) -> (u32, u32) {
let (_, mem_ptr) = _get_memory(&mut caller);
let len = len as usize;
let lhs = lhs as usize;
let rhs = rhs as usize;
if (len + lhs) > mem_ptr.len() || (len + rhs) > mem_ptr.len() {
return (4, 0);
}
for i in 0..len {
let diff = mem_ptr[lhs + i] - mem_ptr[rhs + i];
if diff != 0 {
return (0, diff as u32);
}
}
(0, 0)
}
fn memory_fill(mut caller: Caller<'_, WasmScriptState>, dest: u32, ch: u32, len: u32) -> u32 {
let (_, mem_ptr) = _get_memory(&mut caller);
let len = len as usize;
let dest = dest as usize;
let ch = ch as u8;
if (len + dest) > mem_ptr.len() {
return 4;
}
for i in 0..len {
mem_ptr[dest + i] = ch;
}
0
}
fn memory_copy(mut caller: Caller<'_, WasmScriptState>, dest: u32, src: u32, len: u32) -> u32 {
let (_, mem_ptr) = _get_memory(&mut caller);
let len = len as usize;
let dest = dest as usize;
let src = src as usize;
if (len + dest) > mem_ptr.len() || (len + src) > mem_ptr.len() {
return 4;
}
// check for overlap
if (dest < src && dest + len > src) || (src < dest && src + len > dest) {
let src = mem_ptr[src..src + len].to_vec();
let dest = &mut mem_ptr[dest..dest + len];
dest.clone_from_slice(&src);
} else {
for i in 0..len {
mem_ptr[dest + i] = mem_ptr[src + i];
}
}
0
}
fn memory_copy_until(
mut caller: Caller<'_, WasmScriptState>,
dest: u32,
src: u32,
len: u32,
delimiter: u32,
) -> u32 {
let (_, mem_ptr) = _get_memory(&mut caller);
let len = len as usize;
let dest = dest as usize;
let src = src as usize;
let delimiter = delimiter as u8;
if (len + dest) > mem_ptr.len() || (len + src) > mem_ptr.len() {
return 4;
}
// check for overlap
if (dest < src && dest + len > src) || (src < dest && src + len > dest) {
let cloned_src = mem_ptr[src..src + len].to_vec();
let dest = &mut mem_ptr[dest..dest + len];
for i in 0..len {
let ch = cloned_src[i];
dest[i] = ch;
if ch == delimiter {
return (src + i + 1) as u32;
}
}
} else {
for i in 0..len {
let ch = mem_ptr[src + i];
mem_ptr[dest + i] = ch;
if ch == delimiter {
return (src + i + 1) as u32;
}
}
}
0
}
fn memory_concatenate(
mut caller: Caller<'_, WasmScriptState>,
dest: u32,
src: u32,
dest_len: u32,
src_len: u32,
) -> u32 {
let (_, mem_ptr) = _get_memory(&mut caller);
let dest = dest as usize;
let src = src as usize;
let dest_len = dest_len as usize;
let src_len = src_len as usize;
if (dest_len + src_len + dest) > mem_ptr.len() || (src_len + src) > mem_ptr.len() {
return 4;
}
let src = mem_ptr[src..src + src_len].to_vec();
let dest_offset = dest + dest_len;
let dest = &mut mem_ptr[dest_offset..dest_offset + src_len];
dest.clone_from_slice(&src);
0
}
pub fn library(manager: &mut ScriptManager) -> Option<()> {
manager.add_library_function(LIBRARY_NAME, "memchr", memory_search)?;
manager.add_library_function(LIBRARY_NAME, "memrchr", memory_search_last)?;
manager.add_library_function(LIBRARY_NAME, "memcmp", memory_compare)?;
manager.add_library_function(LIBRARY_NAME, "memset", memory_fill)?;
manager.add_library_function(LIBRARY_NAME, "memcpy", memory_copy)?;
manager.add_library_function(LIBRARY_NAME, "memccpy", memory_copy_until)?;
manager.add_library_function(LIBRARY_NAME, "memcat", memory_concatenate)?;
Some(())
}
|