1use std::borrow::Cow;
2use std::ffi::{CStr, CString};
3use std::panic;
4use std::path::PathBuf;
5
6#[repr(C)]
7#[derive(PartialEq, Debug, Copy, Clone)]
8pub enum FCPResponseStatus {
9 FCPNoError = 0,
11 FCPUnclassifiedError = 1,
12 FCPCallerError = 2,
13 FCPReceiverError = 3,
14}
15
16pub trait CodeAndMessage {
18 fn set_error(&mut self, code_and_message: (FCPResponseStatus, *const libc::c_char));
20}
21
22#[macro_export]
27macro_rules! code_and_message_impl {
28 { $response:ty } => {
29 impl CodeAndMessage for $response {
30 fn set_error(&mut self, (code, message): (FCPResponseStatus, *const libc::c_char)) {
31 self.status_code = code;
32 self.error_msg = message;
33 }
34 }
35 }
36}
37
38pub fn rust_str_to_c_str<T: Into<String>>(s: T) -> *mut libc::c_char {
40 CString::new(s.into()).unwrap().into_raw()
41}
42
43pub unsafe fn free_c_str(ptr: *mut libc::c_char) {
45 if !ptr.is_null() {
46 let _ = CString::from_raw(ptr);
47 }
48}
49
50pub fn raw_ptr<T>(thing: T) -> *mut T {
52 Box::into_raw(Box::new(thing))
53}
54
55pub unsafe fn c_str_to_rust_str<'a>(x: *const libc::c_char) -> Cow<'a, str> {
57 if x.is_null() {
58 Cow::from("")
59 } else {
60 CStr::from_ptr(x).to_string_lossy()
61 }
62}
63
64pub unsafe fn cast_const<'a, T>(x: *mut T) -> &'a T {
66 assert!(!x.is_null(), "Object argument was null");
67 (&(*x))
68}
69
70pub unsafe fn c_str_to_pbuf(x: *const libc::c_char) -> PathBuf {
72 PathBuf::from(String::from(c_str_to_rust_str(x)))
73}
74
75pub fn catch_panic_response<F, T>(callback: F) -> *mut T
77where
78 T: Default + CodeAndMessage,
79 F: FnOnce() -> *mut T,
80{
81 let maybe_panic = panic::catch_unwind(panic::AssertUnwindSafe(callback));
84 match maybe_panic {
85 Ok(return_value) => return_value,
86 Err(panic) => {
87 let error_msg = match panic.downcast_ref::<&'static str>() {
88 Some(message) => message,
89 _ => "no unwind information",
90 };
91 let mut response = T::default();
92 let message = CString::new(format!("Rust panic: {}", error_msg))
93 .unwrap()
94 .into_raw();
95 response.set_error((FCPResponseStatus::FCPUnclassifiedError, message));
96 raw_ptr(response)
97 }
98 }
99}