use std::ffi::{CStr, c_char};
pub unsafe fn cstr<'a>(c: *const c_char) -> Option<&'a CStr> {
if !c.is_null() {
Some(unsafe { CStr::from_ptr(c) })
} else {
None
}
}
pub unsafe fn str<'a>(c: *const c_char) -> Option<&'a str> {
unsafe { cstr(c) }.and_then(|cstr| cstr.to_str().ok())
}
pub unsafe fn slice<'a>(ptr: *const u8, len: usize) -> Option<&'a [u8]> {
if ptr.is_null() {
return (len == 0).then_some(&[]);
}
Some(unsafe { core::slice::from_raw_parts(ptr, len) })
}
pub unsafe fn slice_mut<'a>(ptr: *mut u8, len: usize) -> Option<&'a mut [u8]> {
if ptr.is_null() {
return (len == 0).then_some(&mut []);
}
Some(unsafe { core::slice::from_raw_parts_mut(ptr, len) })
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn slice_helpers_handle_null_and_len_zero() {
assert_eq!(unsafe { slice(core::ptr::null(), 0) }, Some(&[][..]));
assert_eq!(unsafe { slice(core::ptr::null(), 4) }, None);
let data = [1u8, 2, 3, 4];
assert_eq!(unsafe { slice(data.as_ptr(), 4) }, Some(&data[..]));
assert_eq!(
unsafe { slice_mut(core::ptr::null_mut(), 0) },
Some(&mut [][..])
);
assert!(unsafe { slice_mut(core::ptr::null_mut(), 8) }.is_none());
let mut buf = [0u8; 3];
let ptr = buf.as_mut_ptr();
let s = unsafe { slice_mut(ptr, 3) }.expect("non-null buffer");
s[0] = 9;
assert_eq!(buf[0], 9);
}
}