From 85cc6ee94b5b03b657ce07b24bfa0c4f645028a1 Mon Sep 17 00:00:00 2001 From: Mathias Kraus Date: Mon, 15 Jul 2024 05:01:10 +0200 Subject: [PATCH] [#210] Introduce HandleToType trait --- iceoryx2-ffi/ffi-macros/src/lib.rs | 11 +++++- iceoryx2-ffi/ffi/src/lib.rs | 6 +++ iceoryx2-ffi/ffi/src/node.rs | 58 ++++++++++++++++++---------- iceoryx2-ffi/ffi/src/node_builder.rs | 47 +++++++++++----------- iceoryx2-ffi/ffi/src/node_name.rs | 38 +++++++++++------- 5 files changed, 100 insertions(+), 60 deletions(-) diff --git a/iceoryx2-ffi/ffi-macros/src/lib.rs b/iceoryx2-ffi/ffi-macros/src/lib.rs index 4c2d1239..dab4ed51 100644 --- a/iceoryx2-ffi/ffi-macros/src/lib.rs +++ b/iceoryx2-ffi/ffi-macros/src/lib.rs @@ -60,9 +60,9 @@ pub fn iceoryx2_ffi(args: TokenStream, input: TokenStream) -> TokenStream { // Define all the names we need let struct_storage_name = format_ident!("iox2_{}_storage_t", stripped_struct_name); let _struct_h_t_name = format_ident!("iox2_{}_h_t", stripped_struct_name); - let _struct_h_name = format_ident!("iox2_{}_h", stripped_struct_name); + let struct_h_name = format_ident!("iox2_{}_h", stripped_struct_name); let _struct_ref_h_t_name = format_ident!("iox2_{}_ref_h_t", stripped_struct_name); - let _struct_ref_h_name = format_ident!("iox2_{}_ref_h", stripped_struct_name); + let struct_ref_h_name = format_ident!("iox2_{}_ref_h", stripped_struct_name); // NOTE: cbindgen does not play well with adding new structs or fields to existing structs; // this code is kept for reference @@ -128,6 +128,13 @@ pub fn iceoryx2_ffi(args: TokenStream, input: TokenStream) -> TokenStream { #my_struct impl #struct_name { + pub(crate) fn as_handle(&mut self) -> #struct_h_name { + self as *mut _ as _ + } + pub(crate) fn as_ref_handle(&mut self) -> #struct_ref_h_name { + self as *mut _ as _ + } + pub(crate) fn take(&mut self) -> Option<#my_type> { unsafe { self.value.as_option_mut().take() } } diff --git a/iceoryx2-ffi/ffi/src/lib.rs b/iceoryx2-ffi/ffi/src/lib.rs index 6dcb3fcb..1f3d0053 100644 --- a/iceoryx2-ffi/ffi/src/lib.rs +++ b/iceoryx2-ffi/ffi/src/lib.rs @@ -123,3 +123,9 @@ pub extern "C" fn zero_copy_service_list() -> i32 { trait IntoCInt { fn into_c_int(self) -> c_int; } + +pub trait HandleToType { + type Target; + + fn as_type(self) -> Self::Target; +} diff --git a/iceoryx2-ffi/ffi/src/node.rs b/iceoryx2-ffi/ffi/src/node.rs index 9497b3da..b6854008 100644 --- a/iceoryx2-ffi/ffi/src/node.rs +++ b/iceoryx2-ffi/ffi/src/node.rs @@ -14,7 +14,8 @@ use crate::{ iox2_callback_progression_e, iox2_config_ptr, iox2_node_name_ptr, iox2_service_builder_h, - iox2_service_builder_t, iox2_service_name_h, iox2_service_type_e, IntoCInt, IOX2_OK, + iox2_service_builder_t, iox2_service_name_h, iox2_service_type_e, HandleToType, IntoCInt, + IOX2_OK, }; use iceoryx2::node::{NodeId, NodeListFailure, NodeView}; @@ -90,19 +91,31 @@ impl iox2_node_t { self.value.init(value); self.deleter = deleter; } +} - pub(crate) fn cast(node: iox2_node_h) -> *mut Self { - node as *mut _ as _ - } +pub struct iox2_name_h_t; +/// The owning handle for `iox2_node_t`. Passing the handle to an function transfers the ownership. +pub type iox2_node_h = *mut iox2_name_h_t; + +pub struct iox2_noderef_h_t; +/// The non-owning handle for `iox2_node_t`. Passing the handle to an function does not transfers the ownership. +pub type iox2_node_ref_h = *mut iox2_noderef_h_t; + +impl HandleToType for iox2_node_h { + type Target = *mut iox2_node_t; - pub(crate) fn as_handle(&mut self) -> iox2_node_h { + fn as_type(self) -> Self::Target { self as *mut _ as _ } } -pub struct iox2_node_h_t; -/// The handle for `iox2_node_builder_t`. Passing the handle to an function transfers the ownership. -pub type iox2_node_h = *mut iox2_node_h_t; +impl HandleToType for iox2_node_ref_h { + type Target = *mut iox2_node_t; + + fn as_type(self) -> Self::Target { + self as *mut _ as _ + } +} #[repr(C)] #[derive(Copy, Clone)] @@ -154,7 +167,7 @@ pub type iox2_node_list_callback = extern "C" fn( pub unsafe extern "C" fn iox2_node_name(node_handle: iox2_node_h) -> iox2_node_name_ptr { debug_assert!(!node_handle.is_null()); - let node = &mut *iox2_node_t::cast(node_handle); + let node = &mut *node_handle.as_type(); match node.service_type { iox2_service_type_e::IPC => node.value.as_ref().ipc.name(), @@ -171,7 +184,7 @@ pub unsafe extern "C" fn iox2_node_name(node_handle: iox2_node_h) -> iox2_node_n pub unsafe extern "C" fn iox2_node_config(node_handle: iox2_node_h) -> iox2_config_ptr { debug_assert!(!node_handle.is_null()); - let node = &mut *iox2_node_t::cast(node_handle); + let node = &mut *node_handle.as_type(); match node.service_type { iox2_service_type_e::IPC => node.value.as_ref().ipc.config(), @@ -321,7 +334,7 @@ pub unsafe extern "C" fn iox2_node_service_builder( pub unsafe extern "C" fn iox2_node_drop(node_handle: iox2_node_h) { debug_assert!(!node_handle.is_null()); - let node = &mut *iox2_node_t::cast(node_handle); + let node = &mut *node_handle.as_type(); match node.service_type { iox2_service_type_e::IPC => { @@ -341,6 +354,8 @@ mod test { use crate::*; use iceoryx2_bb_testing::assert_that; + use core::{slice, str}; + fn create_sut_node() -> iox2_node_h { unsafe { let node_builder_handle = iox2_node_builder_new(std::ptr::null_mut()); @@ -388,11 +403,8 @@ mod test { fn basic_node_config_test() { unsafe { let node_handle = create_sut_node(); - let expected_config = (*iox2_node_t::cast(node_handle)) - .value - .as_ref() - .ipc - .config(); + + let expected_config = Config::global_config(); let config = iox2_node_config(node_handle); @@ -403,17 +415,23 @@ mod test { } #[test] - fn basic_node_name_test() { + fn basic_node_name_test() -> Result<(), Box> { unsafe { let node_handle = create_sut_node(); - let expected_node_name = (*iox2_node_t::cast(node_handle)).value.as_ref().ipc.name(); - assert_that!(expected_node_name.as_str(), eq("hypnotoad")); let node_name = iox2_node_name(node_handle); - assert_that!(*(node_name as *const NodeName), eq(*expected_node_name)); + let mut node_name_len = 0; + let node_name_c_str = iox2_node_name_as_c_str(node_name, &mut node_name_len); + + let slice = slice::from_raw_parts(node_name_c_str as *const _, node_name_len as _); + let node_name_str = str::from_utf8(slice)?; + + assert_that!(node_name_str, eq("hypnotoad")); iox2_node_drop(node_handle); + + Ok(()) } } diff --git a/iceoryx2-ffi/ffi/src/node_builder.rs b/iceoryx2-ffi/ffi/src/node_builder.rs index 9a99d9b8..d7d3340b 100644 --- a/iceoryx2-ffi/ffi/src/node_builder.rs +++ b/iceoryx2-ffi/ffi/src/node_builder.rs @@ -13,8 +13,8 @@ #![allow(non_camel_case_types)] use crate::{ - iox2_node_h, iox2_node_name_drop, iox2_node_name_h, iox2_node_name_t, iox2_node_t, - iox2_service_type_e, IntoCInt, NodeUnion, IOX2_OK, + iox2_node_h, iox2_node_name_drop, iox2_node_name_h, iox2_node_t, iox2_service_type_e, + HandleToType, IntoCInt, NodeUnion, IOX2_OK, }; use iceoryx2::node::NodeCreationFailure; @@ -57,23 +57,6 @@ pub struct iox2_node_builder_t { deleter: fn(*mut iox2_node_builder_t), } -impl iox2_node_builder_t { - pub(crate) fn cast(node_builder: iox2_node_builder_h) -> *mut Self { - node_builder as *mut _ as _ - } - pub(crate) fn cast_from_ref(node_builder: iox2_node_builder_ref_h) -> *mut Self { - node_builder as *mut _ as _ - } - - pub(crate) fn as_handle(&mut self) -> iox2_node_builder_h { - self as *mut _ as _ - } - - pub(crate) fn as_ref_handle(&mut self) -> iox2_node_builder_ref_h { - self as *mut _ as _ - } -} - pub struct iox2_node_builder_h_t; /// The owning handle for `iox2_node_builder_t`. Passing the handle to an function transfers the ownership. pub type iox2_node_builder_h = *mut iox2_node_builder_h_t; @@ -82,6 +65,22 @@ pub struct iox2_node_builder_ref_h_t; /// The non-owning handle for `iox2_node_builder_t`. Passing the handle to an function does not transfers the ownership. pub type iox2_node_builder_ref_h = *mut iox2_node_builder_ref_h_t; +impl HandleToType for iox2_node_builder_h { + type Target = *mut iox2_node_builder_t; + + fn as_type(self) -> Self::Target { + self as *mut _ as _ + } +} + +impl HandleToType for iox2_node_builder_ref_h { + type Target = *mut iox2_node_builder_t; + + fn as_type(self) -> Self::Target { + self as *mut _ as _ + } +} + // END type definition // BEGIN C API @@ -136,7 +135,7 @@ pub unsafe extern "C" fn iox2_cast_node_builder_ref_h( ) -> iox2_node_builder_ref_h { debug_assert!(!node_builder_handle.is_null()); - (*iox2_node_builder_t::cast(node_builder_handle)).as_ref_handle() + (*node_builder_handle.as_type()).as_ref_handle() } /// Sets the node name for the builder @@ -159,11 +158,11 @@ pub unsafe extern "C" fn iox2_node_builder_set_name( debug_assert!(!node_builder_handle.is_null()); debug_assert!(!node_name_handle.is_null()); - let node_name_struct = &mut *iox2_node_name_t::cast(node_name_handle); + let node_name_struct = &mut *node_name_handle.as_type(); let node_name = node_name_struct.take().unwrap(); iox2_node_name_drop(node_name_handle); - let node_builder_struct = &mut *iox2_node_builder_t::cast_from_ref(node_builder_handle); + let node_builder_struct = &mut *node_builder_handle.as_type(); let node_builder = node_builder_struct.take().unwrap(); let node_builder = node_builder.name(node_name); @@ -186,7 +185,7 @@ pub extern "C" fn iox2_node_builder_set_config( unsafe fn iox2_node_builder_drop(node_builder_handle: iox2_node_builder_h) { debug_assert!(!node_builder_handle.is_null()); - let node_builder = &mut (*iox2_node_builder_t::cast(node_builder_handle)); + let node_builder = &mut *node_builder_handle.as_type(); std::ptr::drop_in_place(node_builder.value.as_option_mut()); (node_builder.deleter)(node_builder); } @@ -216,7 +215,7 @@ pub unsafe extern "C" fn iox2_node_builder_create( debug_assert!(!node_builder_handle.is_null()); debug_assert!(!node_handle_ptr.is_null()); - let node_builder_struct = &mut *iox2_node_builder_t::cast(node_builder_handle); + let node_builder_struct = &mut *node_builder_handle.as_type(); let node_builder = node_builder_struct.take().unwrap(); iox2_node_builder_drop(node_builder_handle); diff --git a/iceoryx2-ffi/ffi/src/node_name.rs b/iceoryx2-ffi/ffi/src/node_name.rs index 737a631b..88de26b9 100644 --- a/iceoryx2-ffi/ffi/src/node_name.rs +++ b/iceoryx2-ffi/ffi/src/node_name.rs @@ -12,7 +12,7 @@ #![allow(non_camel_case_types)] -use crate::{iox2_semantic_string_error_e, IntoCInt, IOX2_OK}; +use crate::{iox2_semantic_string_error_e, HandleToType, IntoCInt, IOX2_OK}; use iceoryx2::prelude::*; use iceoryx2_bb_elementary::static_assert::*; @@ -36,26 +36,36 @@ pub struct iox2_node_name_t { deleter: fn(*mut iox2_node_name_t), } -impl iox2_node_name_t { - pub(crate) fn cast(node_name: iox2_node_name_h) -> *mut Self { - node_name as *mut _ as _ - } - - pub(crate) fn as_handle(&mut self) -> iox2_node_name_h { - self as *mut _ as _ - } -} - pub struct iox2_node_name_h_t; -/// The handle for `iox2_node_name_t`. Passing the handle to an function transfers the ownership. +/// The owning handle for `iox2_node_name_t`. Passing the handle to an function transfers the ownership. pub type iox2_node_name_h = *mut iox2_node_name_h_t; +pub struct iox2_node_name_ref_h_t; +/// The non-owning handle for `iox2_node_name_t`. Passing the handle to an function does not transfers the ownership. +pub type iox2_node_name_ref_h = *mut iox2_node_name_ref_h_t; + // NOTE check the README.md for using opaque types with renaming /// The immutable pointer to the underlying `NodeName` pub type iox2_node_name_ptr = *const NodeName; /// The mutable pointer to the underlying `NodeName` pub type iox2_node_name_mut_ptr = *mut NodeName; +impl HandleToType for iox2_node_name_h { + type Target = *mut iox2_node_name_t; + + fn as_type(self) -> Self::Target { + self as *mut _ as _ + } +} + +impl HandleToType for iox2_node_name_ref_h { + type Target = *mut iox2_node_name_t; + + fn as_type(self) -> Self::Target { + self as *mut _ as _ + } +} + // END type definition // BEGIN C API @@ -144,7 +154,7 @@ pub unsafe extern "C" fn iox2_cast_node_name_ptr( ) -> iox2_node_name_ptr { debug_assert!(!node_name_handle.is_null()); - (*iox2_node_name_t::cast(node_name_handle)).value.as_ref() + (*node_name_handle.as_type()).value.as_ref() } /// This function gives access to the node name as a C-style string @@ -193,7 +203,7 @@ pub unsafe extern "C" fn iox2_node_name_as_c_str( pub unsafe extern "C" fn iox2_node_name_drop(node_name_handle: iox2_node_name_h) { debug_assert!(!node_name_handle.is_null()); - let node_name = &mut (*iox2_node_name_t::cast(node_name_handle)); + let node_name = &mut *node_name_handle.as_type(); std::ptr::drop_in_place(node_name.value.as_option_mut()); (node_name.deleter)(node_name);