use std::os::raw::c_char;
use std::ptr;
use super::conversions::{c_str_to_rust, cast_builder, cast_builder_mut};
use super::errors::set_last_error;
use super::types::{AnalyzerInternal, BuilderInternal, CAnalyzer, CAnalyzerBuilder, CErrorCode};
use crate::async_runtime::DefaultRuntime;
use crate::AnalyzerBuilder;
#[no_mangle]
pub extern "C" fn wqa_builder_new() -> *mut CAnalyzerBuilder {
let builder = AnalyzerBuilder::<DefaultRuntime>::default();
let internal = Box::new(BuilderInternal { builder });
Box::into_raw(internal) as *mut CAnalyzerBuilder
}
#[no_mangle]
pub extern "C" fn wqa_builder_with_profile(
builder: *mut CAnalyzerBuilder,
profile: *const c_char,
) -> CErrorCode {
if builder.is_null() || profile.is_null() {
set_last_error("Null pointer provided".to_string());
return CErrorCode::InvalidPointer;
}
let profile_str = unsafe {
match c_str_to_rust(profile) {
Some(s) => s,
None => {
set_last_error("Invalid UTF-8 in profile name".to_string());
return CErrorCode::Utf8Error;
}
}
};
let internal = unsafe {
match cast_builder_mut(builder) {
Some(b) => b,
None => return CErrorCode::InvalidPointer,
}
};
let temp_builder = std::mem::replace(
&mut internal.builder,
AnalyzerBuilder::<DefaultRuntime>::default(),
);
match temp_builder.with_profile_name(profile_str) {
Ok(new_builder) => {
internal.builder = new_builder;
CErrorCode::Success
}
Err(e) => {
set_last_error(format!("{}", e));
internal.builder = AnalyzerBuilder::<DefaultRuntime>::default();
CErrorCode::InvalidProfile
}
}
}
#[no_mangle]
pub extern "C" fn wqa_builder_disable_metric(
builder: *mut CAnalyzerBuilder,
metric: *const c_char,
) -> CErrorCode {
if builder.is_null() || metric.is_null() {
set_last_error("Null pointer provided".to_string());
return CErrorCode::InvalidPointer;
}
let metric_str = unsafe {
match c_str_to_rust(metric) {
Some(s) => s,
None => {
set_last_error("Invalid UTF-8 in metric name".to_string());
return CErrorCode::Utf8Error;
}
}
};
let internal = unsafe {
match cast_builder_mut(builder) {
Some(b) => b,
None => return CErrorCode::InvalidPointer,
}
};
let temp_builder = std::mem::replace(
&mut internal.builder,
AnalyzerBuilder::<DefaultRuntime>::default(),
);
match temp_builder.disable_metric(metric_str) {
Ok(new_builder) => {
internal.builder = new_builder;
CErrorCode::Success
}
Err(e) => {
set_last_error(format!("{}", e));
internal.builder = AnalyzerBuilder::<DefaultRuntime>::default();
CErrorCode::MetricNotFound
}
}
}
#[no_mangle]
pub extern "C" fn wqa_builder_enable_metric(
builder: *mut CAnalyzerBuilder,
metric: *const c_char,
) -> CErrorCode {
if builder.is_null() || metric.is_null() {
set_last_error("Null pointer provided".to_string());
return CErrorCode::InvalidPointer;
}
let metric_str = unsafe {
match c_str_to_rust(metric) {
Some(s) => s,
None => {
set_last_error("Invalid UTF-8 in metric name".to_string());
return CErrorCode::Utf8Error;
}
}
};
let internal = unsafe {
match cast_builder_mut(builder) {
Some(b) => b,
None => return CErrorCode::InvalidPointer,
}
};
let temp_builder = std::mem::replace(
&mut internal.builder,
AnalyzerBuilder::<DefaultRuntime>::default(),
);
match temp_builder.enable_metric(metric_str) {
Ok(new_builder) => {
internal.builder = new_builder;
CErrorCode::Success
}
Err(e) => {
set_last_error(format!("{}", e));
internal.builder = AnalyzerBuilder::<DefaultRuntime>::default();
CErrorCode::MetricNotFound
}
}
}
#[no_mangle]
pub extern "C" fn wqa_builder_set_metric_weight(
builder: *mut CAnalyzerBuilder,
metric: *const c_char,
weight: f32,
) -> CErrorCode {
if builder.is_null() || metric.is_null() {
set_last_error("Null pointer provided".to_string());
return CErrorCode::InvalidPointer;
}
let metric_str = unsafe {
match c_str_to_rust(metric) {
Some(s) => s,
None => {
set_last_error("Invalid UTF-8 in metric name".to_string());
return CErrorCode::Utf8Error;
}
}
};
let internal = unsafe {
match cast_builder_mut(builder) {
Some(b) => b,
None => return CErrorCode::InvalidPointer,
}
};
let temp_builder = std::mem::replace(
&mut internal.builder,
AnalyzerBuilder::<DefaultRuntime>::default(),
);
match temp_builder.set_metric_weight(metric_str, weight) {
Ok(new_builder) => {
internal.builder = new_builder;
CErrorCode::Success
}
Err(e) => {
set_last_error(format!("{}", e));
internal.builder = AnalyzerBuilder::<DefaultRuntime>::default();
CErrorCode::MetricNotFound
}
}
}
#[no_mangle]
pub extern "C" fn wqa_builder_build(builder: *mut CAnalyzerBuilder) -> *mut CAnalyzer {
if builder.is_null() {
set_last_error("Null builder provided".to_string());
return ptr::null_mut();
}
let internal = unsafe { Box::from_raw(builder as *mut BuilderInternal) };
match internal.builder.build() {
Ok(analyzer) => {
let runtime = match tokio::runtime::Runtime::new() {
Ok(rt) => rt,
Err(e) => {
set_last_error(format!("Failed to create runtime: {}", e));
return ptr::null_mut();
}
};
let analyzer_internal = Box::new(AnalyzerInternal { analyzer, runtime });
Box::into_raw(analyzer_internal) as *mut CAnalyzer
}
Err(e) => {
set_last_error(format!("{}", e));
ptr::null_mut()
}
}
}
#[no_mangle]
pub extern "C" fn wqa_free_analyzer(analyzer: *mut CAnalyzer) {
if !analyzer.is_null() {
unsafe {
let _ = Box::from_raw(analyzer as *mut AnalyzerInternal);
}
}
}
#[no_mangle]
pub extern "C" fn wqa_builder_free(builder: *mut CAnalyzerBuilder) {
if !builder.is_null() {
unsafe {
let _ = Box::from_raw(builder as *mut BuilderInternal);
}
}
}