use crate::errors::{LVInteropError, MgError};
use std::error::Error;
use std::fmt::Display;
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct LVStatusCode(i32);
impl Display for LVStatusCode {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
#[cfg(not(feature = "link"))]
write!(f, "LVStatusCode: {}", self.0)?;
#[cfg(feature = "link")]
write!(f, "LVStatusCode: {} - {}", self.0, self.description())?;
Ok(())
}
}
impl Error for LVStatusCode {}
impl LVStatusCode {
pub const SUCCESS: LVStatusCode = LVStatusCode(0);
#[allow(dead_code)]
pub(crate) fn to_specific_result<T>(self, success_value: T) -> crate::errors::Result<T> {
if self == Self::SUCCESS {
Ok(success_value)
} else {
match MgError::try_from(self) {
Ok(mg_err) => Err(mg_err.into()),
Err(inter_err) => Err(inter_err),
}
}
}
pub fn to_generic_result<T>(self, success_value: T) -> Result<T, LVInteropError> {
if self == Self::SUCCESS {
Ok(success_value)
} else {
Err(LVInteropError::LabviewError(self))
}
}
}
impl From<i32> for LVStatusCode {
fn from(value: i32) -> LVStatusCode {
LVStatusCode(value)
}
}
impl From<LVStatusCode> for i32 {
fn from(code: LVStatusCode) -> i32 {
code.0
}
}
#[cfg(feature = "link")]
mod lv_status_link_features {
use super::*;
use std::borrow::Cow;
impl LVStatusCode {
pub fn description(&self) -> Cow<'static, str> {
use crate::labview::memory_api;
use crate::types::LStrHandle;
use std::mem::MaybeUninit;
static DEFAULT_STRING: &str = "LabVIEW-Interop: Description not retrievable";
let mut error_text_ptr = MaybeUninit::<LStrHandle>::uninit();
let memory_api = match memory_api() {
Ok(api) => api,
Err(_) => return Cow::Borrowed(DEFAULT_STRING),
};
unsafe {
if memory_api
.error_code_description(self.0, error_text_ptr.as_mut_ptr() as *mut usize)
{
let error_text_ptr = error_text_ptr.assume_init();
let desc = error_text_ptr.to_rust_string().to_string();
return Cow::Owned(desc);
}
}
Cow::Borrowed(DEFAULT_STRING)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_lvstatuscode_from_i32() {
let status = LVStatusCode::from(0);
assert_eq!(status, LVStatusCode::SUCCESS);
let status = LVStatusCode::from(1);
assert_eq!(status, LVStatusCode(1));
let status: LVStatusCode = 42.into();
assert_eq!(status, LVStatusCode(42));
}
#[test]
fn test_error_lvstatuscode_from_externc() {
unsafe extern "C" fn mock_externc() -> i32 {
542_002 }
fn post_lv_user_event_safe() -> LVStatusCode {
let result: i32 = unsafe { mock_externc() };
unsafe { std::mem::transmute(result) }
}
let lv_status = post_lv_user_event_safe();
assert_eq!(lv_status, LVStatusCode(542_002));
}
}