use crate::errors::InternalError;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
#[repr(transparent)]
#[derive(PartialEq, Eq)]
pub struct UHandle<'a, T: ?Sized + 'a>(pub *mut *mut T, pub PhantomData<&'a T>);
impl<T: ?Sized> UHandle<'_, T> {
pub unsafe fn as_ref(&self) -> crate::errors::Result<&T> {
self.0
.as_ref()
.and_then(|ptr| ptr.as_ref())
.ok_or(InternalError::InvalidHandle.into())
}
pub unsafe fn as_ref_mut(&self) -> crate::errors::Result<&mut T> {
self.0
.as_ref()
.and_then(|ptr| ptr.as_mut())
.ok_or(InternalError::InvalidHandle.into())
}
pub fn valid(&self) -> bool {
let inner_ref = unsafe { self.as_ref() };
if inner_ref.is_err() {
return false;
}
#[cfg(feature = "link")]
{
let ret = unsafe {
crate::labview::memory_api()
.unwrap()
.check_handle(self.0 as usize)
};
ret == crate::types::LVStatusCode::SUCCESS
}
#[cfg(not(feature = "link"))]
{
return true;
}
}
#[cfg(test)]
pub fn from_raw(ptr: *mut *mut T) -> Self {
Self(ptr, PhantomData)
}
}
impl<T: ?Sized> Deref for UHandle<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.as_ref().unwrap() }
}
}
impl<T: ?Sized> DerefMut for UHandle<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.as_ref_mut().unwrap() }
}
}
impl<T: Debug + ?Sized> Debug for UHandle<'_, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
super::fmt_handle("UHandle", self, f)
}
}
#[cfg(feature = "link")]
mod uhandle_link_features {
use super::*;
use crate::memory::LVCopy;
impl<T: ?Sized> UHandle<'_, T> {
pub unsafe fn resize(&mut self, desired_size: usize) -> crate::errors::Result<()> {
let err = crate::labview::memory_api()?.set_handle_size(self.0 as usize, desired_size);
err.to_specific_result(())
}
}
impl<T: ?Sized + LVCopy + 'static> UHandle<'_, T> {
pub unsafe fn clone_into_pointer(
&self,
other: *mut UHandle<'_, T>,
) -> crate::errors::Result<()> {
if !self.valid() {
return Err(InternalError::InvalidHandle.into());
}
let error =
crate::labview::memory_api()?.copy_handle(other as *mut usize, self.0 as usize);
error.to_specific_result(())
}
}
}
unsafe impl<T: ?Sized> Send for UHandle<'_, T> {}
unsafe impl<T: ?Sized> Sync for UHandle<'_, T> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_handle_debug() {
let mut value = 42;
let mut value_ptr = std::ptr::addr_of_mut!(value);
let handle = UHandle(std::ptr::addr_of_mut!(value_ptr), PhantomData);
assert_eq!(format!("{:?}", handle), "UHandle(42)");
}
#[test]
fn test_invalid_handle_debug() {
let handle = UHandle(std::ptr::null_mut::<*mut i32>(), PhantomData);
assert_eq!(format!("{:?}", handle), "UHandle(Invalid)");
}
#[test]
fn test_handle_debug_inner_from_reference() {
let mut value = 42;
let mut value_ptr = std::ptr::addr_of_mut!(value);
let handle = UHandle(std::ptr::addr_of_mut!(value_ptr), PhantomData);
assert_eq!(format!("{:?}", *handle), "42");
}
#[test]
fn test_handle_deref() {
let mut value = 42;
let mut value_ptr = std::ptr::addr_of_mut!(value);
let handle = UHandle(std::ptr::addr_of_mut!(value_ptr), PhantomData);
assert_eq!(*handle, 42);
}
#[test]
fn test_handle_deref_mut() {
let mut value = 42;
let mut value_ptr = std::ptr::addr_of_mut!(value);
let mut handle = UHandle(std::ptr::addr_of_mut!(value_ptr), PhantomData);
*handle = 43;
assert_eq!(*handle, 43);
}
#[test]
fn handle_as_ref_valid() {
let mut value = 42;
let mut value_ptr = std::ptr::addr_of_mut!(value);
let handle = UHandle(std::ptr::addr_of_mut!(value_ptr), PhantomData);
assert_eq!(unsafe { handle.as_ref() }.unwrap(), &42);
}
#[test]
fn handle_as_ref_outer_null() {
let handle = UHandle(std::ptr::null_mut::<*mut i32>(), PhantomData);
assert!(unsafe { handle.as_ref() }.is_err());
}
#[test]
fn handle_as_ref_inner_null() {
let mut inner_ptr = std::ptr::null_mut::<i32>();
let handle = UHandle(std::ptr::addr_of_mut!(inner_ptr), PhantomData);
assert!(unsafe { handle.as_ref() }.is_err());
}
#[test]
fn handle_as_ref_mut_valid() {
let mut value = 42;
let mut value_ptr = std::ptr::addr_of_mut!(value);
let handle = UHandle(std::ptr::addr_of_mut!(value_ptr), PhantomData);
assert_eq!(unsafe { handle.as_ref_mut() }.unwrap(), &mut 42);
}
#[test]
fn handle_as_ref_mut_outer_null() {
let handle = UHandle(std::ptr::null_mut::<*mut i32>(), PhantomData);
assert!(unsafe { handle.as_ref_mut() }.is_err());
}
#[test]
fn handle_as_ref_mut_inner_null() {
let mut inner_ptr = std::ptr::null_mut::<i32>();
let handle = UHandle(std::ptr::addr_of_mut!(inner_ptr), PhantomData);
assert!(unsafe { handle.as_ref_mut() }.is_err());
}
#[test]
fn handle_valid_check_false_if_null() {
let handle = UHandle(std::ptr::null_mut::<*mut i32>(), PhantomData);
assert!(!handle.valid());
}
#[cfg(not(feature = "link"))]
#[test]
fn handle_valid_check_is_valid_no_link() {
let mut value = 42;
let mut value_ptr = std::ptr::addr_of_mut!(value);
let handle = UHandle(std::ptr::addr_of_mut!(value_ptr), PhantomData);
assert!(handle.valid());
}
}