1use 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}