use crate::errors::InternalError;
use std::ops::{Deref, DerefMut};
#[repr(transparent)]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct UPtr<T: ?Sized>(*mut T);
impl<T: ?Sized> UPtr<T> {
pub fn new(ptr: *mut T) -> Self {
Self(ptr)
}
pub unsafe fn as_ref(&self) -> crate::errors::Result<&T> {
self.0.as_ref().ok_or(InternalError::InvalidHandle.into())
}
pub unsafe fn as_ref_mut(&self) -> crate::errors::Result<&mut T> {
self.0.as_mut().ok_or(InternalError::InvalidHandle.into())
}
}
impl<T: ?Sized> Deref for UPtr<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.as_ref().unwrap() }
}
}
impl<T: ?Sized> DerefMut for UPtr<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.as_ref_mut().unwrap() }
}
}
unsafe impl<T: ?Sized> Send for UPtr<T> {}
unsafe impl<T: ?Sized> Sync for UPtr<T> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_uptr() {
let mut data = 42;
let mut ptr = UPtr(std::ptr::addr_of_mut!(data));
assert_eq!(*ptr, 42);
*ptr = 43;
assert_eq!(*ptr, 43);
}
#[test]
fn test_uptr_as_ref() {
let mut data = 42;
let ptr = UPtr(std::ptr::addr_of_mut!(data));
assert_eq!(unsafe { ptr.as_ref() }.unwrap(), &42);
}
#[test]
fn test_uptr_as_ref_mut() {
let mut data = 42;
let ptr = UPtr(std::ptr::addr_of_mut!(data));
assert_eq!(unsafe { ptr.as_ref_mut() }.unwrap(), &mut 42);
}
#[test]
fn test_uptr_null() {
let ptr: UPtr<i32> = UPtr(std::ptr::null_mut());
assert!(unsafe { ptr.as_ref() }.is_err());
assert!(unsafe { ptr.as_ref_mut() }.is_err());
}
}