use pmpx_plugin::abi::PmpxStr;
pub(super) unsafe fn read_plugin_str(
f: unsafe extern "C" fn() -> PmpxStr,
free: unsafe extern "C" fn(PmpxStr),
) -> String {
let s = unsafe { f() };
let out = unsafe { read_bytes(s) };
unsafe { free(s) };
out
}
pub(super) unsafe fn read_bytes(s: PmpxStr) -> String {
if s.ptr.is_null() || s.len == 0 {
return String::new();
}
let bytes = unsafe { std::slice::from_raw_parts(s.ptr, s.len) };
String::from_utf8_lossy(bytes).into_owned()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reading_an_empty_string_is_safe() {
assert_eq!(unsafe { read_bytes(PmpxStr::EMPTY) }, "");
}
#[test]
fn reading_a_null_pointer_is_safe() {
let s = PmpxStr {
ptr: std::ptr::null(),
len: 99,
};
assert_eq!(
unsafe { read_bytes(s) },
"",
"a null pointer must not be dereferenced"
);
}
#[test]
fn reading_non_utf8_bytes_does_not_panic() {
let bytes = [0xff, 0xfe, 0xfd];
let s = PmpxStr {
ptr: bytes.as_ptr(),
len: bytes.len(),
};
assert!(!unsafe { read_bytes(s) }.is_empty());
}
}