use std::ptr::{self, NonNull};
use crate::{Error, ErrorKind, ErrorOrigin, Result};
fn bad_params() -> Error {
Error::new(ErrorKind::BadParameters).with_origin(ErrorOrigin::API)
}
pub(super) fn deref_mut<T>(ptr: *mut T) -> Result<NonNull<T>> {
NonNull::new(ptr).ok_or_else(bad_params)
}
pub(super) fn deref<T>(ptr: *const T) -> Result<NonNull<T>> {
NonNull::new(ptr as *mut T).ok_or_else(bad_params)
}
#[allow(dead_code)]
pub(super) fn write_raw<T>(ptr: *mut T, value: T) -> Result<()> {
let nn = NonNull::new(ptr).ok_or_else(bad_params)?;
unsafe { nn.as_ptr().write(value) };
Ok(())
}
pub(super) fn read_to_vec<T: Copy>(src: *const T, len: usize) -> Result<Vec<T>> {
if len == 0 {
return Ok(Vec::new());
}
if src.is_null() {
return Err(bad_params());
}
let _nn = NonNull::new(src as *mut T).ok_or_else(bad_params)?;
let slice = unsafe { std::slice::from_raw_parts(src, len) };
Ok(slice.to_vec())
}
pub(super) fn write_from_slice<T: Copy>(dst: *mut T, src: &[T]) -> Result<()> {
if dst.is_null() && !src.is_empty() {
return Err(bad_params());
}
if src.is_empty() {
return Ok(());
}
let _nn = NonNull::new(dst).ok_or_else(bad_params)?;
let dst_slice = unsafe { std::slice::from_raw_parts_mut(dst, src.len()) };
dst_slice.copy_from_slice(src);
Ok(())
}
pub(super) fn add_ptr<T>(ptr: *const T, offset: usize) -> *const T {
if ptr.is_null() {
return ptr::null();
}
unsafe { ptr.add(offset) }
}
pub(super) fn add_ptr_mut<T>(ptr: *mut T, offset: usize) -> *mut T {
if ptr.is_null() {
return ptr::null_mut();
}
unsafe { ptr.add(offset) }
}
#[cfg(test)]
mod safe_ptr_tests {
use super::*;
#[test]
fn test_read_to_vec_and_write_from_slice() {
let arr = [1u8, 2, 3, 4, 5];
let vec = read_to_vec(arr.as_ptr(), arr.len()).expect("从指针读取到 Vec 应该成功");
assert_eq!(vec, arr.to_vec(), "从数组读取的数据应该与原始数组相同");
let mut buf = [0u8; 5];
write_from_slice(buf.as_mut_ptr(), &vec).expect("从切片写入指针应该成功");
assert_eq!(buf.to_vec(), vec, "写入缓冲区后应该与原始数据相同");
}
#[test]
fn test_deref_null() {
use std::ptr;
assert!(deref(ptr::null::<u8>()).is_err());
assert!(deref_mut(ptr::null_mut::<u8>()).is_err());
}
#[test]
fn test_write_from_slice_empty() {
let mut buf = [0u8; 5];
let empty_slice: &[u8] = &[];
let result = write_from_slice(buf.as_mut_ptr(), empty_slice);
assert!(result.is_ok());
}
#[test]
fn test_read_to_vec_zero_length() {
let arr = [1u8, 2, 3];
let result = read_to_vec(arr.as_ptr(), 0);
assert!(result.is_ok());
assert_eq!(result.unwrap().len(), 0, "零长度读取应该返回空向量");
}
#[test]
fn test_write_from_slice_null_dst_with_empty_src() {
use std::ptr;
let empty_slice: &[u8] = &[];
let result = write_from_slice(ptr::null_mut(), empty_slice);
assert!(result.is_ok());
}
#[test]
fn test_add_ptr_boundary() {
let arr = [1u8, 2, 3, 4, 5];
let p = arr.as_ptr();
let p0 = add_ptr(p, 0);
assert_eq!(unsafe { *p0 }, 1);
let p_last = add_ptr(p, 4);
assert_eq!(unsafe { *p_last }, 5);
}
#[test]
fn test_read_to_vec_large_size() {
let large_arr = vec![42u8; 1000];
let result = read_to_vec(large_arr.as_ptr(), large_arr.len());
assert!(result.is_ok());
assert_eq!(result.unwrap().len(), 1000);
}
#[test]
fn test_write_from_slice_various_sizes() {
let mut buf1 = [0u8; 1];
let data1 = [1u8];
assert!(write_from_slice(buf1.as_mut_ptr(), &data1).is_ok());
assert_eq!(buf1[0], 1);
let mut buf2 = [0u8; 100];
let data2 = vec![42u8; 100];
assert!(write_from_slice(buf2.as_mut_ptr(), &data2).is_ok());
assert_eq!(buf2.to_vec(), data2);
let mut buf3 = vec![0u8; 1000];
let data3 = vec![99u8; 1000];
assert!(write_from_slice(buf3.as_mut_ptr(), &data3).is_ok());
assert_eq!(buf3, data3);
}
#[test]
fn test_add_ptr_zero_offset() {
let arr = [5u8, 10, 15];
let p = arr.as_ptr();
let p0 = add_ptr(p, 0);
assert_eq!(unsafe { *p0 }, 5, "偏移 0 应该指向第一个元素");
}
#[test]
fn test_add_ptr_mut_various_offsets() {
let mut arr = [1u8, 2, 3, 4, 5];
let p = arr.as_mut_ptr();
for i in 0..5 {
let p_i = add_ptr_mut(p, i);
assert_eq!(unsafe { *p_i }, (i + 1) as u8);
}
}
#[test]
fn test_deref_and_deref_mut_consistency() {
let mut value = 123u32;
let const_ptr = &value as *const u32;
let result_read = deref(const_ptr);
assert!(result_read.is_ok());
assert_eq!(unsafe { *result_read.unwrap().as_ptr() }, 123);
let mut_ptr = &mut value as *mut u32;
let result_write = deref_mut(mut_ptr);
assert!(result_write.is_ok());
unsafe {
*result_write.unwrap().as_ptr() = 456;
}
assert_eq!(value, 456);
}
#[test]
fn test_add_ptr_null() {
assert!(add_ptr::<u8>(std::ptr::null(), 0).is_null());
assert!(add_ptr::<u8>(std::ptr::null(), 10).is_null());
}
#[test]
fn test_add_ptr_mut_null() {
assert!(add_ptr_mut::<u8>(std::ptr::null_mut(), 0).is_null());
assert!(add_ptr_mut::<u8>(std::ptr::null_mut(), 10).is_null());
}
}