libsql_wasi/
memory.rs

1// Shamelessly stolen from Honza - thx man!!!
2
3use crate::{Error, Result};
4
5pub type Ptr = i32;
6
7pub fn slice(memory: &[u8], ptr: Ptr, len: usize) -> Result<&[u8]> {
8    let ptr = ptr as usize;
9    assert!(ptr != 0 && ptr <= memory.len(), "Invalid pointer");
10    assert!(ptr + len <= memory.len(), "Invalid pointer and length");
11    Ok(&memory[ptr..][..len])
12}
13
14pub fn slice_mut(memory: &mut [u8], ptr: Ptr, len: usize) -> Result<&mut [u8]> {
15    let ptr = ptr as usize;
16    assert!(ptr != 0 && ptr <= memory.len(), "Invalid pointer");
17    assert!(ptr + len <= memory.len(), "Invalid pointer and length");
18    Ok(&mut memory[ptr..][..len])
19}
20
21pub fn read_vec(memory: &[u8], ptr: Ptr, len: usize) -> Result<Vec<u8>> {
22    slice(memory, ptr, len).map(|slice| slice.to_vec())
23}
24
25pub fn read_cstr(memory: &[u8], cstr_ptr: Ptr) -> Result<String> {
26    let Some(data) = read_cstr_bytes(memory, cstr_ptr) else {
27        return Err(Error::MemoryError("Invalid pointer to C string"));
28    };
29    String::from_utf8(data).map_err(|_| Error::MemoryError("Invalid UTF-8 in C string"))
30}
31
32pub fn read_cstr_or_null(memory: &[u8], cstr_ptr: Ptr) -> Result<Option<String>> {
33    if cstr_ptr != 0 {
34        read_cstr(memory, cstr_ptr).map(Some)
35    } else {
36        Ok(None)
37    }
38}
39
40pub fn read_cstr_lossy(memory: &[u8], cstr_ptr: Ptr) -> String {
41    match read_cstr_bytes(memory, cstr_ptr) {
42        Some(data) => match String::from_utf8(data) {
43            Ok(string) => string,
44            Err(err) => String::from_utf8_lossy(err.as_bytes()).into_owned(),
45        },
46        None => String::new(),
47    }
48}
49
50pub fn read_cstr_bytes(memory: &[u8], cstr_ptr: Ptr) -> Option<Vec<u8>> {
51    let cstr_ptr = cstr_ptr as usize;
52    if cstr_ptr == 0 || cstr_ptr >= memory.len() {
53        return None;
54    }
55
56    let data = &memory[cstr_ptr..];
57    let mut strlen = 0;
58    loop {
59        match data.get(strlen) {
60            None => return None,
61            Some(0) => break,
62            Some(_) => strlen += 1,
63        }
64    }
65
66    Some(data[..strlen].to_vec())
67}