1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2026-05-18 09:51:28 +02:00
Files
OpenIntegrations/src/addins/commons/common-core/src/lib.rs
T

193 lines
6.6 KiB
Rust

pub mod from_variant;
pub mod getset;
// Реэкспортируем зависимости
pub use addin1c;
pub use from_variant::FromVariant;
/// Извлекает сообщение об ошибке из panic payload
pub fn extract_panic_message(panic_info: &Box<dyn std::any::Any + Send>) -> String {
if let Some(s) = panic_info.downcast_ref::<&str>() {
s.to_string()
} else if let Some(s) = panic_info.downcast_ref::<String>() {
s.clone()
} else {
"Unknown panic occurred".to_string()
}
}
/// Макрос для генерации экспортируемых функций Native API
#[macro_export]
macro_rules! impl_addin_exports {
($addin_type:ty, $class_name:literal) => {
use std::{
ffi::{c_int, c_long, c_void},
sync::atomic::{AtomicI32, Ordering},
};
use $crate::addin1c::{create_component, destroy_component, name, AttachType, Variant};
pub static mut PLATFORM_CAPABILITIES: AtomicI32 = AtomicI32::new(-1);
#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern "C" fn GetClassObject(
_name: *const u16,
component: *mut *mut c_void,
) -> c_long {
let addin = <$addin_type>::new();
create_component(component, addin)
}
#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern "C" fn DestroyObject(component: *mut *mut c_void) -> c_long {
destroy_component(component)
}
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn GetClassNames() -> *const u16 {
$crate::addin1c::name!($class_name).as_ptr()
}
#[allow(non_snake_case)]
#[no_mangle]
#[allow(static_mut_refs)]
pub unsafe extern "C" fn SetPlatformCapabilities(capabilities: c_int) -> c_int {
PLATFORM_CAPABILITIES.store(capabilities, Ordering::Relaxed);
3
}
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn GetAttachType() -> $crate::addin1c::AttachType {
$crate::addin1c::AttachType::Any
}
};
}
/// Макрос для генерации реализации RawAddin с защитой от panic
#[macro_export]
macro_rules! impl_raw_addin {
($addin_type:ty, $methods:expr, $props:expr, $get_params_amount:expr, $cal_func_fn:expr, $class_name:literal) => {
impl $crate::addin1c::RawAddin for $addin_type {
fn register_extension_as(&mut self) -> &'static [u16] {
$crate::addin1c::name!($class_name)
}
fn get_n_props(&mut self) -> usize {
$props.len()
}
fn find_prop(&mut self, name: &[u16]) -> Option<usize> {
$props.iter().position(|&x| x == name)
}
fn get_prop_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> {
$props.get(num).copied()
}
fn get_prop_val(&mut self, num: usize, val: &mut $crate::addin1c::Variant) -> bool {
let field: &dyn $crate::getset::ValueType = &self[num];
field.get_value(val)
}
fn set_prop_val(&mut self, num: usize, val: &$crate::addin1c::Variant) -> bool {
let field: &mut dyn $crate::getset::ValueType = &mut self[num];
field.set_value(val);
true
}
fn is_prop_readable(&mut self, _num: usize) -> bool {
true
}
fn is_prop_writable(&mut self, _num: usize) -> bool {
true
}
fn get_n_methods(&mut self) -> usize {
$methods.len()
}
fn find_method(&mut self, name: &[u16]) -> Option<usize> {
$methods.iter().position(|&x| x == name)
}
fn get_method_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> {
$methods.get(num).copied()
}
fn get_n_params(&mut self, num: usize) -> usize {
$get_params_amount(num)
}
fn get_param_def_value(
&mut self,
_method_num: usize,
_param_num: usize,
_value: $crate::addin1c::Variant,
) -> bool {
true
}
fn has_ret_val(&mut self, _num: usize) -> bool {
true
}
fn call_as_proc(
&mut self,
_num: usize,
_params: &mut [$crate::addin1c::Variant],
) -> bool {
false
}
fn call_as_func(
&mut self,
num: usize,
params: &mut [$crate::addin1c::Variant],
ret_value: &mut $crate::addin1c::Variant,
) -> bool {
// Защита от panic - перехватываем и возвращаем ошибку в 1С
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
$cal_func_fn(self, num, params)
}));
match result {
Ok(value) => {
// Нормальное выполнение
value.get_value(ret_value)
}
Err(panic_info) => {
// Panic произошёл - извлекаем сообщение и возвращаем как ошибку
let panic_msg = $crate::extract_panic_message(&panic_info);
let error_msg = format!("Internal error (panic): {}", panic_msg);
// Возвращаем ошибку как строку в 1С
let s: Vec<u16> = error_msg.encode_utf16().collect();
let _ = ret_value.set_str1c(s.as_slice());
true
}
}
}
}
// Реализация Index для доступа к полям через []
impl std::ops::Index<usize> for $addin_type {
type Output = dyn $crate::getset::ValueType;
fn index(&self, index: usize) -> &Self::Output {
unsafe { &*self.get_field_ptr(index) }
}
}
// Реализация IndexMut для изменения полей через []
impl std::ops::IndexMut<usize> for $addin_type {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
unsafe { &mut *self.get_field_ptr_mut(index) }
}
}
};
}