#![allow(unsafe_code)]
use std::slice;
use crate::engine::{EngineError, EngineResult};
#[derive(Debug)]
pub(crate) struct FfiPtr;
impl FfiPtr {
pub(crate) unsafe fn bytes_to_str<'a>(p: *const u8, len: usize) -> EngineResult<&'a str> {
let bytes = unsafe { slice::from_raw_parts(p, len) };
match core::str::from_utf8(bytes) {
Ok(s) => Ok(s),
Err(_) => Err(EngineError::InvalidName),
}
}
pub(crate) unsafe fn slice_mut<'a>(p: *mut u8, len: usize) -> &'a mut [u8] {
unsafe { slice::from_raw_parts_mut(p, len) }
}
pub(crate) unsafe fn slice_const<'a>(p: *const u8, len: usize) -> &'a [u8] {
unsafe { slice::from_raw_parts(p, len) }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bytes_to_str_decodes_valid_utf8() {
let bytes = b"rusty";
let decoded = unsafe { FfiPtr::bytes_to_str(bytes.as_ptr(), bytes.len()) };
assert_eq!(decoded, Ok("rusty"));
}
#[test]
fn bytes_to_str_rejects_invalid_utf8() {
let bytes = [0xff_u8, 0xfe];
let decoded = unsafe { FfiPtr::bytes_to_str(bytes.as_ptr(), bytes.len()) };
assert_eq!(decoded, Err(EngineError::InvalidName));
}
#[test]
fn slice_const_views_the_bytes() {
let data = [10u8, 20, 30];
let view = unsafe { FfiPtr::slice_const(data.as_ptr(), data.len()) };
assert_eq!(view, &data);
}
#[test]
fn slice_mut_allows_write_back() {
let mut data = [0u8; 3];
let view = unsafe { FfiPtr::slice_mut(data.as_mut_ptr(), data.len()) };
view[1] = 42;
assert_eq!(data, [0, 42, 0]);
}
}