Skip to main content

nros_node/executor/
ffi.rs

1//! The executor's FFI surface (phase-515 R9, decision D4).
2//!
3//! Methods that exist for `nros-c` and `nros-cpp` -- the C-shaped entry points
4//! (raw pointers, `extern "C"` callbacks, `unsafe` release paths) and the
5//! plumbing those shims reach into -- are not part of the Rust user API. They
6//! live here, behind a SEALED trait that the shims import and `nros` never
7//! re-exports, so a Rust user neither sees them in the `nros` docs nor can
8//! call them through `nros`. Each one is a crate-private inherent method of
9//! [`Executor`]; this trait forwards to it, and nothing else implements it.
10//!
11//! Stage 2 does the same for the untyped action machinery: every method of
12//! [`ActionServerCore`], [`ActionClientCore`], [`ActionServerRawHandle`] and
13//! [`ActionClientRawHandle`] sits behind its own sealed `*Ffi` trait below. The
14//! types stay public, because the sizes probe and the shims' storage name them.
15//!
16//! Not `#[doc(hidden)]`: that leaves a method callable and semver-visible.
17#![allow(clippy::too_many_arguments, clippy::missing_safety_doc)]
18
19use core::mem::MaybeUninit;
20
21use nros_core::{GoalStatusCode, GoalUuid, Time};
22use nros_rmw::QoSProfile;
23
24use super::{
25    action_core::{PendingCancelRequest, RawGoalRequest},
26    *,
27};
28use crate::{session, timer::TimerDuration};
29
30/// phase-515 R10 stage 2 -- `ParameterServer`'s operations, for the shims
31/// that reach the store through this crate rather than `nros-params`.
32#[cfg(feature = "param-store")]
33pub use nros_params::ParameterServerOps;
34
35mod sealed {
36    pub trait Sealed {}
37}
38impl sealed::Sealed for Executor<'_> {}
39
40/// The executor's FFI entry points, for `nros-c` and `nros-cpp`. Sealed.
41pub trait ExecutorFfi<'s>: sealed::Sealed + Sized {
42    // phase-515 R10 stage 1b -- the per-node parameter forms. The `Node`
43    // that `node_mut(id)` returns carries the user-facing verbs; these are
44    // the shims' node-id-keyed entry points.
45
46    #[cfg(all(feature = "param-store", feature = "alloc"))]
47    /// The FFI entry point; see `Executor::argv_param_overrides_on` in `spin.rs`.
48    #[cfg(feature = "param-store")]
49    fn argv_param_overrides_on(
50        &self,
51        node: super::node_record::NodeId,
52    ) -> impl Iterator<Item = (&str, nros_params::ParameterValue)> + '_;
53
54    #[cfg(all(feature = "param-store", feature = "alloc"))]
55    /// The FFI entry point; see `Executor::for_each_argv_param_override_on` in `spin.rs`.
56    #[cfg(feature = "param-store")]
57    fn for_each_argv_param_override_on(
58        &self,
59        node: super::node_record::NodeId,
60        f: impl FnMut(&str, &nros_params::ParameterValue),
61    ) -> usize;
62
63    /// The FFI entry point; see `Executor::declare_parameter_on` in `spin.rs`.
64    #[cfg(feature = "param-store")]
65    fn declare_parameter_on(
66        &mut self,
67        node: super::node_record::NodeId,
68        name: &str,
69        value: nros_params::ParameterValue,
70    ) -> bool;
71
72    /// The FFI entry point; see `Executor::declare_parameter_on_ref` in `spin.rs`.
73    #[cfg(feature = "param-store")]
74    fn declare_parameter_on_ref(
75        &mut self,
76        node: super::node_record::NodeId,
77        name: &str,
78        value: &nros_params::ParameterValue,
79    ) -> bool;
80
81    /// The FFI entry point; see `Executor::declare_parameter_with_descriptor_on` in `spin.rs`.
82    #[cfg(feature = "param-store")]
83    fn declare_parameter_with_descriptor_on(
84        &mut self,
85        node: super::node_record::NodeId,
86        name: &str,
87        value: nros_params::ParameterValue,
88        descriptor: nros_params::ParameterDescriptor,
89    ) -> bool;
90
91    /// The FFI entry point; see `Executor::set_parameter_on` in `spin.rs`.
92    #[cfg(feature = "param-store")]
93    fn set_parameter_on(
94        &mut self,
95        node: super::node_record::NodeId,
96        name: &str,
97        value: nros_params::ParameterValue,
98    ) -> Result<(), nros_params::ParameterError>;
99
100    /// The FFI entry point; see `Executor::set_parameter_on_ref` in `spin.rs`.
101    #[cfg(feature = "param-store")]
102    fn set_parameter_on_ref(
103        &mut self,
104        node: super::node_record::NodeId,
105        name: &str,
106        value: &nros_params::ParameterValue,
107    ) -> Result<(), nros_params::ParameterError>;
108
109    /// The FFI entry point; see `Executor::set_parameter_local_on` in `spin.rs`.
110    #[cfg(feature = "param-store")]
111    fn set_parameter_local_on(
112        &mut self,
113        node: super::node_record::NodeId,
114        name: &str,
115        value: nros_params::ParameterValue,
116    ) -> Result<(), nros_params::ParameterError>;
117
118    #[cfg(feature = "param-services")]
119    /// The FFI entry point; see `Executor::disable_parameter_events_on` in `spin.rs`.
120    #[cfg(feature = "param-store")]
121    fn disable_parameter_events_on(&mut self, node: super::node_record::NodeId);
122
123    #[cfg(feature = "param-services")]
124    /// The FFI entry point; see `Executor::enable_parameter_events_on` in `spin.rs`.
125    #[cfg(feature = "param-store")]
126    fn enable_parameter_events_on(
127        &mut self,
128        node: super::node_record::NodeId,
129    ) -> Result<(), NodeError>;
130
131    /// The FFI entry point; see `Executor::delete_parameters_on_not_set_on` in `spin.rs`.
132    #[cfg(feature = "param-store")]
133    fn delete_parameters_on_not_set_on(&mut self, node: super::node_record::NodeId, on: bool);
134
135    /// The FFI entry point; see `Executor::allow_undeclared_parameters_on` in `spin.rs`.
136    #[cfg(feature = "param-store")]
137    fn allow_undeclared_parameters_on(&mut self, node: super::node_record::NodeId, allow: bool);
138
139    /// The FFI entry point; see `Executor::get_parameter_on` in `spin.rs`.
140    #[cfg(feature = "param-store")]
141    fn get_parameter_on(
142        &self,
143        node: super::node_record::NodeId,
144        name: &str,
145    ) -> Option<&nros_params::ParameterValue>;
146
147    /// The FFI entry point; see `Executor::parameter_on` in `spin.rs`.
148    #[cfg(feature = "param-store")]
149    fn parameter_on<'a, T: nros_params::ParameterVariant>(
150        &'a mut self,
151        node: super::node_record::NodeId,
152        name: &'a str,
153    ) -> Result<nros_params::ParameterBuilder<'a, 's, T>, NodeError>;
154
155    /// The FFI entry point; see `Executor::set_parameter_description_on` in `spin.rs`.
156    #[cfg(feature = "param-store")]
157    fn set_parameter_description_on(
158        &mut self,
159        node: super::node_record::NodeId,
160        name: &str,
161        description: &str,
162        additional_constraints: &str,
163    ) -> bool;
164
165    /// The FFI entry point; see `Executor::set_parameter_read_only_on` in `spin.rs`.
166    #[cfg(feature = "param-store")]
167    fn set_parameter_read_only_on(
168        &mut self,
169        node: super::node_record::NodeId,
170        name: &str,
171        read_only: bool,
172    ) -> bool;
173
174    /// The FFI entry point; see `Executor::set_parameter_integer_range_on` in `spin.rs`.
175    #[cfg(feature = "param-store")]
176    fn set_parameter_integer_range_on(
177        &mut self,
178        node: super::node_record::NodeId,
179        name: &str,
180        min: i64,
181        max: i64,
182        step: i64,
183    ) -> bool;
184
185    /// The FFI entry point; see `Executor::set_parameter_float_range_on` in `spin.rs`.
186    #[cfg(feature = "param-store")]
187    fn set_parameter_float_range_on(
188        &mut self,
189        node: super::node_record::NodeId,
190        name: &str,
191        min: f64,
192        max: f64,
193        step: f64,
194    ) -> bool;
195
196    /// The FFI entry point; see `Executor::describe_parameter_on` in `spin.rs`.
197    #[cfg(feature = "param-store")]
198    fn describe_parameter_on(
199        &self,
200        node: super::node_record::NodeId,
201        name: &str,
202    ) -> Option<&nros_params::ParameterDescriptor>;
203
204    /// The FFI entry point; see `Executor::get_parameter_type_on` in `spin.rs`.
205    #[cfg(feature = "param-store")]
206    fn get_parameter_type_on(
207        &self,
208        node: super::node_record::NodeId,
209        name: &str,
210    ) -> Option<nros_params::ParameterType>;
211
212    /// The FFI entry point; see `Executor::list_parameters_on` in `spin.rs`.
213    #[cfg(feature = "param-store")]
214    fn list_parameters_on<'p>(
215        &'p self,
216        node: super::node_record::NodeId,
217        prefix: &'p str,
218    ) -> impl Iterator<Item = &'p str>;
219
220    /// The FFI entry point; see `Executor::set_parameters_atomically_on` in `spin.rs`.
221    #[cfg(feature = "param-store")]
222    fn set_parameters_atomically_on<'x, I>(
223        &mut self,
224        node: super::node_record::NodeId,
225        items: I,
226    ) -> Result<(), nros_params::ParameterError>
227    where
228        I: Iterator<Item = Option<(&'x str, nros_params::ParameterValue)>> + Clone;
229
230    /// The FFI entry point; see `Executor::set_parameters_atomically_with_on` in `spin.rs`.
231    #[cfg(feature = "param-store")]
232    fn set_parameters_atomically_with_on<'x>(
233        &mut self,
234        node: super::node_record::NodeId,
235        count: usize,
236        fill: impl FnMut(usize, &mut nros_params::ParameterValue) -> Option<&'x str>,
237    ) -> Result<(), nros_params::ParameterError>;
238
239    /// The FFI entry point; see `Executor::undeclare_parameter_on` in `spin.rs`.
240    #[cfg(feature = "param-store")]
241    fn undeclare_parameter_on(&mut self, node: super::node_record::NodeId, name: &str) -> bool;
242
243    /// The FFI entry point; see `Executor::add_on_set_parameters_callback_on` in `spin.rs`.
244    #[cfg(feature = "param-store")]
245    fn add_on_set_parameters_callback_on(
246        &mut self,
247        node: super::node_record::NodeId,
248        callback: nros_params::OnSetParameterFn,
249        ctx: nros_params::OnSetContext,
250    ) -> Option<nros_params::OnSetParameterHandle>;
251
252    /// The FFI entry point; see `Executor::use_undeclared_parameters_on` in `spin.rs`.
253    #[cfg(feature = "param-store")]
254    fn use_undeclared_parameters_on(
255        &mut self,
256        node: super::node_record::NodeId,
257    ) -> Result<nros_params::Parameters<'_, 's>, NodeError>;
258
259    /// The FFI entry point; see `Executor::add_arena_subscription_c_callback` in `spin.rs`.
260    #[allow(clippy::too_many_arguments)]
261    fn add_arena_subscription_c_callback<const RX_BUF: usize>(
262        &mut self,
263        node_id: Option<super::node_record::NodeId>,
264        topic_name: &str,
265        type_name: &str,
266        type_hash: &str,
267        qos: QoSProfile,
268        callback: RawSubscriptionCallback,
269        context: *mut core::ffi::c_void,
270        group: Option<&str>,
271        rx_buffer_hint: usize,
272    ) -> Result<HandleId, NodeError>;
273
274    /// The FFI entry point; see `Executor::add_arena_subscription_c_callback_with_capture` in `spin.rs`.
275    #[allow(clippy::too_many_arguments)]
276    fn add_arena_subscription_c_callback_with_capture<const RX_BUF: usize>(
277        &mut self,
278        node_id: Option<super::node_record::NodeId>,
279        topic_name: &str,
280        type_name: &str,
281        type_hash: &str,
282        qos: QoSProfile,
283        callback: RawSubscriptionCallback,
284        context: *mut core::ffi::c_void,
285        group: Option<&str>,
286        rx_buffer_hint: usize,
287        capture: Option<&[u8]>,
288        capture_drop: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>,
289    ) -> Result<HandleId, NodeError>;
290
291    /// The FFI entry point; see `Executor::add_arena_subscription_c_info_callback` in `spin.rs`.
292    #[allow(clippy::too_many_arguments)]
293    fn add_arena_subscription_c_info_callback<const RX_BUF: usize>(
294        &mut self,
295        node_id: Option<super::node_record::NodeId>,
296        topic_name: &str,
297        type_name: &str,
298        type_hash: &str,
299        qos: QoSProfile,
300        callback: RawSubscriptionInfoCallback,
301        context: *mut core::ffi::c_void,
302        rx_buffer_hint: usize,
303    ) -> Result<HandleId, NodeError>;
304
305    /// The FFI entry point; see `Executor::add_arena_subscription_c_typed_callback` in `spin.rs`.
306    #[allow(clippy::too_many_arguments)]
307    unsafe fn add_arena_subscription_c_typed_callback<const RX_BUF: usize>(
308        &mut self,
309        node_id: Option<super::node_record::NodeId>,
310        topic_name: &str,
311        type_name: &str,
312        type_hash: &str,
313        qos: QoSProfile,
314        msg: core::ptr::NonNull<core::ffi::c_void>,
315        deserialize: RawMessageDeserializeFn,
316        callback: TypedSubscriptionCallback,
317        context: *mut core::ffi::c_void,
318        group: Option<&str>,
319        rx_buffer_hint: usize,
320    ) -> Result<HandleId, NodeError>;
321
322    /// The FFI entry point; see `Executor::add_arena_subscription_c_validated_callback` in `spin.rs`.
323    #[cfg(feature = "safety-e2e")]
324    #[allow(clippy::too_many_arguments)]
325    fn add_arena_subscription_c_validated_callback<const RX_BUF: usize>(
326        &mut self,
327        node_id: Option<super::node_record::NodeId>,
328        topic_name: &str,
329        type_name: &str,
330        type_hash: &str,
331        qos: QoSProfile,
332        callback: super::types::RawSubscriptionSafetyCallback,
333        context: *mut core::ffi::c_void,
334        rx_buffer_hint: usize,
335    ) -> Result<HandleId, NodeError>;
336
337    /// The FFI entry point; see `Executor::add_on_shutdown_callback` in `spin.rs`.
338    unsafe fn add_on_shutdown_callback(
339        &mut self,
340        callback: super::types::ShutdownCallbackFn,
341        context: *mut core::ffi::c_void,
342    ) -> Result<super::types::ShutdownCallbackHandle, NodeError>;
343
344    /// The FFI entry point; see `Executor::add_pre_shutdown_callback` in `spin.rs`.
345    unsafe fn add_pre_shutdown_callback(
346        &mut self,
347        callback: super::types::ShutdownCallbackFn,
348        context: *mut core::ffi::c_void,
349    ) -> Result<super::types::ShutdownCallbackHandle, NodeError>;
350
351    /// The FFI entry point; see `Executor::remove_pre_shutdown_callback` in `spin.rs`.
352    fn remove_pre_shutdown_callback(
353        &mut self,
354        handle: super::types::ShutdownCallbackHandle,
355    ) -> bool;
356
357    /// The FFI entry point; see `Executor::remove_on_shutdown_callback` in `spin.rs`.
358    fn remove_on_shutdown_callback(&mut self, handle: super::types::ShutdownCallbackHandle)
359    -> bool;
360
361    /// The FFI entry point; see `Executor::from_session_ptr_in` in `spin.rs`.
362    unsafe fn from_session_ptr_in(
363        session_ptr: *mut session::ConcreteSession,
364        backing: &'s mut [MaybeUninit<u64>],
365        sizing: super::storage::ExecutorSizing,
366    ) -> Self;
367
368    /// The FFI entry point; see `Executor::open_multi_in` in `spin.rs`.
369    #[cfg(feature = "rmw-cffi")]
370    unsafe fn open_multi_in(
371        specs: &[SessionSpec<'_>],
372        backing: &'s mut [MaybeUninit<u64>],
373        sizing: super::storage::ExecutorSizing,
374    ) -> Result<Self, NodeError>;
375
376    /// The FFI entry point; see `Executor::open_with_session_handle_in` in `spin.rs`.
377    unsafe fn open_with_session_handle_in(
378        handle: SessionHandle,
379        backing: &'s mut [MaybeUninit<u64>],
380        sizing: super::storage::ExecutorSizing,
381    ) -> Self;
382
383    /// The FFI entry point; see `Executor::register_service_client_raw_sized` in `spin.rs`.
384    #[allow(clippy::too_many_arguments)]
385    fn register_service_client_raw_sized<const REPLY_BUF: usize>(
386        &mut self,
387        service_name: &str,
388        service_type: &str,
389        service_hash: &str,
390        qos: QoSProfile,
391        callback: Option<RawResponseCallback>,
392        context: *mut core::ffi::c_void,
393    ) -> Result<HandleId, NodeError>;
394
395    /// The FFI entry point; see `Executor::register_service_client_raw_capturing` in `spin.rs`.
396    #[allow(clippy::too_many_arguments)]
397    fn register_service_client_raw_capturing<const REPLY_BUF: usize>(
398        &mut self,
399        node_id: Option<super::node_record::NodeId>,
400        service_name: &str,
401        service_type: &str,
402        service_hash: &str,
403        qos: QoSProfile,
404        callback: Option<RawResponseCallback>,
405        capture: Option<&[u8]>,
406    ) -> Result<HandleId, NodeError>;
407
408    /// The FFI entry point; see `Executor::register_service_raw_capturing` in `spin.rs`.
409    #[allow(clippy::too_many_arguments)]
410    fn register_service_raw_capturing<const REQ_BUF: usize, const REPLY_BUF: usize>(
411        &mut self,
412        node_id: Option<super::node_record::NodeId>,
413        service_name: &str,
414        service_type: &str,
415        service_hash: &str,
416        qos: QoSProfile,
417        callback: RawServiceCallback,
418        capture: Option<&[u8]>,
419        capture_drop: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>,
420    ) -> Result<HandleId, NodeError>;
421
422    /// The FFI entry point; see `Executor::register_service_raw_sized` in `spin.rs`.
423    #[allow(clippy::too_many_arguments)]
424    fn register_service_raw_sized<const REQ_BUF: usize, const REPLY_BUF: usize>(
425        &mut self,
426        service_name: &str,
427        service_type: &str,
428        service_hash: &str,
429        qos: QoSProfile,
430        callback: RawServiceCallback,
431        context: *mut core::ffi::c_void,
432    ) -> Result<HandleId, NodeError>;
433
434    /// The FFI entry point; see `Executor::register_timer_c_capturing` in `spin.rs`.
435    fn register_timer_c_capturing(
436        &mut self,
437        node_id: Option<super::node_record::NodeId>,
438        period: TimerDuration,
439        source: TimerClockSource,
440        callback: unsafe extern "C" fn(*mut core::ffi::c_void),
441        capture: Option<&[u8]>,
442        capture_drop: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>,
443    ) -> Result<HandleId, NodeError>;
444
445    /// The FFI entry point; see `Executor::register_timer_c_capturing_with_info` in `spin.rs`.
446    #[allow(clippy::too_many_arguments)]
447    fn register_timer_c_capturing_with_info<I>(
448        &mut self,
449        node_id: Option<super::node_record::NodeId>,
450        period: TimerDuration,
451        source: TimerClockSource,
452        autostart: bool,
453        group: Option<&str>,
454        callback: unsafe extern "C" fn(*const I, *mut core::ffi::c_void),
455        capture: Option<&[u8]>,
456        capture_drop: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>,
457    ) -> Result<HandleId, NodeError>
458    where
459        I: From<TimerCallInfo> + 'static;
460
461    /// The FFI entry point; see `Executor::release_action_client_raw` in `action.rs`.
462    unsafe fn release_action_client_raw(&mut self, entry_index: usize) -> bool;
463
464    /// The FFI entry point; see `Executor::release_action_server_raw` in `action.rs`.
465    unsafe fn release_action_server_raw(&mut self, handle: &ActionServerRawHandle) -> bool;
466
467    /// The FFI entry point; see `Executor::release_node` in `spin.rs`.
468    unsafe fn release_node(&mut self, node: crate::executor::NodeId) -> usize;
469
470    /// The FFI entry point; see `Executor::release_service` in `spin.rs`.
471    unsafe fn release_service(&mut self, handle: HandleId) -> bool;
472
473    /// The FFI entry point; see `Executor::release_service_client` in `spin.rs`.
474    unsafe fn release_service_client(&mut self, handle: HandleId) -> bool;
475
476    /// The FFI entry point; see `Executor::release_subscription` in `spin.rs`.
477    unsafe fn release_subscription(&mut self, handle: HandleId) -> bool;
478
479    /// The FFI entry point; see `Executor::release_timer` in `spin.rs`.
480    unsafe fn release_timer(&mut self, handle: HandleId) -> bool;
481
482    /// The FFI entry point; see `Executor::retarget_action_client_raw` in `action.rs`.
483    unsafe fn retarget_action_client_raw(
484        &mut self,
485        entry_index: usize,
486        context: *mut core::ffi::c_void,
487    ) -> bool;
488
489    /// The FFI entry point; see `Executor::retarget_action_server_raw` in `action.rs`.
490    unsafe fn retarget_action_server_raw(
491        &mut self,
492        handle: &ActionServerRawHandle,
493        context: *mut core::ffi::c_void,
494    ) -> bool;
495
496    /// The FFI entry point; see `Executor::service_client_handle` in `spin.rs`.
497    #[doc(hidden)]
498    unsafe fn service_client_handle(
499        &self,
500        entry_index: usize,
501    ) -> Option<&session::RmwServiceClient>;
502
503    /// The FFI entry point; see `Executor::service_server_handle` in `spin.rs`.
504    #[doc(hidden)]
505    unsafe fn service_server_handle(
506        &self,
507        entry_index: usize,
508    ) -> Option<&session::RmwServiceServer>;
509
510    /// The FFI entry point; see `Executor::set_park_primitive` in `spin.rs`.
511    fn set_park_primitive(
512        &mut self,
513        park: ParkUntilFn,
514        ctx: *mut core::ffi::c_void,
515        granularity_us: u64,
516    );
517
518    /// The FFI entry point; see `Executor::set_wake_hook` in `spin.rs`.
519    fn set_wake_hook(&mut self, hook: Option<WakeHookFn>, ctx: *mut core::ffi::c_void) -> bool;
520
521    /// The FFI entry point; see `Executor::subscription_handle` in `spin.rs`.
522    #[doc(hidden)]
523    unsafe fn subscription_handle(&self, entry_index: usize) -> Option<&session::RmwSubscriber>;
524
525    /// The FFI entry point; see `Executor::subscription_handle_mut` in `spin.rs`.
526    #[doc(hidden)]
527    unsafe fn subscription_handle_mut(
528        &mut self,
529        entry_index: usize,
530    ) -> Option<&mut session::RmwSubscriber>;
531
532    /// The FFI entry point; see `Executor::wake_raw_ptr` in `spin.rs`.
533    #[cfg(all(feature = "alloc", feature = "rmw-cffi"))]
534    fn wake_raw_ptr(&self) -> *mut core::ffi::c_void;
535
536    /// The FFI entry point; see `Executor::enter_spin_loop` in `spin.rs`.
537    fn enter_spin_loop(&self);
538
539    /// The FFI entry point; see `Executor::exit_spin_loop` in `spin.rs`.
540    fn exit_spin_loop(&self);
541
542    /// The FFI entry point; see `Executor::exec_lock` in `spin.rs`.
543    fn exec_lock(&self) -> Option<super::exec_lock::ExecLock>;
544
545    /// The FFI entry point; see `Executor::node_session_mut` in `spin.rs`.
546    fn node_session_mut(
547        &mut self,
548        node_id: super::node_record::NodeId,
549    ) -> Option<&mut session::ConcreteSession>;
550
551    /// The FFI entry point; see `Executor::register_action_client_raw` in `action.rs`.
552    #[doc(hidden)]
553    #[allow(clippy::too_many_arguments)]
554    fn register_action_client_raw(
555        &mut self,
556        spec: RawActionClientSpec<'_>,
557    ) -> Result<ActionClientRawHandle, NodeError>;
558
559    /// The FFI entry point; see `Executor::register_action_server_raw` in `action.rs`.
560    #[doc(hidden)]
561    #[allow(clippy::too_many_arguments)]
562    fn register_action_server_raw(
563        &mut self,
564        spec: RawActionServerSpec<'_>,
565    ) -> Result<ActionServerRawHandle, NodeError>;
566
567    /// The FFI entry point; see `Executor::install_wake_signal_on_primary` in `spin.rs`.
568    #[cfg(all(feature = "alloc", feature = "rmw-cffi"))]
569    fn install_wake_signal_on_primary(&mut self);
570
571    /// The FFI entry point; see `Executor::set_entry_owner` in `spin.rs`.
572    fn set_entry_owner(&mut self, id: HandleId, node: crate::executor::NodeId) -> bool;
573
574    /// The FFI entry point; see `Executor::set_primary_identity` in `spin.rs`.
575    fn set_primary_identity(&mut self, rmw_name: &str, locator: &str);
576
577    /// The FFI entry point; see `Executor::session_io_failures` in `spin.rs`.
578    fn session_io_failures(&self) -> u32;
579
580    /// The FFI entry point; see `Executor::timer_elapsed_us` in `spin.rs`.
581    fn timer_elapsed_us(&self, id: HandleId) -> Option<u64>;
582
583    /// The FFI entry point; see `Executor::timer_is_ready` in `spin.rs`.
584    fn timer_is_ready(&self, id: HandleId) -> Option<bool>;
585
586    /// The FFI entry point; see `Executor::exchange_timer_period_us` in `spin.rs`.
587    fn exchange_timer_period_us(&mut self, id: HandleId, new_period_us: u64) -> Option<u64>;
588
589    /// The FFI entry point; see `Executor::action_client_core_mut` in `spin.rs`.
590    #[doc(hidden)]
591    unsafe fn action_client_core_mut(
592        &mut self,
593        entry_index: usize,
594    ) -> Option<&mut super::action_core::ActionClientCore>;
595
596    /// The FFI entry point; see `Executor::register_service_client_raw_sized_on` in `spin.rs`.
597    #[allow(clippy::too_many_arguments)]
598    fn register_service_client_raw_sized_on<const REPLY_BUF: usize>(
599        &mut self,
600        node_id: super::node_record::NodeId,
601        service_name: &str,
602        service_type: &str,
603        service_hash: &str,
604        qos: QoSProfile,
605        callback: Option<RawResponseCallback>,
606        context: *mut core::ffi::c_void,
607    ) -> Result<HandleId, NodeError>;
608
609    /// The FFI entry point; see `Executor::register_service_raw_sized_on` in `spin.rs`.
610    #[allow(clippy::too_many_arguments)]
611    fn register_service_raw_sized_on<const REQ_BUF: usize, const REPLY_BUF: usize>(
612        &mut self,
613        node_id: super::node_record::NodeId,
614        service_name: &str,
615        service_type: &str,
616        service_hash: &str,
617        qos: QoSProfile,
618        callback: RawServiceCallback,
619        context: *mut core::ffi::c_void,
620    ) -> Result<HandleId, NodeError>;
621
622    /// The FFI entry point; see `Executor::service_client_entry_mut` in `spin.rs`.
623    unsafe fn service_client_entry_mut(
624        &mut self,
625        entry_index: usize,
626    ) -> Option<&mut super::arena::ServiceClientRawArenaEntry<{ crate::config::DEFAULT_RX_BUF_SIZE }>>;
627
628    /// The FFI entry point; see `Executor::from_session_ptr` in `spin.rs`.
629    #[cfg(feature = "alloc")]
630    unsafe fn from_session_ptr(session_ptr: *mut session::ConcreteSession) -> Executor<'static>;
631
632    /// The FFI entry point; see `Executor::from_session_in` in `spin.rs`.
633    unsafe fn from_session_in(
634        session: session::ConcreteSession,
635        backing: &'s mut [MaybeUninit<u64>],
636        sizing: super::storage::ExecutorSizing,
637    ) -> Self;
638
639    /// The FFI entry point; see `Executor::open_with_session_in` in `spin.rs`.
640    unsafe fn open_with_session_in(
641        session: *mut session::ConcreteSession,
642        backing: &'s mut [MaybeUninit<u64>],
643        sizing: super::storage::ExecutorSizing,
644    ) -> Self;
645
646    /// The FFI entry point; see `Executor::open_with_session_slot` in `spin.rs`.
647    #[cfg(feature = "alloc")]
648    unsafe fn open_with_session_slot(
649        session: *mut session::ConcreteSession,
650        slot: &'s mut super::TierExecutorBackingSlot,
651    ) -> Self;
652
653    /// The FFI entry point; see `Executor::open_with_session_handle_slot` in `spin.rs`.
654    #[cfg(feature = "alloc")]
655    unsafe fn open_with_session_handle_slot(
656        handle: SessionHandle,
657        slot: &'s mut super::TierExecutorBackingSlot,
658    ) -> Self;
659
660    /// The FFI entry point; see `Executor::detach_action_client_raw` in `action.rs`.
661    unsafe fn detach_action_client_raw(&mut self, entry_index: usize) -> bool;
662
663    /// The FFI entry point; see `Executor::detach_action_server_raw` in `action.rs`.
664    unsafe fn detach_action_server_raw(&mut self, handle: &ActionServerRawHandle) -> bool;
665
666    /// The FFI entry point; see `Executor::detach_action_server_raw_sized` in `action.rs`.
667    unsafe fn detach_action_server_raw_sized<
668        const GOAL_BUF: usize,
669        const RESULT_BUF: usize,
670        const FEEDBACK_BUF: usize,
671        const MAX_GOALS: usize,
672    >(
673        &mut self,
674        entry_index: usize,
675    ) -> bool;
676
677    /// The FFI entry point; see `Executor::release_action_client_raw_sized` in `action.rs`.
678    unsafe fn release_action_client_raw_sized<
679        const GOAL_BUF: usize,
680        const RESULT_BUF: usize,
681        const FEEDBACK_BUF: usize,
682    >(
683        &mut self,
684        entry_index: usize,
685    ) -> bool;
686
687    /// The FFI entry point; see `Executor::release_action_server_raw_sized` in `action.rs`.
688    unsafe fn release_action_server_raw_sized<
689        const GOAL_BUF: usize,
690        const RESULT_BUF: usize,
691        const FEEDBACK_BUF: usize,
692        const MAX_GOALS: usize,
693    >(
694        &mut self,
695        entry_index: usize,
696    ) -> bool;
697
698    /// The FFI entry point; see `Executor::register_service_raw` in `spin.rs`.
699    fn register_service_raw(
700        &mut self,
701        service_name: &str,
702        service_type: &str,
703        service_hash: &str,
704        callback: RawServiceCallback,
705        context: *mut core::ffi::c_void,
706    ) -> Result<HandleId, NodeError>;
707
708    /// The FFI entry point; see `Executor::register_service_client_raw` in `spin.rs`.
709    fn register_service_client_raw(
710        &mut self,
711        service_name: &str,
712        service_type: &str,
713        service_hash: &str,
714        callback: Option<RawResponseCallback>,
715        context: *mut core::ffi::c_void,
716    ) -> Result<HandleId, NodeError>;
717
718    /// The FFI entry point; see `Executor::register_action_client_core` in `action.rs`.
719    #[doc(hidden)]
720    fn register_action_client_core<
721        const GOAL_BUF: usize,
722        const RESULT_BUF: usize,
723        const FEEDBACK_BUF: usize,
724    >(
725        &mut self,
726        core: ActionClientCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF>,
727        goal_response_callback: Option<RawGoalResponseCallback>,
728        feedback_callback: Option<RawFeedbackCallback>,
729        result_callback: Option<RawResultCallback>,
730        cancel_response_callback: Option<RawCancelResponseCallback>,
731        context: *mut core::ffi::c_void,
732    ) -> Result<ActionClientRawHandle, NodeError>;
733
734    /// The FFI entry point; see `Executor::release_guard_condition` in `spin.rs`.
735    unsafe fn release_guard_condition(&mut self, handle: HandleId) -> bool;
736}
737
738impl<'s> ExecutorFfi<'s> for Executor<'s> {
739    #[cfg(all(feature = "param-store", feature = "alloc"))]
740    #[inline]
741    #[cfg(feature = "param-store")]
742    fn argv_param_overrides_on(
743        &self,
744        node: super::node_record::NodeId,
745    ) -> impl Iterator<Item = (&str, nros_params::ParameterValue)> + '_ {
746        Executor::argv_param_overrides_on(self, node)
747    }
748
749    #[cfg(all(feature = "param-store", feature = "alloc"))]
750    #[inline]
751    #[cfg(feature = "param-store")]
752    fn for_each_argv_param_override_on(
753        &self,
754        node: super::node_record::NodeId,
755        f: impl FnMut(&str, &nros_params::ParameterValue),
756    ) -> usize {
757        Executor::for_each_argv_param_override_on(self, node, f)
758    }
759
760    #[inline]
761    #[cfg(feature = "param-store")]
762    fn declare_parameter_on(
763        &mut self,
764        node: super::node_record::NodeId,
765        name: &str,
766        value: nros_params::ParameterValue,
767    ) -> bool {
768        Executor::declare_parameter_on(self, node, name, value)
769    }
770
771    #[inline]
772    #[cfg(feature = "param-store")]
773    fn declare_parameter_on_ref(
774        &mut self,
775        node: super::node_record::NodeId,
776        name: &str,
777        value: &nros_params::ParameterValue,
778    ) -> bool {
779        Executor::declare_parameter_on_ref(self, node, name, value)
780    }
781
782    #[inline]
783    #[cfg(feature = "param-store")]
784    fn declare_parameter_with_descriptor_on(
785        &mut self,
786        node: super::node_record::NodeId,
787        name: &str,
788        value: nros_params::ParameterValue,
789        descriptor: nros_params::ParameterDescriptor,
790    ) -> bool {
791        Executor::declare_parameter_with_descriptor_on(self, node, name, value, descriptor)
792    }
793
794    #[inline]
795    #[cfg(feature = "param-store")]
796    fn set_parameter_on(
797        &mut self,
798        node: super::node_record::NodeId,
799        name: &str,
800        value: nros_params::ParameterValue,
801    ) -> Result<(), nros_params::ParameterError> {
802        Executor::set_parameter_on(self, node, name, value)
803    }
804
805    #[inline]
806    #[cfg(feature = "param-store")]
807    fn set_parameter_on_ref(
808        &mut self,
809        node: super::node_record::NodeId,
810        name: &str,
811        value: &nros_params::ParameterValue,
812    ) -> Result<(), nros_params::ParameterError> {
813        Executor::set_parameter_on_ref(self, node, name, value)
814    }
815
816    #[inline]
817    #[cfg(feature = "param-store")]
818    fn set_parameter_local_on(
819        &mut self,
820        node: super::node_record::NodeId,
821        name: &str,
822        value: nros_params::ParameterValue,
823    ) -> Result<(), nros_params::ParameterError> {
824        Executor::set_parameter_local_on(self, node, name, value)
825    }
826
827    #[cfg(feature = "param-services")]
828    #[inline]
829    #[cfg(feature = "param-store")]
830    fn disable_parameter_events_on(&mut self, node: super::node_record::NodeId) {
831        Executor::disable_parameter_events_on(self, node)
832    }
833
834    #[cfg(feature = "param-services")]
835    #[inline]
836    #[cfg(feature = "param-store")]
837    fn enable_parameter_events_on(
838        &mut self,
839        node: super::node_record::NodeId,
840    ) -> Result<(), NodeError> {
841        Executor::enable_parameter_events_on(self, node)
842    }
843
844    #[inline]
845    #[cfg(feature = "param-store")]
846    fn delete_parameters_on_not_set_on(&mut self, node: super::node_record::NodeId, on: bool) {
847        Executor::delete_parameters_on_not_set_on(self, node, on)
848    }
849
850    #[inline]
851    #[cfg(feature = "param-store")]
852    fn allow_undeclared_parameters_on(&mut self, node: super::node_record::NodeId, allow: bool) {
853        Executor::allow_undeclared_parameters_on(self, node, allow)
854    }
855
856    #[inline]
857    #[cfg(feature = "param-store")]
858    fn get_parameter_on(
859        &self,
860        node: super::node_record::NodeId,
861        name: &str,
862    ) -> Option<&nros_params::ParameterValue> {
863        Executor::get_parameter_on(self, node, name)
864    }
865
866    #[inline]
867    #[cfg(feature = "param-store")]
868    fn parameter_on<'a, T: nros_params::ParameterVariant>(
869        &'a mut self,
870        node: super::node_record::NodeId,
871        name: &'a str,
872    ) -> Result<nros_params::ParameterBuilder<'a, 's, T>, NodeError> {
873        Executor::parameter_on::<T>(self, node, name)
874    }
875
876    #[inline]
877    #[cfg(feature = "param-store")]
878    fn set_parameter_description_on(
879        &mut self,
880        node: super::node_record::NodeId,
881        name: &str,
882        description: &str,
883        additional_constraints: &str,
884    ) -> bool {
885        Executor::set_parameter_description_on(
886            self,
887            node,
888            name,
889            description,
890            additional_constraints,
891        )
892    }
893
894    #[inline]
895    #[cfg(feature = "param-store")]
896    fn set_parameter_read_only_on(
897        &mut self,
898        node: super::node_record::NodeId,
899        name: &str,
900        read_only: bool,
901    ) -> bool {
902        Executor::set_parameter_read_only_on(self, node, name, read_only)
903    }
904
905    #[inline]
906    #[cfg(feature = "param-store")]
907    fn set_parameter_integer_range_on(
908        &mut self,
909        node: super::node_record::NodeId,
910        name: &str,
911        min: i64,
912        max: i64,
913        step: i64,
914    ) -> bool {
915        Executor::set_parameter_integer_range_on(self, node, name, min, max, step)
916    }
917
918    #[inline]
919    #[cfg(feature = "param-store")]
920    fn set_parameter_float_range_on(
921        &mut self,
922        node: super::node_record::NodeId,
923        name: &str,
924        min: f64,
925        max: f64,
926        step: f64,
927    ) -> bool {
928        Executor::set_parameter_float_range_on(self, node, name, min, max, step)
929    }
930
931    #[inline]
932    #[cfg(feature = "param-store")]
933    fn describe_parameter_on(
934        &self,
935        node: super::node_record::NodeId,
936        name: &str,
937    ) -> Option<&nros_params::ParameterDescriptor> {
938        Executor::describe_parameter_on(self, node, name)
939    }
940
941    #[inline]
942    #[cfg(feature = "param-store")]
943    fn get_parameter_type_on(
944        &self,
945        node: super::node_record::NodeId,
946        name: &str,
947    ) -> Option<nros_params::ParameterType> {
948        Executor::get_parameter_type_on(self, node, name)
949    }
950
951    #[inline]
952    #[cfg(feature = "param-store")]
953    fn list_parameters_on<'p>(
954        &'p self,
955        node: super::node_record::NodeId,
956        prefix: &'p str,
957    ) -> impl Iterator<Item = &'p str> {
958        Executor::list_parameters_on(self, node, prefix)
959    }
960
961    #[inline]
962    #[cfg(feature = "param-store")]
963    fn set_parameters_atomically_on<'x, I>(
964        &mut self,
965        node: super::node_record::NodeId,
966        items: I,
967    ) -> Result<(), nros_params::ParameterError>
968    where
969        I: Iterator<Item = Option<(&'x str, nros_params::ParameterValue)>> + Clone,
970    {
971        Executor::set_parameters_atomically_on::<I>(self, node, items)
972    }
973
974    #[inline]
975    #[cfg(feature = "param-store")]
976    fn set_parameters_atomically_with_on<'x>(
977        &mut self,
978        node: super::node_record::NodeId,
979        count: usize,
980        fill: impl FnMut(usize, &mut nros_params::ParameterValue) -> Option<&'x str>,
981    ) -> Result<(), nros_params::ParameterError> {
982        Executor::set_parameters_atomically_with_on(self, node, count, fill)
983    }
984
985    #[inline]
986    #[cfg(feature = "param-store")]
987    fn undeclare_parameter_on(&mut self, node: super::node_record::NodeId, name: &str) -> bool {
988        Executor::undeclare_parameter_on(self, node, name)
989    }
990
991    #[inline]
992    #[cfg(feature = "param-store")]
993    fn add_on_set_parameters_callback_on(
994        &mut self,
995        node: super::node_record::NodeId,
996        callback: nros_params::OnSetParameterFn,
997        ctx: nros_params::OnSetContext,
998    ) -> Option<nros_params::OnSetParameterHandle> {
999        Executor::add_on_set_parameters_callback_on(self, node, callback, ctx)
1000    }
1001
1002    #[inline]
1003    #[cfg(feature = "param-store")]
1004    fn use_undeclared_parameters_on(
1005        &mut self,
1006        node: super::node_record::NodeId,
1007    ) -> Result<nros_params::Parameters<'_, 's>, NodeError> {
1008        Executor::use_undeclared_parameters_on(self, node)
1009    }
1010
1011    #[allow(clippy::too_many_arguments)]
1012    #[inline]
1013    fn add_arena_subscription_c_callback<const RX_BUF: usize>(
1014        &mut self,
1015        node_id: Option<super::node_record::NodeId>,
1016        topic_name: &str,
1017        type_name: &str,
1018        type_hash: &str,
1019        qos: QoSProfile,
1020        callback: RawSubscriptionCallback,
1021        context: *mut core::ffi::c_void,
1022        group: Option<&str>,
1023        rx_buffer_hint: usize,
1024    ) -> Result<HandleId, NodeError> {
1025        Executor::add_arena_subscription_c_callback::<RX_BUF>(
1026            self,
1027            node_id,
1028            topic_name,
1029            type_name,
1030            type_hash,
1031            qos,
1032            callback,
1033            context,
1034            group,
1035            rx_buffer_hint,
1036        )
1037    }
1038
1039    #[allow(clippy::too_many_arguments)]
1040    #[inline]
1041    fn add_arena_subscription_c_callback_with_capture<const RX_BUF: usize>(
1042        &mut self,
1043        node_id: Option<super::node_record::NodeId>,
1044        topic_name: &str,
1045        type_name: &str,
1046        type_hash: &str,
1047        qos: QoSProfile,
1048        callback: RawSubscriptionCallback,
1049        context: *mut core::ffi::c_void,
1050        group: Option<&str>,
1051        rx_buffer_hint: usize,
1052        capture: Option<&[u8]>,
1053        capture_drop: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>,
1054    ) -> Result<HandleId, NodeError> {
1055        Executor::add_arena_subscription_c_callback_with_capture::<RX_BUF>(
1056            self,
1057            node_id,
1058            topic_name,
1059            type_name,
1060            type_hash,
1061            qos,
1062            callback,
1063            context,
1064            group,
1065            rx_buffer_hint,
1066            capture,
1067            capture_drop,
1068        )
1069    }
1070
1071    #[allow(clippy::too_many_arguments)]
1072    #[inline]
1073    fn add_arena_subscription_c_info_callback<const RX_BUF: usize>(
1074        &mut self,
1075        node_id: Option<super::node_record::NodeId>,
1076        topic_name: &str,
1077        type_name: &str,
1078        type_hash: &str,
1079        qos: QoSProfile,
1080        callback: RawSubscriptionInfoCallback,
1081        context: *mut core::ffi::c_void,
1082        rx_buffer_hint: usize,
1083    ) -> Result<HandleId, NodeError> {
1084        Executor::add_arena_subscription_c_info_callback::<RX_BUF>(
1085            self,
1086            node_id,
1087            topic_name,
1088            type_name,
1089            type_hash,
1090            qos,
1091            callback,
1092            context,
1093            rx_buffer_hint,
1094        )
1095    }
1096
1097    #[allow(clippy::too_many_arguments)]
1098    #[inline]
1099    unsafe fn add_arena_subscription_c_typed_callback<const RX_BUF: usize>(
1100        &mut self,
1101        node_id: Option<super::node_record::NodeId>,
1102        topic_name: &str,
1103        type_name: &str,
1104        type_hash: &str,
1105        qos: QoSProfile,
1106        msg: core::ptr::NonNull<core::ffi::c_void>,
1107        deserialize: RawMessageDeserializeFn,
1108        callback: TypedSubscriptionCallback,
1109        context: *mut core::ffi::c_void,
1110        group: Option<&str>,
1111        rx_buffer_hint: usize,
1112    ) -> Result<HandleId, NodeError> {
1113        unsafe {
1114            Executor::add_arena_subscription_c_typed_callback::<RX_BUF>(
1115                self,
1116                node_id,
1117                topic_name,
1118                type_name,
1119                type_hash,
1120                qos,
1121                msg,
1122                deserialize,
1123                callback,
1124                context,
1125                group,
1126                rx_buffer_hint,
1127            )
1128        }
1129    }
1130
1131    #[cfg(feature = "safety-e2e")]
1132    #[allow(clippy::too_many_arguments)]
1133    #[inline]
1134    fn add_arena_subscription_c_validated_callback<const RX_BUF: usize>(
1135        &mut self,
1136        node_id: Option<super::node_record::NodeId>,
1137        topic_name: &str,
1138        type_name: &str,
1139        type_hash: &str,
1140        qos: QoSProfile,
1141        callback: super::types::RawSubscriptionSafetyCallback,
1142        context: *mut core::ffi::c_void,
1143        rx_buffer_hint: usize,
1144    ) -> Result<HandleId, NodeError> {
1145        Executor::add_arena_subscription_c_validated_callback::<RX_BUF>(
1146            self,
1147            node_id,
1148            topic_name,
1149            type_name,
1150            type_hash,
1151            qos,
1152            callback,
1153            context,
1154            rx_buffer_hint,
1155        )
1156    }
1157
1158    #[inline]
1159    unsafe fn add_on_shutdown_callback(
1160        &mut self,
1161        callback: super::types::ShutdownCallbackFn,
1162        context: *mut core::ffi::c_void,
1163    ) -> Result<super::types::ShutdownCallbackHandle, NodeError> {
1164        unsafe { Executor::add_on_shutdown_callback(self, callback, context) }
1165    }
1166
1167    #[inline]
1168    unsafe fn add_pre_shutdown_callback(
1169        &mut self,
1170        callback: super::types::ShutdownCallbackFn,
1171        context: *mut core::ffi::c_void,
1172    ) -> Result<super::types::ShutdownCallbackHandle, NodeError> {
1173        unsafe { Executor::add_pre_shutdown_callback(self, callback, context) }
1174    }
1175
1176    #[inline]
1177    fn remove_pre_shutdown_callback(
1178        &mut self,
1179        handle: super::types::ShutdownCallbackHandle,
1180    ) -> bool {
1181        Executor::remove_pre_shutdown_callback(self, handle)
1182    }
1183
1184    #[inline]
1185    fn remove_on_shutdown_callback(
1186        &mut self,
1187        handle: super::types::ShutdownCallbackHandle,
1188    ) -> bool {
1189        Executor::remove_on_shutdown_callback(self, handle)
1190    }
1191
1192    #[inline]
1193    unsafe fn from_session_ptr_in(
1194        session_ptr: *mut session::ConcreteSession,
1195        backing: &'s mut [MaybeUninit<u64>],
1196        sizing: super::storage::ExecutorSizing,
1197    ) -> Self {
1198        unsafe { Executor::from_session_ptr_in(session_ptr, backing, sizing) }
1199    }
1200
1201    #[cfg(feature = "rmw-cffi")]
1202    #[inline]
1203    unsafe fn open_multi_in(
1204        specs: &[SessionSpec<'_>],
1205        backing: &'s mut [MaybeUninit<u64>],
1206        sizing: super::storage::ExecutorSizing,
1207    ) -> Result<Self, NodeError> {
1208        unsafe { Executor::open_multi_in(specs, backing, sizing) }
1209    }
1210
1211    #[inline]
1212    unsafe fn open_with_session_handle_in(
1213        handle: SessionHandle,
1214        backing: &'s mut [MaybeUninit<u64>],
1215        sizing: super::storage::ExecutorSizing,
1216    ) -> Self {
1217        unsafe { Executor::open_with_session_handle_in(handle, backing, sizing) }
1218    }
1219
1220    #[allow(clippy::too_many_arguments)]
1221    #[inline]
1222    fn register_service_client_raw_sized<const REPLY_BUF: usize>(
1223        &mut self,
1224        service_name: &str,
1225        service_type: &str,
1226        service_hash: &str,
1227        qos: QoSProfile,
1228        callback: Option<RawResponseCallback>,
1229        context: *mut core::ffi::c_void,
1230    ) -> Result<HandleId, NodeError> {
1231        Executor::register_service_client_raw_sized::<REPLY_BUF>(
1232            self,
1233            service_name,
1234            service_type,
1235            service_hash,
1236            qos,
1237            callback,
1238            context,
1239        )
1240    }
1241
1242    #[allow(clippy::too_many_arguments)]
1243    #[inline]
1244    fn register_service_client_raw_capturing<const REPLY_BUF: usize>(
1245        &mut self,
1246        node_id: Option<super::node_record::NodeId>,
1247        service_name: &str,
1248        service_type: &str,
1249        service_hash: &str,
1250        qos: QoSProfile,
1251        callback: Option<RawResponseCallback>,
1252        capture: Option<&[u8]>,
1253    ) -> Result<HandleId, NodeError> {
1254        Executor::register_service_client_raw_capturing::<REPLY_BUF>(
1255            self,
1256            node_id,
1257            service_name,
1258            service_type,
1259            service_hash,
1260            qos,
1261            callback,
1262            capture,
1263        )
1264    }
1265
1266    #[allow(clippy::too_many_arguments)]
1267    #[inline]
1268    fn register_service_raw_capturing<const REQ_BUF: usize, const REPLY_BUF: usize>(
1269        &mut self,
1270        node_id: Option<super::node_record::NodeId>,
1271        service_name: &str,
1272        service_type: &str,
1273        service_hash: &str,
1274        qos: QoSProfile,
1275        callback: RawServiceCallback,
1276        capture: Option<&[u8]>,
1277        capture_drop: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>,
1278    ) -> Result<HandleId, NodeError> {
1279        Executor::register_service_raw_capturing::<REQ_BUF, REPLY_BUF>(
1280            self,
1281            node_id,
1282            service_name,
1283            service_type,
1284            service_hash,
1285            qos,
1286            callback,
1287            capture,
1288            capture_drop,
1289        )
1290    }
1291
1292    #[allow(clippy::too_many_arguments)]
1293    #[inline]
1294    fn register_service_raw_sized<const REQ_BUF: usize, const REPLY_BUF: usize>(
1295        &mut self,
1296        service_name: &str,
1297        service_type: &str,
1298        service_hash: &str,
1299        qos: QoSProfile,
1300        callback: RawServiceCallback,
1301        context: *mut core::ffi::c_void,
1302    ) -> Result<HandleId, NodeError> {
1303        Executor::register_service_raw_sized::<REQ_BUF, REPLY_BUF>(
1304            self,
1305            service_name,
1306            service_type,
1307            service_hash,
1308            qos,
1309            callback,
1310            context,
1311        )
1312    }
1313
1314    #[inline]
1315    fn register_timer_c_capturing(
1316        &mut self,
1317        node_id: Option<super::node_record::NodeId>,
1318        period: TimerDuration,
1319        source: TimerClockSource,
1320        callback: unsafe extern "C" fn(*mut core::ffi::c_void),
1321        capture: Option<&[u8]>,
1322        capture_drop: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>,
1323    ) -> Result<HandleId, NodeError> {
1324        Executor::register_timer_c_capturing(
1325            self,
1326            node_id,
1327            period,
1328            source,
1329            callback,
1330            capture,
1331            capture_drop,
1332        )
1333    }
1334
1335    #[allow(clippy::too_many_arguments)]
1336    #[inline]
1337    fn register_timer_c_capturing_with_info<I>(
1338        &mut self,
1339        node_id: Option<super::node_record::NodeId>,
1340        period: TimerDuration,
1341        source: TimerClockSource,
1342        autostart: bool,
1343        group: Option<&str>,
1344        callback: unsafe extern "C" fn(*const I, *mut core::ffi::c_void),
1345        capture: Option<&[u8]>,
1346        capture_drop: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>,
1347    ) -> Result<HandleId, NodeError>
1348    where
1349        I: From<TimerCallInfo> + 'static,
1350    {
1351        Executor::register_timer_c_capturing_with_info::<I>(
1352            self,
1353            node_id,
1354            period,
1355            source,
1356            autostart,
1357            group,
1358            callback,
1359            capture,
1360            capture_drop,
1361        )
1362    }
1363
1364    #[inline]
1365    unsafe fn release_action_client_raw(&mut self, entry_index: usize) -> bool {
1366        unsafe { Executor::release_action_client_raw(self, entry_index) }
1367    }
1368
1369    #[inline]
1370    unsafe fn release_action_server_raw(&mut self, handle: &ActionServerRawHandle) -> bool {
1371        unsafe { Executor::release_action_server_raw(self, handle) }
1372    }
1373
1374    #[inline]
1375    unsafe fn release_node(&mut self, node: crate::executor::NodeId) -> usize {
1376        unsafe { Executor::release_node(self, node) }
1377    }
1378
1379    #[inline]
1380    unsafe fn release_service(&mut self, handle: HandleId) -> bool {
1381        unsafe { Executor::release_service(self, handle) }
1382    }
1383
1384    #[inline]
1385    unsafe fn release_service_client(&mut self, handle: HandleId) -> bool {
1386        unsafe { Executor::release_service_client(self, handle) }
1387    }
1388
1389    #[inline]
1390    unsafe fn release_subscription(&mut self, handle: HandleId) -> bool {
1391        unsafe { Executor::release_subscription(self, handle) }
1392    }
1393
1394    #[inline]
1395    unsafe fn release_timer(&mut self, handle: HandleId) -> bool {
1396        unsafe { Executor::release_timer(self, handle) }
1397    }
1398
1399    #[inline]
1400    unsafe fn retarget_action_client_raw(
1401        &mut self,
1402        entry_index: usize,
1403        context: *mut core::ffi::c_void,
1404    ) -> bool {
1405        unsafe { Executor::retarget_action_client_raw(self, entry_index, context) }
1406    }
1407
1408    #[inline]
1409    unsafe fn retarget_action_server_raw(
1410        &mut self,
1411        handle: &ActionServerRawHandle,
1412        context: *mut core::ffi::c_void,
1413    ) -> bool {
1414        unsafe { Executor::retarget_action_server_raw(self, handle, context) }
1415    }
1416
1417    #[doc(hidden)]
1418    #[inline]
1419    unsafe fn service_client_handle(
1420        &self,
1421        entry_index: usize,
1422    ) -> Option<&session::RmwServiceClient> {
1423        unsafe { Executor::service_client_handle(self, entry_index) }
1424    }
1425
1426    #[doc(hidden)]
1427    #[inline]
1428    unsafe fn service_server_handle(
1429        &self,
1430        entry_index: usize,
1431    ) -> Option<&session::RmwServiceServer> {
1432        unsafe { Executor::service_server_handle(self, entry_index) }
1433    }
1434
1435    #[inline]
1436    fn set_park_primitive(
1437        &mut self,
1438        park: ParkUntilFn,
1439        ctx: *mut core::ffi::c_void,
1440        granularity_us: u64,
1441    ) {
1442        Executor::set_park_primitive(self, park, ctx, granularity_us)
1443    }
1444
1445    #[inline]
1446    fn set_wake_hook(&mut self, hook: Option<WakeHookFn>, ctx: *mut core::ffi::c_void) -> bool {
1447        Executor::set_wake_hook(self, hook, ctx)
1448    }
1449
1450    #[doc(hidden)]
1451    #[inline]
1452    unsafe fn subscription_handle(&self, entry_index: usize) -> Option<&session::RmwSubscriber> {
1453        unsafe { Executor::subscription_handle(self, entry_index) }
1454    }
1455
1456    #[doc(hidden)]
1457    #[inline]
1458    unsafe fn subscription_handle_mut(
1459        &mut self,
1460        entry_index: usize,
1461    ) -> Option<&mut session::RmwSubscriber> {
1462        unsafe { Executor::subscription_handle_mut(self, entry_index) }
1463    }
1464
1465    #[cfg(all(feature = "alloc", feature = "rmw-cffi"))]
1466    #[inline]
1467    fn wake_raw_ptr(&self) -> *mut core::ffi::c_void {
1468        Executor::wake_raw_ptr(self)
1469    }
1470
1471    #[inline]
1472    fn enter_spin_loop(&self) {
1473        Executor::enter_spin_loop(self)
1474    }
1475
1476    #[inline]
1477    fn exit_spin_loop(&self) {
1478        Executor::exit_spin_loop(self)
1479    }
1480
1481    #[inline]
1482    fn exec_lock(&self) -> Option<super::exec_lock::ExecLock> {
1483        Executor::exec_lock(self)
1484    }
1485
1486    #[inline]
1487    fn node_session_mut(
1488        &mut self,
1489        node_id: super::node_record::NodeId,
1490    ) -> Option<&mut session::ConcreteSession> {
1491        Executor::node_session_mut(self, node_id)
1492    }
1493
1494    #[doc(hidden)]
1495    #[allow(clippy::too_many_arguments)]
1496    #[inline]
1497    fn register_action_client_raw(
1498        &mut self,
1499        spec: RawActionClientSpec<'_>,
1500    ) -> Result<ActionClientRawHandle, NodeError> {
1501        Executor::register_action_client_raw(self, spec)
1502    }
1503
1504    #[doc(hidden)]
1505    #[allow(clippy::too_many_arguments)]
1506    #[inline]
1507    fn register_action_server_raw(
1508        &mut self,
1509        spec: RawActionServerSpec<'_>,
1510    ) -> Result<ActionServerRawHandle, NodeError> {
1511        Executor::register_action_server_raw(self, spec)
1512    }
1513
1514    #[cfg(all(feature = "alloc", feature = "rmw-cffi"))]
1515    #[inline]
1516    fn install_wake_signal_on_primary(&mut self) {
1517        Executor::install_wake_signal_on_primary(self)
1518    }
1519
1520    #[inline]
1521    fn set_entry_owner(&mut self, id: HandleId, node: crate::executor::NodeId) -> bool {
1522        Executor::set_entry_owner(self, id, node)
1523    }
1524
1525    #[inline]
1526    fn set_primary_identity(&mut self, rmw_name: &str, locator: &str) {
1527        Executor::set_primary_identity(self, rmw_name, locator)
1528    }
1529
1530    #[inline]
1531    fn session_io_failures(&self) -> u32 {
1532        Executor::session_io_failures(self)
1533    }
1534
1535    #[inline]
1536    fn timer_elapsed_us(&self, id: HandleId) -> Option<u64> {
1537        Executor::timer_elapsed_us(self, id)
1538    }
1539
1540    #[inline]
1541    fn timer_is_ready(&self, id: HandleId) -> Option<bool> {
1542        Executor::timer_is_ready(self, id)
1543    }
1544
1545    #[inline]
1546    fn exchange_timer_period_us(&mut self, id: HandleId, new_period_us: u64) -> Option<u64> {
1547        Executor::exchange_timer_period_us(self, id, new_period_us)
1548    }
1549
1550    #[doc(hidden)]
1551    #[inline]
1552    unsafe fn action_client_core_mut(
1553        &mut self,
1554        entry_index: usize,
1555    ) -> Option<&mut super::action_core::ActionClientCore> {
1556        unsafe { Executor::action_client_core_mut(self, entry_index) }
1557    }
1558
1559    #[allow(clippy::too_many_arguments)]
1560    #[inline]
1561    fn register_service_client_raw_sized_on<const REPLY_BUF: usize>(
1562        &mut self,
1563        node_id: super::node_record::NodeId,
1564        service_name: &str,
1565        service_type: &str,
1566        service_hash: &str,
1567        qos: QoSProfile,
1568        callback: Option<RawResponseCallback>,
1569        context: *mut core::ffi::c_void,
1570    ) -> Result<HandleId, NodeError> {
1571        Executor::register_service_client_raw_sized_on::<REPLY_BUF>(
1572            self,
1573            node_id,
1574            service_name,
1575            service_type,
1576            service_hash,
1577            qos,
1578            callback,
1579            context,
1580        )
1581    }
1582
1583    #[allow(clippy::too_many_arguments)]
1584    #[inline]
1585    fn register_service_raw_sized_on<const REQ_BUF: usize, const REPLY_BUF: usize>(
1586        &mut self,
1587        node_id: super::node_record::NodeId,
1588        service_name: &str,
1589        service_type: &str,
1590        service_hash: &str,
1591        qos: QoSProfile,
1592        callback: RawServiceCallback,
1593        context: *mut core::ffi::c_void,
1594    ) -> Result<HandleId, NodeError> {
1595        Executor::register_service_raw_sized_on::<REQ_BUF, REPLY_BUF>(
1596            self,
1597            node_id,
1598            service_name,
1599            service_type,
1600            service_hash,
1601            qos,
1602            callback,
1603            context,
1604        )
1605    }
1606
1607    #[inline]
1608    unsafe fn service_client_entry_mut(
1609        &mut self,
1610        entry_index: usize,
1611    ) -> Option<&mut super::arena::ServiceClientRawArenaEntry<{ crate::config::DEFAULT_RX_BUF_SIZE }>>
1612    {
1613        unsafe { Executor::service_client_entry_mut(self, entry_index) }
1614    }
1615
1616    #[cfg(feature = "alloc")]
1617    #[inline]
1618    unsafe fn from_session_ptr(session_ptr: *mut session::ConcreteSession) -> Executor<'static> {
1619        unsafe { Executor::<'static>::from_session_ptr(session_ptr) }
1620    }
1621
1622    #[inline]
1623    unsafe fn from_session_in(
1624        session: session::ConcreteSession,
1625        backing: &'s mut [MaybeUninit<u64>],
1626        sizing: super::storage::ExecutorSizing,
1627    ) -> Self {
1628        unsafe { Executor::from_session_in(session, backing, sizing) }
1629    }
1630
1631    #[inline]
1632    unsafe fn open_with_session_in(
1633        session: *mut session::ConcreteSession,
1634        backing: &'s mut [MaybeUninit<u64>],
1635        sizing: super::storage::ExecutorSizing,
1636    ) -> Self {
1637        unsafe { Executor::open_with_session_in(session, backing, sizing) }
1638    }
1639
1640    #[cfg(feature = "alloc")]
1641    #[inline]
1642    unsafe fn open_with_session_slot(
1643        session: *mut session::ConcreteSession,
1644        slot: &'s mut super::TierExecutorBackingSlot,
1645    ) -> Self {
1646        unsafe { Executor::open_with_session_slot(session, slot) }
1647    }
1648
1649    #[cfg(feature = "alloc")]
1650    #[inline]
1651    unsafe fn open_with_session_handle_slot(
1652        handle: SessionHandle,
1653        slot: &'s mut super::TierExecutorBackingSlot,
1654    ) -> Self {
1655        unsafe { Executor::open_with_session_handle_slot(handle, slot) }
1656    }
1657
1658    #[inline]
1659    unsafe fn detach_action_client_raw(&mut self, entry_index: usize) -> bool {
1660        unsafe { Executor::detach_action_client_raw(self, entry_index) }
1661    }
1662
1663    #[inline]
1664    unsafe fn detach_action_server_raw(&mut self, handle: &ActionServerRawHandle) -> bool {
1665        unsafe { Executor::detach_action_server_raw(self, handle) }
1666    }
1667
1668    #[inline]
1669    unsafe fn detach_action_server_raw_sized<
1670        const GOAL_BUF: usize,
1671        const RESULT_BUF: usize,
1672        const FEEDBACK_BUF: usize,
1673        const MAX_GOALS: usize,
1674    >(
1675        &mut self,
1676        entry_index: usize,
1677    ) -> bool {
1678        unsafe {
1679            Executor::detach_action_server_raw_sized::<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF, MAX_GOALS>(
1680                self,
1681                entry_index,
1682            )
1683        }
1684    }
1685
1686    #[inline]
1687    unsafe fn release_action_client_raw_sized<
1688        const GOAL_BUF: usize,
1689        const RESULT_BUF: usize,
1690        const FEEDBACK_BUF: usize,
1691    >(
1692        &mut self,
1693        entry_index: usize,
1694    ) -> bool {
1695        unsafe {
1696            Executor::release_action_client_raw_sized::<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF>(
1697                self,
1698                entry_index,
1699            )
1700        }
1701    }
1702
1703    #[inline]
1704    unsafe fn release_action_server_raw_sized<
1705        const GOAL_BUF: usize,
1706        const RESULT_BUF: usize,
1707        const FEEDBACK_BUF: usize,
1708        const MAX_GOALS: usize,
1709    >(
1710        &mut self,
1711        entry_index: usize,
1712    ) -> bool {
1713        unsafe {
1714            Executor::release_action_server_raw_sized::<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF, MAX_GOALS>(
1715                self,
1716                entry_index,
1717            )
1718        }
1719    }
1720
1721    #[inline]
1722    fn register_service_raw(
1723        &mut self,
1724        service_name: &str,
1725        service_type: &str,
1726        service_hash: &str,
1727        callback: RawServiceCallback,
1728        context: *mut core::ffi::c_void,
1729    ) -> Result<HandleId, NodeError> {
1730        Executor::register_service_raw(
1731            self,
1732            service_name,
1733            service_type,
1734            service_hash,
1735            callback,
1736            context,
1737        )
1738    }
1739
1740    #[inline]
1741    fn register_service_client_raw(
1742        &mut self,
1743        service_name: &str,
1744        service_type: &str,
1745        service_hash: &str,
1746        callback: Option<RawResponseCallback>,
1747        context: *mut core::ffi::c_void,
1748    ) -> Result<HandleId, NodeError> {
1749        Executor::register_service_client_raw(
1750            self,
1751            service_name,
1752            service_type,
1753            service_hash,
1754            callback,
1755            context,
1756        )
1757    }
1758
1759    #[doc(hidden)]
1760    #[inline]
1761    fn register_action_client_core<
1762        const GOAL_BUF: usize,
1763        const RESULT_BUF: usize,
1764        const FEEDBACK_BUF: usize,
1765    >(
1766        &mut self,
1767        core: ActionClientCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF>,
1768        goal_response_callback: Option<RawGoalResponseCallback>,
1769        feedback_callback: Option<RawFeedbackCallback>,
1770        result_callback: Option<RawResultCallback>,
1771        cancel_response_callback: Option<RawCancelResponseCallback>,
1772        context: *mut core::ffi::c_void,
1773    ) -> Result<ActionClientRawHandle, NodeError> {
1774        Executor::register_action_client_core::<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF>(
1775            self,
1776            core,
1777            goal_response_callback,
1778            feedback_callback,
1779            result_callback,
1780            cancel_response_callback,
1781            context,
1782        )
1783    }
1784
1785    #[inline]
1786    unsafe fn release_guard_condition(&mut self, handle: HandleId) -> bool {
1787        unsafe { Executor::release_guard_condition(self, handle) }
1788    }
1789}
1790
1791// ── phase-515 R9 stage 2: the action cores and raw handles ─────────────
1792
1793impl<
1794    const GOAL_BUF: usize,
1795    const RESULT_BUF: usize,
1796    const FEEDBACK_BUF: usize,
1797    const MAX_GOALS: usize,
1798> sealed::Sealed for ActionServerCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF, MAX_GOALS>
1799{
1800}
1801impl<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize> sealed::Sealed
1802    for ActionClientCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF>
1803{
1804}
1805impl sealed::Sealed for ActionServerRawHandle {}
1806impl sealed::Sealed for ActionClientRawHandle {}
1807
1808/// [`ActionServerCore`]'s methods, for `nros-c`, `nros-cpp` and the `nros` runtime. Sealed.
1809pub trait ActionServerCoreFfi: sealed::Sealed + Sized {
1810    /// The FFI entry point; see `ActionServerCore::from_channels` in `action_core.rs`.
1811    fn from_channels(
1812        send_goal_server: session::RmwServiceServer,
1813        cancel_goal_server: session::RmwServiceServer,
1814        get_result_server: session::RmwServiceServer,
1815        feedback_publisher: session::RmwPublisher,
1816        status_publisher: session::RmwPublisher,
1817    ) -> Self;
1818
1819    /// The FFI entry point; see `ActionServerCore::try_recv_goal_request` in `action_core.rs`.
1820    fn try_recv_goal_request(&mut self) -> Result<Option<RawGoalRequest>, NodeError>;
1821
1822    /// The FFI entry point; see `ActionServerCore::goal_buffer` in `action_core.rs`.
1823    fn goal_buffer(&self) -> &[u8];
1824
1825    /// The FFI entry point; see `ActionServerCore::accept_goal` in `action_core.rs`.
1826    fn accept_goal(&mut self, goal_id: GoalUuid, seq: i64) -> Result<(), NodeError>;
1827
1828    /// The FFI entry point; see `ActionServerCore::reject_goal` in `action_core.rs`.
1829    fn reject_goal(&mut self, seq: i64) -> Result<(), NodeError>;
1830
1831    /// The FFI entry point; see `ActionServerCore::publish_feedback_raw` in `action_core.rs`.
1832    fn publish_feedback_raw(
1833        &mut self,
1834        goal_id: &GoalUuid,
1835        feedback_cdr: &[u8],
1836    ) -> Result<(), NodeError>;
1837
1838    /// The FFI entry point; see `ActionServerCore::set_goal_status` in `action_core.rs`.
1839    fn set_goal_status(&mut self, goal_id: &GoalUuid, status: GoalStatusCode);
1840
1841    /// The FFI entry point; see `ActionServerCore::expire_completed_results` in `action_core.rs`.
1842    fn expire_completed_results(&mut self) -> usize;
1843
1844    /// The FFI entry point; see `ActionServerCore::completed_result_count` in `action_core.rs`.
1845    fn completed_result_count(&self) -> usize;
1846
1847    /// The FFI entry point; see `ActionServerCore::result_slab_used` in `action_core.rs`.
1848    fn result_slab_used(&self) -> usize;
1849
1850    /// The FFI entry point; see `ActionServerCore::goal_exists` in `action_core.rs`.
1851    fn goal_exists(&self, goal_id: &GoalUuid) -> bool;
1852
1853    /// The FFI entry point; see `ActionServerCore::has_completed_result` in `action_core.rs`.
1854    fn has_completed_result(&self, goal_id: &GoalUuid) -> bool;
1855
1856    /// The FFI entry point; see `ActionServerCore::complete_goal_raw` in `action_core.rs`.
1857    fn complete_goal_raw(
1858        &mut self,
1859        goal_id: &GoalUuid,
1860        status: GoalStatusCode,
1861        result_cdr: &[u8],
1862    ) -> Result<(), NodeError>;
1863
1864    /// The FFI entry point; see `ActionServerCore::register_goal_waker` in `action_core.rs`.
1865    fn register_goal_waker(&self, waker: &core::task::Waker) -> bool;
1866
1867    /// The FFI entry point; see `ActionServerCore::register_cancel_waker` in `action_core.rs`.
1868    fn register_cancel_waker(&self, waker: &core::task::Waker) -> bool;
1869
1870    /// The FFI entry point; see `ActionServerCore::register_get_result_waker` in `action_core.rs`.
1871    fn register_get_result_waker(&self, waker: &core::task::Waker) -> bool;
1872
1873    /// The FFI entry point; see `ActionServerCore::try_recv_cancel_request` in `action_core.rs`.
1874    fn try_recv_cancel_request(&mut self) -> Result<Option<PendingCancelRequest>, NodeError>;
1875
1876    /// The FFI entry point; see `ActionServerCore::send_cancel_reply` in `action_core.rs`.
1877    fn send_cancel_reply(
1878        &mut self,
1879        sequence_number: i64,
1880        return_code: nros_core::CancelResponseCode,
1881        accepted: &[GoalUuid],
1882    ) -> Result<(), NodeError>;
1883
1884    /// The FFI entry point; see `ActionServerCore::try_handle_cancel` in `action_core.rs`.
1885    fn try_handle_cancel(
1886        &mut self,
1887        cancel_handler: impl FnMut(&GoalUuid, GoalStatusCode) -> nros_core::CancelResponse,
1888    ) -> Result<Option<(GoalUuid, nros_core::CancelResponse)>, NodeError>;
1889
1890    /// The FFI entry point; see `ActionServerCore::try_handle_get_result_raw` in `action_core.rs`.
1891    fn try_handle_get_result_raw(
1892        &mut self,
1893        default_result_cdr: &[u8],
1894    ) -> Result<Option<GoalUuid>, NodeError>;
1895
1896    /// The FFI entry point; see `ActionServerCore::active_goal_count` in `action_core.rs`.
1897    fn active_goal_count(&self) -> usize;
1898
1899    /// The FFI entry point; see `ActionServerCore::active_goals` in `action_core.rs`.
1900    fn active_goals(&self) -> &[RawActiveGoal];
1901
1902    /// The FFI entry point; see `ActionServerCore::goal_stamp` in `action_core.rs`.
1903    fn goal_stamp(&self, goal_id: &GoalUuid) -> Time;
1904
1905    /// The FFI entry point; see `ActionServerCore::find_goal_status` in `action_core.rs`.
1906    fn find_goal_status(&self, goal_id: &GoalUuid) -> GoalStatusCode;
1907
1908    /// The FFI entry point; see `ActionServerCore::publish_status_array` in `action_core.rs`.
1909    fn publish_status_array(&self) -> Result<(), NodeError>;
1910}
1911
1912impl<
1913    const GOAL_BUF: usize,
1914    const RESULT_BUF: usize,
1915    const FEEDBACK_BUF: usize,
1916    const MAX_GOALS: usize,
1917> ActionServerCoreFfi for ActionServerCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF, MAX_GOALS>
1918{
1919    #[inline]
1920    fn from_channels(
1921        send_goal_server: session::RmwServiceServer,
1922        cancel_goal_server: session::RmwServiceServer,
1923        get_result_server: session::RmwServiceServer,
1924        feedback_publisher: session::RmwPublisher,
1925        status_publisher: session::RmwPublisher,
1926    ) -> Self {
1927        Self::from_channels(
1928            send_goal_server,
1929            cancel_goal_server,
1930            get_result_server,
1931            feedback_publisher,
1932            status_publisher,
1933        )
1934    }
1935
1936    #[inline]
1937    fn try_recv_goal_request(&mut self) -> Result<Option<RawGoalRequest>, NodeError> {
1938        Self::try_recv_goal_request(self)
1939    }
1940
1941    #[inline]
1942    fn goal_buffer(&self) -> &[u8] {
1943        Self::goal_buffer(self)
1944    }
1945
1946    #[inline]
1947    fn accept_goal(&mut self, goal_id: GoalUuid, seq: i64) -> Result<(), NodeError> {
1948        Self::accept_goal(self, goal_id, seq)
1949    }
1950
1951    #[inline]
1952    fn reject_goal(&mut self, seq: i64) -> Result<(), NodeError> {
1953        Self::reject_goal(self, seq)
1954    }
1955
1956    #[inline]
1957    fn publish_feedback_raw(
1958        &mut self,
1959        goal_id: &GoalUuid,
1960        feedback_cdr: &[u8],
1961    ) -> Result<(), NodeError> {
1962        Self::publish_feedback_raw(self, goal_id, feedback_cdr)
1963    }
1964
1965    #[inline]
1966    fn set_goal_status(&mut self, goal_id: &GoalUuid, status: GoalStatusCode) {
1967        Self::set_goal_status(self, goal_id, status)
1968    }
1969
1970    #[inline]
1971    fn expire_completed_results(&mut self) -> usize {
1972        Self::expire_completed_results(self)
1973    }
1974
1975    #[inline]
1976    fn completed_result_count(&self) -> usize {
1977        Self::completed_result_count(self)
1978    }
1979
1980    #[inline]
1981    fn result_slab_used(&self) -> usize {
1982        Self::result_slab_used(self)
1983    }
1984
1985    #[inline]
1986    fn goal_exists(&self, goal_id: &GoalUuid) -> bool {
1987        Self::goal_exists(self, goal_id)
1988    }
1989
1990    #[inline]
1991    fn has_completed_result(&self, goal_id: &GoalUuid) -> bool {
1992        Self::has_completed_result(self, goal_id)
1993    }
1994
1995    #[inline]
1996    fn complete_goal_raw(
1997        &mut self,
1998        goal_id: &GoalUuid,
1999        status: GoalStatusCode,
2000        result_cdr: &[u8],
2001    ) -> Result<(), NodeError> {
2002        Self::complete_goal_raw(self, goal_id, status, result_cdr)
2003    }
2004
2005    #[inline]
2006    fn register_goal_waker(&self, waker: &core::task::Waker) -> bool {
2007        Self::register_goal_waker(self, waker)
2008    }
2009
2010    #[inline]
2011    fn register_cancel_waker(&self, waker: &core::task::Waker) -> bool {
2012        Self::register_cancel_waker(self, waker)
2013    }
2014
2015    #[inline]
2016    fn register_get_result_waker(&self, waker: &core::task::Waker) -> bool {
2017        Self::register_get_result_waker(self, waker)
2018    }
2019
2020    #[inline]
2021    fn try_recv_cancel_request(&mut self) -> Result<Option<PendingCancelRequest>, NodeError> {
2022        Self::try_recv_cancel_request(self)
2023    }
2024
2025    #[inline]
2026    fn send_cancel_reply(
2027        &mut self,
2028        sequence_number: i64,
2029        return_code: nros_core::CancelResponseCode,
2030        accepted: &[GoalUuid],
2031    ) -> Result<(), NodeError> {
2032        Self::send_cancel_reply(self, sequence_number, return_code, accepted)
2033    }
2034
2035    #[inline]
2036    fn try_handle_cancel(
2037        &mut self,
2038        cancel_handler: impl FnMut(&GoalUuid, GoalStatusCode) -> nros_core::CancelResponse,
2039    ) -> Result<Option<(GoalUuid, nros_core::CancelResponse)>, NodeError> {
2040        Self::try_handle_cancel(self, cancel_handler)
2041    }
2042
2043    #[inline]
2044    fn try_handle_get_result_raw(
2045        &mut self,
2046        default_result_cdr: &[u8],
2047    ) -> Result<Option<GoalUuid>, NodeError> {
2048        Self::try_handle_get_result_raw(self, default_result_cdr)
2049    }
2050
2051    #[inline]
2052    fn active_goal_count(&self) -> usize {
2053        Self::active_goal_count(self)
2054    }
2055
2056    #[inline]
2057    fn active_goals(&self) -> &[RawActiveGoal] {
2058        Self::active_goals(self)
2059    }
2060
2061    #[inline]
2062    fn goal_stamp(&self, goal_id: &GoalUuid) -> Time {
2063        Self::goal_stamp(self, goal_id)
2064    }
2065
2066    #[inline]
2067    fn find_goal_status(&self, goal_id: &GoalUuid) -> GoalStatusCode {
2068        Self::find_goal_status(self, goal_id)
2069    }
2070
2071    #[inline]
2072    fn publish_status_array(&self) -> Result<(), NodeError> {
2073        Self::publish_status_array(self)
2074    }
2075}
2076
2077/// [`ActionClientCore`]'s methods, for `nros-c`, `nros-cpp` and the `nros` runtime. Sealed.
2078pub trait ActionClientCoreFfi: sealed::Sealed + Sized {
2079    /// The FFI entry point; see `ActionClientCore::is_server_ready` in `action_core.rs`.
2080    fn is_server_ready(&self) -> bool;
2081
2082    /// The FFI entry point; see `ActionClientCore::server_readiness` in `action_core.rs`.
2083    fn server_readiness(&self) -> Result<bool, nros_rmw::TransportError>;
2084
2085    /// The FFI entry point; see `ActionClientCore::new` in `action_core.rs`.
2086    fn new(
2087        send_goal_client: session::RmwServiceClient,
2088        cancel_goal_client: session::RmwServiceClient,
2089        get_result_client: session::RmwServiceClient,
2090        feedback_subscriber: session::RmwSubscriber,
2091    ) -> Self;
2092
2093    /// The FFI entry point; see `ActionClientCore::send_goal_raw` in `action_core.rs`.
2094    fn send_goal_raw(&mut self, goal_cdr: &[u8]) -> Result<GoalUuid, NodeError>;
2095
2096    /// The FFI entry point; see `ActionClientCore::try_recv_feedback_raw` in `action_core.rs`.
2097    fn try_recv_feedback_raw(&mut self) -> Result<Option<(GoalUuid, usize)>, NodeError>;
2098
2099    /// The FFI entry point; see `ActionClientCore::send_cancel_request` in `action_core.rs`.
2100    fn send_cancel_request(&mut self, goal_id: &GoalUuid) -> Result<(), NodeError>;
2101
2102    /// The FFI entry point; see `ActionClientCore::send_cancel_request_stamped` in `action_core.rs`.
2103    fn send_cancel_request_stamped(
2104        &mut self,
2105        goal_id: &GoalUuid,
2106        stamp_sec: i32,
2107        stamp_nanosec: u32,
2108    ) -> Result<i64, NodeError>;
2109
2110    /// The FFI entry point; see `ActionClientCore::send_get_result_request` in `action_core.rs`.
2111    fn send_get_result_request(&mut self, goal_id: &GoalUuid) -> Result<(), NodeError>;
2112
2113    /// The FFI entry point; see `ActionClientCore::register_goal_response_waker` in `action_core.rs`.
2114    fn register_goal_response_waker(&self, waker: &core::task::Waker) -> bool;
2115
2116    /// The FFI entry point; see `ActionClientCore::register_cancel_response_waker` in `action_core.rs`.
2117    fn register_cancel_response_waker(&self, waker: &core::task::Waker) -> bool;
2118
2119    /// The FFI entry point; see `ActionClientCore::register_result_waker` in `action_core.rs`.
2120    fn register_result_waker(&self, waker: &core::task::Waker) -> bool;
2121
2122    /// The FFI entry point; see `ActionClientCore::register_feedback_waker` in `action_core.rs`.
2123    fn register_feedback_waker(&self, waker: &core::task::Waker) -> bool;
2124
2125    /// The FFI entry point; see `ActionClientCore::try_recv_cancel_reply` in `action_core.rs`.
2126    fn try_recv_cancel_reply(&mut self) -> Result<Option<usize>, NodeError>;
2127
2128    /// The FFI entry point; see `ActionClientCore::try_recv_cancel_reply_for` in `action_core.rs`.
2129    fn try_recv_cancel_reply_for(&mut self) -> Result<Option<(usize, GoalUuid)>, NodeError>;
2130
2131    /// The FFI entry point; see `ActionClientCore::try_recv_cancel_reply_seq` in `action_core.rs`.
2132    fn try_recv_cancel_reply_seq(&mut self) -> Result<Option<(usize, i64, GoalUuid)>, NodeError>;
2133
2134    /// The FFI entry point; see `ActionClientCore::try_recv_get_result_reply` in `action_core.rs`.
2135    fn try_recv_get_result_reply(&mut self) -> Result<Option<usize>, NodeError>;
2136
2137    /// The FFI entry point; see `ActionClientCore::try_recv_get_result_reply_for` in `action_core.rs`.
2138    fn try_recv_get_result_reply_for(&mut self) -> Result<Option<(usize, GoalUuid)>, NodeError>;
2139
2140    /// The FFI entry point; see `ActionClientCore::try_recv_send_goal_reply` in `action_core.rs`.
2141    fn try_recv_send_goal_reply(&mut self) -> Result<Option<usize>, NodeError>;
2142
2143    /// The FFI entry point; see `ActionClientCore::try_recv_send_goal_reply_for` in `action_core.rs`.
2144    fn try_recv_send_goal_reply_for(&mut self) -> Result<Option<(usize, GoalUuid)>, NodeError>;
2145
2146    /// The FFI entry point; see `ActionClientCore::forget_send_goal` in `action_core.rs`.
2147    fn forget_send_goal(&mut self, goal_id: &GoalUuid) -> bool;
2148
2149    /// The FFI entry point; see `ActionClientCore::forget_get_result` in `action_core.rs`.
2150    fn forget_get_result(&mut self, goal_id: &GoalUuid) -> bool;
2151
2152    /// The FFI entry point; see `ActionClientCore::forget_cancel` in `action_core.rs`.
2153    fn forget_cancel(&mut self, goal_id: &GoalUuid) -> bool;
2154
2155    /// The FFI entry point; see `ActionClientCore::result_buffer_ref` in `action_core.rs`.
2156    fn result_buffer_ref(&self) -> &[u8];
2157
2158    /// The FFI entry point; see `ActionClientCore::feedback_buffer_ref` in `action_core.rs`.
2159    fn feedback_buffer_ref(&self) -> &[u8];
2160
2161    /// The FFI entry point; see `ActionClientCore::goal_counter` in `action_core.rs`.
2162    fn goal_counter(&self) -> u64;
2163}
2164
2165impl<const GOAL_BUF: usize, const RESULT_BUF: usize, const FEEDBACK_BUF: usize> ActionClientCoreFfi
2166    for ActionClientCore<GOAL_BUF, RESULT_BUF, FEEDBACK_BUF>
2167{
2168    #[inline]
2169    fn is_server_ready(&self) -> bool {
2170        Self::is_server_ready(self)
2171    }
2172
2173    #[inline]
2174    fn server_readiness(&self) -> Result<bool, nros_rmw::TransportError> {
2175        Self::server_readiness(self)
2176    }
2177
2178    #[inline]
2179    fn new(
2180        send_goal_client: session::RmwServiceClient,
2181        cancel_goal_client: session::RmwServiceClient,
2182        get_result_client: session::RmwServiceClient,
2183        feedback_subscriber: session::RmwSubscriber,
2184    ) -> Self {
2185        Self::new(
2186            send_goal_client,
2187            cancel_goal_client,
2188            get_result_client,
2189            feedback_subscriber,
2190        )
2191    }
2192
2193    #[inline]
2194    fn send_goal_raw(&mut self, goal_cdr: &[u8]) -> Result<GoalUuid, NodeError> {
2195        Self::send_goal_raw(self, goal_cdr)
2196    }
2197
2198    #[inline]
2199    fn try_recv_feedback_raw(&mut self) -> Result<Option<(GoalUuid, usize)>, NodeError> {
2200        Self::try_recv_feedback_raw(self)
2201    }
2202
2203    #[inline]
2204    fn send_cancel_request(&mut self, goal_id: &GoalUuid) -> Result<(), NodeError> {
2205        Self::send_cancel_request(self, goal_id)
2206    }
2207
2208    #[inline]
2209    fn send_cancel_request_stamped(
2210        &mut self,
2211        goal_id: &GoalUuid,
2212        stamp_sec: i32,
2213        stamp_nanosec: u32,
2214    ) -> Result<i64, NodeError> {
2215        Self::send_cancel_request_stamped(self, goal_id, stamp_sec, stamp_nanosec)
2216    }
2217
2218    #[inline]
2219    fn send_get_result_request(&mut self, goal_id: &GoalUuid) -> Result<(), NodeError> {
2220        Self::send_get_result_request(self, goal_id)
2221    }
2222
2223    #[inline]
2224    fn register_goal_response_waker(&self, waker: &core::task::Waker) -> bool {
2225        Self::register_goal_response_waker(self, waker)
2226    }
2227
2228    #[inline]
2229    fn register_cancel_response_waker(&self, waker: &core::task::Waker) -> bool {
2230        Self::register_cancel_response_waker(self, waker)
2231    }
2232
2233    #[inline]
2234    fn register_result_waker(&self, waker: &core::task::Waker) -> bool {
2235        Self::register_result_waker(self, waker)
2236    }
2237
2238    #[inline]
2239    fn register_feedback_waker(&self, waker: &core::task::Waker) -> bool {
2240        Self::register_feedback_waker(self, waker)
2241    }
2242
2243    #[inline]
2244    fn try_recv_cancel_reply(&mut self) -> Result<Option<usize>, NodeError> {
2245        Self::try_recv_cancel_reply(self)
2246    }
2247
2248    #[inline]
2249    fn try_recv_cancel_reply_for(&mut self) -> Result<Option<(usize, GoalUuid)>, NodeError> {
2250        Self::try_recv_cancel_reply_for(self)
2251    }
2252
2253    #[inline]
2254    fn try_recv_cancel_reply_seq(&mut self) -> Result<Option<(usize, i64, GoalUuid)>, NodeError> {
2255        Self::try_recv_cancel_reply_seq(self)
2256    }
2257
2258    #[inline]
2259    fn try_recv_get_result_reply(&mut self) -> Result<Option<usize>, NodeError> {
2260        Self::try_recv_get_result_reply(self)
2261    }
2262
2263    #[inline]
2264    fn try_recv_get_result_reply_for(&mut self) -> Result<Option<(usize, GoalUuid)>, NodeError> {
2265        Self::try_recv_get_result_reply_for(self)
2266    }
2267
2268    #[inline]
2269    fn try_recv_send_goal_reply(&mut self) -> Result<Option<usize>, NodeError> {
2270        Self::try_recv_send_goal_reply(self)
2271    }
2272
2273    #[inline]
2274    fn try_recv_send_goal_reply_for(&mut self) -> Result<Option<(usize, GoalUuid)>, NodeError> {
2275        Self::try_recv_send_goal_reply_for(self)
2276    }
2277
2278    #[inline]
2279    fn forget_send_goal(&mut self, goal_id: &GoalUuid) -> bool {
2280        Self::forget_send_goal(self, goal_id)
2281    }
2282
2283    #[inline]
2284    fn forget_get_result(&mut self, goal_id: &GoalUuid) -> bool {
2285        Self::forget_get_result(self, goal_id)
2286    }
2287
2288    #[inline]
2289    fn forget_cancel(&mut self, goal_id: &GoalUuid) -> bool {
2290        Self::forget_cancel(self, goal_id)
2291    }
2292
2293    #[inline]
2294    fn result_buffer_ref(&self) -> &[u8] {
2295        Self::result_buffer_ref(self)
2296    }
2297
2298    #[inline]
2299    fn feedback_buffer_ref(&self) -> &[u8] {
2300        Self::feedback_buffer_ref(self)
2301    }
2302
2303    #[inline]
2304    fn goal_counter(&self) -> u64 {
2305        Self::goal_counter(self)
2306    }
2307}
2308
2309/// [`ActionServerRawHandle`]'s methods, for `nros-c`, `nros-cpp` and the `nros` runtime. Sealed.
2310pub trait ActionServerRawHandleFfi: sealed::Sealed + Sized {
2311    /// The FFI entry point; see `ActionServerRawHandle::invalid` in `action.rs`
2312    /// (a `const fn` there; a trait method cannot be one).
2313    fn invalid() -> Self;
2314
2315    /// The FFI entry point; see `ActionServerRawHandle::is_invalid` in `action.rs`.
2316    fn is_invalid(&self) -> bool;
2317
2318    /// The FFI entry point; see `ActionServerRawHandle::handle_id` in `action.rs`.
2319    fn handle_id(&self) -> HandleId;
2320
2321    /// The FFI entry point; see `ActionServerRawHandle::publish_feedback_raw` in `action.rs`.
2322    fn publish_feedback_raw(
2323        &self,
2324        executor: &mut Executor,
2325        goal_id: &nros_core::GoalUuid,
2326        feedback_data: &[u8],
2327    ) -> Result<(), NodeError>;
2328
2329    /// The FFI entry point; see `ActionServerRawHandle::complete_goal_raw` in `action.rs`.
2330    fn complete_goal_raw(
2331        &self,
2332        executor: &mut Executor,
2333        goal_id: &nros_core::GoalUuid,
2334        status: nros_core::GoalStatusCode,
2335        result_data: &[u8],
2336    ) -> Result<(), NodeError>;
2337
2338    /// The FFI entry point; see `ActionServerRawHandle::set_goal_status` in `action.rs`.
2339    fn set_goal_status(
2340        &self,
2341        executor: &mut Executor,
2342        goal_id: &nros_core::GoalUuid,
2343        status: nros_core::GoalStatusCode,
2344    );
2345
2346    /// The FFI entry point; see `ActionServerRawHandle::active_goal_count` in `action.rs`.
2347    fn active_goal_count(&self, executor: &Executor) -> usize;
2348
2349    /// The FFI entry point; see `ActionServerRawHandle::goal_exists` in `action.rs`.
2350    fn goal_exists(&self, executor: &Executor, goal_id: &nros_core::GoalUuid) -> bool;
2351
2352    /// The FFI entry point; see `ActionServerRawHandle::expire_goals` in `action.rs`.
2353    fn expire_goals(&self, executor: &mut Executor) -> usize;
2354
2355    /// The FFI entry point; see `ActionServerRawHandle::for_each_active_goal` in `action.rs`.
2356    fn for_each_active_goal(&self, executor: &Executor, f: impl FnMut(&RawActiveGoal));
2357
2358    /// The FFI entry point; see `ActionServerRawHandle::goal_status` in `action.rs`.
2359    fn goal_status(
2360        &self,
2361        executor: &Executor,
2362        goal_id: &nros_core::GoalUuid,
2363    ) -> Option<nros_core::GoalStatusCode>;
2364}
2365
2366impl ActionServerRawHandleFfi for ActionServerRawHandle {
2367    #[inline]
2368    fn invalid() -> Self {
2369        Self::invalid()
2370    }
2371
2372    #[inline]
2373    fn is_invalid(&self) -> bool {
2374        Self::is_invalid(self)
2375    }
2376
2377    #[inline]
2378    fn handle_id(&self) -> HandleId {
2379        Self::handle_id(self)
2380    }
2381
2382    #[inline]
2383    fn publish_feedback_raw(
2384        &self,
2385        executor: &mut Executor,
2386        goal_id: &nros_core::GoalUuid,
2387        feedback_data: &[u8],
2388    ) -> Result<(), NodeError> {
2389        Self::publish_feedback_raw(self, executor, goal_id, feedback_data)
2390    }
2391
2392    #[inline]
2393    fn complete_goal_raw(
2394        &self,
2395        executor: &mut Executor,
2396        goal_id: &nros_core::GoalUuid,
2397        status: nros_core::GoalStatusCode,
2398        result_data: &[u8],
2399    ) -> Result<(), NodeError> {
2400        Self::complete_goal_raw(self, executor, goal_id, status, result_data)
2401    }
2402
2403    #[inline]
2404    fn set_goal_status(
2405        &self,
2406        executor: &mut Executor,
2407        goal_id: &nros_core::GoalUuid,
2408        status: nros_core::GoalStatusCode,
2409    ) {
2410        Self::set_goal_status(self, executor, goal_id, status)
2411    }
2412
2413    #[inline]
2414    fn active_goal_count(&self, executor: &Executor) -> usize {
2415        Self::active_goal_count(self, executor)
2416    }
2417
2418    #[inline]
2419    fn goal_exists(&self, executor: &Executor, goal_id: &nros_core::GoalUuid) -> bool {
2420        Self::goal_exists(self, executor, goal_id)
2421    }
2422
2423    #[inline]
2424    fn expire_goals(&self, executor: &mut Executor) -> usize {
2425        Self::expire_goals(self, executor)
2426    }
2427
2428    #[inline]
2429    fn for_each_active_goal(&self, executor: &Executor, f: impl FnMut(&RawActiveGoal)) {
2430        Self::for_each_active_goal(self, executor, f)
2431    }
2432
2433    #[inline]
2434    fn goal_status(
2435        &self,
2436        executor: &Executor,
2437        goal_id: &nros_core::GoalUuid,
2438    ) -> Option<nros_core::GoalStatusCode> {
2439        Self::goal_status(self, executor, goal_id)
2440    }
2441}
2442
2443/// [`ActionClientRawHandle`]'s methods, for `nros-c`, `nros-cpp` and the `nros` runtime. Sealed.
2444pub trait ActionClientRawHandleFfi: sealed::Sealed + Sized {
2445    /// The FFI entry point; see `ActionClientRawHandle::entry_index` in `action.rs`.
2446    fn entry_index(&self) -> usize;
2447}
2448
2449impl ActionClientRawHandleFfi for ActionClientRawHandle {
2450    #[inline]
2451    fn entry_index(&self) -> usize {
2452        Self::entry_index(self)
2453    }
2454}