1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2025-01-16 05:06:02 +02:00

Добавление проверок сеттеров и ВК для MongoDB

This commit is contained in:
Anton Titovets 2024-12-09 14:44:15 +03:00
parent ff80f858e1
commit 0fd4806605
13 changed files with 2970 additions and 25 deletions

2552
src/addins/mongo/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
[package]
name = "opi_mongodb"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[profile.release]
lto = true # Enable Link Time Optimization
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
panic = "abort" # Abort on panic
strip = true # Automatically strip symbols from the binary.
[dependencies]
addin1c = "0.5.0"
mongodb = { version = "2.0", features = ["sync"] }
bson = "2.0"

View File

@ -0,0 +1,83 @@
use addin1c::{Variant};
use crate::component::AddIn;
use mongodb::{Client, Collection, options::ClientOptions, bson::{doc, Bson, Document}};
use std::error::Error;
pub fn amount(obj: &AddIn, params: &mut [Variant]) -> i32 {
let result = params[0].get_i32().unwrap() + params[1].get_i32().unwrap();
params[0].set_i32(999);
result
}
pub struct MongoClient {
client: Client,
}
impl MongoClient {
// Конструктор для создания клиента
pub fn new(uri: &str) -> MongoClient {
match ClientOptions::parse(uri) {
Ok(client_options) => match Client::with_options(client_options) {
Ok(client) => MongoClient { client },
Err(_) => MongoClient { client: Client::with_options(ClientOptions::default()).unwrap() }, // Возвращаем дефолтный клиент в случае ошибки
},
Err(_) => MongoClient { client: Client::with_options(ClientOptions::default()).unwrap() }, // Возвращаем дефолтный клиент в случае ошибки
}
}
// Синхронный метод для вставки данных, возвращающий строку или ошибку
pub fn insert_data(&self, db_name: &str, collection_name: &str, data: &str) -> String {
let collection: Collection<Document> = self.client.database(db_name).collection(collection_name);
let doc = doc! { "name": data };
match collection.insert_one(doc, None) {
Ok(_) => "Insert successful".to_string(),
Err(err) => format!("Insert failed: {}", err),
}
}
// Синхронный метод для поиска данных, возвращающий строку или ошибку
pub fn find_data(&self, db_name: &str, collection_name: &str, query: &str) -> String {
let collection: Collection<Document> = self.client.database(db_name).collection(collection_name);
let filter = doc! { "name": query };
match collection.find_one(filter, None) {
Ok(Some(doc)) => match doc.get_str("name") {
Ok(name) => name.to_string(),
Err(_) => "Error reading name from document".to_string(),
},
Ok(None) => "Document not found".to_string(),
Err(err) => format!("Find failed: {}", err),
}
}
// Синхронный метод для подсчета документов, возвращающий количество или ошибку
pub fn count_documents(&self, db_name: &str, collection_name: &str) -> i32 {
let collection: Collection<Document> = self.client.database(db_name).collection(collection_name);
match collection.count_documents(None, None) {
Ok(count) => count as i32,
Err(_) => -1, // Возвращаем -1 в случае ошибки
}
}
// Синхронный метод для проверки наличия документа, возвращающий булевый результат
pub fn document_exists(&self, db_name: &str, collection_name: &str, query: &str) -> bool {
let collection: Collection<Document> = self.client.database(db_name).collection(collection_name);
let filter = doc! { "name": query };
match collection.find_one(filter, None) {
Ok(Some(_)) => true,
Ok(None) => false,
Err(_) => false, // Возвращаем false в случае ошибки
}
}
}

View File

