From a52ef72f924e88453fae490225f0f4e23ee8724a Mon Sep 17 00:00:00 2001 From: Pierre Avital Date: Mon, 26 Feb 2024 10:58:52 +0100 Subject: [PATCH 1/8] introduce owned buffers --- include/zenoh_commons.h | 19 +++++++++-- include/zenoh_macros.h | 10 ++++++ src/attachment.rs | 4 ++- src/collections.rs | 70 ++++++++++++++++++++++++++++++++++++-- src/commons.rs | 21 +++--------- src/config.rs | 7 +--- src/get.rs | 2 +- src/keyexpr.rs | 20 ++--------- src/lib.rs | 22 +++++++++++- src/publication_cache.rs | 25 ++------------ src/publisher.rs | 4 +-- src/pull_subscriber.rs | 15 +------- src/queryable.rs | 21 ++---------- src/querying_subscriber.rs | 26 +++----------- src/session.rs | 22 ++---------- src/subscriber.rs | 23 ++----------- 16 files changed, 144 insertions(+), 167 deletions(-) diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 9bf02fe81..c7d46f932 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -155,8 +155,8 @@ typedef enum zcu_reply_keyexpr_t { * and empty slices are represented using a possibly dangling pointer for `start`. */ typedef struct z_bytes_t { - size_t len; const uint8_t *start; + size_t len; } z_bytes_t; /** * The body of a loop over an attachment's key-value pairs. @@ -189,6 +189,15 @@ typedef struct z_attachment_t { const void *data; z_attachment_iter_driver_t iteration_driver; } z_attachment_t; +/** + * A buffer owned by Zenoh. + */ +typedef struct z_owned_buffer_t { + size_t _inner[5]; +} z_owned_buffer_t; +typedef struct z_buffer_t { + size_t _inner; +} z_buffer_t; /** * A map of maybe-owned vector of bytes to owned vector of bytes. * @@ -862,7 +871,7 @@ typedef struct zc_owned_liveliness_get_options_t { */ typedef struct zc_owned_payload_t { struct z_bytes_t payload; - size_t _owner[5]; + struct z_owned_buffer_t _owner; } zc_owned_payload_t; typedef struct zc_owned_shmbuf_t { size_t _0[9]; @@ -1027,6 +1036,12 @@ int8_t z_attachment_iterate(struct z_attachment_t this_, * Returns the gravestone value for `z_attachment_t`. */ ZENOHC_API struct z_attachment_t z_attachment_null(void); +ZENOHC_API bool z_buffer_check(const struct z_owned_buffer_t *buffer); +ZENOHC_API struct z_owned_buffer_t z_buffer_clone(struct z_buffer_t buffer); +ZENOHC_API void z_buffer_drop(struct z_owned_buffer_t *buffer); +ZENOHC_API struct z_buffer_t z_buffer_loan(const struct z_owned_buffer_t *buffer); +ZENOHC_API struct z_owned_buffer_t z_buffer_null(void); +ZENOHC_API struct z_bytes_t z_buffer_payload(struct z_buffer_t buffer); /** * Returns ``true`` if `b` is initialized. */ diff --git a/include/zenoh_macros.h b/include/zenoh_macros.h index fa6668d48..494d01fb9 100644 --- a/include/zenoh_macros.h +++ b/include/zenoh_macros.h @@ -14,6 +14,7 @@ z_owned_hello_t : z_hello_loan, \ z_owned_str_t : z_str_loan, \ z_owned_query_t : z_query_loan, \ + z_owned_buffer_t: z_buffer_loan, \ ze_owned_querying_subscriber_t : ze_querying_subscriber_loan \ )(&x) @@ -42,6 +43,7 @@ z_owned_reply_channel_t * : z_reply_channel_drop, \ z_owned_query_channel_t * : z_query_channel_drop, \ z_owned_bytes_map_t * : z_bytes_map_drop, \ + z_owned_buffer_t * : z_buffer_drop, \ zc_owned_payload_t * : zc_payload_drop, \ zc_owned_shmbuf_t * : zc_shmbuf_drop, \ zc_owned_shm_manager_t * : zc_shm_manager_drop, \ @@ -73,6 +75,7 @@ z_owned_reply_channel_closure_t * : z_reply_channel_closure_null, \ z_owned_reply_channel_t * : z_reply_channel_null, \ z_owned_bytes_map_t * : z_bytes_map_null, \ + z_owned_buffer_t * : z_buffer_null, \ z_attachment_t * : z_attachment_null, \ zc_owned_payload_t * : zc_payload_null, \ zc_owned_shmbuf_t * : zc_shmbuf_null, \ @@ -98,6 +101,7 @@ z_owned_query_t : z_query_check, \ z_owned_str_t : z_str_check, \ z_owned_bytes_map_t : z_bytes_map_check, \ + z_owned_buffer_t : z_buffer_check, \ z_attachment_t : z_attachment_check, \ zc_owned_payload_t : zc_payload_check, \ zc_owned_shmbuf_t : zc_shmbuf_check, \ @@ -141,6 +145,7 @@ template<> struct zenoh_loan_type{ typedef z_pull_sub template<> struct zenoh_loan_type{ typedef z_encoding_t type; }; template<> struct zenoh_loan_type{ typedef z_hello_t type; }; template<> struct zenoh_loan_type{ typedef const char* type; }; +template<> struct zenoh_loan_type{ typedef z_buffer_t type; }; template<> struct zenoh_loan_type{ typedef ze_querying_subscriber_t type; }; template<> inline z_session_t z_loan(const z_owned_session_t& x) { return z_session_loan(&x); } @@ -153,6 +158,7 @@ template<> inline z_encoding_t z_loan(const z_owned_encoding_t& x) { return z_en template<> inline z_hello_t z_loan(const z_owned_hello_t& x) { return z_hello_loan(&x); } template<> inline z_query_t z_loan(const z_owned_query_t& x) { return z_query_loan(&x); } template<> inline const char* z_loan(const z_owned_str_t& x) { return z_str_loan(&x); } +template<> inline z_buffer_t z_loan(const z_owned_buffer_t& x) { return z_buffer_loan(&x); } template<> inline ze_querying_subscriber_t z_loan(const ze_owned_querying_subscriber_t& x) { return ze_querying_subscriber_loan(&x); } template struct zenoh_drop_type { typedef T type; }; @@ -171,6 +177,7 @@ template<> struct zenoh_drop_type { typedef void type; }; template<> struct zenoh_drop_type { typedef void type; }; template<> struct zenoh_drop_type { typedef void type; }; template<> struct zenoh_drop_type { typedef void type; }; +template<> struct zenoh_drop_type { typedef void type; }; template<> struct zenoh_drop_type { typedef void type; }; template<> struct zenoh_drop_type { typedef void type; }; template<> struct zenoh_drop_type { typedef void type; }; @@ -200,6 +207,7 @@ template<> inline void z_drop(z_owned_reply_t* v) { z_reply_drop(v); } template<> inline void z_drop(z_owned_hello_t* v) { z_hello_drop(v); } template<> inline void z_drop(z_owned_query_t* v) { z_query_drop(v); } template<> inline void z_drop(z_owned_str_t* v) { z_str_drop(v); } +template<> inline void z_drop(z_owned_buffer_t* v) { z_buffer_drop(v); } template<> inline void z_drop(zc_owned_payload_t* v) { zc_payload_drop(v); } template<> inline void z_drop(zc_owned_shmbuf_t* v) { zc_shmbuf_drop(v); } template<> inline void z_drop(zc_owned_shm_manager_t* v) { zc_shm_manager_drop(v); } @@ -229,6 +237,7 @@ inline void z_null(z_owned_reply_t& v) { v = z_reply_null(); } inline void z_null(z_owned_hello_t& v) { v = z_hello_null(); } inline void z_null(z_owned_query_t& v) { v = z_query_null(); } inline void z_null(z_owned_str_t& v) { v = z_str_null(); } +inline void z_null(z_owned_buffer_t& v) { v = z_buffer_null(); } inline void z_null(zc_owned_payload_t& v) { v = zc_payload_null(); } inline void z_null(zc_owned_shmbuf_t& v) { v = zc_shmbuf_null(); } inline void z_null(zc_owned_shm_manager_t& v) { v = zc_shm_manager_null(); } @@ -263,6 +272,7 @@ inline bool z_check(const z_owned_reply_t& v) { return z_reply_check(&v); } inline bool z_check(const z_owned_hello_t& v) { return z_hello_check(&v); } inline bool z_check(const z_owned_query_t& v) { return z_query_check(&v); } inline bool z_check(const z_owned_str_t& v) { return z_str_check(&v); } +inline bool z_check(const z_owned_buffer_t& v) { return z_buffer_check(&v); } inline bool z_check(const z_owned_bytes_map_t& v) { return z_bytes_map_check(&v); } inline bool z_check(const z_attachment_t& v) { return z_attachment_check(&v); } inline bool z_check(const zc_owned_liveliness_token_t& v) { return zc_liveliness_token_check(&v); } diff --git a/src/attachment.rs b/src/attachment.rs index 5dbbfec5c..051edafdc 100644 --- a/src/attachment.rs +++ b/src/attachment.rs @@ -13,6 +13,7 @@ use zenoh::sample::{Attachment, AttachmentBuilder}; /// /// Returning `0` is treated as `continue`. /// Returning any other value is treated as `break`. +#[allow(non_camel_case_types)] pub type z_attachment_iter_body_t = extern "C" fn(key: z_bytes_t, value: z_bytes_t, context: *mut c_void) -> i8; @@ -20,6 +21,7 @@ pub type z_attachment_iter_body_t = /// /// This function is expected to call `loop_body` once for each key-value pair /// within `iterator`, passing `context`, and returning any non-zero value immediately (breaking iteration). +#[allow(non_camel_case_types)] pub type z_attachment_iter_driver_t = Option< extern "C" fn( iterator: *const c_void, @@ -124,7 +126,7 @@ pub struct z_owned_bytes_map_t { _1: [usize; 4], } -impl_guarded_transmute!( +impl_guarded_transmute!(noderefs Option, Cow<'static, [u8]>>>, z_owned_bytes_map_t ); diff --git a/src/collections.rs b/src/collections.rs index 9fd0c3c16..9ac7831c0 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -11,8 +11,14 @@ // Contributors: // ZettaScale Zenoh team, // + use libc::{c_char, size_t}; -use zenoh::prelude::ZenohId; +use zenoh::{ + buffers::{buffer::SplitBuffer, ZBuf}, + prelude::ZenohId, +}; + +use crate::impl_guarded_transmute; /// A contiguous view of bytes owned by some other entity. /// @@ -21,8 +27,8 @@ use zenoh::prelude::ZenohId; #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct z_bytes_t { - pub len: size_t, pub start: *const u8, + pub len: size_t, } impl z_bytes_t { @@ -155,3 +161,63 @@ impl From<&[u8]> for z_bytes_t { } } } + +/// A buffer owned by Zenoh. +#[repr(C)] +pub struct z_owned_buffer_t { + _inner: [usize; 5], +} +impl_guarded_transmute!(Option, z_owned_buffer_t); + +#[no_mangle] +pub extern "C" fn z_buffer_null() -> z_owned_buffer_t { + None.into() +} +#[no_mangle] +pub extern "C" fn z_buffer_drop(buffer: &mut z_owned_buffer_t) { + core::mem::drop(buffer.take()) +} + +#[no_mangle] +pub extern "C" fn z_buffer_check(buffer: &z_owned_buffer_t) -> bool { + buffer.is_some() +} +#[no_mangle] +pub extern "C" fn z_buffer_loan(buffer: &z_owned_buffer_t) -> z_buffer_t { + buffer.as_ref().into() +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct z_buffer_t { + _inner: usize, +} +impl_guarded_transmute!(noderefs Option<&ZBuf>, z_buffer_t); +impl From for Option<&'static ZBuf> { + fn from(value: z_buffer_t) -> Self { + unsafe { core::mem::transmute(value) } + } +} +impl From> for z_buffer_t { + fn from(value: Option<&ZBuf>) -> Self { + unsafe { core::mem::transmute(value) } + } +} +#[no_mangle] +pub extern "C" fn z_buffer_clone(buffer: z_buffer_t) -> z_owned_buffer_t { + unsafe { Some(core::mem::transmute::<_, &ZBuf>(buffer).clone()).into() } +} + +#[no_mangle] +pub extern "C" fn z_buffer_payload(buffer: z_buffer_t) -> z_bytes_t { + let Some(buffer): Option<&ZBuf> = buffer.into() else { + return z_bytes_null(); + }; + match buffer.contiguous() { + std::borrow::Cow::Borrowed(buffer) => buffer.into(), + std::borrow::Cow::Owned(_) => { + log::error!("A non-contiguous buffer reached user code, this is definitely a bug, please inform us at https://github.com/eclipse-zenoh/zenoh-c/issues/new"); + z_bytes_null() + } + } +} diff --git a/src/commons.rs b/src/commons.rs index 8ac21cb11..f96b9b09b 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -104,7 +104,7 @@ impl From> for z_timestamp_t { #[repr(C)] pub struct zc_owned_payload_t { pub payload: z_bytes_t, - pub _owner: [usize; 5], + pub _owner: z_owned_buffer_t, } impl Default for zc_owned_payload_t { fn default() -> Self { @@ -130,7 +130,9 @@ impl zc_owned_payload_t { } let start = std::mem::replace(&mut self.payload.start, std::ptr::null()); let len = std::mem::replace(&mut self.payload.len, 0); - let mut buf: ZBuf = unsafe { std::mem::transmute(self._owner) }; + let Some(mut buf) = self._owner.take() else { + return None; + }; { let mut slices = buf.zslices_mut(); let slice = slices.next().unwrap(); @@ -153,7 +155,7 @@ impl zc_owned_payload_t { if !z_bytes_check(&self.payload) { return None; } - unsafe { std::mem::transmute(&self._owner) } + self._owner.as_ref() } } impl Drop for zc_owned_payload_t { @@ -198,19 +200,6 @@ pub extern "C" fn zc_payload_null() -> zc_owned_payload_t { pub struct z_qos_t(u8); impl_guarded_transmute!(QoS, z_qos_t); -impl_guarded_transmute!(z_qos_t, QoS); - -impl From for z_qos_t { - fn from(qos: QoS) -> Self { - qos.transmute() - } -} - -impl From for QoS { - fn from(qos: z_qos_t) -> QoS { - qos.transmute() - } -} /// Returns message priority. #[no_mangle] diff --git a/src/config.rs b/src/config.rs index 6e259f3b5..80e3a38f1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -15,7 +15,7 @@ use libc::{c_char, c_uint}; use std::ffi::CStr; use zenoh::config::{Config, ValidatedMap, WhatAmI}; -use crate::{impl_guarded_transmute, z_owned_str_t, z_str_null, GuardedTransmute}; +use crate::{impl_guarded_transmute, z_owned_str_t, z_str_null}; #[no_mangle] pub static Z_ROUTER: c_uint = WhatAmI::Router as c_uint; @@ -76,11 +76,6 @@ pub struct z_config_t(*const z_owned_config_t); pub struct z_owned_config_t(*mut ()); impl_guarded_transmute!(Option>, z_owned_config_t); -impl From>> for z_owned_config_t { - fn from(v: Option>) -> Self { - v.transmute() - } -} /// Returns a :c:type:`z_config_t` loaned from `s`. #[no_mangle] pub extern "C" fn z_config_loan(s: &z_owned_config_t) -> z_config_t { diff --git a/src/get.rs b/src/get.rs index 07bf0de65..41e3cf204 100644 --- a/src/get.rs +++ b/src/get.rs @@ -60,7 +60,7 @@ pub struct z_owned_reply_t([u64; 30]); #[repr(C, align(8))] pub struct z_owned_reply_t([u64; 19]); -impl_guarded_transmute!(ReplyInner, z_owned_reply_t); +impl_guarded_transmute!(noderefs ReplyInner, z_owned_reply_t); impl From for z_owned_reply_t { fn from(mut val: ReplyInner) -> Self { diff --git a/src/keyexpr.rs b/src/keyexpr.rs index 04efe0c99..06784a8dc 100644 --- a/src/keyexpr.rs +++ b/src/keyexpr.rs @@ -62,27 +62,11 @@ pub struct z_owned_keyexpr_t([u32; 5]); impl_guarded_transmute!(Option>, z_owned_keyexpr_t); -impl From>> for z_owned_keyexpr_t { - fn from(val: Option>) -> Self { - val.transmute() - } -} impl From> for z_owned_keyexpr_t { fn from(val: KeyExpr<'static>) -> Self { Some(val).into() } } -impl Deref for z_owned_keyexpr_t { - type Target = Option>; - fn deref(&self) -> &Self::Target { - unsafe { std::mem::transmute(self) } - } -} -impl DerefMut for z_owned_keyexpr_t { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { std::mem::transmute(self) } - } -} impl z_owned_keyexpr_t { pub fn null() -> Self { None::.into() @@ -156,8 +140,8 @@ pub struct z_keyexpr_t([u64; 4]); #[repr(C, align(4))] pub struct z_keyexpr_t([u32; 5]); -impl_guarded_transmute!(Option>, z_keyexpr_t); -impl_guarded_transmute!(z_keyexpr_t, z_owned_keyexpr_t); +impl_guarded_transmute!(noderefs Option>, z_keyexpr_t); +impl_guarded_transmute!(noderefs z_keyexpr_t, z_owned_keyexpr_t); impl<'a> From> for z_keyexpr_t { fn from(val: KeyExpr<'a>) -> Self { diff --git a/src/lib.rs b/src/lib.rs index 718475444..19c22fa2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,6 +61,26 @@ trait GuardedTransmute { #[macro_export] macro_rules! impl_guarded_transmute { ($src_type:ty, $dst_type:ty) => { + impl_guarded_transmute!(noderefs $src_type, $dst_type); + impl From<$src_type> for $dst_type { + fn from(value: $src_type) -> $dst_type { + unsafe { core::mem::transmute(value) } + } + } + impl core::ops::Deref for $dst_type { + type Target = $src_type; + fn deref(&self) -> &$src_type { + unsafe { core::mem::transmute(self) } + } + } + impl core::ops::DerefMut for $dst_type { + fn deref_mut(&mut self) -> &mut $src_type { + unsafe { core::mem::transmute(self) } + } + } + + }; + (noderefs $src_type:ty, $dst_type:ty) => { const _: () = { let src = std::mem::align_of::<$src_type>(); let dst = std::mem::align_of::<$dst_type>(); @@ -77,7 +97,7 @@ macro_rules! impl_guarded_transmute { }); } }; - impl $crate::GuardedTransmute<$dst_type> for $src_type { + impl $crate::GuardedTransmute<$dst_type> for $src_type { fn transmute(self) -> $dst_type { unsafe { std::mem::transmute::<$src_type, $dst_type>(self) } } diff --git a/src/publication_cache.rs b/src/publication_cache.rs index 5b96a904c..ee4c85959 100644 --- a/src/publication_cache.rs +++ b/src/publication_cache.rs @@ -20,7 +20,7 @@ use zenoh_util::core::SyncResolve; use crate::{ impl_guarded_transmute, z_keyexpr_t, z_session_t, zcu_locality_default, zcu_locality_t, - GuardedTransmute, UninitializedKeyExprError, + UninitializedKeyExprError, }; /// Options passed to the :c:func:`ze_declare_publication_cache` function. @@ -53,8 +53,6 @@ pub extern "C" fn ze_publication_cache_options_default() -> ze_publication_cache } } -type PublicationCache = Option>>; - /// An owned zenoh publication_cache. /// /// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. @@ -68,26 +66,9 @@ type PublicationCache = Option>>; #[repr(C)] pub struct ze_owned_publication_cache_t([usize; 1]); +type PublicationCache = Option>>; impl_guarded_transmute!(PublicationCache, ze_owned_publication_cache_t); -impl From for ze_owned_publication_cache_t { - fn from(val: PublicationCache) -> Self { - val.transmute() - } -} - -impl AsRef for ze_owned_publication_cache_t { - fn as_ref(&self) -> &PublicationCache { - unsafe { std::mem::transmute(self) } - } -} - -impl AsMut for ze_owned_publication_cache_t { - fn as_mut(&mut self) -> &mut PublicationCache { - unsafe { std::mem::transmute(self) } - } -} - impl ze_owned_publication_cache_t { pub fn new(pub_cache: zenoh_ext::PublicationCache<'static>) -> Self { Some(Box::new(pub_cache)).into() @@ -187,7 +168,7 @@ pub extern "C" fn ze_publication_cache_check(pub_cache: &ze_owned_publication_ca pub extern "C" fn ze_undeclare_publication_cache( pub_cache: &mut ze_owned_publication_cache_t, ) -> i8 { - if let Some(p) = pub_cache.as_mut().take() { + if let Some(p) = pub_cache.take() { if let Err(e) = p.close().res_sync() { log::error!("{}", e); return e.errno().get(); diff --git a/src/publisher.rs b/src/publisher.rs index 42681093f..f49d8cd31 100644 --- a/src/publisher.rs +++ b/src/publisher.rs @@ -75,7 +75,7 @@ pub struct z_owned_publisher_t([u64; 7]); #[repr(C, align(4))] pub struct z_owned_publisher_t([u32; 8]); -impl_guarded_transmute!(Option>, z_owned_publisher_t); +impl_guarded_transmute!(noderefs Option>, z_owned_publisher_t); impl<'a> From>> for z_owned_publisher_t { fn from(val: Option) -> Self { @@ -387,7 +387,7 @@ pub extern "C" fn z_publisher_keyexpr(publisher: z_publisher_t) -> z_owned_keyex #[repr(C, align(8))] pub struct zcu_owned_matching_listener_t([u64; 4]); -impl_guarded_transmute!( +impl_guarded_transmute!(noderefs Option>, zcu_owned_matching_listener_t ); diff --git a/src/pull_subscriber.rs b/src/pull_subscriber.rs index 931b48d84..0eee4bc94 100644 --- a/src/pull_subscriber.rs +++ b/src/pull_subscriber.rs @@ -1,4 +1,3 @@ -use crate::GuardedTransmute; // // Copyright (c) 2017, 2022 ZettaScale Technology. // @@ -56,21 +55,9 @@ impl_guarded_transmute!(PullSubscriber, z_owned_pull_subscriber_t); #[allow(non_camel_case_types)] pub struct z_pull_subscriber_t<'a>(&'a z_owned_pull_subscriber_t); -impl From for z_owned_pull_subscriber_t { - fn from(val: PullSubscriber) -> Self { - val.transmute() - } -} - -impl AsRef for z_owned_pull_subscriber_t { - fn as_ref(&self) -> &PullSubscriber { - unsafe { std::mem::transmute(self) } - } -} - impl<'a> AsRef for z_pull_subscriber_t<'a> { fn as_ref(&self) -> &PullSubscriber { - self.0.as_ref() + self.0 } } diff --git a/src/queryable.rs b/src/queryable.rs index 5a7112afc..1906dc735 100644 --- a/src/queryable.rs +++ b/src/queryable.rs @@ -17,8 +17,7 @@ use crate::attachment::{ }; use crate::{ impl_guarded_transmute, z_bytes_t, z_closure_query_call, z_encoding_default, z_encoding_t, - z_keyexpr_t, z_owned_closure_query_t, z_session_t, z_value_t, GuardedTransmute, - LOG_INVALID_SESSION, + z_keyexpr_t, z_owned_closure_query_t, z_session_t, z_value_t, LOG_INVALID_SESSION, }; use libc::c_void; use std::ops::{Deref, DerefMut}; @@ -52,22 +51,6 @@ pub struct z_owned_queryable_t([u32; 4]); impl_guarded_transmute!(Queryable, z_owned_queryable_t); -impl From for z_owned_queryable_t { - fn from(val: Queryable) -> Self { - val.transmute() - } -} -impl AsRef for z_owned_queryable_t { - fn as_ref(&self) -> &Queryable { - unsafe { std::mem::transmute(self) } - } -} -impl AsMut for z_owned_queryable_t { - fn as_mut(&mut self) -> &mut Queryable { - unsafe { std::mem::transmute(self) } - } -} - impl z_owned_queryable_t { pub fn null() -> Self { None.into() @@ -263,7 +246,7 @@ pub extern "C" fn z_declare_queryable( #[allow(clippy::missing_safety_doc)] #[no_mangle] pub extern "C" fn z_undeclare_queryable(qable: &mut z_owned_queryable_t) -> i8 { - if let Some(qable) = qable.as_mut().take() { + if let Some(qable) = qable.take() { if let Err(e) = qable.undeclare().res_sync() { log::error!("{}", e); return e.errno().get(); diff --git a/src/querying_subscriber.rs b/src/querying_subscriber.rs index d407f9646..cdec44f0f 100644 --- a/src/querying_subscriber.rs +++ b/src/querying_subscriber.rs @@ -25,10 +25,10 @@ use crate::{ z_owned_closure_sample_t, z_query_consolidation_none, z_query_consolidation_t, z_query_target_default, z_query_target_t, z_reliability_t, z_sample_t, z_session_t, zcu_locality_default, zcu_locality_t, zcu_reply_keyexpr_default, zcu_reply_keyexpr_t, - GuardedTransmute, LOG_INVALID_SESSION, + LOG_INVALID_SESSION, }; -struct FetchingSubscriberWrapper { +pub struct FetchingSubscriberWrapper { fetching_subscriber: zenoh_ext::FetchingSubscriber<'static, ()>, session: z_session_t, } @@ -54,27 +54,9 @@ impl_guarded_transmute!(FetchingSubscriber, ze_owned_querying_subscriber_t); #[allow(non_camel_case_types)] pub struct ze_querying_subscriber_t<'a>(&'a ze_owned_querying_subscriber_t); -impl From for ze_owned_querying_subscriber_t { - fn from(val: FetchingSubscriber) -> Self { - val.transmute() - } -} - -impl AsRef for ze_owned_querying_subscriber_t { - fn as_ref(&self) -> &FetchingSubscriber { - unsafe { std::mem::transmute(self) } - } -} - impl<'a> AsRef for ze_querying_subscriber_t<'a> { fn as_ref(&self) -> &FetchingSubscriber { - self.0.as_ref() - } -} - -impl AsMut for ze_owned_querying_subscriber_t { - fn as_mut(&mut self) -> &mut FetchingSubscriber { - unsafe { std::mem::transmute(self) } + self.0 } } @@ -276,7 +258,7 @@ pub unsafe extern "C" fn ze_querying_subscriber_get( #[allow(clippy::missing_safety_doc)] #[no_mangle] pub extern "C" fn ze_undeclare_querying_subscriber(sub: &mut ze_owned_querying_subscriber_t) -> i8 { - if let Some(s) = sub.as_mut().take() { + if let Some(s) = sub.take() { if let Err(e) = s.fetching_subscriber.close().res_sync() { log::warn!("{}", e); return e.errno().get(); diff --git a/src/session.rs b/src/session.rs index a4329fbf6..2caab85ea 100644 --- a/src/session.rs +++ b/src/session.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh team, // -use crate::{config::*, impl_guarded_transmute, zc_init_logger, GuardedTransmute}; +use crate::{config::*, impl_guarded_transmute, zc_init_logger}; use std::sync::{Arc, Weak}; use zenoh::prelude::sync::SyncResolve; use zenoh::Session; @@ -33,24 +33,6 @@ pub struct z_owned_session_t(usize); impl_guarded_transmute!(Option>, z_owned_session_t); -impl From>> for z_owned_session_t { - fn from(val: Option>) -> Self { - val.transmute() - } -} - -impl AsRef>> for z_owned_session_t { - fn as_ref(&self) -> &Option> { - unsafe { std::mem::transmute(self) } - } -} - -impl AsMut>> for z_owned_session_t { - fn as_mut(&mut self) -> &mut Option> { - unsafe { std::mem::transmute(self) } - } -} - impl AsRef>> for z_session_t { fn as_ref(&self) -> &Option> { unsafe { std::mem::transmute(self) } @@ -150,7 +132,7 @@ pub extern "C" fn z_session_check(session: &z_owned_session_t) -> bool { #[allow(clippy::missing_safety_doc)] #[no_mangle] pub extern "C" fn z_close(session: &mut z_owned_session_t) -> i8 { - let Some(s) = session.as_mut().take() else { + let Some(s) = session.take() else { return 0; }; let s = match Arc::try_unwrap(s) { diff --git a/src/subscriber.rs b/src/subscriber.rs index 910ec424b..b9488960a 100644 --- a/src/subscriber.rs +++ b/src/subscriber.rs @@ -18,7 +18,6 @@ use crate::keyexpr::*; use crate::session::*; use crate::z_closure_sample_call; use crate::z_owned_closure_sample_t; -use crate::GuardedTransmute; use crate::LOG_INVALID_SESSION; use zenoh::prelude::sync::SyncResolve; use zenoh::prelude::SessionDeclarations; @@ -84,24 +83,6 @@ pub struct z_owned_subscriber_t([u32; 1]); impl_guarded_transmute!(Subscriber, z_owned_subscriber_t); -impl From for z_owned_subscriber_t { - fn from(sub: Subscriber) -> Self { - sub.transmute() - } -} - -impl AsRef for z_owned_subscriber_t { - fn as_ref(&self) -> &Subscriber { - unsafe { std::mem::transmute(self) } - } -} - -impl AsMut for z_owned_subscriber_t { - fn as_mut(&mut self) -> &mut Subscriber { - unsafe { std::mem::transmute(self) } - } -} - impl z_owned_subscriber_t { pub fn new(sub: zenoh::subscriber::Subscriber<'static, ()>) -> Self { Some(Box::new(sub)).into() @@ -125,7 +106,7 @@ pub struct z_subscriber_t(*const z_owned_subscriber_t); impl AsRef for z_subscriber_t { fn as_ref(&self) -> &Subscriber { - unsafe { (*self.0).as_ref() } + unsafe { &(*self.0) } } } @@ -240,7 +221,7 @@ pub extern "C" fn z_subscriber_keyexpr(subscriber: z_subscriber_t) -> z_owned_ke #[allow(clippy::missing_safety_doc)] #[no_mangle] pub extern "C" fn z_undeclare_subscriber(sub: &mut z_owned_subscriber_t) -> i8 { - if let Some(s) = sub.as_mut().take() { + if let Some(s) = sub.take() { if let Err(e) = s.undeclare().res_sync() { log::warn!("{}", e); return e.errno().get(); From 8dbbf37dc2d8848d23ea0efcc572d656fd586168 Mon Sep 17 00:00:00 2001 From: Pierre Avital Date: Mon, 26 Feb 2024 15:02:36 +0100 Subject: [PATCH 2/8] privatize sample --- examples/z_get.c | 5 +- examples/z_get_liveliness.c | 2 +- examples/z_non_blocking_get.c | 5 +- examples/z_pong.c | 10 +- examples/z_pull.c | 7 +- examples/z_query_sub.c | 7 +- examples/z_sub.c | 7 +- examples/z_sub_attachment.c | 14 +- examples/z_sub_liveliness.c | 4 +- include/zenoh_commons.h | 163 +++++++++++--------- include/zenoh_macros.h | 3 - src/collections.rs | 54 +++++-- src/commons.rs | 194 ++++++++++-------------- src/get.rs | 2 +- src/lib.rs | 24 +++ src/liveliness.rs | 12 +- src/pull_subscriber.rs | 12 +- src/querying_subscriber.rs | 12 +- src/subscriber.rs | 12 +- tests/z_api_alignment_test.c | 4 +- tests/z_int_pub_cache_query_sub_test.c | 4 +- tests/z_int_pub_sub_attachment_test.c | 9 +- tests/z_int_pub_sub_test.c | 10 +- tests/z_int_queryable_attachment_test.c | 6 +- tests/z_int_queryable_test.c | 4 +- 25 files changed, 311 insertions(+), 275 deletions(-) diff --git a/examples/z_get.c b/examples/z_get.c index 272bef89a..853366210 100644 --- a/examples/z_get.c +++ b/examples/z_get.c @@ -65,8 +65,9 @@ int main(int argc, char **argv) { for (z_call(channel.recv, &reply); z_check(reply); z_call(channel.recv, &reply)) { if (z_reply_is_ok(&reply)) { z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(">> Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample.payload.len, sample.payload.start); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(&sample)); + z_bytes_t payload = z_sample_payload(&sample); + printf(">> Received ('%s': '%.*s')\n", z_loan(keystr), (int)payload.len, payload.start); z_drop(z_move(keystr)); } else { printf("Received an error\n"); diff --git a/examples/z_get_liveliness.c b/examples/z_get_liveliness.c index c667cb03a..9a00f3ca3 100644 --- a/examples/z_get_liveliness.c +++ b/examples/z_get_liveliness.c @@ -53,7 +53,7 @@ int main(int argc, char **argv) { for (z_call(channel.recv, &reply); z_check(reply); z_call(channel.recv, &reply)) { if (z_reply_is_ok(&reply)) { z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(&sample)); printf(">> Alive token ('%s')\n", z_loan(keystr)); z_drop(z_move(keystr)); } else { diff --git a/examples/z_non_blocking_get.c b/examples/z_non_blocking_get.c index c0b02a274..a741d6071 100644 --- a/examples/z_non_blocking_get.c +++ b/examples/z_non_blocking_get.c @@ -58,8 +58,9 @@ int main(int argc, char **argv) { } if (z_reply_is_ok(&reply)) { z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(">> Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample.payload.len, sample.payload.start); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(&sample)); + z_bytes_t payload = z_sample_payload(&sample); + printf(">> Received ('%s': '%.*s')\n", z_loan(keystr), (int)payload.len, payload.start); z_drop(z_move(keystr)); } else { printf("Received an error\n"); diff --git a/examples/z_pong.c b/examples/z_pong.c index 8dbb2631e..4047ff3d2 100644 --- a/examples/z_pong.c +++ b/examples/z_pong.c @@ -6,7 +6,7 @@ void callback(const z_sample_t* sample, void* context) { z_publisher_t pub = z_loan(*(z_owned_publisher_t*)context); #ifdef ZENOH_C // The zc_owned_payload_t API is exclusive to zenoh-c, but allows avoiding some copies. - zc_owned_payload_t payload = zc_sample_payload_rcinc(sample); + z_owned_buffer_t payload = z_sample_owned_payload(sample); zc_publisher_put_owned(pub, z_move(payload), NULL); #else z_publisher_put(pub, sample->payload.start, sample->payload.len, NULL); @@ -21,15 +21,17 @@ void drop(void* context) { // valid. } struct args_t { - char* config_path; // -c - uint8_t help_requested; // -h + char* config_path; // -c + uint8_t help_requested; // -h }; struct args_t parse_args(int argc, char** argv); int main(int argc, char** argv) { struct args_t args = parse_args(argc, argv); if (args.help_requested) { - printf("-c (optional, string): the path to a configuration file for the session. If this option isn't passed, the default configuration will be used.\n"); + printf( + "-c (optional, string): the path to a configuration file for the session. If this option isn't passed, the " + "default configuration will be used.\n"); return 1; } z_owned_config_t config = args.config_path ? zc_config_from_file(args.config_path) : z_config_default(); diff --git a/examples/z_pull.c b/examples/z_pull.c index d7039e902..badbd6f44 100644 --- a/examples/z_pull.c +++ b/examples/z_pull.c @@ -23,9 +23,10 @@ const char *kind_to_str(z_sample_kind_t kind); void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), - (int)sample->payload.len, sample->payload.start); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(sample)); + z_bytes_t payload = z_sample_payload(sample); + printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + (int)payload.len, payload.start); z_drop(z_move(keystr)); } diff --git a/examples/z_query_sub.c b/examples/z_query_sub.c index 680cfd973..7653a6c77 100644 --- a/examples/z_query_sub.c +++ b/examples/z_query_sub.c @@ -23,9 +23,10 @@ const char *kind_to_str(z_sample_kind_t kind); void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), - (int)sample->payload.len, sample->payload.start); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(sample)); + z_bytes_t payload = z_sample_payload(sample); + printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + (int)payload.len, payload.start); z_drop(z_move(keystr)); } diff --git a/examples/z_sub.c b/examples/z_sub.c index ccfb32825..b52db8850 100644 --- a/examples/z_sub.c +++ b/examples/z_sub.c @@ -23,9 +23,10 @@ const char *kind_to_str(z_sample_kind_t kind); void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), - (int)sample->payload.len, sample->payload.start); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(sample)); + z_bytes_t payload = z_sample_payload(sample); + printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + (int)payload.len, payload.start); z_drop(z_move(keystr)); } diff --git a/examples/z_sub_attachment.c b/examples/z_sub_attachment.c index 26cc95ed8..c3d22e39f 100644 --- a/examples/z_sub_attachment.c +++ b/examples/z_sub_attachment.c @@ -29,17 +29,19 @@ int8_t attachment_reader(z_bytes_t key, z_bytes_t val, void *ctx) { } void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), - (int)sample->payload.len, sample->payload.start); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(sample)); + z_bytes_t payload = z_sample_payload(sample); + printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + (int)payload.len, payload.start); + z_attachment_t attachment = z_sample_attachment(sample); // checks if attachment exists - if (z_check(sample->attachment)) { + if (z_check(attachment)) { // reads full attachment - z_attachment_iterate(sample->attachment, attachment_reader, NULL); + z_attachment_iterate(attachment, attachment_reader, NULL); // reads particular attachment item - z_bytes_t index = z_attachment_get(sample->attachment, z_bytes_from_str("index")); + z_bytes_t index = z_attachment_get(attachment, z_bytes_from_str("index")); if (z_check(index)) { printf(" message number: %.*s\n", (int)index.len, index.start); } diff --git a/examples/z_sub_liveliness.c b/examples/z_sub_liveliness.c index f67ac5a68..67c87001a 100644 --- a/examples/z_sub_liveliness.c +++ b/examples/z_sub_liveliness.c @@ -21,8 +21,8 @@ #include "zenoh.h" void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - switch (sample->kind) { + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(sample)); + switch (z_sample_kind(sample)) { case Z_SAMPLE_KIND_PUT: printf(">> [LivelinessSubscriber] New alive token ('%s')\n", z_loan(keystr)); break; diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index c7d46f932..1d56fe95f 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -196,7 +196,7 @@ typedef struct z_owned_buffer_t { size_t _inner[5]; } z_owned_buffer_t; typedef struct z_buffer_t { - size_t _inner; + const void *_inner; } z_buffer_t; /** * A map of maybe-owned vector of bytes to owned vector of bytes. @@ -368,52 +368,6 @@ typedef struct z_owned_closure_reply_t { void (*call)(struct z_owned_reply_t*, void*); void (*drop)(void*); } z_owned_closure_reply_t; -/** - * A loaned key expression. - * - * Key expressions can identify a single key or a set of keys. - * - * Examples : - * - ``"key/expression"``. - * - ``"key/ex*"``. - * - * Using :c:func:`z_declare_keyexpr` allows zenoh to optimize a key expression, - * both for local processing and network-wise. - */ -#if !defined(TARGET_ARCH_ARM) -typedef struct ALIGN(8) z_keyexpr_t { - uint64_t _0[4]; -} z_keyexpr_t; -#endif -#if defined(TARGET_ARCH_ARM) -typedef struct ALIGN(4) z_keyexpr_t { - uint32_t _0[5]; -} z_keyexpr_t; -#endif -/** - * The encoding of a payload, in a MIME-like format. - * - * For wire and matching efficiency, common MIME types are represented using an integer as `prefix`, and a `suffix` may be used to either provide more detail, or in combination with the `Empty` prefix to write arbitrary MIME types. - * - * Members: - * z_encoding_prefix_t prefix: The integer prefix of this encoding. - * z_bytes_t suffix: The suffix of this encoding. `suffix` MUST be a valid UTF-8 string. - */ -typedef struct z_encoding_t { - enum z_encoding_prefix_t prefix; - struct z_bytes_t suffix; -} z_encoding_t; -typedef struct z_timestamp_t { - uint64_t time; - struct z_id_t id; -} z_timestamp_t; -/** - * QoS settings of zenoh message. - * - */ -typedef struct z_qos_t { - uint8_t _0; -} z_qos_t; /** * A data sample. * @@ -428,14 +382,7 @@ typedef struct z_qos_t { * z_attachment_t attachment: The attachment of this data sample. */ typedef struct z_sample_t { - struct z_keyexpr_t keyexpr; - struct z_bytes_t payload; - struct z_encoding_t encoding; - const void *_zc_buf; - enum z_sample_kind_t kind; - struct z_timestamp_t timestamp; - struct z_qos_t qos; - struct z_attachment_t attachment; + const void *_inner; } z_sample_t; /** * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. @@ -550,6 +497,28 @@ typedef struct ALIGN(4) z_owned_keyexpr_t { uint32_t _0[5]; } z_owned_keyexpr_t; #endif +/** + * A loaned key expression. + * + * Key expressions can identify a single key or a set of keys. + * + * Examples : + * - ``"key/expression"``. + * - ``"key/ex*"``. + * + * Using :c:func:`z_declare_keyexpr` allows zenoh to optimize a key expression, + * both for local processing and network-wise. + */ +#if !defined(TARGET_ARCH_ARM) +typedef struct ALIGN(8) z_keyexpr_t { + uint64_t _0[4]; +} z_keyexpr_t; +#endif +#if defined(TARGET_ARCH_ARM) +typedef struct ALIGN(4) z_keyexpr_t { + uint32_t _0[5]; +} z_keyexpr_t; +#endif /** * An owned zenoh publisher. * @@ -618,6 +587,19 @@ typedef struct z_delete_options_t { enum z_congestion_control_t congestion_control; enum z_priority_t priority; } z_delete_options_t; +/** + * The encoding of a payload, in a MIME-like format. + * + * For wire and matching efficiency, common MIME types are represented using an integer as `prefix`, and a `suffix` may be used to either provide more detail, or in combination with the `Empty` prefix to write arbitrary MIME types. + * + * Members: + * z_encoding_prefix_t prefix: The integer prefix of this encoding. + * z_bytes_t suffix: The suffix of this encoding. `suffix` MUST be a valid UTF-8 string. + */ +typedef struct z_encoding_t { + uint64_t prefix; + struct z_bytes_t suffix; +} z_encoding_t; /** * An owned payload encoding. * @@ -632,7 +614,7 @@ typedef struct z_delete_options_t { * To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. */ typedef struct z_owned_encoding_t { - enum z_encoding_prefix_t prefix; + uint64_t prefix; struct z_bytes_t suffix; bool _dropped; } z_owned_encoding_t; @@ -746,6 +728,13 @@ typedef struct z_put_options_t { enum z_priority_t priority; struct z_attachment_t attachment; } z_put_options_t; +/** + * QoS settings of zenoh message. + * + */ +typedef struct z_qos_t { + uint8_t _0; +} z_qos_t; /** * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks: * - `this` is a pointer to an arbitrary state. @@ -808,6 +797,10 @@ typedef struct z_owned_reply_channel_t { struct z_owned_closure_reply_t send; struct z_owned_reply_channel_closure_t recv; } z_owned_reply_channel_t; +typedef struct z_timestamp_t { + uint64_t time; + struct z_id_t id; +} z_timestamp_t; typedef struct z_owned_scouting_config_t { struct z_owned_config_t _config; unsigned long zc_timeout_ms; @@ -869,10 +862,7 @@ typedef struct zc_owned_liveliness_get_options_t { * Should this invariant be broken when the payload is passed to one of zenoh's `put_owned` * functions, then the operation will fail (but the passed value will still be consumed). */ -typedef struct zc_owned_payload_t { - struct z_bytes_t payload; - struct z_owned_buffer_t _owner; -} zc_owned_payload_t; +typedef struct z_owned_buffer_t zc_owned_payload_t; typedef struct zc_owned_shmbuf_t { size_t _0[9]; } zc_owned_shmbuf_t; @@ -1982,6 +1972,41 @@ ZENOHC_API struct z_owned_reply_t z_reply_null(void); */ ZENOHC_API struct z_sample_t z_reply_ok(const struct z_owned_reply_t *reply); +/** + * The sample's attachment. + * + * `sample` is aliased by the return value. + */ +ZENOHC_API struct z_attachment_t z_sample_attachment(const struct z_sample_t *sample); +/** + * The encoding of the payload. + */ +ZENOHC_API struct z_encoding_t z_sample_encoding(const struct z_sample_t *sample); +/** + * The Key Expression of the sample. + * + * `sample` is aliased by its return value. + */ +ZENOHC_API struct z_keyexpr_t z_sample_keyexpr(const struct z_sample_t *sample); +/** + * The sample's kind (put or delete). + */ +ZENOHC_API enum z_sample_kind_t z_sample_kind(const struct z_sample_t *sample); +/** + * Returns the sample's payload after incrementing its internal reference count. + * + * Note that other samples may have received the same buffer, meaning that mutating this buffer may + * affect the samples received by other subscribers. + */ +ZENOHC_API struct z_owned_buffer_t z_sample_owned_payload(const struct z_sample_t *sample); +/** + * The sample's data, the return value aliases the sample. + * + * If you need ownership of the buffer, you may use `z_sample_owned_payload`. + */ +ZENOHC_API struct z_bytes_t z_sample_payload(const struct z_sample_t *sample); +ZENOHC_API struct z_qos_t z_sample_qos(const struct z_sample_t *sample); +ZENOHC_API struct z_timestamp_t z_sample_timestamp(const struct z_sample_t *sample); /** * Scout for routers and/or peers. * @@ -2277,19 +2302,19 @@ ZENOHC_API void zc_liveliness_undeclare_token(struct zc_owned_liveliness_token_t /** * Returns `false` if `payload` is the gravestone value. */ -ZENOHC_API bool zc_payload_check(const struct zc_owned_payload_t *payload); +ZENOHC_API bool zc_payload_check(const zc_owned_payload_t *payload); /** * Decrements `payload`'s backing refcount, releasing the memory if appropriate. */ -ZENOHC_API void zc_payload_drop(struct zc_owned_payload_t *payload); +ZENOHC_API void zc_payload_drop(zc_owned_payload_t *payload); /** * Constructs `zc_owned_payload_t`'s gravestone value. */ -ZENOHC_API struct zc_owned_payload_t zc_payload_null(void); +ZENOHC_API zc_owned_payload_t zc_payload_null(void); /** * Clones the `payload` by incrementing its reference counter. */ -ZENOHC_API struct zc_owned_payload_t zc_payload_rcinc(const struct zc_owned_payload_t *payload); +ZENOHC_API zc_owned_payload_t zc_payload_rcinc(const zc_owned_payload_t *payload); /** * Sends a `PUT` message onto the publisher's key expression, transfering the buffer ownership. * @@ -2309,7 +2334,7 @@ ZENOHC_API struct zc_owned_payload_t zc_payload_rcinc(const struct zc_owned_payl */ ZENOHC_API int8_t zc_publisher_put_owned(struct z_publisher_t publisher, - struct zc_owned_payload_t *payload, + zc_owned_payload_t *payload, const struct z_publisher_put_options_t *options); /** * Put data, transfering the buffer ownership. @@ -2331,7 +2356,7 @@ int8_t zc_publisher_put_owned(struct z_publisher_t publisher, ZENOHC_API int8_t zc_put_owned(struct z_session_t session, struct z_keyexpr_t keyexpr, - struct zc_owned_payload_t *payload, + zc_owned_payload_t *payload, const struct z_put_options_t *opts); /** * Creates a new blocking fifo channel, returned as a pair of closures. @@ -2385,10 +2410,6 @@ struct z_owned_reply_channel_t zc_reply_fifo_new(size_t bound); */ ZENOHC_API struct z_owned_reply_channel_t zc_reply_non_blocking_fifo_new(size_t bound); -/** - * Clones the sample's payload by incrementing its backing refcount (this doesn't imply any copies). - */ -ZENOHC_API struct zc_owned_payload_t zc_sample_payload_rcinc(const struct z_sample_t *sample); /** * Increments the session's reference count, returning a new owning handle. */ @@ -2443,7 +2464,7 @@ ZENOHC_API void zc_shmbuf_drop(struct zc_owned_shmbuf_t *buf); /** * Constructs an owned payload from an owned SHM buffer. */ -ZENOHC_API struct zc_owned_payload_t zc_shmbuf_into_payload(struct zc_owned_shmbuf_t *buf); +ZENOHC_API zc_owned_payload_t zc_shmbuf_into_payload(struct zc_owned_shmbuf_t *buf); /** * Returns the length of the SHM buffer. * diff --git a/include/zenoh_macros.h b/include/zenoh_macros.h index 494d01fb9..dba68f29a 100644 --- a/include/zenoh_macros.h +++ b/include/zenoh_macros.h @@ -44,7 +44,6 @@ z_owned_query_channel_t * : z_query_channel_drop, \ z_owned_bytes_map_t * : z_bytes_map_drop, \ z_owned_buffer_t * : z_buffer_drop, \ - zc_owned_payload_t * : zc_payload_drop, \ zc_owned_shmbuf_t * : zc_shmbuf_drop, \ zc_owned_shm_manager_t * : zc_shm_manager_drop, \ zc_owned_liveliness_token_t * : zc_liveliness_undeclare_token, \ @@ -77,7 +76,6 @@ z_owned_bytes_map_t * : z_bytes_map_null, \ z_owned_buffer_t * : z_buffer_null, \ z_attachment_t * : z_attachment_null, \ - zc_owned_payload_t * : zc_payload_null, \ zc_owned_shmbuf_t * : zc_shmbuf_null, \ zc_owned_shm_manager_t * : zc_shm_manager_null, \ ze_owned_publication_cache_t * : ze_publication_cache_null, \ @@ -103,7 +101,6 @@ z_owned_bytes_map_t : z_bytes_map_check, \ z_owned_buffer_t : z_buffer_check, \ z_attachment_t : z_attachment_check, \ - zc_owned_payload_t : zc_payload_check, \ zc_owned_shmbuf_t : zc_shmbuf_check, \ zc_owned_shm_manager_t : zc_shm_manager_check, \ zc_owned_liveliness_token_t : zc_liveliness_token_check, \ diff --git a/src/collections.rs b/src/collections.rs index 9ac7831c0..7f34a8fdd 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -60,7 +60,7 @@ pub extern "C" fn z_bytes_check(b: &z_bytes_t) -> bool { /// Returns the gravestone value for `z_bytes_t` #[no_mangle] -pub extern "C" fn z_bytes_null() -> z_bytes_t { +pub const extern "C" fn z_bytes_null() -> z_bytes_t { z_bytes_t { len: 0, start: core::ptr::null(), @@ -167,11 +167,45 @@ impl From<&[u8]> for z_bytes_t { pub struct z_owned_buffer_t { _inner: [usize; 5], } -impl_guarded_transmute!(Option, z_owned_buffer_t); +impl_guarded_transmute!(noderefs Option, z_owned_buffer_t); +impl Default for z_owned_buffer_t { + fn default() -> Self { + z_buffer_null() + } +} +impl From for z_owned_buffer_t { + fn from(value: ZBuf) -> Self { + let value = match value.contiguous() { + std::borrow::Cow::Borrowed(_) => value, + std::borrow::Cow::Owned(value) => value.into(), + }; + unsafe { core::mem::transmute(Some(value)) } + } +} +impl From> for z_owned_buffer_t { + fn from(value: Option) -> Self { + match value { + Some(value) => value.into(), + None => z_buffer_null(), + } + } +} +impl core::ops::Deref for z_owned_buffer_t { + type Target = Option; + + fn deref(&self) -> &Self::Target { + unsafe { core::mem::transmute(self) } + } +} +impl core::ops::DerefMut for z_owned_buffer_t { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { core::mem::transmute(self) } + } +} #[no_mangle] pub extern "C" fn z_buffer_null() -> z_owned_buffer_t { - None.into() + unsafe { core::mem::transmute(None::) } } #[no_mangle] pub extern "C" fn z_buffer_drop(buffer: &mut z_owned_buffer_t) { @@ -189,20 +223,16 @@ pub extern "C" fn z_buffer_loan(buffer: &z_owned_buffer_t) -> z_buffer_t { #[repr(C)] #[derive(Clone, Copy)] -pub struct z_buffer_t { - _inner: usize, +pub struct z_buffer_t<'a> { + _inner: &'a (), } -impl_guarded_transmute!(noderefs Option<&ZBuf>, z_buffer_t); -impl From for Option<&'static ZBuf> { +impl_guarded_transmute!(Option<&'a ZBuf>, z_buffer_t<'a>, 'a); +impl<'a> From> for Option<&'a ZBuf> { fn from(value: z_buffer_t) -> Self { unsafe { core::mem::transmute(value) } } } -impl From> for z_buffer_t { - fn from(value: Option<&ZBuf>) -> Self { - unsafe { core::mem::transmute(value) } - } -} + #[no_mangle] pub extern "C" fn z_buffer_clone(buffer: z_buffer_t) -> z_owned_buffer_t { unsafe { Some(core::mem::transmute::<_, &ZBuf>(buffer).clone()).into() } diff --git a/src/commons.rs b/src/commons.rs index f96b9b09b..6ca6e19b4 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -20,7 +20,6 @@ use crate::z_priority_t; use crate::{impl_guarded_transmute, GuardedTransmute}; use libc::c_void; use libc::{c_char, c_ulong}; -use zenoh::buffers::ZBuf; use zenoh::prelude::SampleKind; use zenoh::prelude::SplitBuffer; use zenoh::query::ReplyKeyExpr; @@ -101,97 +100,27 @@ impl From> for z_timestamp_t { /// Should this invariant be broken when the payload is passed to one of zenoh's `put_owned` /// functions, then the operation will fail (but the passed value will still be consumed). #[allow(non_camel_case_types)] -#[repr(C)] -pub struct zc_owned_payload_t { - pub payload: z_bytes_t, - pub _owner: z_owned_buffer_t, -} -impl Default for zc_owned_payload_t { - fn default() -> Self { - zc_payload_null() - } -} -impl TryFrom for zc_owned_payload_t { - type Error = (); - fn try_from(buf: ZBuf) -> Result { - let std::borrow::Cow::Borrowed(payload) = buf.contiguous() else { - return Err(()); - }; - Ok(Self { - payload: payload.into(), - _owner: unsafe { std::mem::transmute(buf) }, - }) - } -} -impl zc_owned_payload_t { - pub fn take(&mut self) -> Option { - if !z_bytes_check(&self.payload) { - return None; - } - let start = std::mem::replace(&mut self.payload.start, std::ptr::null()); - let len = std::mem::replace(&mut self.payload.len, 0); - let Some(mut buf) = self._owner.take() else { - return None; - }; - { - let mut slices = buf.zslices_mut(); - let slice = slices.next().unwrap(); - assert!( - slices.next().is_none(), - "A multi-slice buffer reached zenoh-c, which is definitely a bug, please report it." - ); - let start_offset = unsafe { start.offset_from(slice.as_slice().as_ptr()) }; - let Ok(start_offset) = start_offset.try_into() else { - return None; - }; - *slice = match slice.subslice(start_offset, start_offset + len) { - Some(s) => s, - None => return None, - }; - } - Some(buf) - } - fn owner(&self) -> Option<&ZBuf> { - if !z_bytes_check(&self.payload) { - return None; - } - self._owner.as_ref() - } -} -impl Drop for zc_owned_payload_t { - fn drop(&mut self) { - self.take(); - } -} +pub type zc_owned_payload_t = z_owned_buffer_t; /// Clones the `payload` by incrementing its reference counter. #[no_mangle] pub extern "C" fn zc_payload_rcinc(payload: &zc_owned_payload_t) -> zc_owned_payload_t { - match payload.owner() { - None => Default::default(), - Some(payload) => payload.clone().try_into().unwrap_or_default(), - } + z_buffer_clone(z_buffer_loan(payload)) } /// Returns `false` if `payload` is the gravestone value. #[no_mangle] pub extern "C" fn zc_payload_check(payload: &zc_owned_payload_t) -> bool { - !payload.payload.start.is_null() + z_buffer_check(payload) } /// Decrements `payload`'s backing refcount, releasing the memory if appropriate. #[no_mangle] pub extern "C" fn zc_payload_drop(payload: &mut zc_owned_payload_t) { - unsafe { std::ptr::replace(payload, zc_payload_null()) }; + z_buffer_drop(payload) } /// Constructs `zc_owned_payload_t`'s gravestone value. #[no_mangle] pub extern "C" fn zc_payload_null() -> zc_owned_payload_t { - zc_owned_payload_t { - payload: z_bytes_t { - len: 0, - start: std::ptr::null(), - }, - _owner: unsafe { core::mem::MaybeUninit::zeroed().assume_init() }, - } + z_buffer_null() } /// QoS settings of zenoh message. @@ -235,50 +164,77 @@ pub extern "C" fn z_qos_default() -> z_qos_t { /// z_attachment_t attachment: The attachment of this data sample. #[repr(C)] pub struct z_sample_t<'a> { - pub keyexpr: z_keyexpr_t, - pub payload: z_bytes_t, - pub encoding: z_encoding_t, - pub _zc_buf: &'a c_void, - pub kind: z_sample_kind_t, - pub timestamp: z_timestamp_t, - pub qos: z_qos_t, - pub attachment: z_attachment_t, + _inner: &'a (), +} +impl<'a> core::ops::Deref for z_sample_t<'a> { + type Target = Sample; + fn deref(&self) -> &Self::Target { + unsafe { core::mem::transmute::<&(), &Sample>(self._inner) } + } } impl<'a> z_sample_t<'a> { - pub fn new(sample: &'a Sample, owner: &'a ZBuf) -> Self { - let std::borrow::Cow::Borrowed(payload) = owner.contiguous() else { + pub fn new(sample: &'a Sample) -> Self { + if !sample.value.payload.zslices().count() <= 1 { panic!("Attempted to construct z_sample_t from discontiguous buffer, this is definitely a bug in zenoh-c, please report it.") }; z_sample_t { - keyexpr: (&sample.key_expr).into(), - payload: z_bytes_t::from(payload), - encoding: (&sample.encoding).into(), - _zc_buf: unsafe { std::mem::transmute(owner) }, - kind: sample.kind.into(), - timestamp: sample.timestamp.as_ref().into(), - qos: sample.qos.into(), - attachment: match &sample.attachment { - Some(attachment) => z_attachment_t { - data: attachment as *const _ as *mut c_void, - iteration_driver: Some(attachment_iteration_driver), - }, - None => z_attachment_null(), - }, + _inner: unsafe { core::mem::transmute(sample) }, } } } -/// Clones the sample's payload by incrementing its backing refcount (this doesn't imply any copies). +/// The Key Expression of the sample. +/// +/// `sample` is aliased by its return value. #[no_mangle] -pub extern "C" fn zc_sample_payload_rcinc(sample: Option<&z_sample_t>) -> zc_owned_payload_t { - let Some(sample) = sample else { - return zc_payload_null(); - }; - let buf = unsafe { std::mem::transmute::<_, &ZBuf>(sample._zc_buf).clone() }; - zc_owned_payload_t { - payload: sample.payload, - _owner: unsafe { std::mem::transmute(buf) }, +pub extern "C" fn z_sample_keyexpr(sample: &z_sample_t) -> z_keyexpr_t { + (&sample.key_expr).into() +} +/// The encoding of the payload. +#[no_mangle] +pub extern "C" fn z_sample_encoding(sample: &z_sample_t) -> z_encoding_t { + (&sample.encoding).into() +} +/// The sample's data, the return value aliases the sample. +/// +/// If you need ownership of the buffer, you may use `z_sample_owned_payload`. +#[no_mangle] +pub extern "C" fn z_sample_payload(sample: &z_sample_t) -> z_bytes_t { + sample.payload.slices().next().unwrap_or(b"").into() +} +/// Returns the sample's payload after incrementing its internal reference count. +/// +/// Note that other samples may have received the same buffer, meaning that mutating this buffer may +/// affect the samples received by other subscribers. +#[no_mangle] +pub extern "C" fn z_sample_owned_payload(sample: &z_sample_t) -> z_owned_buffer_t { + sample.payload.clone().into() +} +/// The sample's kind (put or delete). +#[no_mangle] +pub extern "C" fn z_sample_kind(sample: &z_sample_t) -> z_sample_kind_t { + sample.kind.into() +} +#[no_mangle] +pub extern "C" fn z_sample_timestamp(sample: &z_sample_t) -> z_timestamp_t { + sample.timestamp.as_ref().into() +} +#[no_mangle] +pub extern "C" fn z_sample_qos(sample: &z_sample_t) -> z_qos_t { + sample.qos.into() +} +/// The sample's attachment. +/// +/// `sample` is aliased by the return value. +#[no_mangle] +pub extern "C" fn z_sample_attachment(sample: &z_sample_t) -> z_attachment_t { + match &sample.attachment { + Some(attachment) => z_attachment_t { + data: attachment as *const _ as *mut c_void, + iteration_driver: Some(attachment_iteration_driver), + }, + None => z_attachment_null(), } } @@ -425,21 +381,24 @@ impl From for z_encoding_prefix_t { #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct z_encoding_t { - pub prefix: z_encoding_prefix_t, + pub prefix: u64, pub suffix: z_bytes_t, } impl From for zenoh_protocol::core::Encoding { fn from(enc: z_encoding_t) -> Self { if enc.suffix.len == 0 { - zenoh_protocol::core::Encoding::Exact(enc.prefix.into()) + zenoh_protocol::core::Encoding::Exact((enc.prefix as u8).try_into().unwrap()) } else { let suffix = unsafe { let slice: &'static [u8] = std::slice::from_raw_parts(enc.suffix.start, enc.suffix.len); std::str::from_utf8_unchecked(slice) }; - zenoh_protocol::core::Encoding::WithSuffix(enc.prefix.into(), suffix.into()) + zenoh_protocol::core::Encoding::WithSuffix( + (enc.prefix as u8).try_into().unwrap(), + suffix.into(), + ) } } } @@ -448,7 +407,7 @@ impl From<&zenoh_protocol::core::Encoding> for z_encoding_t { fn from(val: &zenoh_protocol::core::Encoding) -> Self { let suffix = val.suffix(); z_encoding_t { - prefix: (*val.prefix()).into(), + prefix: u8::from(*val.prefix()) as u64, suffix: z_bytes_t { start: suffix.as_ptr(), len: suffix.len(), @@ -470,7 +429,7 @@ impl From<&zenoh_protocol::core::Encoding> for z_encoding_t { /// To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. #[repr(C)] pub struct z_owned_encoding_t { - pub prefix: z_encoding_prefix_t, + pub prefix: u64, pub suffix: z_bytes_t, pub _dropped: bool, } @@ -478,7 +437,7 @@ pub struct z_owned_encoding_t { impl z_owned_encoding_t { pub fn null() -> Self { z_owned_encoding_t { - prefix: z_encoding_prefix_t::Empty, + prefix: 0, suffix: z_bytes_t::default(), _dropped: true, } @@ -506,7 +465,10 @@ pub unsafe extern "C" fn z_encoding( len: libc::strlen(suffix), } }; - z_encoding_t { prefix, suffix } + z_encoding_t { + prefix: prefix as u64, + suffix, + } } /// Constructs a default :c:type:`z_encoding_t`. diff --git a/src/get.rs b/src/get.rs index 41e3cf204..423810a4f 100644 --- a/src/get.rs +++ b/src/get.rs @@ -108,7 +108,7 @@ pub unsafe extern "C" fn z_reply_ok(reply: &z_owned_reply_t) -> z_sample_t { if let Cow::Owned(_) = sample.payload.contiguous() { unreachable!("z_reply_ok found a payload that wasn't contiguous by the time it was reached, which breaks some crate assertions. This is definitely a bug with zenoh, please contact us.") } - z_sample_t::new(sample, &sample.payload) + z_sample_t::new(sample) } else { panic!("Assertion failed: tried to treat `z_owned_reply_t` as Ok despite that not being the case") } diff --git a/src/lib.rs b/src/lib.rs index 19c22fa2e..9c01e4aa2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -103,6 +103,30 @@ macro_rules! impl_guarded_transmute { } } }; + ($src_type:ty, $dst_type:ty, $($gen: tt)*) => { + impl<$($gen)*> $crate::GuardedTransmute<$dst_type> for $src_type { + fn transmute(self) -> $dst_type { + unsafe { std::mem::transmute::<$src_type, $dst_type>(self) } + } + } + impl<$($gen)*> From<$src_type> for $dst_type { + fn from(value: $src_type) -> $dst_type { + unsafe { core::mem::transmute(value) } + } + } + impl<$($gen)*> core::ops::Deref for $dst_type { + type Target = $src_type; + fn deref(&self) -> &$src_type { + unsafe { core::mem::transmute(self) } + } + } + impl<$($gen)*> core::ops::DerefMut for $dst_type { + fn deref_mut(&mut self) -> &mut $src_type { + unsafe { core::mem::transmute(self) } + } + } + + }; } pub(crate) const LOG_INVALID_SESSION: &str = "Invalid session"; diff --git a/src/liveliness.rs b/src/liveliness.rs index 040205892..69ee2d2e2 100644 --- a/src/liveliness.rs +++ b/src/liveliness.rs @@ -176,13 +176,11 @@ pub extern "C" fn zc_liveliness_declare_subscriber( match session .liveliness() .declare_subscriber(key) - .callback(move |sample| { - let payload = sample.payload.contiguous(); - let owner = match payload { - std::borrow::Cow::Owned(v) => zenoh::buffers::ZBuf::from(v), - _ => sample.payload.clone(), - }; - let sample = z_sample_t::new(&sample, &owner); + .callback(move |mut sample| { + if let std::borrow::Cow::Owned(v) = sample.payload.contiguous() { + sample.payload = v.into(); + } + let sample = z_sample_t::new(&sample); z_closure_sample_call(&callback, &sample) }) .res() diff --git a/src/pull_subscriber.rs b/src/pull_subscriber.rs index 0eee4bc94..247484cb1 100644 --- a/src/pull_subscriber.rs +++ b/src/pull_subscriber.rs @@ -149,13 +149,11 @@ pub extern "C" fn z_declare_pull_subscriber( Some(s) => { let mut res = s .declare_subscriber(keyexpr) - .callback(move |sample| { - let payload = sample.payload.contiguous(); - let owner = match payload { - std::borrow::Cow::Owned(v) => zenoh::buffers::ZBuf::from(v), - _ => sample.payload.clone(), - }; - let sample = z_sample_t::new(&sample, &owner); + .callback(move |mut sample| { + if let std::borrow::Cow::Owned(v) = sample.payload.contiguous() { + sample.payload = v.into(); + } + let sample = z_sample_t::new(&sample); z_closure_sample_call(&closure, &sample) }) .pull_mode(); diff --git a/src/querying_subscriber.rs b/src/querying_subscriber.rs index cdec44f0f..a4681b4e9 100644 --- a/src/querying_subscriber.rs +++ b/src/querying_subscriber.rs @@ -185,13 +185,11 @@ pub unsafe extern "C" fn ze_declare_querying_subscriber( } } match sub - .callback(move |sample| { - let payload = sample.payload.contiguous(); - let owner = match payload { - std::borrow::Cow::Owned(v) => zenoh::buffers::ZBuf::from(v), - _ => sample.payload.clone(), - }; - let sample = z_sample_t::new(&sample, &owner); + .callback(move |mut sample| { + if let std::borrow::Cow::Owned(v) = sample.payload.contiguous() { + sample.payload = v.into(); + } + let sample = z_sample_t::new(&sample); z_closure_sample_call(&closure, &sample) }) .res() diff --git a/src/subscriber.rs b/src/subscriber.rs index b9488960a..7d15e740a 100644 --- a/src/subscriber.rs +++ b/src/subscriber.rs @@ -179,13 +179,11 @@ pub extern "C" fn z_declare_subscriber( match session.upgrade() { Some(s) => { - let mut res = s.declare_subscriber(keyexpr).callback(move |sample| { - let payload = sample.payload.contiguous(); - let owner = match payload { - std::borrow::Cow::Owned(v) => zenoh::buffers::ZBuf::from(v), - _ => sample.payload.clone(), - }; - let sample = z_sample_t::new(&sample, &owner); + let mut res = s.declare_subscriber(keyexpr).callback(move |mut sample| { + if let std::borrow::Cow::Owned(v) = sample.payload.contiguous() { + sample.payload = v.into(); + } + let sample = z_sample_t::new(&sample); z_closure_sample_call(&closure, &sample) }); if let Some(opts) = opts { diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index ee63017c2..8dcff3317 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -76,7 +76,7 @@ void reply_handler(z_owned_reply_t *reply, void *arg) { if (z_reply_is_ok(reply)) { z_sample_t sample = z_reply_ok(reply); - z_owned_str_t k_str = z_keyexpr_to_string(sample.keyexpr); + z_owned_str_t k_str = z_keyexpr_to_string(z_sample_keyexpr(&sample)); #ifdef ZENOH_PICO if (k_str == NULL) { k_str = zp_keyexpr_resolve(*(z_session_t *)arg, sample.keyexpr); @@ -95,7 +95,7 @@ volatile unsigned int datas = 0; void data_handler(const z_sample_t *sample, void *arg) { datas++; - z_owned_str_t k_str = z_keyexpr_to_string(sample->keyexpr); + z_owned_str_t k_str = z_keyexpr_to_string(z_sample_keyexpr(sample)); #ifdef ZENOH_PICO if (k_str == NULL) { k_str = zp_keyexpr_resolve(*(z_session_t *)arg, sample->keyexpr); diff --git a/tests/z_int_pub_cache_query_sub_test.c b/tests/z_int_pub_cache_query_sub_test.c index 6674aec55..7495939f2 100644 --- a/tests/z_int_pub_cache_query_sub_test.c +++ b/tests/z_int_pub_cache_query_sub_test.c @@ -85,14 +85,14 @@ int run_publisher() { void data_handler(const z_sample_t *sample, void *arg) { static int val_num = 0; - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(sample)); if (strcmp(keyexpr, z_loan(keystr))) { perror("Unexpected key received"); exit(-1); } z_drop(z_move(keystr)); - ASSERT_STR_BYTES_EQUAL(values[val_num], sample->payload); + ASSERT_STR_BYTES_EQUAL(values[val_num], z_sample_payload(sample)); printf("data_handler: %i\n", val_num); if (++val_num == values_count) { diff --git a/tests/z_int_pub_sub_attachment_test.c b/tests/z_int_pub_sub_attachment_test.c index 75ae88547..554d1fd57 100644 --- a/tests/z_int_pub_sub_attachment_test.c +++ b/tests/z_int_pub_sub_attachment_test.c @@ -66,22 +66,23 @@ int run_publisher() { void data_handler(const z_sample_t *sample, void *arg) { static int val_num = 0; - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(sample)); if (strcmp(keyexpr, z_loan(keystr))) { perror("Unexpected key received"); exit(-1); } z_drop(z_move(keystr)); - if (strncmp(values[val_num], (const char *)sample->payload.start, (int)sample->payload.len)) { + z_bytes_t payload = z_sample_payload(sample); + if (strncmp(values[val_num], (const char *)payload.start, (int)payload.len)) { perror("Unexpected value received"); exit(-1); } - z_bytes_t v_const = z_attachment_get(sample->attachment, z_bytes_from_str(K_CONST)); + z_bytes_t v_const = z_attachment_get(z_sample_attachment(sample), z_bytes_from_str(K_CONST)); ASSERT_STR_BYTES_EQUAL(V_CONST, v_const); - z_bytes_t v_var = z_attachment_get(sample->attachment, z_bytes_from_str(K_VAR)); + z_bytes_t v_var = z_attachment_get(z_sample_attachment(sample), z_bytes_from_str(K_VAR)); ASSERT_STR_BYTES_EQUAL(values[val_num], v_var); if (++val_num == values_count) { diff --git a/tests/z_int_pub_sub_test.c b/tests/z_int_pub_sub_test.c index cf005a80f..6e48fef5a 100644 --- a/tests/z_int_pub_sub_test.c +++ b/tests/z_int_pub_sub_test.c @@ -59,21 +59,21 @@ int run_publisher() { void data_handler(const z_sample_t *sample, void *arg) { static int val_num = 0; - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(sample)); if (strcmp(keyexpr, z_loan(keystr))) { perror("Unexpected key received"); exit(-1); } z_drop(z_move(keystr)); - if (strncmp(values[val_num], (const char *)sample->payload.start, (int)sample->payload.len)) { + z_bytes_t payload = z_sample_payload(sample); + if (strncmp(values[val_num], (const char *)payload.start, (int)payload.len)) { perror("Unexpected value received"); exit(-1); } - if (z_qos_get_congestion_control(sample->qos) != Z_CONGESTION_CONTROL_BLOCK - || z_qos_get_priority(sample->qos) != Z_PRIORITY_DATA - ) { + if (z_qos_get_congestion_control(z_sample_qos(sample)) != Z_CONGESTION_CONTROL_BLOCK || + z_qos_get_priority(z_sample_qos(sample)) != Z_PRIORITY_DATA) { perror("Unexpected QoS values"); exit(-1); } diff --git a/tests/z_int_queryable_attachment_test.c b/tests/z_int_queryable_attachment_test.c index b2f2a7ab8..836f8d988 100644 --- a/tests/z_int_queryable_attachment_test.c +++ b/tests/z_int_queryable_attachment_test.c @@ -109,11 +109,11 @@ int run_get() { assert(z_reply_is_ok(&reply)); z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(&sample)); - ASSERT_STR_BYTES_EQUAL(values[val_num], sample.payload); + ASSERT_STR_BYTES_EQUAL(values[val_num], z_sample_payload(&sample)); - z_bytes_t v_const = z_attachment_get(sample.attachment, z_bytes_from_str(K_CONST)); + z_bytes_t v_const = z_attachment_get(z_sample_attachment(&sample), z_bytes_from_str(K_CONST)); ASSERT_STR_BYTES_EQUAL(V_CONST, v_const); z_drop(z_move(keystr)); diff --git a/tests/z_int_queryable_test.c b/tests/z_int_queryable_test.c index 4244af2c7..67c690f8e 100644 --- a/tests/z_int_queryable_test.c +++ b/tests/z_int_queryable_test.c @@ -85,9 +85,9 @@ int run_get() { assert(z_reply_is_ok(&reply)); z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); + z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(&sample)); - ASSERT_STR_BYTES_EQUAL(values[val_num], sample.payload); + ASSERT_STR_BYTES_EQUAL(values[val_num], z_sample_payload(&sample)); z_drop(z_move(keystr)); } From 3551d3843f2980556e9edc54db17cf4b3fa03013 Mon Sep 17 00:00:00 2001 From: Pierre Avital Date: Thu, 29 Feb 2024 11:40:39 +0100 Subject: [PATCH 3/8] add support for owned samples --- Cargo.toml | 2 +- include/zenoh_commons.h | 34 ++++++++++++++++++++++++++++++++ src/commons.rs | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 52deaa71c..638c6422d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,7 @@ serde_yaml = "0.9.19" [lib] path="src/lib.rs" -name = "zenohc" +name = "zenohcd" crate-type = ["cdylib", "staticlib"] doctest = false diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 1d56fe95f..3fa477cd3 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -863,6 +863,12 @@ typedef struct zc_owned_liveliness_get_options_t { * functions, then the operation will fail (but the passed value will still be consumed). */ typedef struct z_owned_buffer_t zc_owned_payload_t; +typedef struct zc_owned_sample_t { + struct z_owned_keyexpr_t _0; + struct z_owned_buffer_t _1; + struct z_owned_buffer_t _2; + size_t _3[12]; +} zc_owned_sample_t; typedef struct zc_owned_shmbuf_t { size_t _0[9]; } zc_owned_shmbuf_t; @@ -2005,7 +2011,13 @@ ZENOHC_API struct z_owned_buffer_t z_sample_owned_payload(const struct z_sample_ * If you need ownership of the buffer, you may use `z_sample_owned_payload`. */ ZENOHC_API struct z_bytes_t z_sample_payload(const struct z_sample_t *sample); +/** + * The qos with which the sample was received. + */ ZENOHC_API struct z_qos_t z_sample_qos(const struct z_sample_t *sample); +/** + * The samples timestamp + */ ZENOHC_API struct z_timestamp_t z_sample_timestamp(const struct z_sample_t *sample); /** * Scout for routers and/or peers. @@ -2410,6 +2422,28 @@ struct z_owned_reply_channel_t zc_reply_fifo_new(size_t bound); */ ZENOHC_API struct z_owned_reply_channel_t zc_reply_non_blocking_fifo_new(size_t bound); +/** + * Returns `true` if `sample` is valid. + * + * Note that there exist no fallinle constructors for `zc_owned_sample_t`, so validity is always guaranteed + * unless the value has been dropped already. + */ +ZENOHC_API +bool zc_sample_check(const struct zc_owned_sample_t *sample); +/** + * Clone a sample in the cheapest way available. + */ +ZENOHC_API struct zc_owned_sample_t zc_sample_clone(const struct z_sample_t *sample); +/** + * Destroy the sample. + */ +ZENOHC_API void zc_sample_drop(struct zc_owned_sample_t *sample); +/** + * Borrow the sample, allowing calling its accessor methods. + * + * Calling this function using a dropped sample is undefined behaviour. + */ +ZENOHC_API struct z_sample_t zc_sample_loan(const struct zc_owned_sample_t *sample); /** * Increments the session's reference count, returning a new owning handle. */ diff --git a/src/commons.rs b/src/commons.rs index 6ca6e19b4..085a0df5a 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -12,6 +12,8 @@ // ZettaScale Zenoh team, // +use std::ops::Deref; + use crate::collections::*; use crate::keyexpr::*; use crate::z_congestion_control_t; @@ -216,10 +218,12 @@ pub extern "C" fn z_sample_owned_payload(sample: &z_sample_t) -> z_owned_buffer_ pub extern "C" fn z_sample_kind(sample: &z_sample_t) -> z_sample_kind_t { sample.kind.into() } +/// The samples timestamp #[no_mangle] pub extern "C" fn z_sample_timestamp(sample: &z_sample_t) -> z_timestamp_t { sample.timestamp.as_ref().into() } +/// The qos with which the sample was received. #[no_mangle] pub extern "C" fn z_sample_qos(sample: &z_sample_t) -> z_qos_t { sample.qos.into() @@ -238,6 +242,45 @@ pub extern "C" fn z_sample_attachment(sample: &z_sample_t) -> z_attachment_t { } } +#[repr(C)] +pub struct zc_owned_sample_t { + _0: z_owned_keyexpr_t, + _1: z_owned_buffer_t, + _2: z_owned_buffer_t, + _3: [usize; 12], +} + +impl_guarded_transmute!(Option, zc_owned_sample_t); + +/// Clone a sample in the cheapest way available. +#[no_mangle] +pub extern "C" fn zc_sample_clone(sample: &z_sample_t) -> zc_owned_sample_t { + Some(sample.deref().clone()).into() +} + +/// Returns `true` if `sample` is valid. +/// +/// Note that there exist no fallinle constructors for `zc_owned_sample_t`, so validity is always guaranteed +/// unless the value has been dropped already. +#[no_mangle] +pub extern "C" fn zc_sample_check(sample: &zc_owned_sample_t) -> bool { + sample.is_some() +} + +/// Borrow the sample, allowing calling its accessor methods. +/// +/// Calling this function using a dropped sample is undefined behaviour. +#[no_mangle] +pub extern "C" fn zc_sample_loan(sample: &zc_owned_sample_t) -> z_sample_t { + z_sample_t::new(unsafe { sample.as_ref().unwrap_unchecked() }) +} + +/// Destroy the sample. +#[no_mangle] +pub extern "C" fn zc_sample_drop(sample: &mut zc_owned_sample_t) { + core::mem::drop(sample.take()); +} + /// A :c:type:`z_encoding_t` integer `prefix`. /// /// - **Z_ENCODING_PREFIX_EMPTY** From 7148d5b57ab81907621c1c4c0202735fb36c12b5 Mon Sep 17 00:00:00 2001 From: Pierre Avital Date: Thu, 29 Feb 2024 14:18:57 +0100 Subject: [PATCH 4/8] document the owned sample type itself --- include/zenoh_commons.h | 6 ++++++ src/commons.rs | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 3fa477cd3..53c80c75c 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -863,6 +863,12 @@ typedef struct zc_owned_liveliness_get_options_t { * functions, then the operation will fail (but the passed value will still be consumed). */ typedef struct z_owned_buffer_t zc_owned_payload_t; +/** + * An owned sample. + * + * This is a read only type that can only be constructed by cloning a `z_sample_t`. + * Like all owned types, its memory must be freed by passing a mutable reference to it to `zc_sample_drop`. + */ typedef struct zc_owned_sample_t { struct z_owned_keyexpr_t _0; struct z_owned_buffer_t _1; diff --git a/src/commons.rs b/src/commons.rs index 085a0df5a..555a380be 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -242,6 +242,10 @@ pub extern "C" fn z_sample_attachment(sample: &z_sample_t) -> z_attachment_t { } } +/// An owned sample. +/// +/// This is a read only type that can only be constructed by cloning a `z_sample_t`. +/// Like all owned types, its memory must be freed by passing a mutable reference to it to `zc_sample_drop`. #[repr(C)] pub struct zc_owned_sample_t { _0: z_owned_keyexpr_t, From 9c9f1ac5ad6eaa0b9939e70d473031fa210afe63 Mon Sep 17 00:00:00 2001 From: Pierre Avital Date: Thu, 29 Feb 2024 14:53:08 +0100 Subject: [PATCH 5/8] fix macro usages --- src/platform/synchronization.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/platform/synchronization.rs b/src/platform/synchronization.rs index dbd9d94b8..a16664352 100644 --- a/src/platform/synchronization.rs +++ b/src/platform/synchronization.rs @@ -22,8 +22,8 @@ pub struct ZMutexPtr { #[derive(Clone, Copy)] pub struct z_mutex_t(usize); -impl_guarded_transmute!(z_mutex_t, ZMutexPtr); -impl_guarded_transmute!(ZMutexPtr, z_mutex_t); +impl_guarded_transmute!(noderefs z_mutex_t, ZMutexPtr); +impl_guarded_transmute!(noderefs ZMutexPtr, z_mutex_t); // using the same error codes as in GNU pthreads, but with negative sign // due to convention to return negative values on error @@ -141,8 +141,8 @@ struct ZCondvarPtr { #[derive(Clone, Copy)] pub struct z_condvar_t(usize); -impl_guarded_transmute!(z_condvar_t, ZCondvarPtr); -impl_guarded_transmute!(ZCondvarPtr, z_condvar_t); +impl_guarded_transmute!(noderefs z_condvar_t, ZCondvarPtr); +impl_guarded_transmute!(noderefs ZCondvarPtr, z_condvar_t); #[no_mangle] #[allow(clippy::missing_safety_doc)] @@ -233,8 +233,8 @@ pub struct z_task_t(usize); #[derive(Clone, Copy)] pub struct z_task_attr_t(usize); -impl_guarded_transmute!(z_task_t, ZTaskPtr); -impl_guarded_transmute!(ZTaskPtr, z_task_t); +impl_guarded_transmute!(noderefs z_task_t, ZTaskPtr); +impl_guarded_transmute!(noderefs ZTaskPtr, z_task_t); struct FunArgPair { fun: unsafe extern "C" fn(arg: *mut c_void), From 3eb72362b564c04734d46c2bc05227a80e55f2d7 Mon Sep 17 00:00:00 2001 From: Pierre Avital Date: Fri, 1 Mar 2024 16:07:56 +0100 Subject: [PATCH 6/8] fix auto-generated zenohcd --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 638c6422d..52deaa71c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,7 @@ serde_yaml = "0.9.19" [lib] path="src/lib.rs" -name = "zenohcd" +name = "zenohc" crate-type = ["cdylib", "staticlib"] doctest = false From 769d824adf227f013f2f6f1f0b666f152a5aeeb4 Mon Sep 17 00:00:00 2001 From: Pierre Avital Date: Tue, 5 Mar 2024 17:09:53 +0100 Subject: [PATCH 7/8] introduce split buffers in zenoh-c --- include/zenoh_commons.h | 55 +++++++++++++++++++++++++++++++++- src/collections.rs | 66 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 115 insertions(+), 6 deletions(-) diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 53c80c75c..5e3af4644 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -190,11 +190,22 @@ typedef struct z_attachment_t { z_attachment_iter_driver_t iteration_driver; } z_attachment_t; /** - * A buffer owned by Zenoh. + * A split buffer that owns all of its data. + * + * To minimize copies and reallocations, Zenoh may provide you data in split buffers. + * + * You can use `z_buffer_contiguous` to obtain a contiguous version of a buffer. + * If the buffer was already contiguous, the reference count will simply be increased. + * Otherwise, the split buffer's entire content will be copied in a newly allocated buffer. */ typedef struct z_owned_buffer_t { size_t _inner[5]; } z_owned_buffer_t; +/** + * A loan of a `z_owned_buffer_t`. + * + * As it is a split buffer, it may contain more than one slice. It's number of slices is returned by `z_buffer_slice_count`. + */ typedef struct z_buffer_t { const void *_inner; } z_buffer_t; @@ -1038,12 +1049,54 @@ int8_t z_attachment_iterate(struct z_attachment_t this_, * Returns the gravestone value for `z_attachment_t`. */ ZENOHC_API struct z_attachment_t z_attachment_null(void); +/** + * Returns `true` if the buffer is in a valid state. + */ ZENOHC_API bool z_buffer_check(const struct z_owned_buffer_t *buffer); +/** + * Increments the buffer's reference count, returning an owned version of the buffer. + */ ZENOHC_API struct z_owned_buffer_t z_buffer_clone(struct z_buffer_t buffer); +/** + * Returns an owned version of this buffer whose data is guaranteed to be contiguous in memory. + * + * This is achieved by increasing the reference count if the buffer is already contiguous, and by copying its data in a new contiguous buffer if it wasn't. + */ +ZENOHC_API +struct z_owned_buffer_t z_buffer_contiguous(struct z_buffer_t buffer); +/** + * Decrements the buffer's reference counter, destroying it if applicable. + * + * `buffer` will be reset to `z_buffer_null`, preventing UB on double-frees. + */ ZENOHC_API void z_buffer_drop(struct z_owned_buffer_t *buffer); +/** + * Loans the buffer, allowing you to call functions that only need a loan of it. + */ ZENOHC_API struct z_buffer_t z_buffer_loan(const struct z_owned_buffer_t *buffer); +/** + * The gravestone value for `z_owned_buffer_t`. + */ ZENOHC_API struct z_owned_buffer_t z_buffer_null(void); +/** + * Returns the payload of the buffer if it is contiguous, aliasling it. + * + * If the payload was not contiguous in memory, `z_bytes_null` will be returned instead. + */ ZENOHC_API struct z_bytes_t z_buffer_payload(struct z_buffer_t buffer); +/** + * Returns the `index`th slice of the buffer, aliasing it. + * + * Out of bounds accesses will return `z_bytes_null`. + */ +ZENOHC_API struct z_bytes_t z_buffer_slice_at(struct z_buffer_t buffer, size_t index); +/** + * Returns the number of slices in the buffer. + * + * If the return value is 0 or 1, then the buffer's data is contiguous in memory and `z_buffer_contiguous` will succeed. + */ +ZENOHC_API +size_t z_buffer_slice_count(struct z_buffer_t buffer); /** * Returns ``true`` if `b` is initialized. */ diff --git a/src/collections.rs b/src/collections.rs index 7f34a8fdd..89c0e0438 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -162,7 +162,13 @@ impl From<&[u8]> for z_bytes_t { } } -/// A buffer owned by Zenoh. +/// A split buffer that owns all of its data. +/// +/// To minimize copies and reallocations, Zenoh may provide you data in split buffers. +/// +/// You can use `z_buffer_contiguous` to obtain a contiguous version of a buffer. +/// If the buffer was already contiguous, the reference count will simply be increased. +/// Otherwise, the split buffer's entire content will be copied in a newly allocated buffer. #[repr(C)] pub struct z_owned_buffer_t { _inner: [usize; 5], @@ -203,24 +209,35 @@ impl core::ops::DerefMut for z_owned_buffer_t { } } +/// The gravestone value for `z_owned_buffer_t`. #[no_mangle] pub extern "C" fn z_buffer_null() -> z_owned_buffer_t { unsafe { core::mem::transmute(None::) } } + +/// Decrements the buffer's reference counter, destroying it if applicable. +/// +/// `buffer` will be reset to `z_buffer_null`, preventing UB on double-frees. #[no_mangle] pub extern "C" fn z_buffer_drop(buffer: &mut z_owned_buffer_t) { core::mem::drop(buffer.take()) } +/// Returns `true` if the buffer is in a valid state. #[no_mangle] pub extern "C" fn z_buffer_check(buffer: &z_owned_buffer_t) -> bool { buffer.is_some() } + +/// Loans the buffer, allowing you to call functions that only need a loan of it. #[no_mangle] pub extern "C" fn z_buffer_loan(buffer: &z_owned_buffer_t) -> z_buffer_t { buffer.as_ref().into() } +/// A loan of a `z_owned_buffer_t`. +/// +/// As it is a split buffer, it may contain more than one slice. It's number of slices is returned by `z_buffer_slice_count`. #[repr(C)] #[derive(Clone, Copy)] pub struct z_buffer_t<'a> { @@ -233,11 +250,15 @@ impl<'a> From> for Option<&'a ZBuf> { } } +/// Increments the buffer's reference count, returning an owned version of the buffer. #[no_mangle] pub extern "C" fn z_buffer_clone(buffer: z_buffer_t) -> z_owned_buffer_t { unsafe { Some(core::mem::transmute::<_, &ZBuf>(buffer).clone()).into() } } +/// Returns the payload of the buffer if it is contiguous, aliasling it. +/// +/// If the payload was not contiguous in memory, `z_bytes_null` will be returned instead. #[no_mangle] pub extern "C" fn z_buffer_payload(buffer: z_buffer_t) -> z_bytes_t { let Some(buffer): Option<&ZBuf> = buffer.into() else { @@ -245,9 +266,44 @@ pub extern "C" fn z_buffer_payload(buffer: z_buffer_t) -> z_bytes_t { }; match buffer.contiguous() { std::borrow::Cow::Borrowed(buffer) => buffer.into(), - std::borrow::Cow::Owned(_) => { - log::error!("A non-contiguous buffer reached user code, this is definitely a bug, please inform us at https://github.com/eclipse-zenoh/zenoh-c/issues/new"); - z_bytes_null() - } + std::borrow::Cow::Owned(_) => z_bytes_null(), + } +} + +/// Returns an owned version of this buffer whose data is guaranteed to be contiguous in memory. +/// +/// This is achieved by increasing the reference count if the buffer is already contiguous, and by copying its data in a new contiguous buffer if it wasn't. +#[no_mangle] +pub extern "C" fn z_buffer_contiguous(buffer: z_buffer_t) -> z_owned_buffer_t { + let Some(buf): Option<&ZBuf> = buffer.into() else { + return z_buffer_null(); + }; + match buf.contiguous() { + std::borrow::Cow::Borrowed(_) => buf.clone().into(), + std::borrow::Cow::Owned(buf) => ZBuf::from(buf).into(), + } +} + +/// Returns the number of slices in the buffer. +/// +/// If the return value is 0 or 1, then the buffer's data is contiguous in memory and `z_buffer_contiguous` will succeed. +#[no_mangle] +pub extern "C" fn z_buffer_slice_count(buffer: z_buffer_t) -> usize { + match buffer.into() { + None => 0, + Some(buf) => ZBuf::slices(buf).len(), + } +} + +/// Returns the `index`th slice of the buffer, aliasing it. +/// +/// Out of bounds accesses will return `z_bytes_null`. +#[no_mangle] +pub extern "C" fn z_buffer_slice_at(buffer: z_buffer_t, index: usize) -> z_bytes_t { + match buffer.into() { + None => z_bytes_null(), + Some(buf) => ZBuf::slices(buf) + .nth(index) + .map_or(z_bytes_null(), |slice| slice.into()), } } From 1b09b308accafcbb4c9e54675bf6e878072d18de Mon Sep 17 00:00:00 2001 From: Pierre Avital Date: Fri, 8 Mar 2024 11:16:02 +0100 Subject: [PATCH 8/8] address pr comments --- include/zenoh_commons.h | 9 +-------- src/commons.rs | 16 +++++----------- src/lib.rs | 8 ++++++++ 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 5e3af4644..e0b405014 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -383,14 +383,6 @@ typedef struct z_owned_closure_reply_t { * A data sample. * * A sample is the value associated to a given resource at a given point in time. - * - * Members: - * z_keyexpr_t keyexpr: The resource key of this data sample. - * z_bytes_t payload: The value of this data sample. - * z_encoding_t encoding: The encoding of the value of this data sample. - * z_sample_kind_t kind: The kind of this data sample (PUT or DELETE). - * z_timestamp_t timestamp: The timestamp of this data sample. - * z_attachment_t attachment: The attachment of this data sample. */ typedef struct z_sample_t { const void *_inner; @@ -2503,6 +2495,7 @@ ZENOHC_API void zc_sample_drop(struct zc_owned_sample_t *sample); * Calling this function using a dropped sample is undefined behaviour. */ ZENOHC_API struct z_sample_t zc_sample_loan(const struct zc_owned_sample_t *sample); +ZENOHC_API struct zc_owned_sample_t zc_sample_null(void); /** * Increments the session's reference count, returning a new owning handle. */ diff --git a/src/commons.rs b/src/commons.rs index 555a380be..d23618846 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -156,14 +156,6 @@ pub extern "C" fn z_qos_default() -> z_qos_t { /// A data sample. /// /// A sample is the value associated to a given resource at a given point in time. -/// -/// Members: -/// z_keyexpr_t keyexpr: The resource key of this data sample. -/// z_bytes_t payload: The value of this data sample. -/// z_encoding_t encoding: The encoding of the value of this data sample. -/// z_sample_kind_t kind: The kind of this data sample (PUT or DELETE). -/// z_timestamp_t timestamp: The timestamp of this data sample. -/// z_attachment_t attachment: The attachment of this data sample. #[repr(C)] pub struct z_sample_t<'a> { _inner: &'a (), @@ -177,9 +169,6 @@ impl<'a> core::ops::Deref for z_sample_t<'a> { impl<'a> z_sample_t<'a> { pub fn new(sample: &'a Sample) -> Self { - if !sample.value.payload.zslices().count() <= 1 { - panic!("Attempted to construct z_sample_t from discontiguous buffer, this is definitely a bug in zenoh-c, please report it.") - }; z_sample_t { _inner: unsafe { core::mem::transmute(sample) }, } @@ -285,6 +274,11 @@ pub extern "C" fn zc_sample_drop(sample: &mut zc_owned_sample_t) { core::mem::drop(sample.take()); } +#[no_mangle] +pub extern "C" fn zc_sample_null() -> zc_owned_sample_t { + None.into() +} + /// A :c:type:`z_encoding_t` integer `prefix`. /// /// - **Z_ENCODING_PREFIX_EMPTY** diff --git a/src/lib.rs b/src/lib.rs index 9c01e4aa2..2ff9259c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,6 +58,14 @@ trait GuardedTransmute { fn transmute(self) -> D; } +/// For internal use only. +/// +/// This macro is used to establish the equivalence between a Rust type (first parameter) and a C layout (second parameter). +/// +/// It automatically implements `From`, `Deref` and `DerefMut` to make writing code around these equivalent types. +/// +/// Because carrying around the proper semantics of lifetimes is hard, this macro fails to produce working code when lifetimes are +/// present in either parameter. You may then call it with the `noderefs` prefix to avoid the offending implementations being defined. #[macro_export] macro_rules! impl_guarded_transmute { ($src_type:ty, $dst_type:ty) => {