iceoryx2_ffi/api/
service_builder.rs

1// Copyright (c) 2024 Contributors to the Eclipse Foundation
2//
3// See the NOTICE file(s) distributed with this work for additional
4// information regarding copyright ownership.
5//
6// This program and the accompanying materials are made available under the
7// terms of the Apache Software License 2.0 which is available at
8// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
9// which is available at https://opensource.org/licenses/MIT.
10//
11// SPDX-License-Identifier: Apache-2.0 OR MIT
12
13#![allow(non_camel_case_types)]
14
15use crate::api::{iox2_service_type_e, AssertNonNullHandle, HandleToType};
16
17use iceoryx2::prelude::*;
18use iceoryx2::service::builder::publish_subscribe::CustomHeaderMarker;
19use iceoryx2::service::builder::{
20    event::Builder as ServiceBuilderEvent, publish_subscribe::Builder as ServiceBuilderPubSub,
21    Builder as ServiceBuilderBase,
22};
23use iceoryx2_bb_elementary::static_assert::*;
24use iceoryx2_ffi_macros::iceoryx2_ffi;
25
26use core::mem::ManuallyDrop;
27use core::mem::MaybeUninit;
28
29// BEGIN types definition
30
31pub(super) type UserHeaderFfi = CustomHeaderMarker;
32pub(super) type PayloadFfi = [u8];
33pub(super) type UninitPayloadFfi = [MaybeUninit<u8>];
34
35pub(super) union ServiceBuilderUnionNested<S: Service> {
36    pub(super) base: ManuallyDrop<ServiceBuilderBase<S>>,
37    pub(super) event: ManuallyDrop<ServiceBuilderEvent<S>>,
38    pub(super) pub_sub: ManuallyDrop<ServiceBuilderPubSub<PayloadFfi, UserHeaderFfi, S>>,
39}
40
41pub(super) union ServiceBuilderUnion {
42    pub(super) ipc: ManuallyDrop<ServiceBuilderUnionNested<ipc::Service>>,
43    pub(super) local: ManuallyDrop<ServiceBuilderUnionNested<local::Service>>,
44}
45
46impl ServiceBuilderUnion {
47    pub(super) fn new_ipc_base(service_builder: ServiceBuilderBase<ipc::Service>) -> Self {
48        Self {
49            ipc: ManuallyDrop::new(ServiceBuilderUnionNested::<ipc::Service> {
50                base: ManuallyDrop::new(service_builder),
51            }),
52        }
53    }
54
55    pub(super) fn new_ipc_event(service_builder: ServiceBuilderEvent<ipc::Service>) -> Self {
56        Self {
57            ipc: ManuallyDrop::new(ServiceBuilderUnionNested::<ipc::Service> {
58                event: ManuallyDrop::new(service_builder),
59            }),
60        }
61    }
62
63    pub(super) fn new_ipc_pub_sub(
64        service_builder: ServiceBuilderPubSub<PayloadFfi, UserHeaderFfi, ipc::Service>,
65    ) -> Self {
66        Self {
67            ipc: ManuallyDrop::new(ServiceBuilderUnionNested::<ipc::Service> {
68                pub_sub: ManuallyDrop::new(service_builder),
69            }),
70        }
71    }
72
73    pub(super) fn new_local_base(service_builder: ServiceBuilderBase<local::Service>) -> Self {
74        Self {
75            local: ManuallyDrop::new(ServiceBuilderUnionNested::<local::Service> {
76                base: ManuallyDrop::new(service_builder),
77            }),
78        }
79    }
80
81    pub(super) fn new_local_event(service_builder: ServiceBuilderEvent<local::Service>) -> Self {
82        Self {
83            local: ManuallyDrop::new(ServiceBuilderUnionNested::<local::Service> {
84                event: ManuallyDrop::new(service_builder),
85            }),
86        }
87    }
88
89    pub(super) fn new_local_pub_sub(
90        service_builder: ServiceBuilderPubSub<PayloadFfi, UserHeaderFfi, local::Service>,
91    ) -> Self {
92        Self {
93            local: ManuallyDrop::new(ServiceBuilderUnionNested::<local::Service> {
94                pub_sub: ManuallyDrop::new(service_builder),
95            }),
96        }
97    }
98}
99
100#[repr(C)]
101#[repr(align(8))] // alignment of Option<ServiceBuilderUnion>
102pub struct iox2_service_builder_storage_t {
103    internal: [u8; 464], // magic number obtained with size_of::<Option<ServiceBuilderUnion>>()
104}
105
106#[repr(C)]
107#[iceoryx2_ffi(ServiceBuilderUnion)]
108pub struct iox2_service_builder_t {
109    pub(super) service_type: iox2_service_type_e,
110    pub(super) value: iox2_service_builder_storage_t,
111    pub(super) deleter: fn(*mut iox2_service_builder_t),
112}
113
114impl iox2_service_builder_t {
115    pub(super) fn init(
116        &mut self,
117        service_type: iox2_service_type_e,
118        value: ServiceBuilderUnion,
119        deleter: fn(*mut iox2_service_builder_t),
120    ) {
121        self.service_type = service_type;
122        self.value.init(value);
123        self.deleter = deleter;
124    }
125}
126
127pub struct iox2_service_builder_h_t;
128/// The owning handle for `iox2_service_builder_t`. Passing the handle to an function transfers the ownership.
129pub type iox2_service_builder_h = *mut iox2_service_builder_h_t;
130/// The non-owning handle for `iox2_service_builder_t`. Passing the handle to an function does not transfers the ownership.
131pub type iox2_service_builder_h_ref = *const iox2_service_builder_h;
132
133pub struct iox2_service_builder_event_h_t;
134/// The owning handle for `iox2_service_builder_t` which is already configured as event. Passing the handle to an function transfers the ownership.
135pub type iox2_service_builder_event_h = *mut iox2_service_builder_event_h_t;
136/// The non-owning handle for `iox2_service_builder_t` which is already configured as event. Passing the handle to an function does not transfers the ownership.
137pub type iox2_service_builder_event_h_ref = *const iox2_service_builder_event_h;
138
139pub struct iox2_service_builder_pub_sub_h_t;
140/// The owning handle for `iox2_service_builder_t` which is already configured as event. Passing the handle to an function transfers the ownership.
141pub type iox2_service_builder_pub_sub_h = *mut iox2_service_builder_pub_sub_h_t;
142/// The non-owning handle for `iox2_service_builder_t` which is already configured as event. Passing the handle to an function does not transfers the ownership.
143pub type iox2_service_builder_pub_sub_h_ref = *const iox2_service_builder_pub_sub_h;
144
145impl AssertNonNullHandle for iox2_service_builder_event_h {
146    fn assert_non_null(self) {
147        debug_assert!(!self.is_null());
148    }
149}
150
151impl AssertNonNullHandle for iox2_service_builder_event_h_ref {
152    fn assert_non_null(self) {
153        debug_assert!(!self.is_null());
154        unsafe {
155            debug_assert!(!(*self).is_null());
156        }
157    }
158}
159
160impl AssertNonNullHandle for iox2_service_builder_pub_sub_h {
161    fn assert_non_null(self) {
162        debug_assert!(!self.is_null());
163    }
164}
165
166impl AssertNonNullHandle for iox2_service_builder_pub_sub_h_ref {
167    fn assert_non_null(self) {
168        debug_assert!(!self.is_null());
169        unsafe {
170            debug_assert!(!(*self).is_null());
171        }
172    }
173}
174
175impl HandleToType for iox2_service_builder_h {
176    type Target = *mut iox2_service_builder_t;
177
178    fn as_type(self) -> Self::Target {
179        self as *mut _ as _
180    }
181}
182
183impl HandleToType for iox2_service_builder_h_ref {
184    type Target = *mut iox2_service_builder_t;
185
186    fn as_type(self) -> Self::Target {
187        unsafe { *self as *mut _ as _ }
188    }
189}
190
191impl HandleToType for iox2_service_builder_event_h {
192    type Target = *mut iox2_service_builder_t;
193
194    fn as_type(self) -> Self::Target {
195        self as *mut _ as _
196    }
197}
198
199impl HandleToType for iox2_service_builder_event_h_ref {
200    type Target = *mut iox2_service_builder_t;
201
202    fn as_type(self) -> Self::Target {
203        unsafe { *self as *mut _ as _ }
204    }
205}
206
207impl HandleToType for iox2_service_builder_pub_sub_h {
208    type Target = *mut iox2_service_builder_t;
209
210    fn as_type(self) -> Self::Target {
211        self as *mut _ as _
212    }
213}
214
215impl HandleToType for iox2_service_builder_pub_sub_h_ref {
216    type Target = *mut iox2_service_builder_t;
217
218    fn as_type(self) -> Self::Target {
219        unsafe { *self as *mut _ as _ }
220    }
221}
222
223// END type definition
224
225// BEGIN C API
226
227/// This function transform the [`iox2_service_builder_h`] to an event service builder.
228///
229/// # Arguments
230///
231/// * `service_builder_handle` - Must be a valid [`iox2_service_builder_event_h`] obtained by [`iox2_node_service_builder`](crate::iox2_node_service_builder)
232///
233/// Returns a [`iox2_service_builder_event_h`] for the event service builder
234///
235/// # Safety
236///
237/// * The `service_builder_handle` is invalid after this call; The corresponding `iox2_service_builder_t` is now owned by the returned handle.
238#[no_mangle]
239pub unsafe extern "C" fn iox2_service_builder_event(
240    service_builder_handle: iox2_service_builder_h,
241) -> iox2_service_builder_event_h {
242    debug_assert!(!service_builder_handle.is_null());
243
244    let service_builders_struct = unsafe { &mut *service_builder_handle.as_type() };
245
246    match service_builders_struct.service_type {
247        iox2_service_type_e::IPC => {
248            let service_builder =
249                ManuallyDrop::take(&mut service_builders_struct.value.as_mut().ipc);
250
251            let service_builder = ManuallyDrop::into_inner(service_builder.base);
252            service_builders_struct
253                .set(ServiceBuilderUnion::new_ipc_event(service_builder.event()));
254        }
255        iox2_service_type_e::LOCAL => {
256            let service_builder =
257                ManuallyDrop::take(&mut service_builders_struct.value.as_mut().local);
258
259            let service_builder = ManuallyDrop::into_inner(service_builder.base);
260            service_builders_struct.set(ServiceBuilderUnion::new_local_event(
261                service_builder.event(),
262            ));
263        }
264    }
265
266    service_builder_handle as *mut _ as _
267}
268
269/// This function transform the [`iox2_service_builder_h`] to a publish-subscribe service builder.
270///
271/// # Arguments
272///
273/// * `service_builder_handle` - Must be a valid [`iox2_service_builder_pub_sub_h`] obtained by [`iox2_node_service_builder`](crate::iox2_node_service_builder)
274///
275/// Returns a [`iox2_service_builder_pub_sub_h`] for the publish-subscribe service builder
276///
277/// # Safety
278///
279/// * The `service_builder_handle` is invalid after this call; The corresponding `iox2_service_builder_t` is now owned by the returned handle.
280#[no_mangle]
281pub unsafe extern "C" fn iox2_service_builder_pub_sub(
282    service_builder_handle: iox2_service_builder_h,
283) -> iox2_service_builder_pub_sub_h {
284    debug_assert!(!service_builder_handle.is_null());
285
286    let service_builders_struct = unsafe { &mut *service_builder_handle.as_type() };
287
288    match service_builders_struct.service_type {
289        iox2_service_type_e::IPC => {
290            let service_builder =
291                ManuallyDrop::take(&mut service_builders_struct.value.as_mut().ipc);
292
293            let service_builder = ManuallyDrop::into_inner(service_builder.base);
294            service_builders_struct.set(ServiceBuilderUnion::new_ipc_pub_sub(
295                service_builder
296                    .publish_subscribe::<PayloadFfi>()
297                    .user_header::<UserHeaderFfi>(),
298            ));
299        }
300        iox2_service_type_e::LOCAL => {
301            let service_builder =
302                ManuallyDrop::take(&mut service_builders_struct.value.as_mut().local);
303
304            let service_builder = ManuallyDrop::into_inner(service_builder.base);
305            service_builders_struct.set(ServiceBuilderUnion::new_local_pub_sub(
306                service_builder
307                    .publish_subscribe::<PayloadFfi>()
308                    .user_header::<UserHeaderFfi>(),
309            ));
310        }
311    }
312
313    service_builder_handle as *mut _ as _
314}
315
316// END C API