@ -0,0 +1,111 @@
mod methods;
use addin1c::{name, Variant};
use crate::core::getset;
// МЕТОДЫ КОМПОНЕНТЫ -------------------------------------------------------------------------------
// Синонимы
pub const METHODS: &[&[u16]] = &[
name!("InsertData"), // 2
name!("FindData"), // 3
name!("CountDocuments"), // 4
name!("DocumentExists"), // 5
];
// Число параметров функций компоненты
pub fn get_params_amount(num: usize) -> usize {
match num {
0 => 3,
1 => 3,
2 => 2,
3 => 2,
_ => 0,
}
}
// Соответствие функций Rust функциям компоненты
// Вызовы должны быть обернуты в Box::new
pub fn cal_func(obj: &AddIn, num: usize, params: &mut [Variant]) -> Box<dyn crate::core::getset::ValueType> {
let address = &obj.address;
let client = methods::MongoClient::new(address);
match num {
0 => {
let db_name = params[0].get_string().unwrap_or(String::new());
let collection_name= params[1].get_string().unwrap_or(String::new());
let data = params[2].get_string().unwrap_or(String::new());
Box::new(client.insert_data(&db_name, &collection_name, &data))
},
1 => {
let db_name = params[0].get_string().unwrap_or(String::new());
let collection_name= params[1].get_string().unwrap_or(String::new());
let query = params[2].get_string().unwrap_or(String::new());
Box::new(client.find_data(&db_name, &collection_name, &query))
},
2 => {
let db_name = params[0].get_string().unwrap_or(String::new());
let collection_name= params[1].get_string().unwrap_or(String::new());
Box::new(client.count_documents(&db_name, &collection_name))
},
3 => {
let db_name = params[0].get_string().unwrap_or(String::new());
let collection_name= params[1].get_string().unwrap_or(String::new());
let query = params[2].get_string().unwrap_or(String::new());
Box::new(client.document_exists(&db_name, &collection_name, &query))
}
_ => Box::new(false),
}
}
// -------------------------------------------------------------------------------------------------
// ПОЛЯ КОМПОНЕНТЫ ---------------------------------------------------------------------------------
// Синонимы
pub const PROPS: &[&[u16]] = &[
name!("address")
];
// Имена и типы
pub struct AddIn {
address: String
}
// Конструктор
impl AddIn {
// Значения по умолчанию
pub fn new() -> AddIn {
AddIn {
address: String::from("")
}
}
// Сюда просто нужно еще раз добавить имена полей
pub fn get_field_ptr(&self, index: usize) -> *const dyn getset::ValueType {
match index {
0 => &self.address as &dyn getset::ValueType as *const _,
_ => panic!("Index out of bounds"),
}
}
pub fn get_field_ptr_mut(&mut self, index: usize) -> *mut dyn getset::ValueType { self.get_field_ptr(index) as *mut _ }
}
// -------------------------------------------------------------------------------------------------

View File

@ -0,0 +1,78 @@
use addin1c::{Variant, Tm};
pub trait ValueType {
fn get_value(&self, val: &mut Variant) -> bool;
fn set_value(&mut self, val: &Variant);
}
// Реализация для i32
impl ValueType for i32 {
fn get_value(&self, val: &mut Variant) -> bool {
val.set_i32(*self);
true
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_i32().unwrap_or(0);
}
}
// Реализация для f64
impl ValueType for f64 {
fn get_value(&self, val: &mut Variant) -> bool {
val.set_f64(*self);
true
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_f64().unwrap_or(0.0);
}
}
// Реализация для bool
impl ValueType for bool {
fn get_value(&self, val: &mut Variant) -> bool {
val.set_bool(*self);
true
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_bool().unwrap_or(false);
}
}
// Реализация для tm
impl ValueType for Tm {
fn get_value(&self, val: &mut Variant) -> bool {
val.set_date(*self);
true
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_date().unwrap_or(Tm::default());
}
}
// Реализация для String
impl ValueType for String {
fn get_value(&self, val: &mut Variant) -> bool {
let s: Vec<u16> = self.encode_utf16().collect();
val.set_str1c(s.as_slice()).is_ok()
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_string().unwrap_or("".to_string());
}
}
// Реализация для Vec<u8>
impl ValueType for Vec<u8> {
fn get_value(&self, val: &mut Variant) -> bool {
val.set_blob(self.as_slice()).is_ok()
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_blob().unwrap_or(&[]).to_vec()
}
}

View File

@ -0,0 +1,59 @@
pub mod getset;
use addin1c::{name, RawAddin, Variant};
use crate::component::METHODS;
use crate::component::PROPS;
use crate::component::get_params_amount;
use crate::component::cal_func;
use crate::component::AddIn;
// Обработка удаления объекта
impl Drop for AddIn {
fn drop(&mut self) {}
}
// Определение класса
impl RawAddin for AddIn {
fn register_extension_as(&mut self) -> &'static [u16] {
name!("Test")
}
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 Variant) -> bool {let field: &dyn getset::ValueType = &self[num]; field.get_value(val) }
fn set_prop_val(&mut self, num: usize, val: &Variant) -> bool {let field: &mut dyn 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: Variant, ) -> bool { true }
fn has_ret_val(&mut self, num: usize) -> bool { true }
fn call_as_proc(&mut self, _num: usize, _params: &mut [Variant]) -> bool { false }
fn call_as_func(&mut self, num: usize, params: &mut [Variant], ret_value: &mut Variant, ) -> bool { cal_func(self, num, params).get_value(ret_value) }
}
impl std::ops::Index<usize> for AddIn {
type Output = dyn getset::ValueType;
fn index(&self, index: usize) -> &Self::Output {
unsafe { &*self.get_field_ptr(index) }
}
}
impl std::ops::IndexMut<usize> for AddIn {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
unsafe { &mut *self.get_field_ptr_mut(index) }
}
}

