sz_rust_sdk/ffi/
helpers.rs1use crate::error::{SzError, SzResult};
4use libc::{c_char, c_void, size_t};
5use std::ffi::{CStr, CString};
6use std::ptr;
7
8pub(crate) fn str_to_c_string(s: &str) -> SzResult<CString> {
10 CString::new(s).map_err(SzError::from)
11}
12
13#[inline]
18pub(crate) unsafe fn sz_free(ptr: *mut c_char) {
19 if !ptr.is_null() {
20 unsafe { super::SzHelper_free(ptr as *mut c_void) };
21 }
22}
23
24pub(crate) unsafe fn c_str_to_string(ptr: *mut c_char) -> SzResult<String> {
31 if ptr.is_null() {
32 return Ok(String::new());
33 }
34
35 let c_str = unsafe { CStr::from_ptr(ptr) };
36 let result = match c_str.to_str() {
37 Ok(s) => Ok(s.to_string()),
38 Err(_) => {
39 let bytes = c_str.to_bytes();
41 Ok(hex::encode(bytes))
42 }
43 };
44
45 unsafe { sz_free(ptr) };
47
48 result
49}
50
51pub(crate) unsafe fn c_str_to_string_no_free(ptr: *mut c_char) -> SzResult<String> {
58 if ptr.is_null() {
59 return Ok(String::new());
60 }
61
62 let c_str = unsafe { CStr::from_ptr(ptr) };
63 match c_str.to_str() {
64 Ok(s) => Ok(s.to_string()),
65 Err(_) => {
66 let bytes = c_str.to_bytes();
67 Ok(hex::encode(bytes))
68 }
69 }
70}
71
72pub(crate) unsafe fn c_str_to_bytes(ptr: *mut c_char) -> SzResult<Vec<u8>> {
79 if ptr.is_null() {
80 return Ok(Vec::new());
81 }
82
83 let c_str = unsafe { CStr::from_ptr(ptr) };
84 let bytes = c_str.to_bytes().to_vec();
85
86 unsafe { sz_free(ptr) };
87
88 Ok(bytes)
89}
90
91pub(crate) struct ResponseBuffer {
93 pub ptr: *mut c_char,
94 pub size: size_t,
95}
96
97impl Default for ResponseBuffer {
98 fn default() -> Self {
99 Self::new()
100 }
101}
102
103impl ResponseBuffer {
104 pub(crate) fn new() -> Self {
105 Self {
106 ptr: ptr::null_mut(),
107 size: 0,
108 }
109 }
110
111 pub(crate) fn as_string(&self) -> SzResult<String> {
112 unsafe { c_str_to_string(self.ptr) }
113 }
114}
115
116impl Drop for ResponseBuffer {
117 fn drop(&mut self) {
118 if !self.ptr.is_null() {
119 unsafe {
120 sz_free(self.ptr);
121 }
122 }
123 }
124}
125
126pub(crate) fn check_return_code(return_code: i64) -> SzResult<()> {
128 if return_code == 0 {
129 return Ok(());
130 }
131
132 let actual_error_code = unsafe { super::Sz_getLastExceptionCode() };
133 Err(SzError::from_code_with_message(
134 actual_error_code,
135 crate::error::SzComponent::Engine,
136 ))
137}
138
139pub(crate) fn check_config_return_code(return_code: i64) -> SzResult<()> {
141 if return_code == 0 {
142 return Ok(());
143 }
144
145 let actual_error_code = unsafe { super::SzConfig_getLastExceptionCode() };
146 Err(SzError::from_code_with_message(
147 actual_error_code,
148 crate::error::SzComponent::Config,
149 ))
150}
151
152pub(crate) fn check_config_mgr_return_code(return_code: i64) -> SzResult<()> {
154 if return_code == 0 {
155 return Ok(());
156 }
157
158 let actual_error_code = unsafe { super::SzConfigMgr_getLastExceptionCode() };
159 Err(SzError::from_code_with_message(
160 actual_error_code,
161 crate::error::SzComponent::ConfigMgr,
162 ))
163}
164
165pub(crate) fn check_product_return_code(return_code: i64) -> SzResult<()> {
167 if return_code == 0 {
168 return Ok(());
169 }
170
171 let actual_error_code = unsafe { super::SzProduct_getLastExceptionCode() };
172 Err(SzError::from_code_with_message(
173 actual_error_code,
174 crate::error::SzComponent::Product,
175 ))
176}
177
178pub(crate) fn check_diagnostic_return_code(return_code: i64) -> SzResult<()> {
180 if return_code == 0 {
181 return Ok(());
182 }
183
184 let actual_error_code = unsafe { super::SzDiagnostic_getLastExceptionCode() };
185 Err(SzError::from_code_with_message(
186 actual_error_code,
187 crate::error::SzComponent::Diagnostic,
188 ))
189}
190
191#[doc(hidden)]
193#[macro_export]
194macro_rules! ffi_call {
195 ($ffi_fn:expr) => {{
196 #[allow(clippy::macro_metavars_in_unsafe)]
197 let result = unsafe { $ffi_fn };
198 $crate::ffi::helpers::check_return_code(result)?;
199 }};
200}
201
202#[doc(hidden)]
204#[macro_export]
205macro_rules! ffi_call_config {
206 ($ffi_fn:expr) => {{
207 #[allow(clippy::macro_metavars_in_unsafe)]
208 let result = unsafe { $ffi_fn };
209 $crate::ffi::helpers::check_config_return_code(result)?;
210 }};
211}
212
213#[doc(hidden)]
215#[macro_export]
216macro_rules! ffi_call_config_mgr {
217 ($ffi_fn:expr) => {{
218 #[allow(clippy::macro_metavars_in_unsafe)]
219 let result = unsafe { $ffi_fn };
220 $crate::ffi::helpers::check_config_mgr_return_code(result)?;
221 }};
222}
223
224#[doc(hidden)]
226#[macro_export]
227macro_rules! ffi_call_product {
228 ($ffi_fn:expr) => {{
229 #[allow(clippy::macro_metavars_in_unsafe)]
230 let result = unsafe { $ffi_fn };
231 $crate::ffi::helpers::check_product_return_code(result)?;
232 }};
233}
234
235#[doc(hidden)]
237#[macro_export]
238macro_rules! ffi_call_diagnostic {
239 ($ffi_fn:expr) => {{
240 #[allow(clippy::macro_metavars_in_unsafe)]
241 let result = unsafe { $ffi_fn };
242 $crate::ffi::helpers::check_diagnostic_return_code(result)?;
243 }};
244}
245
246#[doc(hidden)]
248#[macro_export]
249macro_rules! ffi_call_i64 {
250 ($ffi_fn:expr) => {{
251 #[allow(clippy::macro_metavars_in_unsafe)]
252 let result = unsafe { $ffi_fn };
253 $crate::ffi::helpers::check_return_code(result)?;
254 }};
255}
256
257#[doc(hidden)]
259#[macro_export]
260macro_rules! ffi_call_with_response {
261 ($ffi_fn:expr) => {{
262 let mut response = $crate::ffi::helpers::ResponseBuffer::new();
263 let result = unsafe { $ffi_fn(&mut response.ptr, &mut response.size) };
264 $crate::ffi::helpers::check_return_code(result)?;
265 response.as_string()
266 }};
267}
268
269#[doc(hidden)]
272#[macro_export]
273macro_rules! process_result {
274 ($result:expr, $check_fn:path) => {{
275 $check_fn($result.returnCode)?;
276 unsafe { $crate::ffi::helpers::c_str_to_string($result.response) }
277 }};
278}
279
280#[doc(hidden)]
282#[macro_export]
283macro_rules! process_engine_result {
284 ($result:expr) => {{
285 $crate::ffi::helpers::check_return_code($result.returnCode)?;
286 unsafe { $crate::ffi::helpers::c_str_to_string($result.response) }
287 }};
288}
289
290#[doc(hidden)]
292#[macro_export]
293macro_rules! process_config_result {
294 ($result:expr) => {{
295 $crate::ffi::helpers::check_config_return_code($result.returnCode)?;
296 unsafe { $crate::ffi::helpers::c_str_to_string($result.response) }
297 }};
298}
299
300#[doc(hidden)]
302#[macro_export]
303macro_rules! process_config_mgr_result {
304 ($result:expr) => {{
305 $crate::ffi::helpers::check_config_mgr_return_code($result.returnCode)?;
306 unsafe { $crate::ffi::helpers::c_str_to_string($result.response) }
307 }};
308}
309
310#[doc(hidden)]
312#[macro_export]
313macro_rules! process_config_mgr_long_result {
314 ($result:expr) => {{
315 $crate::ffi::helpers::check_config_mgr_return_code($result.returnCode)?;
316 Ok($result.configID)
317 }};
318}
319
320#[doc(hidden)]
322#[macro_export]
323macro_rules! process_diagnostic_result {
324 ($result:expr) => {{
325 $crate::ffi::helpers::check_diagnostic_return_code($result.returnCode)?;
326 unsafe { $crate::ffi::helpers::c_str_to_string($result.response) }
327 }};
328}
329
330#[doc(hidden)]
332#[macro_export]
333macro_rules! process_product_result {
334 ($result:expr) => {{
335 $crate::ffi::helpers::check_product_return_code($result.returnCode)?;
336 unsafe { $crate::ffi::helpers::c_str_to_string($result.response) }
337 }};
338}