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