View File

@ -0,0 +1,48 @@
pub mod component;
mod core;
use std::{
ffi::{c_int, c_long, c_void},
sync::atomic::{AtomicI32, Ordering},
};
use component::AddIn;
use addin1c::{create_component, destroy_component, name, AttachType};
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::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 {
// small strings for performance
name!("Client").as_ptr()
}
#[allow(non_snake_case)]
#[no_mangle]
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() -> AttachType {
AttachType::Any
}

View File

@ -4,9 +4,9 @@ version = 4
[[package]]
name = "addin1c"
version = "0.2.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f985421a06951cfab1529e5bf26203b42fba9d792de9adc99486fbf3214dc3"
checksum = "ef34e8b7ff4c43e87491a4cc30a4779a9f67c50db43378a36362c7a56246e05b"
dependencies = [
"smallvec",
"utf16_lit",

View File

@ -13,4 +13,4 @@ panic = "abort" # Abort on panic
strip = true # Automatically strip symbols from the binary.
[dependencies]
addin1c = "0.2.0"
addin1c = "0.5.0"

View File

@ -1,20 +1,18 @@
use addin1c::{Variant, ParamValue};
use addin1c::{Variant};
use crate::component::AddIn;
pub fn send_message(obj: &AddIn, params: &[Variant]) -> String {
let field1 = &obj.field1;
if let ParamValue::Str(x) = &params[0].get() {
let pref = String::from_utf16(*x).unwrap();
pref + field1
} else {
"Param error".to_string()
}
params[0].get_string().unwrap_or("".to_string()) + field1
}
pub fn amount(obj: &AddIn, params: &[Variant]) -> i32 {
params[0].get_i32().unwrap() + params[1].get_i32().unwrap()
pub fn amount(obj: &AddIn, params: &mut [Variant]) -> i32 {
let result = params[0].get_i32().unwrap() + params[1].get_i32().unwrap();
params[0].set_i32(999);
result
}

View File

@ -3,7 +3,6 @@ mod methods;
use addin1c::{name, Variant};
use crate::core::getset;
// МЕТОДЫ КОМПОНЕНТЫ -------------------------------------------------------------------------------
// Синонимы
@ -27,7 +26,7 @@ pub fn cal_func(obj: &AddIn, num: usize, params: &mut [Variant]) -> Box<dyn crat
match num {
0 => Box::new(methods::send_message(&obj, &params)),
1 => Box::new(methods::amount(&obj, &params)),
1 => Box::new(methods::amount(&obj, params)),
_ => Box::new(false),
}

View File

@ -1,12 +1,12 @@
use addin1c::{Variant, ParamValue, Tm};
use addin1c::{Variant, Tm};
// Реализация для i32
pub trait ValueType {
fn get_value(&self, val: &mut Variant) -> bool;
fn set_value(&mut self, val: &Variant);
}
// Реализация для i32
impl ValueType for i32 {
fn get_value(&self, val: &mut Variant) -> bool {
val.set_i32(*self);
@ -14,7 +14,7 @@ impl ValueType for i32 {
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_i32().unwrap();
*self = val.get_i32().unwrap_or(0);
}
}
@ -26,7 +26,7 @@ impl ValueType for f64 {
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_f64().unwrap();
*self = val.get_f64().unwrap_or(0.0);
}
}
@ -38,7 +38,7 @@ impl ValueType for bool {
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_bool().unwrap();
*self = val.get_bool().unwrap_or(false);
}
}
@ -50,7 +50,7 @@ impl ValueType for Tm {
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_date().unwrap();
*self = val.get_date().unwrap_or(Tm::default());
}
}
@ -73,6 +73,6 @@ impl ValueType for Vec<u8> {
}
fn set_value(&mut self, val: &Variant) {
*self = val.get_blob().unwrap().to_vec()
*self = val.get_blob().unwrap_or(&[]).to_vec()
}
}

View File

@ -1,7 +1,6 @@
pub mod getset;
use addin1c::{name, ParamValue, RawAddin, Variant};
use std::ops::{Index, IndexMut};
use addin1c::{name, RawAddin, Variant};
use crate::component::METHODS;
use crate::component::PROPS;