From 7f1cbe8375bc5e5104c6a89e70c4db9b2a6799a7 Mon Sep 17 00:00:00 2001 From: Christian Eltzschig Date: Fri, 25 Oct 2024 11:40:32 +0200 Subject: [PATCH] [#488] Implement streaming operator for WaitSetAttachmentId --- iceoryx2-ffi/cxx/include/iox2/waitset.hpp | 5 ++ iceoryx2-ffi/cxx/src/waitset.cpp | 11 ++++ .../ffi/src/api/waitset_attachment_id.rs | 60 ++++++++++++++++++- iceoryx2/src/port/waitset.rs | 13 +++- 4 files changed, 87 insertions(+), 2 deletions(-) diff --git a/iceoryx2-ffi/cxx/include/iox2/waitset.hpp b/iceoryx2-ffi/cxx/include/iox2/waitset.hpp index 2addf55b1..a1884a02a 100644 --- a/iceoryx2-ffi/cxx/include/iox2/waitset.hpp +++ b/iceoryx2-ffi/cxx/include/iox2/waitset.hpp @@ -80,6 +80,8 @@ class WaitSetAttachmentId { friend auto operator==(const WaitSetAttachmentId&, const WaitSetAttachmentId&) -> bool; template friend auto operator<(const WaitSetAttachmentId&, const WaitSetAttachmentId&) -> bool; + template + friend auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream&; void drop(); @@ -92,6 +94,9 @@ auto operator==(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& template auto operator<(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& rhs) -> bool; +template +auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream&; + /// The [`WaitSet`] implements a reactor pattern and allows to wait on multiple events in one /// single call [`WaitSet::try_wait_and_process()`] until it wakes up or to run repeatedly with /// [`WaitSet::wait_and_process()`] until the a interrupt or termination signal was received or the user diff --git a/iceoryx2-ffi/cxx/src/waitset.cpp b/iceoryx2-ffi/cxx/src/waitset.cpp index 6460cfb56..91a9d061b 100644 --- a/iceoryx2-ffi/cxx/src/waitset.cpp +++ b/iceoryx2-ffi/cxx/src/waitset.cpp @@ -78,6 +78,14 @@ auto operator<(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& return iox2_waitset_attachment_id_less(&lhs.m_handle, &rhs.m_handle); } +template +auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream& { + auto len = iox2_waitset_attachment_id_debug_len(&self.m_handle); + std::string empty(len, '\0'); + iox2_waitset_attachment_id_debug(&self.m_handle, empty.data(), len); + stream << empty; + return stream; +} //////////////////////////// // END: WaitSetAttachmentId @@ -328,4 +336,7 @@ template auto operator<(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& rhs) -> bool; template auto operator<(const WaitSetAttachmentId& lhs, const WaitSetAttachmentId& rhs) -> bool; +template auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream&; +template auto operator<<(std::ostream& stream, const WaitSetAttachmentId& self) -> std::ostream&; + } // namespace iox2 diff --git a/iceoryx2-ffi/ffi/src/api/waitset_attachment_id.rs b/iceoryx2-ffi/ffi/src/api/waitset_attachment_id.rs index 8f3147b29..8d03383da 100644 --- a/iceoryx2-ffi/ffi/src/api/waitset_attachment_id.rs +++ b/iceoryx2-ffi/ffi/src/api/waitset_attachment_id.rs @@ -12,7 +12,8 @@ #![allow(non_camel_case_types)] -use std::mem::ManuallyDrop; +use crate::c_size_t; +use std::{ffi::c_char, mem::ManuallyDrop}; use iceoryx2::{ prelude::WaitSetAttachmentId, @@ -303,4 +304,61 @@ pub unsafe extern "C" fn iox2_waitset_attachment_id_from_guard( *attachment_id_handle_ptr = (*attachment_id_struct_ptr).as_handle(); } + +/// Stores the debug output in the provided `debug_output` variable that must provide enough +/// memory to store the content. The content length can be acquired with +/// [`iox2_waitset_attachment_id_debug_len()`] +/// +/// # Safety +/// * `handle` must be valid and non-null. +/// * `debug_output` must be valid and provide enough memory +/// * `debug_len` the provided memory length of `debug_output` +#[no_mangle] +pub unsafe extern "C" fn iox2_waitset_attachment_id_debug( + handle: iox2_waitset_attachment_id_h_ref, + debug_output: *mut c_char, + debug_len: c_size_t, +) -> bool { + handle.assert_non_null(); + debug_assert!(!debug_output.is_null()); + + let attachment_id = &mut *handle.as_type(); + + let raw_str = match attachment_id.service_type { + iox2_service_type_e::IPC => format!("{:?}\0", *attachment_id.value.as_mut().ipc), + iox2_service_type_e::LOCAL => format!("{:?}\0", *attachment_id.value.as_mut().local), + }; + + if debug_len < raw_str.len() { + return false; + } + + std::ptr::copy_nonoverlapping( + raw_str.as_bytes().as_ptr().cast(), + debug_output, + raw_str.len(), + ); + + true +} + +/// Returns the length of the debug output. Shall be used before calling +/// [`iox2_waitset_attachment_id_debug()`] to acquire enough memory to store the output. +/// +/// # Safety +/// * `handle` must be valid and non-null. +#[no_mangle] +pub unsafe extern "C" fn iox2_waitset_attachment_id_debug_len( + handle: iox2_waitset_attachment_id_h_ref, +) -> c_size_t { + handle.assert_non_null(); + + let attachment_id = &mut *handle.as_type(); + + match attachment_id.service_type { + iox2_service_type_e::IPC => format!("{:?}\0", *attachment_id.value.as_mut().ipc).len(), + iox2_service_type_e::LOCAL => format!("{:?}\0", *attachment_id.value.as_mut().local).len(), + } +} + // END C API diff --git a/iceoryx2/src/port/waitset.rs b/iceoryx2/src/port/waitset.rs index 74f0a1e97..44f864731 100644 --- a/iceoryx2/src/port/waitset.rs +++ b/iceoryx2/src/port/waitset.rs @@ -274,12 +274,23 @@ enum AttachmentIdType { } /// Represents an attachment to the [`WaitSet`] -#[derive(Debug, Clone, Copy)] +#[derive(Clone, Copy)] pub struct WaitSetAttachmentId { attachment_type: AttachmentIdType, _data: PhantomData, } +impl Debug for WaitSetAttachmentId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "WaitSetAttachmentId<{}> {{ attachment_type: {:?} }}", + core::any::type_name::(), + self.attachment_type + ) + } +} + impl WaitSetAttachmentId { /// Creates an [`WaitSetAttachmentId`] from a [`WaitSetGuard`] that was returned via /// [`WaitSet::attach_interval()`], [`WaitSet::attach_notification()`] or