use alloc::ffi::CString;
use core::ffi::{c_char, c_int};
use core::ptr;
use crate::ZeroDdsStatus;
use crate::entities::{ZeroDdsDomainParticipant, ZeroDdsTopic};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn zerodds_topic_get_name(t: *mut ZeroDdsTopic) -> *mut c_char {
if t.is_null() {
return ptr::null_mut();
}
let tt = unsafe { &*t };
match CString::new(tt.name.as_str()) {
Ok(c) => c.into_raw(),
Err(_) => ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn zerodds_topic_get_type_name(t: *mut ZeroDdsTopic) -> *mut c_char {
if t.is_null() {
return ptr::null_mut();
}
let tt = unsafe { &*t };
match CString::new(tt.type_name.as_str()) {
Ok(c) => c.into_raw(),
Err(_) => ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn zerodds_topic_get_participant(
t: *mut ZeroDdsTopic,
) -> *mut ZeroDdsDomainParticipant {
if t.is_null() {
return ptr::null_mut();
}
unsafe { (*t).participant }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn zerodds_string_free(s: *mut c_char) {
if s.is_null() {
return;
}
let _ = unsafe { CString::from_raw(s) };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn zerodds_topic_get_qos(
t: *mut ZeroDdsTopic,
out: *mut crate::qos_ffi::ZeroDdsTopicQos,
) -> c_int {
if t.is_null() || out.is_null() {
return ZeroDdsStatus::BadParameter as c_int;
}
let tt = unsafe { &*t };
let qos = tt.qos.lock().map(|g| g.clone()).unwrap_or_default();
unsafe { crate::qos_ffi::topic_qos_to_c(&qos, out) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn zerodds_topic_set_qos(
t: *mut ZeroDdsTopic,
qos: *const crate::qos_ffi::ZeroDdsTopicQos,
) -> c_int {
if t.is_null() {
return ZeroDdsStatus::BadHandle as c_int;
}
let tt = unsafe { &*t };
let new_qos = if qos.is_null() {
zerodds_dcps::qos::TopicQos::default()
} else {
unsafe { crate::qos_ffi::topic_qos_from_c(qos) }
};
if let Ok(mut g) = tt.qos.lock() {
*g = new_qos;
}
ZeroDdsStatus::Ok as c_int
}
#[repr(C)]
#[derive(Debug, Default, Clone, Copy)]
pub struct ZeroDdsInconsistentTopicStatus {
pub total_count: i32,
pub total_count_change: i32,
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn zerodds_topic_get_inconsistent_topic_status(
t: *mut ZeroDdsTopic,
out: *mut ZeroDdsInconsistentTopicStatus,
) -> c_int {
if t.is_null() || out.is_null() {
return ZeroDdsStatus::BadParameter as c_int;
}
unsafe {
*out = ZeroDdsInconsistentTopicStatus::default();
}
ZeroDdsStatus::Ok as c_int
}
#[cfg(test)]
#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
mod tests {
use super::*;
use crate::factory_ffi::{
zerodds_dpf_create_participant, zerodds_dpf_delete_participant, zerodds_dpf_get_instance,
};
use crate::participant_ffi::{
zerodds_dp_create_topic, zerodds_dp_delete_contained_entities, zerodds_dp_delete_topic,
};
use std::ffi::CStr;
fn mk_participant(domain: u32) -> *mut ZeroDdsDomainParticipant {
let f = zerodds_dpf_get_instance();
unsafe { zerodds_dpf_create_participant(f, domain, ptr::null()) }
}
#[test]
fn topic_get_name_and_type_roundtrip() {
let p = mk_participant(31);
let n = c"Hello";
let tn = c"WorldType";
let t = unsafe { zerodds_dp_create_topic(p, n.as_ptr(), tn.as_ptr(), ptr::null()) };
assert!(!t.is_null());
let raw_n = unsafe { zerodds_topic_get_name(t) };
assert!(!raw_n.is_null());
let s_n = unsafe { CStr::from_ptr(raw_n) }.to_str().unwrap();
assert_eq!(s_n, "Hello");
unsafe { zerodds_string_free(raw_n) };
let raw_tn = unsafe { zerodds_topic_get_type_name(t) };
let s_tn = unsafe { CStr::from_ptr(raw_tn) }.to_str().unwrap();
assert_eq!(s_tn, "WorldType");
unsafe { zerodds_string_free(raw_tn) };
assert_eq!(unsafe { zerodds_topic_get_participant(t) }, p);
let _ = unsafe { zerodds_dp_delete_topic(p, t) };
unsafe { zerodds_dp_delete_contained_entities(p) };
let f = zerodds_dpf_get_instance();
let _ = unsafe { zerodds_dpf_delete_participant(f, p) };
}
#[test]
fn inconsistent_topic_status_default() {
let p = mk_participant(32);
let n = c"T";
let tn = c"TT";
let t = unsafe { zerodds_dp_create_topic(p, n.as_ptr(), tn.as_ptr(), ptr::null()) };
let mut s = ZeroDdsInconsistentTopicStatus::default();
let rc = unsafe { zerodds_topic_get_inconsistent_topic_status(t, &mut s) };
assert_eq!(rc, ZeroDdsStatus::Ok as c_int);
assert_eq!(s.total_count, 0);
let _ = unsafe { zerodds_dp_delete_topic(p, t) };
unsafe { zerodds_dp_delete_contained_entities(p) };
let f = zerodds_dpf_get_instance();
let _ = unsafe { zerodds_dpf_delete_participant(f, p) };
}
}