Skip to main content

cyclonedds_rust_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4#![allow(dead_code)]
5#![allow(deref_nullptr)]
6#![allow(clippy::all)]
7#![allow(clippy::missing_safety_doc)]
8#![allow(missing_docs)]
9#![allow(rustdoc::broken_intra_doc_links)]
10#![allow(rustdoc::invalid_html_tags)]
11
12use std::sync::atomic::{AtomicU32, Ordering};
13
14pub use bindings::*;
15mod bindings {
16    use super::{ddsrt_atomic_uint32_t, ddsrt_byte_order_selector, ddsrt_hh, ddsrt_mtime_t};
17
18    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
19}
20
21pub type ddsrt_hh_hash_fn =
22    ::std::option::Option<unsafe extern "C" fn(a: *const ::std::ffi::c_void) -> u32>;
23pub type ddsrt_hh_equals_fn = ::std::option::Option<
24    unsafe extern "C" fn(a: *const ::std::ffi::c_void, b: *const ::std::ffi::c_void) -> bool,
25>;
26pub type ddsrt_hh_buckets_gc_fn = ::std::option::Option<
27    unsafe extern "C" fn(bs: *mut ::std::ffi::c_void, arg: *mut ::std::ffi::c_void),
28>;
29
30#[repr(C)]
31#[derive(Debug, Copy, Clone)]
32pub struct ddsrt_hh_bucket {
33    pub hopinfo: u32,
34    pub data: *mut ::std::ffi::c_void,
35}
36
37#[repr(C)]
38#[derive(Debug, Copy, Clone)]
39pub struct ddsrt_hh {
40    pub size: u32,
41    pub buckets: *mut ddsrt_hh_bucket,
42    pub hash: ddsrt_hh_hash_fn,
43    pub equals: ddsrt_hh_equals_fn,
44}
45
46#[repr(C)]
47#[derive(Debug, Copy, Clone)]
48pub struct ddsrt_hh_iter {
49    pub hh: *mut ddsrt_hh,
50    pub cursor: u32,
51}
52
53pub type ddsrt_byte_order_selector = ::std::ffi::c_uint;
54pub const DDSRT_BOSEL_NATIVE: ddsrt_byte_order_selector = 0;
55pub const DDSRT_BOSEL_BE: ddsrt_byte_order_selector = 1;
56pub const DDSRT_BOSEL_LE: ddsrt_byte_order_selector = 2;
57
58#[repr(C)]
59#[derive(Debug, Default, Copy, Clone)]
60pub struct ddsrt_atomic_uint32_t {
61    pub v: u32,
62}
63
64#[repr(C)]
65#[derive(Debug, Default, Copy, Clone)]
66pub struct ddsrt_mtime_t {
67    pub v: dds_time_t,
68}
69
70#[inline]
71pub const fn dds_err_nr(err: dds_return_t) -> dds_return_t {
72    err
73}
74
75#[inline]
76pub const fn dds_err_line(_err: dds_return_t) -> u32 {
77    0
78}
79
80#[inline]
81pub const fn dds_err_file_id(_err: dds_return_t) -> u32 {
82    0
83}
84
85// NOTE: dds_loaned_sample and dds_rhc are opaque types in the Windows bindings
86// (only _address field visible). These helpers are only available when the
87// bindings expose the full struct layout (e.g., on macOS/Linux).
88// They are not used by the cyclonedds crate directly.
89
90#[cfg(feature = "internal-ops")]
91#[inline]
92pub unsafe fn dds_loaned_sample_ref(loaned_sample: *mut dds_loaned_sample_t) {
93    let refc = &(*loaned_sample).refc as *const ddsrt_atomic_uint32_t as *const AtomicU32;
94    (*refc).fetch_add(1, Ordering::SeqCst);
95}
96
97#[cfg(feature = "internal-ops")]
98#[inline]
99pub unsafe fn dds_loaned_sample_unref(loaned_sample: *mut dds_loaned_sample_t) {
100    let refc = &(*loaned_sample).refc as *const ddsrt_atomic_uint32_t as *const AtomicU32;
101    if (*refc).fetch_sub(1, Ordering::SeqCst) == 1 {
102        if let Some(free_fn) = (*loaned_sample).ops.free {
103            free_fn(loaned_sample);
104        }
105    }
106}
107
108#[cfg(feature = "internal-ops")]
109#[inline]
110pub unsafe fn dds_rhc_associate(rhc: *mut dds_rhc, reader: *mut dds_reader) -> dds_return_t {
111    ((*(*rhc).common.ops)
112        .associate
113        .expect("dds_rhc associate op"))(rhc, reader)
114}
115
116#[cfg(feature = "internal-ops")]
117#[inline]
118pub unsafe fn dds_rhc_store(
119    rhc: *mut dds_rhc,
120    wrinfo: *const ddsi_writer_info,
121    sample: *mut ddsi_serdata,
122    tk: *mut ddsi_tkmap_instance,
123) -> bool {
124    ((*(*rhc).common.ops)
125        .rhc_ops
126        .store
127        .expect("dds_rhc store op"))(
128        std::ptr::addr_of_mut!((*rhc).common.rhc),
129        wrinfo,
130        sample,
131        tk,
132    )
133}
134
135#[cfg(feature = "internal-ops")]
136#[inline]
137pub unsafe fn dds_rhc_unregister_wr(rhc: *mut dds_rhc, wrinfo: *const ddsi_writer_info) {
138    ((*(*rhc).common.ops)
139        .rhc_ops
140        .unregister_wr
141        .expect("dds_rhc unregister_wr op"))(std::ptr::addr_of_mut!((*rhc).common.rhc), wrinfo)
142}
143
144#[cfg(feature = "internal-ops")]
145#[inline]
146pub unsafe fn dds_rhc_relinquish_ownership(rhc: *mut dds_rhc, wr_iid: u64) {
147    ((*(*rhc).common.ops)
148        .rhc_ops
149        .relinquish_ownership
150        .expect("dds_rhc relinquish_ownership op"))(
151        std::ptr::addr_of_mut!((*rhc).common.rhc),
152        wr_iid,
153    )
154}
155
156#[cfg(feature = "internal-ops")]
157#[inline]
158pub unsafe fn dds_rhc_free(rhc: *mut dds_rhc) {
159    ((*(*rhc).common.ops).rhc_ops.free.expect("dds_rhc free op"))(std::ptr::addr_of_mut!(
160        (*rhc).common.rhc
161    ))
162}
163
164#[cfg(feature = "internal-ops")]
165#[inline]
166pub unsafe fn dds_rhc_peek(
167    rhc: *mut dds_rhc,
168    max_samples: i32,
169    mask: u32,
170    handle: dds_instance_handle_t,
171    cond: *mut dds_readcond,
172    collect_sample: dds_read_with_collector_fn_t,
173    collect_sample_arg: *mut ::std::ffi::c_void,
174) -> i32 {
175    ((*(*rhc).common.ops).peek.expect("dds_rhc peek op"))(
176        rhc,
177        max_samples,
178        mask,
179        handle,
180        cond,
181        collect_sample,
182        collect_sample_arg,
183    )
184}
185
186#[cfg(feature = "internal-ops")]
187#[inline]
188pub unsafe fn dds_rhc_read(
189    rhc: *mut dds_rhc,
190    max_samples: i32,
191    mask: u32,
192    handle: dds_instance_handle_t,
193    cond: *mut dds_readcond,
194    collect_sample: dds_read_with_collector_fn_t,
195    collect_sample_arg: *mut ::std::ffi::c_void,
196) -> i32 {
197    ((*(*rhc).common.ops).read.expect("dds_rhc read op"))(
198        rhc,
199        max_samples,
200        mask,
201        handle,
202        cond,
203        collect_sample,
204        collect_sample_arg,
205    )
206}
207
208#[cfg(feature = "internal-ops")]
209#[inline]
210pub unsafe fn dds_rhc_take(
211    rhc: *mut dds_rhc,
212    max_samples: i32,
213    mask: u32,
214    handle: dds_instance_handle_t,
215    cond: *mut dds_readcond,
216    collect_sample: dds_read_with_collector_fn_t,
217    collect_sample_arg: *mut ::std::ffi::c_void,
218) -> i32 {
219    ((*(*rhc).common.ops).take.expect("dds_rhc take op"))(
220        rhc,
221        max_samples,
222        mask,
223        handle,
224        cond,
225        collect_sample,
226        collect_sample_arg,
227    )
228}
229
230#[cfg(feature = "internal-ops")]
231#[inline]
232pub unsafe fn dds_rhc_add_readcondition(rhc: *mut dds_rhc, cond: *mut dds_readcond) -> bool {
233    ((*(*rhc).common.ops)
234        .add_readcondition
235        .expect("dds_rhc add_readcondition op"))(rhc, cond)
236}
237
238#[cfg(feature = "internal-ops")]
239#[inline]
240pub unsafe fn dds_rhc_remove_readcondition(rhc: *mut dds_rhc, cond: *mut dds_readcond) {
241    ((*(*rhc).common.ops)
242        .remove_readcondition
243        .expect("dds_rhc remove_readcondition op"))(rhc, cond)
244}
245
246unsafe extern "C" {
247    pub fn ddsi_sertype_ref(tp: *const ddsi_sertype) -> *mut ddsi_sertype;
248    pub fn ddsi_sertype_unref(tp: *mut ddsi_sertype);
249    pub fn ddsi_sertype_equal(a: *const ddsi_sertype, b: *const ddsi_sertype) -> bool;
250    pub fn ddsi_sertype_hash(tp: *const ddsi_sertype) -> u32;
251}
252
253// ── ddsi_serdata vtable helpers ──
254//
255// The C headers define these as inline functions that dereference the serdata
256// ops vtable.  Since bindgen produces an opaque `ddsi_serdata` struct, we
257// re-implement them here by calling through the exported (non-inline)
258// vtable-based helper, or – where that is not available – by reconstructing
259// the offset arithmetic ourselves.
260//
261// The layout of `struct ddsi_serdata` (from ddsi_serdata.h):
262//   offset 0:  ops    : *const ddsi_serdata_ops
263//   offset 8:  hash   : u32
264//   offset 12: refc   : ddsrt_atomic_uint32_t  (u32)
265//   offset 16: kind   : c_int
266//   offset 24: type   : *const ddsi_sertype
267//   offset 32: timestamp
268//   offset 40: statusinfo
269//   ...
270//   offset 56: loan   : *mut dds_loaned_sample
271//
272// The vtable (`ddsi_serdata_ops`, from ddsi_serdata.h):
273//   offset 0:   eqkey
274//   offset 8:   get_size
275//   offset 16:  from_ser
276//   offset 24:  from_ser_iov
277//   offset 32:  from_keyhash
278//   offset 40:  from_sample
279//   offset 48:  to_ser
280//   offset 56:  to_ser_ref
281//   offset 64:  to_ser_unref
282//   offset 72:  to_sample
283//   offset 80:  to_untyped
284//   offset 88:  untyped_to_sample
285//   offset 96:  free
286//   ...
287
288/// Increment the reference count of a serdata, returning the same pointer.
289///
290/// # Safety
291/// `d` must be a valid, non-null `ddsi_serdata` pointer.
292#[inline]
293pub unsafe fn ddsi_serdata_ref(d: *const ddsi_serdata) -> *mut ddsi_serdata {
294    // refc is at offset 12 on 64-bit (after ops:8, hash:4)
295    let refc_ptr = (d as *const u8).add(12) as *const AtomicU32;
296    (*refc_ptr).fetch_add(1, Ordering::SeqCst);
297    d as *mut ddsi_serdata
298}
299
300/// Decrement the reference count; free the serdata when it drops to zero.
301///
302/// # Safety
303/// `d` must be a valid, non-null `ddsi_serdata` pointer that the caller
304/// currently holds a reference to.
305#[inline]
306pub unsafe fn ddsi_serdata_unref(d: *mut ddsi_serdata) {
307    // refc at offset 12
308    let refc_ptr = (d as *const u8).add(12) as *const AtomicU32;
309    if (*refc_ptr).fetch_sub(1, Ordering::SeqCst) == 1 {
310        // ops at offset 0; free is at offset 96 in the vtable
311        let ops = *(d as *const *const u8);
312        let free_fn: unsafe extern "C" fn(*mut ddsi_serdata) =
313            ::std::mem::transmute(*(ops as *const u8).add(96) as *const ::std::ffi::c_void);
314        free_fn(d);
315    }
316}
317
318/// Return the serialized size (in bytes) of a serdata.
319///
320/// # Safety
321/// `d` must be a valid, non-null `ddsi_serdata` pointer.
322#[inline]
323pub unsafe fn ddsi_serdata_size(d: *const ddsi_serdata) -> u32 {
324    let ops = *(d as *const *const u8);
325    let get_size: unsafe extern "C" fn(*const ddsi_serdata) -> u32 =
326        ::std::mem::transmute(*(ops as *const u8).add(8) as *const ::std::ffi::c_void);
327    get_size(d)
328}
329
330/// Copy serialized bytes from a serdata into the provided buffer.
331///
332/// # Safety
333/// `d` must be a valid, non-null `ddsi_serdata` pointer.
334/// `buf` must point to a buffer of at least `sz` bytes.
335#[inline]
336pub unsafe fn ddsi_serdata_to_ser(d: *const ddsi_serdata, off: usize, sz: usize, buf: *mut ::std::ffi::c_void) {
337    let ops = *(d as *const *const u8);
338    let to_ser: unsafe extern "C" fn(*const ddsi_serdata, usize, usize, *mut ::std::ffi::c_void) =
339        ::std::mem::transmute(*(ops as *const u8).add(48) as *const ::std::ffi::c_void);
340    to_ser(d, off, sz, buf);
341}
342
343pub type ddsi_typeid_kind_t = ::std::ffi::c_int;
344pub const DDSI_TYPEID_KIND_MINIMAL: ddsi_typeid_kind_t = 0;
345pub const DDSI_TYPEID_KIND_COMPLETE: ddsi_typeid_kind_t = 1;
346pub const DDSI_TYPEID_KIND_PLAIN_COLLECTION_MINIMAL: ddsi_typeid_kind_t = 2;
347pub const DDSI_TYPEID_KIND_PLAIN_COLLECTION_COMPLETE: ddsi_typeid_kind_t = 3;
348pub const DDSI_TYPEID_KIND_FULLY_DESCRIPTIVE: ddsi_typeid_kind_t = 4;
349pub const DDSI_TYPEID_KIND_INVALID: ddsi_typeid_kind_t = 5;
350
351unsafe extern "C" {
352    pub fn ddsi_typeinfo_minimal_typeid(typeinfo: *const dds_typeinfo_t) -> *const dds_typeid_t;
353    pub fn ddsi_typeinfo_complete_typeid(typeinfo: *const dds_typeinfo_t) -> *const dds_typeid_t;
354    pub fn ddsi_typeinfo_present(typeinfo: *const dds_typeinfo_t) -> bool;
355    pub fn ddsi_typeinfo_valid(typeinfo: *const dds_typeinfo_t) -> bool;
356    pub fn ddsi_typeid_compare(a: *const dds_typeid_t, b: *const dds_typeid_t)
357        -> ::std::ffi::c_int;
358    pub fn ddsi_typeid_is_none(type_id: *const dds_typeid_t) -> bool;
359    pub fn ddsi_typeid_is_hash(type_id: *const dds_typeid_t) -> bool;
360    pub fn ddsi_typeid_is_minimal(type_id: *const dds_typeid_t) -> bool;
361    pub fn ddsi_typeid_is_complete(type_id: *const dds_typeid_t) -> bool;
362    pub fn ddsi_typeid_is_fully_descriptive(type_id: *const dds_typeid_t) -> bool;
363    pub fn ddsi_typeid_kind(type_id: *const dds_typeid_t) -> ddsi_typeid_kind_t;
364    pub fn ddsi_typeid_dup(src: *const dds_typeid_t) -> *mut dds_typeid_t;
365    pub fn ddsi_typeid_fini(type_id: *mut dds_typeid_t);
366}
367
368pub type DDS_XTypes_EquivalenceHash = [u8; 14];
369
370#[repr(C)]
371#[derive(Debug, Copy, Clone)]
372pub struct ddsi_typeid_str {
373    pub str_: [::std::ffi::c_char; 50usize],
374}
375
376pub type ddsi_type_include_deps_t = ::std::ffi::c_int;
377pub const DDSI_TYPE_IGNORE_DEPS: ddsi_type_include_deps_t = 0;
378pub const DDSI_TYPE_INCLUDE_DEPS: ddsi_type_include_deps_t = 1;
379
380unsafe extern "C" {
381    pub fn ddsi_typeinfo_equal(
382        a: *const dds_typeinfo_t,
383        b: *const dds_typeinfo_t,
384        deps: ddsi_type_include_deps_t,
385    ) -> bool;
386    pub fn ddsi_typeinfo_typeid(
387        type_info: *const dds_typeinfo_t,
388        kind: ddsi_typeid_kind_t,
389    ) -> *mut dds_typeid_t;
390    pub fn ddsi_typeinfo_dup(src: *const dds_typeinfo_t) -> *mut dds_typeinfo_t;
391    pub fn ddsi_typeinfo_free(typeinfo: *mut dds_typeinfo_t);
392    pub fn ddsi_make_typeid_str(
393        buf: *mut ddsi_typeid_str,
394        type_id: *const dds_typeid_t,
395    ) -> *mut ::std::ffi::c_char;
396    pub fn ddsi_typeid_get_equivalence_hash(
397        type_id: *const dds_typeid_t,
398        hash: *mut DDS_XTypes_EquivalenceHash,
399    );
400}