use std::ffi::CStr;
use std::os::raw::c_char;
use std::ptr;
use std::sync::Arc;
use hdds::api::{Participant, Publisher, QoS, Subscriber};
use super::{BytePayload, HddsDataReader, HddsDataWriter, HddsParticipant, HddsQoS};
#[repr(C)]
pub struct HddsPublisher {
_private: [u8; 0],
}
#[repr(C)]
pub struct HddsSubscriber {
_private: [u8; 0],
}
#[no_mangle]
pub unsafe extern "C" fn hdds_publisher_create(
participant: *mut HddsParticipant,
) -> *mut HddsPublisher {
hdds_publisher_create_with_qos(participant, ptr::null())
}
#[no_mangle]
pub unsafe extern "C" fn hdds_publisher_create_with_qos(
participant: *mut HddsParticipant,
qos: *const HddsQoS,
) -> *mut HddsPublisher {
if participant.is_null() {
return ptr::null_mut();
}
let participant_ref = &*participant.cast::<Arc<Participant>>();
let qos_value = if qos.is_null() {
QoS::default()
} else {
(*qos.cast::<QoS>()).clone()
};
match participant_ref.create_publisher(qos_value) {
Ok(publisher) => Box::into_raw(Box::new(publisher)).cast::<HddsPublisher>(),
Err(e) => {
log::error!("Failed to create publisher: {:?}", e);
ptr::null_mut()
}
}
}
#[no_mangle]
pub unsafe extern "C" fn hdds_publisher_destroy(publisher: *mut HddsPublisher) {
if !publisher.is_null() {
let _ = Box::from_raw(publisher.cast::<Publisher>());
}
}
#[no_mangle]
pub unsafe extern "C" fn hdds_subscriber_create(
participant: *mut HddsParticipant,
) -> *mut HddsSubscriber {
hdds_subscriber_create_with_qos(participant, ptr::null())
}
#[no_mangle]
pub unsafe extern "C" fn hdds_subscriber_create_with_qos(
participant: *mut HddsParticipant,
qos: *const HddsQoS,
) -> *mut HddsSubscriber {
if participant.is_null() {
return ptr::null_mut();
}
let participant_ref = &*participant.cast::<Arc<Participant>>();
let qos_value = if qos.is_null() {
QoS::default()
} else {
(*qos.cast::<QoS>()).clone()
};
match participant_ref.create_subscriber(qos_value) {
Ok(subscriber) => Box::into_raw(Box::new(subscriber)).cast::<HddsSubscriber>(),
Err(e) => {
log::error!("Failed to create subscriber: {:?}", e);
ptr::null_mut()
}
}
}
#[no_mangle]
pub unsafe extern "C" fn hdds_subscriber_destroy(subscriber: *mut HddsSubscriber) {
if !subscriber.is_null() {
let _ = Box::from_raw(subscriber.cast::<Subscriber>());
}
}
#[no_mangle]
pub unsafe extern "C" fn hdds_publisher_create_writer(
publisher: *mut HddsPublisher,
topic_name: *const c_char,
) -> *mut HddsDataWriter {
hdds_publisher_create_writer_with_qos(publisher, topic_name, ptr::null())
}
#[no_mangle]
pub unsafe extern "C" fn hdds_publisher_create_writer_with_qos(
publisher: *mut HddsPublisher,
topic_name: *const c_char,
qos: *const HddsQoS,
) -> *mut HddsDataWriter {
if publisher.is_null() || topic_name.is_null() {
return ptr::null_mut();
}
let Ok(topic_str) = CStr::from_ptr(topic_name).to_str() else {
return ptr::null_mut();
};
let publisher_ref = &*publisher.cast::<Publisher>();
let qos_value = if qos.is_null() {
QoS::default()
} else {
(*qos.cast::<QoS>()).clone()
};
let Some(participant) = publisher_ref.participant() else {
log::error!("Publisher has no parent participant");
return ptr::null_mut();
};
match participant
.topic::<BytePayload>(topic_str)
.and_then(|t| t.writer().qos(qos_value).build())
{
Ok(writer) => Box::into_raw(Box::new(writer)).cast::<HddsDataWriter>(),
Err(e) => {
log::error!("Failed to create writer from publisher: {:?}", e);
ptr::null_mut()
}
}
}
#[no_mangle]
pub unsafe extern "C" fn hdds_subscriber_create_reader(
subscriber: *mut HddsSubscriber,
topic_name: *const c_char,
) -> *mut HddsDataReader {
hdds_subscriber_create_reader_with_qos(subscriber, topic_name, ptr::null())
}
#[no_mangle]
pub unsafe extern "C" fn hdds_subscriber_create_reader_with_qos(
subscriber: *mut HddsSubscriber,
topic_name: *const c_char,
qos: *const HddsQoS,
) -> *mut HddsDataReader {
if subscriber.is_null() || topic_name.is_null() {
return ptr::null_mut();
}
let Ok(topic_str) = CStr::from_ptr(topic_name).to_str() else {
return ptr::null_mut();
};
let subscriber_ref = &*subscriber.cast::<Subscriber>();
let qos_value = if qos.is_null() {
QoS::default()
} else {
(*qos.cast::<QoS>()).clone()
};
let Some(participant) = subscriber_ref.participant() else {
log::error!("Subscriber has no parent participant");
return ptr::null_mut();
};
match participant
.topic::<BytePayload>(topic_str)
.and_then(|t| t.reader().qos(qos_value).build())
{
Ok(reader) => Box::into_raw(Box::new(reader)).cast::<HddsDataReader>(),
Err(e) => {
log::error!("Failed to create reader from subscriber: {:?}", e);
ptr::null_mut()
}
}
}