pub struct DevicePtr {
addr: *mut std::ffi::c_void,
}
impl DevicePtr {
#[inline]
pub fn from_addr(addr: *mut std::ffi::c_void) -> Self {
if !addr.is_null() {
DevicePtr { addr }
} else {
panic!("unexpected null pointer");
}
}
#[inline]
pub unsafe fn null() -> Self {
DevicePtr {
addr: std::ptr::null_mut(),
}
}
#[inline]
pub fn is_null(&self) -> bool {
self.addr.is_null()
}
#[inline(always)]
pub fn as_ptr(&self) -> *const std::ffi::c_void {
self.addr as *const std::ffi::c_void
}
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut std::ffi::c_void {
self.addr
}
#[inline]
pub unsafe fn take(&mut self) -> DevicePtr {
DevicePtr {
addr: std::mem::replace(&mut self.addr, std::ptr::null_mut()),
}
}
}
impl std::fmt::Display for DevicePtr {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self.addr)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_it_holds_on() {
let fake = 0xffffffff as *mut std::ffi::c_void;
let ptr = DevicePtr::from_addr(fake);
assert_eq!(ptr.as_ptr(), 0xffffffff as *const std::ffi::c_void);
}
#[test]
#[should_panic]
fn test_it_panics_when_null() {
let _ = DevicePtr::from_addr(std::ptr::null_mut());
}
#[test]
fn test_null() {
let ptr = unsafe { DevicePtr::null() };
assert!(ptr.is_null());
assert_eq!(ptr.as_ptr(), std::ptr::null_mut());
}
#[test]
fn test_take() {
let fake = 0xffffffff as *mut std::ffi::c_void;
let mut ptr = DevicePtr::from_addr(fake);
assert_eq!(
unsafe { ptr.take().as_ptr() },
0xffffffff as *const std::ffi::c_void,
);
}
}