labview_interop/types/
lv_status.rs1use crate::errors::{LVInteropError, MgError};
7use std::error::Error;
8use std::fmt::Display;
9
10#[repr(transparent)]
25#[derive(Debug, Clone, Copy, Eq, PartialEq)]
26pub struct LVStatusCode(i32);
27
28impl Display for LVStatusCode {
29 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
30 #[cfg(not(feature = "link"))]
31 write!(f, "LVStatusCode: {}", self.0)?;
32 #[cfg(feature = "link")]
33 write!(f, "LVStatusCode: {} - {}", self.0, self.description())?;
34 Ok(())
35 }
36}
37
38impl Error for LVStatusCode {}
39
40impl LVStatusCode {
41 pub const SUCCESS: LVStatusCode = LVStatusCode(0);
42
43 #[allow(dead_code)]
47 pub(crate) fn to_specific_result<T>(self, success_value: T) -> crate::errors::Result<T> {
48 if self == Self::SUCCESS {
49 Ok(success_value)
50 } else {
51 match MgError::try_from(self) {
52 Ok(mg_err) => Err(mg_err.into()),
53 Err(inter_err) => Err(inter_err),
54 }
55 }
56 }
57
58 pub fn to_generic_result<T>(self, success_value: T) -> Result<T, LVInteropError> {
60 if self == Self::SUCCESS {
61 Ok(success_value)
62 } else {
63 Err(LVInteropError::LabviewError(self))
64 }
65 }
66}
67
68impl From<i32> for LVStatusCode {
70 fn from(value: i32) -> LVStatusCode {
71 LVStatusCode(value)
72 }
73}
74
75impl From<LVStatusCode> for i32 {
76 fn from(code: LVStatusCode) -> i32 {
77 code.0
78 }
79}
80
81#[cfg(feature = "link")]
82mod lv_status_link_features {
83 use super::*;
84 use std::borrow::Cow;
85 impl LVStatusCode {
86 pub fn description(&self) -> Cow<'static, str> {
87 use crate::labview::memory_api;
88 use crate::types::LStrHandle;
89 use std::mem::MaybeUninit;
90
91 static DEFAULT_STRING: &str = "LabVIEW-Interop: Description not retrievable";
92 let mut error_text_ptr = MaybeUninit::<LStrHandle>::uninit();
93
94 let memory_api = match memory_api() {
95 Ok(api) => api,
96 Err(_) => return Cow::Borrowed(DEFAULT_STRING),
97 };
98
99 unsafe {
100 if memory_api
101 .error_code_description(self.0, error_text_ptr.as_mut_ptr() as *mut usize)
102 {
103 let error_text_ptr = error_text_ptr.assume_init();
104 let desc = error_text_ptr.to_rust_string().to_string();
105 return Cow::Owned(desc);
106 }
107 }
108 Cow::Borrowed(DEFAULT_STRING)
109 }
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_error_lvstatuscode_from_i32() {
119 let status = LVStatusCode::from(0);
120 assert_eq!(status, LVStatusCode::SUCCESS);
121
122 let status = LVStatusCode::from(1);
123 assert_eq!(status, LVStatusCode(1));
124
125 let status: LVStatusCode = 42.into();
126 assert_eq!(status, LVStatusCode(42));
127 }
128
129 #[test]
131 fn test_error_lvstatuscode_from_externc() {
132 unsafe extern "C" fn mock_externc() -> i32 {
134 542_002 }
136
137 fn post_lv_user_event_safe() -> LVStatusCode {
138 let result: i32 = unsafe { mock_externc() };
139
140 unsafe { std::mem::transmute(result) }
142 }
143
144 let lv_status = post_lv_user_event_safe();
145
146 assert_eq!(lv_status, LVStatusCode(542_002));
147 }
148}