From a52ef72f924e88453fae490225f0f4e23ee8724a Mon Sep 17 00:00:00 2001 From: Pierre Avital Date: Mon, 26 Feb 2024 10:58:52 +0100 Subject: [PATCH 01/30] 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 02/30] 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 03/30] 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 04/30] 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 05/30] 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 06/30] 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 07/30] 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 08/30] 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) => { From faad2df77eb248ea61f816be9c109af7224a5e10 Mon Sep 17 00:00:00 2001 From: eclipse-zenoh-bot Date: Thu, 28 Mar 2024 00:11:51 +0000 Subject: [PATCH 09/30] chore: Sync Cargo lockfile with Zenoh's --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c62eb1df..d29080bad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -417,9 +417,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", From de1f606ef4328e9357063eb6a654d90836e249a8 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 28 Mar 2024 11:24:16 +0100 Subject: [PATCH 10/30] make impl_guarded_transmute automatically implement From, Deref and DerefMut traits --- src/attachment.rs | 2 +- src/commons.rs | 14 --------- src/config.rs | 7 +---- src/get.rs | 2 +- src/keyexpr.rs | 20 ++---------- src/lib.rs | 54 ++++++++++++++++++++++++++++++++- src/platform/synchronization.rs | 12 ++++---- src/publication_cache.rs | 23 ++------------ src/publisher.rs | 4 +-- src/pull_subscriber.rs | 15 +-------- src/queryable.rs | 20 ++---------- src/querying_subscriber.rs | 26 +++------------- src/session.rs | 22 ++------------ src/subscriber.rs | 23 ++------------ 14 files changed, 79 insertions(+), 165 deletions(-) diff --git a/src/attachment.rs b/src/attachment.rs index e776fa238..5b327fe66 100644 --- a/src/attachment.rs +++ b/src/attachment.rs @@ -176,7 +176,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/commons.rs b/src/commons.rs index 8ac21cb11..7ddaba873 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -198,20 +198,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] pub extern "C" fn z_qos_get_priority(qos: z_qos_t) -> z_priority_t { 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 012a8abaa..f5b3c6590 100644 --- a/src/get.rs +++ b/src/get.rs @@ -56,7 +56,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 c0a90ae68..7742b3948 100644 --- a/src/keyexpr.rs +++ b/src/keyexpr.rs @@ -63,27 +63,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() @@ -183,8 +167,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 de6584885..5019a0713 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,9 +62,37 @@ 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) => { + 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>(); @@ -81,12 +109,36 @@ 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) } } } }; + ($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/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), diff --git a/src/publication_cache.rs b/src/publication_cache.rs index 5b96a904c..670e17ee0 100644 --- a/src/publication_cache.rs +++ b/src/publication_cache.rs @@ -19,8 +19,7 @@ use zenoh_util::core::zresult::ErrNo; use zenoh_util::core::SyncResolve; use crate::{ - impl_guarded_transmute, z_keyexpr_t, z_session_t, zcu_locality_default, zcu_locality_t, - GuardedTransmute, UninitializedKeyExprError, + impl_guarded_transmute, z_keyexpr_t, z_session_t, zcu_locality_default, zcu_locality_t, UninitializedKeyExprError, }; /// Options passed to the :c:func:`ze_declare_publication_cache` function. @@ -70,24 +69,6 @@ pub struct ze_owned_publication_cache_t([usize; 1]); 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..5f86f6454 100644 --- a/src/queryable.rs +++ b/src/queryable.rs @@ -17,7 +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, + z_keyexpr_t, z_owned_closure_query_t, z_session_t, z_value_t, LOG_INVALID_SESSION, }; use libc::c_void; @@ -52,22 +52,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 +247,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 5e5333f1aa8b7683017f532822dc8d6f47eadae8 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 28 Mar 2024 11:30:53 +0100 Subject: [PATCH 11/30] fmt --- src/publication_cache.rs | 3 ++- src/queryable.rs | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/publication_cache.rs b/src/publication_cache.rs index 670e17ee0..a97354b3b 100644 --- a/src/publication_cache.rs +++ b/src/publication_cache.rs @@ -19,7 +19,8 @@ use zenoh_util::core::zresult::ErrNo; use zenoh_util::core::SyncResolve; use crate::{ - impl_guarded_transmute, z_keyexpr_t, z_session_t, zcu_locality_default, zcu_locality_t, UninitializedKeyExprError, + impl_guarded_transmute, z_keyexpr_t, z_session_t, zcu_locality_default, zcu_locality_t, + UninitializedKeyExprError, }; /// Options passed to the :c:func:`ze_declare_publication_cache` function. diff --git a/src/queryable.rs b/src/queryable.rs index 5f86f6454..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, - 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}; From 4d1816b6b0ee1ae1a290a6d11131afa9993ae90c Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 28 Mar 2024 12:25:27 +0100 Subject: [PATCH 12/30] merge --- Cargo.lock | 548 ++++++++++++------------ Cargo.toml | 2 + Cargo.toml.in | 2 + docs/api.rst | 8 +- docs/requirements.txt | 8 +- examples/z_liveliness.c | 8 +- examples/z_ping.c | 19 +- examples/z_pub.c | 12 +- examples/z_pub_attachment.c | 8 +- examples/z_pub_cache.c | 8 +- examples/z_pub_shm.c | 8 +- examples/z_pull.c | 8 +- examples/z_query_sub.c | 8 +- examples/z_queryable.c | 8 +- examples/z_queryable_with_channels.c | 6 - examples/z_scout.c | 20 +- examples/z_sub.c | 8 +- examples/z_sub_attachment.c | 8 +- examples/z_sub_liveliness.c | 8 +- examples/z_sub_thr.c | 25 +- include/zenoh_commons.h | 132 +++++- src/attachment.rs | 66 +++ src/get.rs | 6 +- src/keyexpr.rs | 97 +++++ src/lib.rs | 27 ++ src/liveliness.rs | 22 +- src/platform/clock.rs | 127 ++++++ src/platform/mod.rs | 9 +- src/platform/random.rs | 34 ++ src/platform/sleep.rs | 19 + src/scouting.rs | 31 +- tests/z_api_alignment_test.c | 48 +-- tests/z_api_attachment_test.c | 14 + tests/z_api_keyexpr_test.c | 30 ++ tests/z_int_pub_cache_query_sub_test.c | 2 +- tests/z_int_pub_sub_attachment_test.c | 2 +- tests/z_int_queryable_attachment_test.c | 2 +- tests/z_int_queryable_test.c | 2 +- 38 files changed, 922 insertions(+), 478 deletions(-) create mode 100644 src/platform/clock.rs create mode 100644 src/platform/random.rs create mode 100644 src/platform/sleep.rs diff --git a/Cargo.lock b/Cargo.lock index 6d2575fae..1c62eb1df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,11 +55,26 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" dependencies = [ "anstyle", "anstyle-parse", @@ -71,9 +86,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -115,16 +130,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" -[[package]] -name = "async-attributes" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "async-channel" version = "1.9.0" @@ -213,23 +218,12 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "async-rustls" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29479d362e242e320fa8f5c831940a5b83c1679af014068196cd20d4bf497b6b" -dependencies = [ - "futures-io", - "rustls", -] - [[package]] name = "async-std" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ - "async-attributes", "async-channel", "async-global-executor", "async-io", @@ -393,7 +387,7 @@ version = "0.24.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b922faaf31122819ec80c4047cc684c6979a087366c069611e33649bf98e18d" dependencies = [ - "clap 3.2.25", + "clap", "heck", "indexmap 1.9.3", "log", @@ -421,6 +415,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.0", +] + [[package]] name = "cipher" version = "0.4.4" @@ -439,47 +447,13 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", "bitflags 1.3.2", - "clap_lex 0.2.4", + "clap_lex", "indexmap 1.9.3", "strsim", "termcolor", "textwrap", ] -[[package]] -name = "clap" -version = "4.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" -dependencies = [ - "anstream", - "anstyle", - "clap_lex 0.6.0", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.33", -] - [[package]] name = "clap_lex" version = "0.2.4" @@ -489,12 +463,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "clap_lex" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" - [[package]] name = "colorchoice" version = "1.0.0" @@ -636,11 +604,21 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -649,6 +627,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -657,23 +648,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] @@ -704,9 +684,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fixedbitset" @@ -906,12 +886,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - [[package]] name = "gloo-timers" version = "0.2.6" @@ -970,12 +944,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - [[package]] name = "hmac" version = "0.12.1" @@ -996,9 +964,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" dependencies = [ "bytes", "fnv", @@ -1017,6 +985,29 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows 0.48.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.4.0" @@ -1092,7 +1083,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.2", - "rustix 0.38.21", + "rustix 0.38.32", "windows-sys 0.48.0", ] @@ -1160,9 +1151,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.148" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -1246,9 +1237,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1509,20 +1500,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pnet" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "130c5b738eeda2dc5796fe2671e49027e6935e817ab51b930a36ec9e6a206a64" -dependencies = [ - "ipnetwork", - "pnet_base", - "pnet_datalink", - "pnet_packet", - "pnet_sys", - "pnet_transport", -] - [[package]] name = "pnet_base" version = "0.34.0" @@ -1545,39 +1522,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "pnet_macros" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804" -dependencies = [ - "proc-macro2", - "quote", - "regex", - "syn 2.0.33", -] - -[[package]] -name = "pnet_macros_support" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56" -dependencies = [ - "pnet_base", -] - -[[package]] -name = "pnet_packet" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a005825396b7fe7a38a8e288dbc342d5034dac80c15212436424fef8ea90ba" -dependencies = [ - "glob", - "pnet_base", - "pnet_macros", - "pnet_macros_support", -] - [[package]] name = "pnet_sys" version = "0.34.0" @@ -1588,18 +1532,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "pnet_transport" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2637e14d7de974ee2f74393afccbc8704f3e54e6eb31488715e72481d1662cc3" -dependencies = [ - "libc", - "pnet_base", - "pnet_packet", - "pnet_sys", -] - [[package]] name = "polling" version = "2.8.0" @@ -1648,7 +1580,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls", + "rustls 0.21.7", "thiserror", "tokio", "tracing", @@ -1664,7 +1596,7 @@ dependencies = [ "rand", "ring 0.16.20", "rustc-hash", - "rustls", + "rustls 0.21.7", "rustls-native-certs 0.6.3", "slab", "thiserror", @@ -1680,7 +1612,7 @@ checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" dependencies = [ "bytes", "libc", - "socket2 0.5.4", + "socket2 0.5.6", "tracing", "windows-sys 0.48.0", ] @@ -1733,15 +1665,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_users" version = "0.4.3" @@ -1749,7 +1672,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "redox_syscall", "thiserror", ] @@ -1880,15 +1803,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ "bitflags 2.4.0", "errno", "libc", "linux-raw-sys 0.4.13", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1903,6 +1826,20 @@ dependencies = [ "sct", ] +[[package]] +name = "rustls" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +dependencies = [ + "log", + "ring 0.17.6", + "rustls-pki-types", + "rustls-webpki 0.102.2", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -1949,9 +1886,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.0.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb0a1f9b9efec70d32e6d6aa3e58ebd88c3754ec98dfe9145c63cf54cc829b83" +checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" [[package]] name = "rustls-webpki" @@ -1965,9 +1902,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.0" +version = "0.102.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2635c8bc2b88d367767c5de8ea1d8db9af3f6219eba28442242d9ab81d1b89" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" dependencies = [ "ring 0.17.6", "rustls-pki-types", @@ -2233,12 +2170,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2320,22 +2257,21 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.0.1", - "redox_syscall 0.4.1", - "rustix 0.38.21", - "windows-sys 0.48.0", + "fastrand 2.0.2", + "rustix 0.38.32", + "windows-sys 0.52.0", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -2392,9 +2328,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.32.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -2402,27 +2338,48 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.4", + "socket2 0.5.6", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", "syn 2.0.33", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.7", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.2", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-tungstenite" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2dbec703c26b00d74844519606ef15d09a7d6857860f84ad223dec002ddea2" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" dependencies = [ "futures-util", "log", @@ -2430,6 +2387,21 @@ dependencies = [ "tungstenite", ] +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "futures-util", + "hashbrown 0.14.0", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.5.11" @@ -2474,9 +2446,9 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ "byteorder", "bytes", @@ -2515,9 +2487,9 @@ checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "uhlc" -version = "0.6.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1eadef1fa26cbbae1276c46781e8f4d888bdda434779c18ae6c2a0e69991885" +checksum = "99b6df3f3e948b40e20c38a6d1fd6d8f91b3573922fc164e068ad3331560487e" dependencies = [ "humantime", "lazy_static", @@ -2760,7 +2732,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b7b128a98c1cfa201b09eb49ba285887deb3cbe7466a98850eb1adabb452be5" dependencies = [ - "windows", + "windows 0.34.0", ] [[package]] @@ -2807,6 +2779,15 @@ dependencies = [ "windows_x86_64_msvc 0.34.0", ] +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -2972,20 +2953,17 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "zenoh" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-global-executor", - "async-std", "async-trait", "base64", "const_format", - "env_logger", + "env_logger 0.11.2", "event-listener 4.0.0", "flume", "form_urlencoded", "futures", "git-version", - "hex", "lazy_static", "log", "ordered-float", @@ -2996,8 +2974,10 @@ dependencies = [ "rustc_version", "serde", "serde_json", - "socket2 0.5.4", + "socket2 0.5.6", "stop-token", + "tokio", + "tokio-util", "uhlc", "uuid", "vec_map", @@ -3013,6 +2993,7 @@ dependencies = [ "zenoh-plugin-trait", "zenoh-protocol", "zenoh-result", + "zenoh-runtime", "zenoh-shm", "zenoh-sync", "zenoh-transport", @@ -3022,7 +3003,7 @@ dependencies = [ [[package]] name = "zenoh-buffers" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "zenoh-collections", ] @@ -3034,10 +3015,12 @@ dependencies = [ "async-std", "async-trait", "cbindgen", - "env_logger", + "chrono", + "env_logger 0.10.2", "fs2", "futures", "json5", + "lazy_static", "libc", "log", "rand", @@ -3052,7 +3035,7 @@ dependencies = [ [[package]] name = "zenoh-codec" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "log", "serde", @@ -3065,15 +3048,16 @@ dependencies = [ [[package]] name = "zenoh-collections" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" [[package]] name = "zenoh-config" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "flume", "json5", + "log", "num_cpus", "secrecy", "serde", @@ -3089,17 +3073,19 @@ dependencies = [ [[package]] name = "zenoh-core" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-std", + "async-global-executor", "lazy_static", + "tokio", "zenoh-result", + "zenoh-runtime", ] [[package]] name = "zenoh-crypto" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "aes", "hmac", @@ -3112,19 +3098,20 @@ dependencies = [ [[package]] name = "zenoh-ext" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-std", "bincode", - "env_logger", + "env_logger 0.11.2", "flume", "futures", "log", "serde", + "tokio", "zenoh", "zenoh-core", "zenoh-macros", "zenoh-result", + "zenoh-runtime", "zenoh-sync", "zenoh-util", ] @@ -3132,7 +3119,7 @@ dependencies = [ [[package]] name = "zenoh-keyexpr" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "hashbrown 0.14.0", "keyed-set", @@ -3146,9 +3133,8 @@ dependencies = [ [[package]] name = "zenoh-link" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-std", "async-trait", "zenoh-config", "zenoh-link-commons", @@ -3165,46 +3151,50 @@ dependencies = [ [[package]] name = "zenoh-link-commons" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-std", "async-trait", "flume", + "futures", "log", - "lz4_flex", + "rustls 0.22.2", + "rustls-webpki 0.102.2", "serde", - "typenum", + "tokio", + "tokio-util", "zenoh-buffers", "zenoh-codec", "zenoh-core", "zenoh-protocol", "zenoh-result", - "zenoh-sync", + "zenoh-runtime", "zenoh-util", ] [[package]] name = "zenoh-link-quic" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-rustls", - "async-std", "async-trait", "base64", "futures", "log", "quinn", - "rustls", + "rustls 0.21.7", "rustls-native-certs 0.7.0", "rustls-pemfile 2.0.0", - "rustls-webpki 0.102.0", + "rustls-webpki 0.102.2", "secrecy", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util", "zenoh-config", "zenoh-core", "zenoh-link-commons", "zenoh-protocol", "zenoh-result", + "zenoh-runtime", "zenoh-sync", "zenoh-util", ] @@ -3212,15 +3202,17 @@ dependencies = [ [[package]] name = "zenoh-link-tcp" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-std", "async-trait", "log", + "tokio", + "tokio-util", "zenoh-core", "zenoh-link-commons", "zenoh-protocol", "zenoh-result", + "zenoh-runtime", "zenoh-sync", "zenoh-util", ] @@ -3228,24 +3220,27 @@ dependencies = [ [[package]] name = "zenoh-link-tls" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-rustls", - "async-std", "async-trait", "base64", "futures", "log", - "rustls", + "rustls 0.22.2", "rustls-pemfile 2.0.0", - "rustls-webpki 0.102.0", + "rustls-pki-types", + "rustls-webpki 0.102.2", "secrecy", + "tokio", + "tokio-rustls 0.25.0", + "tokio-util", "webpki-roots", "zenoh-config", "zenoh-core", "zenoh-link-commons", "zenoh-protocol", "zenoh-result", + "zenoh-runtime", "zenoh-sync", "zenoh-util", ] @@ -3253,18 +3248,20 @@ dependencies = [ [[package]] name = "zenoh-link-udp" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-std", "async-trait", "log", - "socket2 0.5.4", + "socket2 0.5.6", + "tokio", + "tokio-util", "zenoh-buffers", "zenoh-collections", "zenoh-core", "zenoh-link-commons", "zenoh-protocol", "zenoh-result", + "zenoh-runtime", "zenoh-sync", "zenoh-util", ] @@ -3272,37 +3269,40 @@ dependencies = [ [[package]] name = "zenoh-link-unixsock_stream" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-std", "async-trait", "futures", "log", "nix 0.27.1", + "tokio", + "tokio-util", "uuid", "zenoh-core", "zenoh-link-commons", "zenoh-protocol", "zenoh-result", + "zenoh-runtime", "zenoh-sync", ] [[package]] name = "zenoh-link-ws" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-std", "async-trait", "futures-util", "log", "tokio", "tokio-tungstenite", + "tokio-util", "url", "zenoh-core", "zenoh-link-commons", "zenoh-protocol", "zenoh-result", + "zenoh-runtime", "zenoh-sync", "zenoh-util", ] @@ -3310,20 +3310,18 @@ dependencies = [ [[package]] name = "zenoh-macros" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "proc-macro2", "quote", - "rustc_version", "syn 2.0.33", - "unzip-n", "zenoh-keyexpr", ] [[package]] name = "zenoh-plugin-trait" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "const_format", "libloading", @@ -3339,14 +3337,12 @@ dependencies = [ [[package]] name = "zenoh-protocol" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "const_format", - "hex", "rand", "serde", "uhlc", - "uuid", "zenoh-buffers", "zenoh-keyexpr", "zenoh-result", @@ -3355,17 +3351,27 @@ dependencies = [ [[package]] name = "zenoh-result" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "anyhow", ] +[[package]] +name = "zenoh-runtime" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "lazy_static", + "tokio", + "zenoh-collections", + "zenoh-result", +] + [[package]] name = "zenoh-shm" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "bincode", "log", "serde", "shared_memory", @@ -3376,26 +3382,22 @@ dependencies = [ [[package]] name = "zenoh-sync" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-std", "event-listener 4.0.0", - "flume", "futures", "tokio", "zenoh-buffers", "zenoh-collections", "zenoh-core", + "zenoh-runtime", ] [[package]] name = "zenoh-transport" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ - "async-executor", - "async-global-executor", - "async-std", "async-trait", "flume", "log", @@ -3406,6 +3408,8 @@ dependencies = [ "rsa", "serde", "sha3", + "tokio", + "tokio-util", "zenoh-buffers", "zenoh-codec", "zenoh-collections", @@ -3415,6 +3419,7 @@ dependencies = [ "zenoh-link", "zenoh-protocol", "zenoh-result", + "zenoh-runtime", "zenoh-shm", "zenoh-sync", "zenoh-util", @@ -3423,27 +3428,22 @@ dependencies = [ [[package]] name = "zenoh-util" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#7d9d684cf953f9f813eb320812eaf95f767ef200" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" dependencies = [ "async-std", "async-trait", - "clap 4.4.11", - "const_format", "flume", - "futures", - "hex", "home", "humantime", "lazy_static", "libc", "libloading", "log", - "pnet", "pnet_datalink", "shellexpand", + "tokio", "winapi", "zenoh-core", - "zenoh-protocol", "zenoh-result", ] diff --git a/Cargo.toml b/Cargo.toml index 52deaa71c..95867f95f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,9 +41,11 @@ maintenance = { status = "actively-developed" } [dependencies] async-std = "=1.12.0" async-trait = "0.1.66" +chrono = "0.4.34" env_logger = "0.10.0" futures = "0.3.26" json5 = "0.4.1" +lazy_static = "1.4.0" libc = "0.2.139" log = "0.4.17" rand = "0.8.5" diff --git a/Cargo.toml.in b/Cargo.toml.in index d1eec11bd..f434df3a1 100644 --- a/Cargo.toml.in +++ b/Cargo.toml.in @@ -41,9 +41,11 @@ maintenance = { status = "actively-developed" } [dependencies] async-std = "=1.12.0" async-trait = "0.1.66" +chrono = "0.4.34" env_logger = "0.10.0" futures = "0.3.26" json5 = "0.4.1" +lazy_static = "1.4.0" libc = "0.2.139" log = "0.4.17" rand = "0.8.5" diff --git a/docs/api.rst b/docs/api.rst index 6694af4a5..758c405b5 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -38,6 +38,8 @@ Bytes map .. autocfunction:: zenoh_commons.h::z_bytes_map_null .. autocfunction:: zenoh_commons.h::z_bytes_map_drop .. autocfunction:: zenoh_commons.h::z_bytes_map_get +.. autocfunction:: zenoh_commons.h::z_bytes_map_len +.. autocfunction:: zenoh_commons.h::z_bytes_map_is_empty .. autocfunction:: zenoh_commons.h::z_bytes_map_insert_by_alias .. autocfunction:: zenoh_commons.h::z_bytes_map_insert_by_copy .. autocfunction:: zenoh_commons.h::z_bytes_map_iter @@ -106,6 +108,7 @@ Key expression .. autocstruct:: zenoh_commons.h::z_owned_keyexpr_t .. autocfunction:: zenoh_commons.h::z_keyexpr +.. autocfunction:: zenoh_commons.h::z_keyexpr_autocanonize .. autocfunction:: zenoh_commons.h::z_keyexpr_unchecked .. autocfunction:: zenoh_commons.h::z_keyexpr_to_string .. autocfunction:: zenoh_commons.h::z_keyexpr_as_bytes @@ -120,6 +123,7 @@ Key expression .. autocfunction:: zenoh_commons.h::z_keyexpr_intersects .. autocfunction:: zenoh_commons.h::z_keyexpr_new +.. autocfunction:: zenoh_commons.h::z_keyexpr_new_autocanonize .. autocfunction:: zenoh_commons.h::z_keyexpr_loan .. autocfunction:: zenoh_commons.h::z_keyexpr_check .. autocfunction:: zenoh_commons.h::z_keyexpr_drop @@ -157,6 +161,8 @@ Attachment .. autocfunction:: zenoh_commons.h::z_attachment_null .. autocfunction:: zenoh_commons.h::z_attachment_get +.. autocfunction:: zenoh_commons.h::z_attachment_len +.. autocfunction:: zenoh_commons.h::z_attachment_is_empty .. autocfunction:: zenoh_commons.h::z_attachment_check .. autocfunction:: zenoh_commons.h::z_attachment_iterate @@ -299,7 +305,7 @@ Types .. autocstruct:: zenoh_commons.h::zc_owned_liveliness_token_t .. autocstruct:: zenoh_commons.h::zc_owned_liveliness_declaration_options_t -.. autocstruct:: zenoh_commons.h::zc_owned_liveliness_get_options_t +.. autocstruct:: zenoh_commons.h::zc_liveliness_get_options_t .. autocstruct:: zenoh_commons.h::zc_owned_liveliness_declare_subscriber_options_t Functions diff --git a/docs/requirements.txt b/docs/requirements.txt index 670562c3e..a5a4b5f60 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,4 @@ -sphinx==4.5.0 -sphinx_c_autodoc -sphinx_rtd_theme -clang==14 +sphinx==7.2.6 +sphinx_c_autodoc==1.3.0 +sphinx_rtd_theme==2.0.0 +clang==14.0 diff --git a/examples/z_liveliness.c b/examples/z_liveliness.c index b21cc40bc..4191b0496 100644 --- a/examples/z_liveliness.c +++ b/examples/z_liveliness.c @@ -13,12 +13,6 @@ #include #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" int main(int argc, char **argv) { @@ -63,7 +57,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } else if (c == 'd') { printf("Undeclaring liveliness token...\n"); z_drop(z_move(token)); diff --git a/examples/z_ping.c b/examples/z_ping.c index bb061baee..fdc08f71d 100644 --- a/examples/z_ping.c +++ b/examples/z_ping.c @@ -2,7 +2,6 @@ #include #include #include -#include #include "zenoh.h" @@ -58,35 +57,27 @@ int main(int argc, char** argv) { z_mutex_lock(&mutex); if (args.warmup_ms) { printf("Warming up for %dms...\n", args.warmup_ms); - struct timespec wmup_start, wmup_stop, wmup_timeout; - clock_gettime(CLOCK_MONOTONIC, &wmup_start); + z_clock_t warmup_start = z_clock_now(); + unsigned long elapsed_us = 0; while (elapsed_us < args.warmup_ms * 1000) { - clock_gettime(CLOCK_REALTIME, &wmup_timeout); - wmup_timeout.tv_sec += PING_TIMEOUT_SEC; z_publisher_put(z_loan(pub), data, args.size, NULL); int s = z_condvar_wait(&cond, &mutex); if (s != 0) { handle_error_en(s, "z_condvar_wait"); } - clock_gettime(CLOCK_MONOTONIC, &wmup_stop); - elapsed_us = - (1000000 * (wmup_stop.tv_sec - wmup_start.tv_sec) + (wmup_stop.tv_nsec - wmup_start.tv_nsec) / 1000); + elapsed_us = z_clock_elapsed_us(&warmup_start); } } - struct timespec t_start, t_stop, t_timeout; unsigned long* results = z_malloc(sizeof(unsigned long) * args.number_of_pings); for (int i = 0; i < args.number_of_pings; i++) { - clock_gettime(CLOCK_REALTIME, &t_timeout); - t_timeout.tv_sec += PING_TIMEOUT_SEC; - clock_gettime(CLOCK_MONOTONIC, &t_start); + z_clock_t measure_start = z_clock_now(); z_publisher_put(z_loan(pub), data, args.size, NULL); int s = z_condvar_wait(&cond, &mutex); if (s != 0) { handle_error_en(s, "z_condvar_wait"); } - clock_gettime(CLOCK_MONOTONIC, &t_stop); - results[i] = (1000000 * (t_stop.tv_sec - t_start.tv_sec) + (t_stop.tv_nsec - t_start.tv_nsec) / 1000); + results[i] = z_clock_elapsed_us(&measure_start); } for (int i = 0; i < args.number_of_pings; i++) { printf("%d bytes: seq=%d rtt=%luµs, lat=%luµs\n", args.size, i, results[i], results[i] / 2); diff --git a/examples/z_pub.c b/examples/z_pub.c index 73fd02287..ecc95e42d 100644 --- a/examples/z_pub.c +++ b/examples/z_pub.c @@ -15,12 +15,6 @@ #include #include "zenoh.h" -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif void matching_status_handler(const zcu_matching_status_t *matching_status, void *arg) { if (matching_status->matching) { @@ -41,11 +35,11 @@ int main(int argc, char **argv) { z_owned_config_t config = z_config_default(); if (argc > 4) { - if (zc_config_insert_json(z_loan(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) { + if (zc_config_insert_json(z_loan(config), Z_CONFIG_CONNECT_KEY, argv[4]) < 0) { printf( "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " "JSON-serialized list of strings\n", - argv[3], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); + argv[4], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); exit(-1); } } @@ -72,7 +66,7 @@ int main(int argc, char **argv) { char buf[256]; for (int idx = 0; 1; ++idx) { - sleep(1); + z_sleep_s(1); sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); z_publisher_put_options_t options = z_publisher_put_options_default(); diff --git a/examples/z_pub_attachment.c b/examples/z_pub_attachment.c index b75f245c3..a24133e91 100644 --- a/examples/z_pub_attachment.c +++ b/examples/z_pub_attachment.c @@ -15,12 +15,6 @@ #include #include "zenoh.h" -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif int main(int argc, char **argv) { char *keyexpr = "demo/example/zenoh-c-pub"; @@ -69,7 +63,7 @@ int main(int argc, char **argv) { char buf[256]; char buf_ind[16]; for (int idx = 0; 1; ++idx) { - sleep(1); + z_sleep_s(1); // add some other attachment value sprintf(buf_ind, "%d", idx); diff --git a/examples/z_pub_cache.c b/examples/z_pub_cache.c index 8c1d36221..770bf9d93 100644 --- a/examples/z_pub_cache.c +++ b/examples/z_pub_cache.c @@ -15,12 +15,6 @@ #include #include "zenoh.h" -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif int main(int argc, char **argv) { char *keyexpr = "demo/example/zenoh-c-pub"; @@ -66,7 +60,7 @@ int main(int argc, char **argv) { char buf[256]; for (int idx = 0; 1; ++idx) { - sleep(1); + z_sleep_s(1); sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)buf, strlen(buf), NULL); diff --git a/examples/z_pub_shm.c b/examples/z_pub_shm.c index f26c65c08..10970bf62 100644 --- a/examples/z_pub_shm.c +++ b/examples/z_pub_shm.c @@ -17,12 +17,6 @@ #include #include "zenoh.h" -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #define N 10 @@ -85,7 +79,7 @@ int main(int argc, char **argv) { snprintf(buf, 255, "[%4d] %s", idx, value); size_t len = strlen(buf); zc_shmbuf_set_length(&shmbuf, len); - sleep(1); + z_sleep_s(1); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); z_publisher_put_options_t options = z_publisher_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); diff --git a/examples/z_pull.c b/examples/z_pull.c index badbd6f44..4f2de7945 100644 --- a/examples/z_pull.c +++ b/examples/z_pull.c @@ -12,12 +12,6 @@ // ZettaScale Zenoh Team, // #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *kind_to_str(z_sample_kind_t kind); @@ -67,7 +61,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } else { z_subscriber_pull(z_loan(sub)); } diff --git a/examples/z_query_sub.c b/examples/z_query_sub.c index 7653a6c77..d60bc2bf1 100644 --- a/examples/z_query_sub.c +++ b/examples/z_query_sub.c @@ -12,12 +12,6 @@ // ZettaScale Zenoh Team, // #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *kind_to_str(z_sample_kind_t kind); @@ -69,7 +63,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_queryable.c b/examples/z_queryable.c index f74f5d355..9d6ec7702 100644 --- a/examples/z_queryable.c +++ b/examples/z_queryable.c @@ -13,12 +13,6 @@ #include #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *expr = "demo/example/zenoh-c-queryable"; @@ -81,7 +75,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_queryable_with_channels.c b/examples/z_queryable_with_channels.c index 80c98d689..672ddd607 100644 --- a/examples/z_queryable_with_channels.c +++ b/examples/z_queryable_with_channels.c @@ -14,12 +14,6 @@ #include #include #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *expr = "demo/example/zenoh-c-queryable"; diff --git a/examples/z_scout.c b/examples/z_scout.c index 3b882f547..1b7b3c21d 100644 --- a/examples/z_scout.c +++ b/examples/z_scout.c @@ -12,14 +12,6 @@ // ZettaScale Zenoh Team, #include - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif - #include "zenoh.h" void fprintpid(FILE *stream, z_id_t pid) { @@ -41,13 +33,9 @@ void fprintpid(FILE *stream, z_id_t pid) { } void fprintwhatami(FILE *stream, unsigned int whatami) { - if (whatami == Z_ROUTER) { - fprintf(stream, "\"Router\""); - } else if (whatami == Z_PEER) { - fprintf(stream, "\"Peer\""); - } else { - fprintf(stream, "\"Other\""); - } + char buf[64]; + z_whatami_to_str(whatami, buf, sizeof(buf)); + fprintf(stream, "%s", buf); } void fprintlocators(FILE *stream, const z_str_array_t *locs) { @@ -96,6 +84,6 @@ int main(int argc, char **argv) { z_owned_closure_hello_t closure = z_closure(callback, drop, context); printf("Scouting...\n"); z_scout(z_move(config), z_move(closure)); - sleep(1); + z_sleep_s(1); return 0; } \ No newline at end of file diff --git a/examples/z_sub.c b/examples/z_sub.c index b52db8850..378a717e6 100644 --- a/examples/z_sub.c +++ b/examples/z_sub.c @@ -12,12 +12,6 @@ // ZettaScale Zenoh Team, // #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *kind_to_str(z_sample_kind_t kind); @@ -74,7 +68,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_sub_attachment.c b/examples/z_sub_attachment.c index c3d22e39f..2031d1155 100644 --- a/examples/z_sub_attachment.c +++ b/examples/z_sub_attachment.c @@ -13,12 +13,6 @@ // #include #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *kind_to_str(z_sample_kind_t kind); @@ -86,7 +80,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_sub_liveliness.c b/examples/z_sub_liveliness.c index 67c87001a..5916200b2 100644 --- a/examples/z_sub_liveliness.c +++ b/examples/z_sub_liveliness.c @@ -12,12 +12,6 @@ // ZettaScale Zenoh Team, // #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" void data_handler(const z_sample_t *sample, void *arg) { @@ -76,7 +70,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_sub_thr.c b/examples/z_sub_thr.c index d32480174..05ee709d3 100644 --- a/examples/z_sub_thr.c +++ b/examples/z_sub_thr.c @@ -12,7 +12,6 @@ // ZettaScale Zenoh Team, // #include -#include #include "zenoh.h" @@ -21,46 +20,40 @@ typedef struct { volatile unsigned long count; volatile unsigned long finished_rounds; - struct timespec start; - struct timespec first_start; + z_clock_t start; + z_clock_t first_start; + bool started; } z_stats_t; z_stats_t *z_stats_make() { z_stats_t *stats = z_malloc(sizeof(z_stats_t)); stats->count = 0; stats->finished_rounds = 0; - stats->first_start.tv_nsec = 0; + stats->started = false; return stats; } -static inline double get_elapsed_s(const struct timespec *start, const struct timespec *end) { - return (double)(end->tv_sec - start->tv_sec) + (double)(end->tv_nsec - start->tv_nsec) / 1.0E9; -} - void on_sample(const z_sample_t *sample, void *context) { z_stats_t *stats = (z_stats_t *)context; if (stats->count == 0) { - clock_gettime(CLOCK_MONOTONIC, &stats->start); - if (stats->first_start.tv_nsec == 0) { + stats->start = z_clock_now(); + if (!stats->started) { stats->first_start = stats->start; + stats->started = true; } stats->count++; } else if (stats->count < N) { stats->count++; } else { - struct timespec end; - clock_gettime(CLOCK_MONOTONIC, &end); stats->finished_rounds++; - printf("%f msg/s\n", (double)N / get_elapsed_s(&stats->start, &end)); + printf("%f msg/s\n", 1000.0 * N / z_clock_elapsed_ms(&stats->start)); stats->count = 0; } } void drop_stats(void *context) { const z_stats_t *stats = (z_stats_t *)context; const unsigned long sent_messages = N * stats->finished_rounds + stats->count; - struct timespec end; - clock_gettime(CLOCK_MONOTONIC, &end); - double elapsed_s = get_elapsed_s(&stats->first_start, &end); + double elapsed_s = z_clock_elapsed_s(&stats->first_start); printf("Stats being dropped after unsubscribing: sent %ld messages over %f seconds (%f msg/s)\n", sent_messages, elapsed_s, (double)sent_messages / elapsed_s); z_free(context); diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index e0b405014..55a52f82d 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -93,6 +93,20 @@ typedef enum z_encoding_prefix_t { Z_ENCODING_PREFIX_IMAGE_PNG = 19, Z_ENCODING_PREFIX_IMAGE_GIF = 20, } z_encoding_prefix_t; +/** + * A :c:type:`z_keyexpr_intersection_level_t`. + * + * - **Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT** + * - **Z_KEYEXPR_INTERSECTION_LEVEL_INTERSECTS** + * - **Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES** + * - **Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS** + */ +typedef enum z_keyexpr_intersection_level_t { + Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT = 0, + Z_KEYEXPR_INTERSECTION_LEVEL_INTERSECTS = 1, + Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES = 2, + Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS = 3, +} z_keyexpr_intersection_level_t; /** * The priority of zenoh messages. * @@ -218,6 +232,14 @@ typedef struct z_owned_bytes_map_t { uint64_t _0[2]; size_t _1[4]; } z_owned_bytes_map_t; +/** + * Clock + * Uses monotonic clock + */ +typedef struct z_clock_t { + uint64_t t; + const void *t_base; +} z_clock_t; /** * Represents a Zenoh ID. * @@ -343,13 +365,8 @@ typedef struct z_owned_closure_query_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. */ -#if defined(TARGET_ARCH_X86_64) +#if !defined(TARGET_ARCH_ARM) typedef struct ALIGN(8) z_owned_reply_t { - uint64_t _0[28]; -} z_owned_reply_t; -#endif -#if defined(TARGET_ARCH_AARCH64) -typedef struct ALIGN(16) z_owned_reply_t { uint64_t _0[30]; } z_owned_reply_t; #endif @@ -825,6 +842,13 @@ typedef struct z_task_t { typedef struct z_task_attr_t { size_t _0; } z_task_attr_t; +/** + * Time + * Uses system clock + */ +typedef struct z_time_t { + uint64_t t; +} z_time_t; /** * The options for `zc_liveliness_declare_token` */ @@ -850,9 +874,9 @@ typedef struct zc_owned_liveliness_token_t { /** * The options for :c:func:`zc_liveliness_declare_subscriber` */ -typedef struct zc_owned_liveliness_get_options_t { +typedef struct zc_liveliness_get_options_t { uint32_t timeout_ms; -} zc_owned_liveliness_get_options_t; +} zc_liveliness_get_options_t; /** * An owned payload, backed by a reference counted owner. * @@ -1025,6 +1049,10 @@ ZENOHC_API bool z_attachment_check(const struct z_attachment_t *this_); * Returns the value associated with the key. */ ZENOHC_API struct z_bytes_t z_attachment_get(struct z_attachment_t this_, struct z_bytes_t key); +/** + * Returns true if `z_attachment_t` contains no key-value pairs, false otherwise. + */ +ZENOHC_API bool z_attachment_is_empty(struct z_attachment_t this_); /** * Iterate over `this`'s key-value pairs, breaking if `body` returns a non-zero * value for a key-value pair, and returning the latest return value. @@ -1037,6 +1065,12 @@ ZENOHC_API int8_t z_attachment_iterate(struct z_attachment_t this_, z_attachment_iter_body_t body, void *context); +/** + * Returns number of key-value pairs for `z_attachment_t`. + * + * Does so by iterating over all existing key-value pairs. + */ +ZENOHC_API size_t z_attachment_len(struct z_attachment_t this_); /** * Returns the gravestone value for `z_attachment_t`. */ @@ -1154,6 +1188,10 @@ ZENOHC_API void z_bytes_map_insert_by_copy(const struct z_owned_bytes_map_t *this_, struct z_bytes_t key, struct z_bytes_t value); +/** + * Returns true if the map is empty, false otherwise. + */ +ZENOHC_API bool z_bytes_map_is_empty(struct z_owned_bytes_map_t *this_); /** * Iterates over the key-value pairs in the map. * @@ -1170,6 +1208,10 @@ ZENOHC_API int8_t z_bytes_map_iter(const struct z_owned_bytes_map_t *this_, z_attachment_iter_body_t body, void *ctx); +/** + * Returns number of key-value pairs in the map. + */ +ZENOHC_API size_t z_bytes_map_len(struct z_owned_bytes_map_t *this_); /** * Constructs a new map. */ @@ -1193,6 +1235,10 @@ ZENOHC_API struct z_bytes_t z_bytes_null(void); * Constructs a `len` bytes long view starting at `start`. */ ZENOHC_API struct z_bytes_t z_bytes_wrap(const uint8_t *start, size_t len); +ZENOHC_API uint64_t z_clock_elapsed_ms(const struct z_clock_t *time); +ZENOHC_API uint64_t z_clock_elapsed_s(const struct z_clock_t *time); +ZENOHC_API uint64_t z_clock_elapsed_us(const struct z_clock_t *time); +ZENOHC_API struct z_clock_t z_clock_now(void); /** * Closes a zenoh session. This drops and invalidates `session` for double-drop safety. * @@ -1594,6 +1640,14 @@ ZENOHC_API struct z_keyexpr_t z_keyexpr(const char *name); * Currently exclusive to zenoh-c */ ZENOHC_API struct z_bytes_t z_keyexpr_as_bytes(struct z_keyexpr_t keyexpr); +/** + * Constructs a :c:type:`z_keyexpr_t` departing from a string. + * It is a loaned key expression that aliases `name`. + * The string is canonized in-place before being passed to keyexpr. + * May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). + */ +ZENOHC_API +struct z_keyexpr_t z_keyexpr_autocanonize(char *name); /** * Canonizes the passed string in place, possibly shortening it by modifying `len`. * @@ -1682,10 +1736,23 @@ ZENOHC_API struct z_keyexpr_t z_keyexpr_loan(const struct z_owned_keyexpr_t *key * Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string. */ ZENOHC_API struct z_owned_keyexpr_t z_keyexpr_new(const char *name); +/** + * Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string. The copied string is canonized. + */ +ZENOHC_API +struct z_owned_keyexpr_t z_keyexpr_new_autocanonize(const char *name); /** * Constructs a null safe-to-drop value of 'z_owned_keyexpr_t' type */ ZENOHC_API struct z_owned_keyexpr_t z_keyexpr_null(void); +/** + * Returns the relation between `left` and `right` from `left`'s point of view. + * + * Note that this is slower than `z_keyexpr_intersects` and `keyexpr_includes`, so you should favor these methods for most applications. + */ +ZENOHC_API +enum z_keyexpr_intersection_level_t z_keyexpr_relation_to(struct z_keyexpr_t left, + struct z_keyexpr_t right); /** * Constructs a null-terminated string departing from a :c:type:`z_keyexpr_t`. * The user is responsible of droping the returned string using `z_drop` @@ -1971,6 +2038,11 @@ ZENOHC_API struct z_owned_queryable_t z_queryable_null(void); * Constructs the default value for :c:type:`z_query_reply_options_t`. */ ZENOHC_API struct z_queryable_options_t z_queryable_options_default(void); +ZENOHC_API void z_random_fill(void *buf, size_t len); +ZENOHC_API uint16_t z_random_u16(void); +ZENOHC_API uint32_t z_random_u32(void); +ZENOHC_API uint64_t z_random_u64(void); +ZENOHC_API uint8_t z_random_u8(void); /** * Calls the closure. Calling an uninitialized closure is a no-op. */ @@ -2108,6 +2180,9 @@ struct z_session_t z_session_loan(const struct z_owned_session_t *s); * Constructs a null safe-to-drop value of 'z_owned_session_t' type */ ZENOHC_API struct z_owned_session_t z_session_null(void); +ZENOHC_API int8_t z_sleep_ms(size_t time); +ZENOHC_API int8_t z_sleep_s(size_t time); +ZENOHC_API int8_t z_sleep_us(size_t time); /** * Returns ``true`` if `strs` is valid. */ @@ -2170,6 +2245,11 @@ int8_t z_task_init(struct z_task_t *task, void (*fun)(void *arg), void *arg); ZENOHC_API int8_t z_task_join(struct z_task_t *task); +ZENOHC_API uint64_t z_time_elapsed_ms(const struct z_time_t *time); +ZENOHC_API uint64_t z_time_elapsed_s(const struct z_time_t *time); +ZENOHC_API uint64_t z_time_elapsed_us(const struct z_time_t *time); +ZENOHC_API struct z_time_t z_time_now(void); +ZENOHC_API const char *z_time_now_as_str(const char *buf, size_t len); /** * Returns ``true`` if `ts` is a valid timestamp */ @@ -2200,6 +2280,18 @@ ZENOHC_API int8_t z_undeclare_queryable(struct z_owned_queryable_t *qable); */ ZENOHC_API int8_t z_undeclare_subscriber(struct z_owned_subscriber_t *sub); +/** + * Converts the kind of zenoh entity into a string. + * + * Parameters: + * whatami: A whatami bitmask of zenoh entity kind. + * buf: Buffer to write a null-terminated string to. + * len: Maximum number of bytes that can be written to the `buf`. + * + * Returns 0 if successful, negative values if whatami contains an invalid bitmask or `buf` is null, + * or number of remaining bytes, if the null-terminated string size exceeds `len`. + */ +ZENOHC_API int8_t z_whatami_to_str(uint8_t whatami, char *buf, size_t len); /** * Constructs a configuration by parsing a file at `path`. Currently supported format is JSON5, a superset of JSON. */ @@ -2245,6 +2337,15 @@ ZENOHC_API void zc_init_logger(void); * It is a loaned key expression that aliases `name`. */ ZENOHC_API struct z_keyexpr_t zc_keyexpr_from_slice(const char *name, size_t len); +/** + * Constructs a :c:type:`z_keyexpr_t` departing from a string. + * It is a loaned key expression that aliases `name`. + * The string is canonized in-place before being passed to keyexpr. + * May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). + */ +ZENOHC_API +struct z_keyexpr_t zc_keyexpr_from_slice_autocanonize(char *name, + size_t *len); /** * Constructs a :c:type:`z_keyexpr_t` departing from a string without checking any of `z_keyexpr_t`'s assertions: * - `name` MUST be valid UTF8. @@ -2317,24 +2418,23 @@ ZENOHC_API int8_t zc_liveliness_get(struct z_session_t session, struct z_keyexpr_t key, struct z_owned_closure_reply_t *callback, - const struct zc_owned_liveliness_get_options_t *options); + const struct zc_liveliness_get_options_t *options); /** * Returns `true` if the options are valid. */ -ZENOHC_API -bool zc_liveliness_get_options_check(const struct zc_owned_liveliness_get_options_t *_opts); +ZENOHC_API bool zc_liveliness_get_options_check(const struct zc_liveliness_get_options_t *_opts); /** - * The gravestone value for `zc_owned_liveliness_get_options_t` + * The gravestone value for `zc_liveliness_get_options_t` */ -ZENOHC_API struct zc_owned_liveliness_get_options_t zc_liveliness_get_options_default(void); +ZENOHC_API struct zc_liveliness_get_options_t zc_liveliness_get_options_default(void); /** * Destroys the options. */ -ZENOHC_API void zc_liveliness_get_options_drop(struct zc_owned_liveliness_get_options_t *opts); +ZENOHC_API void zc_liveliness_get_options_drop(struct zc_liveliness_get_options_t *opts); /** - * The gravestone value for `zc_owned_liveliness_get_options_t` + * The gravestone value for `zc_liveliness_get_options_t` */ -ZENOHC_API struct zc_owned_liveliness_get_options_t zc_liveliness_get_options_null(void); +ZENOHC_API struct zc_liveliness_get_options_t zc_liveliness_get_options_null(void); /** * Returns `true` if the options are valid. */ diff --git a/src/attachment.rs b/src/attachment.rs index 051edafdc..7b456a9c1 100644 --- a/src/attachment.rs +++ b/src/attachment.rs @@ -117,6 +117,58 @@ pub extern "C" fn z_attachment_get(this: z_attachment_t, key: z_bytes_t) -> z_by } } +fn _z_attachment_len(this: z_attachment_t, check_if_non_empty: bool) -> usize { + match this.iteration_driver.as_ref() { + None => 0, + Some(iteration_driver) => { + struct count_context_t { + count: usize, + stop_if_not_empty: bool, + } + + extern "C" fn attachment_count_iterator( + _key: z_bytes_t, + _value: z_bytes_t, + context: *mut c_void, + ) -> i8 { + unsafe { + let context = &mut *(context as *mut count_context_t); + context.count += 1; + if context.stop_if_not_empty { + 1 + } else { + 0 + } + } + } + let mut count_context = count_context_t { + count: 0, + stop_if_not_empty: check_if_non_empty, + }; + (iteration_driver)( + this.data, + attachment_count_iterator, + &mut count_context as *mut _ as *mut c_void, + ); + count_context.count + } + } +} + +/// Returns number of key-value pairs for `z_attachment_t`. +/// +/// Does so by iterating over all existing key-value pairs. +#[no_mangle] +pub extern "C" fn z_attachment_len(this: z_attachment_t) -> usize { + _z_attachment_len(this, false) +} + +/// Returns true if `z_attachment_t` contains no key-value pairs, false otherwise. +#[no_mangle] +pub extern "C" fn z_attachment_is_empty(this: z_attachment_t) -> bool { + _z_attachment_len(this, true) == 0 +} + /// A map of maybe-owned vector of bytes to owned vector of bytes. /// /// In Zenoh C, this map is backed by Rust's standard HashMap, with a DoS-resistant hasher @@ -164,6 +216,20 @@ pub extern "C" fn z_bytes_map_drop(this: &mut z_owned_bytes_map_t) { this.take(); } +/// Returns number of key-value pairs in the map. +#[no_mangle] +pub extern "C" fn z_bytes_map_len(this: &mut z_owned_bytes_map_t) -> usize { + let this = unsafe { &*this.get() }; + this.as_ref().map(|m| m.len()).unwrap_or(0) +} + +/// Returns true if the map is empty, false otherwise. +#[no_mangle] +pub extern "C" fn z_bytes_map_is_empty(this: &mut z_owned_bytes_map_t) -> bool { + let this = unsafe { &*this.get() }; + this.as_ref().map(|m| m.is_empty()).unwrap_or(true) +} + /// Returns the value associated with `key`, returning a gravestone value if: /// - `this` or `key` is in gravestone state. /// - `this` has no value associated to `key` diff --git a/src/get.rs b/src/get.rs index 423810a4f..bc37d7039 100644 --- a/src/get.rs +++ b/src/get.rs @@ -48,12 +48,8 @@ type ReplyInner = Option; /// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. /// /// 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. -#[cfg(target_arch = "x86_64")] +#[cfg(not(target_arch = "arm"))] #[repr(C, align(8))] -pub struct z_owned_reply_t([u64; 28]); - -#[cfg(target_arch = "aarch64")] -#[repr(C, align(16))] pub struct z_owned_reply_t([u64; 30]); #[cfg(target_arch = "arm")] diff --git a/src/keyexpr.rs b/src/keyexpr.rs index 06784a8dc..7742b3948 100644 --- a/src/keyexpr.rs +++ b/src/keyexpr.rs @@ -24,6 +24,7 @@ use crate::z_str_null; use crate::GuardedTransmute; use crate::LOG_INVALID_SESSION; use libc::c_char; +use zenoh::key_expr::SetIntersectionLevel; use zenoh::prelude::keyexpr; use zenoh::prelude::sync::SyncResolve; use zenoh::prelude::KeyExpr; @@ -103,6 +104,32 @@ pub unsafe extern "C" fn z_keyexpr_new(name: *const c_char) -> z_owned_keyexpr_t } } +/// Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string. The copied string is canonized. +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +pub unsafe extern "C" fn z_keyexpr_new_autocanonize(name: *const c_char) -> z_owned_keyexpr_t { + if name.is_null() { + return z_owned_keyexpr_t::null(); + } + let name = std::slice::from_raw_parts(name as _, libc::strlen(name)); + match std::str::from_utf8(name) { + Ok(name) => { + let name_owned = name.to_owned(); + match KeyExpr::autocanonize(name_owned) { + Ok(v) => v.into_owned().into(), + Err(e) => { + log::error!("Couldn't construct a keyexpr from {:02x?}: {}", name, e); + z_owned_keyexpr_t::null() + } + } + } + Err(e) => { + log::error!("{}", e); + z_owned_keyexpr_t::null() + } + } +} + /// Returns a :c:type:`z_keyexpr_t` loaned from :c:type:`z_owned_keyexpr_t`. #[no_mangle] pub extern "C" fn z_keyexpr_loan(keyexpr: &z_owned_keyexpr_t) -> z_keyexpr_t { @@ -293,6 +320,22 @@ pub unsafe extern "C" fn zc_keyexpr_from_slice(name: *const c_char, len: usize) } } +/// Constructs a :c:type:`z_keyexpr_t` departing from a string. +/// It is a loaned key expression that aliases `name`. +/// The string is canonized in-place before being passed to keyexpr. +/// May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +pub unsafe extern "C" fn zc_keyexpr_from_slice_autocanonize( + name: *mut c_char, + len: &mut usize, +) -> z_keyexpr_t { + if z_keyexpr_canonize(name, len) < 0 { + return z_keyexpr_t::null(); + } + zc_keyexpr_from_slice(name, *len) +} + /// Constructs a :c:type:`z_keyexpr_t` departing from a string. /// It is a loaned key expression that aliases `name`. #[allow(clippy::missing_safety_doc)] @@ -305,6 +348,20 @@ pub unsafe extern "C" fn z_keyexpr(name: *const c_char) -> z_keyexpr_t { } } +/// Constructs a :c:type:`z_keyexpr_t` departing from a string. +/// It is a loaned key expression that aliases `name`. +/// The string is canonized in-place before being passed to keyexpr. +/// May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +pub unsafe extern "C" fn z_keyexpr_autocanonize(name: *mut c_char) -> z_keyexpr_t { + if name.is_null() || z_keyexpr_canonize_null_terminated(name) < 0 { + z_keyexpr_t::null() + } else { + z_keyexpr(name) + } +} + /// Constructs a :c:type:`z_keyexpr_t` departing from a string without checking any of `z_keyexpr_t`'s assertions: /// - `name` MUST be valid UTF8. /// - `name` MUST follow the Key Expression specification, ie: @@ -552,3 +609,43 @@ pub extern "C" fn z_keyexpr_join(left: z_keyexpr_t, right: z_keyexpr_t) -> z_own } } } + +/// A :c:type:`z_keyexpr_intersection_level_t`. +/// +/// - **Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT** +/// - **Z_KEYEXPR_INTERSECTION_LEVEL_INTERSECTS** +/// - **Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES** +/// - **Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS** +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(C)] +pub enum z_keyexpr_intersection_level_t { + DISJOINT = 0, + INTERSECTS = 1, + INCLUDES = 2, + EQUALS = 3, +} + +impl From for z_keyexpr_intersection_level_t { + fn from(val: SetIntersectionLevel) -> Self { + match val { + SetIntersectionLevel::Disjoint => z_keyexpr_intersection_level_t::DISJOINT, + SetIntersectionLevel::Intersects => z_keyexpr_intersection_level_t::INTERSECTS, + SetIntersectionLevel::Includes => z_keyexpr_intersection_level_t::INCLUDES, + SetIntersectionLevel::Equals => z_keyexpr_intersection_level_t::EQUALS, + } + } +} + +#[no_mangle] +/// Returns the relation between `left` and `right` from `left`'s point of view. +/// +/// Note that this is slower than `z_keyexpr_intersects` and `keyexpr_includes`, so you should favor these methods for most applications. +pub extern "C" fn z_keyexpr_relation_to( + left: z_keyexpr_t, + right: z_keyexpr_t, +) -> z_keyexpr_intersection_level_t { + match (&*left, &*right) { + (Some(l), Some(r)) => l.relation_to(r).into(), + _ => z_keyexpr_intersection_level_t::DISJOINT, + } +} diff --git a/src/lib.rs b/src/lib.rs index 2ff9259c6..5019a0713 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,9 @@ #![allow(non_camel_case_types)] mod collections; +use std::cmp::min; +use std::slice; + pub use crate::collections::*; mod config; pub use crate::config::*; @@ -43,6 +46,7 @@ pub use crate::publisher::*; mod closures; pub use closures::*; mod liveliness; +use libc::c_void; pub use liveliness::*; mod publication_cache; pub use publication_cache::*; @@ -174,3 +178,26 @@ fn test_no_default_features() { ) ); } + +trait CopyableToCArray { + fn copy_to_c_array(&self, buf: *mut c_void, len: usize) -> usize; +} + +impl CopyableToCArray for &[u8] { + fn copy_to_c_array(&self, buf: *mut c_void, len: usize) -> usize { + if buf.is_null() || (len == 0 && !self.is_empty()) { + return 0; + } + + let max_len = min(len, self.len()); + let b = unsafe { slice::from_raw_parts_mut(buf as *mut u8, max_len) }; + b[0..max_len].copy_from_slice(&self[0..max_len]); + max_len + } +} + +impl CopyableToCArray for &str { + fn copy_to_c_array(&self, buf: *mut c_void, len: usize) -> usize { + self.as_bytes().copy_to_c_array(buf, len) + } +} diff --git a/src/liveliness.rs b/src/liveliness.rs index 69ee2d2e2..d66508cd5 100644 --- a/src/liveliness.rs +++ b/src/liveliness.rs @@ -195,29 +195,27 @@ pub extern "C" fn zc_liveliness_declare_subscriber( /// The options for :c:func:`zc_liveliness_declare_subscriber` #[repr(C)] -pub struct zc_owned_liveliness_get_options_t { +pub struct zc_liveliness_get_options_t { timeout_ms: u32, } -/// The gravestone value for `zc_owned_liveliness_get_options_t` +/// The gravestone value for `zc_liveliness_get_options_t` #[no_mangle] -pub extern "C" fn zc_liveliness_get_options_null() -> zc_owned_liveliness_get_options_t { - zc_owned_liveliness_get_options_t { timeout_ms: 0 } +pub extern "C" fn zc_liveliness_get_options_null() -> zc_liveliness_get_options_t { + zc_liveliness_get_options_t { timeout_ms: 0 } } -/// The gravestone value for `zc_owned_liveliness_get_options_t` +/// The gravestone value for `zc_liveliness_get_options_t` #[no_mangle] -pub extern "C" fn zc_liveliness_get_options_default() -> zc_owned_liveliness_get_options_t { - zc_owned_liveliness_get_options_t { timeout_ms: 10000 } +pub extern "C" fn zc_liveliness_get_options_default() -> zc_liveliness_get_options_t { + zc_liveliness_get_options_t { timeout_ms: 10000 } } /// Returns `true` if the options are valid. #[no_mangle] -pub extern "C" fn zc_liveliness_get_options_check( - _opts: &zc_owned_liveliness_get_options_t, -) -> bool { +pub extern "C" fn zc_liveliness_get_options_check(_opts: &zc_liveliness_get_options_t) -> bool { true } /// Destroys the options. #[no_mangle] -pub extern "C" fn zc_liveliness_get_options_drop(opts: &mut zc_owned_liveliness_get_options_t) { +pub extern "C" fn zc_liveliness_get_options_drop(opts: &mut zc_liveliness_get_options_t) { *opts = zc_liveliness_get_options_null() } @@ -231,7 +229,7 @@ pub extern "C" fn zc_liveliness_get( session: z_session_t, key: z_keyexpr_t, callback: &mut z_owned_closure_reply_t, - options: Option<&zc_owned_liveliness_get_options_t>, + options: Option<&zc_liveliness_get_options_t>, ) -> i8 { let Some(session) = session.upgrade() else { log::error!("Failed to declare liveliness token: provided session was invalid"); diff --git a/src/platform/clock.rs b/src/platform/clock.rs new file mode 100644 index 000000000..196d697cb --- /dev/null +++ b/src/platform/clock.rs @@ -0,0 +1,127 @@ +use chrono::{DateTime, Local}; +use libc::c_char; +use std::{ + os::raw::c_void, + time::{Duration, Instant, SystemTime, UNIX_EPOCH}, +}; + +use crate::CopyableToCArray; +use lazy_static::lazy_static; + +// Use initial time stored in static variable as a reference time, +// to be able to return number of ns passed since. +// This is to avoid wrapping Instant into a c type and not +// have to account for its platform-dependent size and alignment. +lazy_static! { + static ref CLOCK_BASE: Instant = Instant::now(); +} + +/// Clock +/// Uses monotonic clock +#[repr(C)] +#[derive(Clone, Copy)] +pub struct z_clock_t { + t: u64, + t_base: *const c_void, +} + +#[no_mangle] +pub extern "C" fn z_clock_now() -> z_clock_t { + z_clock_t { + t: CLOCK_BASE.elapsed().as_nanos() as u64, + t_base: &CLOCK_BASE as *const CLOCK_BASE as *const c_void, + } +} +#[allow(clippy::missing_safety_doc)] +unsafe fn get_elapsed_nanos(time: *const z_clock_t) -> u64 { + if time.is_null() { + return 0; + } + let now_t = (*((*time).t_base as *const CLOCK_BASE)) + .elapsed() + .as_nanos() as u64; + if now_t > (*time).t { + now_t - (*time).t + } else { + 0 + } +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_clock_elapsed_s(time: *const z_clock_t) -> u64 { + get_elapsed_nanos(time) / 1_000_000_000 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_clock_elapsed_ms(time: *const z_clock_t) -> u64 { + get_elapsed_nanos(time) / 1_000_000 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_clock_elapsed_us(time: *const z_clock_t) -> u64 { + get_elapsed_nanos(time) / 1_000 +} + +/// Time +/// Uses system clock +#[repr(C)] +#[derive(Clone, Copy)] +pub struct z_time_t { + t: u64, +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_time_now_as_str(buf: *const c_char, len: usize) -> *const c_char { + if len == 0 || buf.is_null() { + return buf; + } + let datetime: DateTime = SystemTime::now().into(); + let s = datetime.format("%Y-%m-%dT%H:%M:%SZ").to_string(); + let res = s.as_str().copy_to_c_array(buf as *mut c_void, len - 1); + *((buf as usize + res) as *mut c_char) = 0; + buf +} + +#[no_mangle] +pub extern "C" fn z_time_now() -> z_time_t { + z_time_t { + t: SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or(Duration::new(0, 0)) + .as_nanos() as u64, + } +} +#[allow(clippy::missing_safety_doc)] +unsafe fn get_elapsed_nanos_system_clock(time: *const z_time_t) -> u64 { + if time.is_null() { + return 0; + } + let now_t = z_time_now().t; + if now_t > (*time).t { + now_t - (*time).t + } else { + 0 + } +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_time_elapsed_s(time: *const z_time_t) -> u64 { + get_elapsed_nanos_system_clock(time) / 1_000_000_000 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_time_elapsed_ms(time: *const z_time_t) -> u64 { + get_elapsed_nanos_system_clock(time) / 1_000_000 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_time_elapsed_us(time: *const z_time_t) -> u64 { + get_elapsed_nanos_system_clock(time) / 1_000 +} diff --git a/src/platform/mod.rs b/src/platform/mod.rs index c9f87a9c7..438763afe 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -1,5 +1,5 @@ // -// Copyright (c) 2017, 2023 ZettaScale Technology. +// Copyright (c) 2017, 2024 ZettaScale Technology. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License 2.0 which is available at @@ -12,5 +12,12 @@ // ZettaScale Zenoh team, // +pub use clock::*; +mod clock; +pub use sleep::*; +mod sleep; pub use synchronization::*; mod synchronization; + +pub use random::*; +mod random; diff --git a/src/platform/random.rs b/src/platform/random.rs new file mode 100644 index 000000000..d466e7b77 --- /dev/null +++ b/src/platform/random.rs @@ -0,0 +1,34 @@ +use std::slice::from_raw_parts_mut; + +use libc::c_void; +use rand::{random, thread_rng, RngCore}; + +#[no_mangle] +pub extern "C" fn z_random_u8() -> u8 { + random::() +} + +#[no_mangle] +pub extern "C" fn z_random_u16() -> u16 { + random::() +} + +#[no_mangle] +pub extern "C" fn z_random_u32() -> u32 { + random::() +} + +#[no_mangle] +pub extern "C" fn z_random_u64() -> u64 { + random::() +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_random_fill(buf: *mut c_void, len: usize) { + if buf.is_null() || len == 0 { + return; + } + let b: &mut [u8] = from_raw_parts_mut(buf as *mut u8, len); + thread_rng().fill_bytes(b); +} diff --git a/src/platform/sleep.rs b/src/platform/sleep.rs new file mode 100644 index 000000000..b2f3e4dd7 --- /dev/null +++ b/src/platform/sleep.rs @@ -0,0 +1,19 @@ +use std::{thread, time}; + +#[no_mangle] +pub extern "C" fn z_sleep_s(time: usize) -> i8 { + thread::sleep(time::Duration::from_secs(time as u64)); + 0 +} + +#[no_mangle] +pub extern "C" fn z_sleep_ms(time: usize) -> i8 { + thread::sleep(time::Duration::from_millis(time as u64)); + 0 +} + +#[no_mangle] +pub extern "C" fn z_sleep_us(time: usize) -> i8 { + thread::sleep(time::Duration::from_micros(time as u64)); + 0 +} diff --git a/src/scouting.rs b/src/scouting.rs index 6df207840..c7dd80be7 100644 --- a/src/scouting.rs +++ b/src/scouting.rs @@ -13,11 +13,11 @@ // use crate::{ z_closure_hello_call, z_config_check, z_config_default, z_config_null, z_config_t, z_id_t, - z_owned_closure_hello_t, z_owned_config_t, zc_init_logger, + z_owned_closure_hello_t, z_owned_config_t, zc_init_logger, CopyableToCArray, }; use async_std::task; use libc::{c_char, c_uint, c_ulong, size_t}; -use std::ffi::CString; +use std::{ffi::CString, os::raw::c_void}; use zenoh::scouting::Hello; use zenoh_protocol::core::{whatami::WhatAmIMatcher, WhatAmI}; use zenoh_util::core::AsyncResolve; @@ -268,3 +268,30 @@ pub extern "C" fn z_scout( }); 0 } + +/// Converts the kind of zenoh entity into a string. +/// +/// Parameters: +/// whatami: A whatami bitmask of zenoh entity kind. +/// buf: Buffer to write a null-terminated string to. +/// len: Maximum number of bytes that can be written to the `buf`. +/// +/// Returns 0 if successful, negative values if whatami contains an invalid bitmask or `buf` is null, +/// or number of remaining bytes, if the null-terminated string size exceeds `len`. +#[no_mangle] +pub extern "C" fn z_whatami_to_str(whatami: u8, buf: *mut c_char, len: usize) -> i8 { + if buf.is_null() || len == 0 { + return -1; + } + match WhatAmIMatcher::try_from(whatami) { + Err(_) => -1, + Ok(w) => { + let s = w.to_str(); + let res = s.copy_to_c_array(buf as *mut c_void, len - 1); + unsafe { + *((buf as usize + res) as *mut c_char) = 0; + } + (s.len() - res) as i8 + } + } +} diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index 8dcff3317..9ade440f3 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -17,14 +17,6 @@ #undef NDEBUG #include - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif - #include "zenoh.h" #define SLEEP 1 @@ -135,7 +127,7 @@ int main(int argc, char **argv) { assert(_ret_int == -1); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); size_t keyexpr_len = strlen(URI); char *keyexpr_str = (char *)z_malloc(keyexpr_len + 1); @@ -157,7 +149,7 @@ int main(int argc, char **argv) { assert(strlen(URI) == keyexpr_len); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); z_owned_config_t _ret_config = z_config_new(); assert(z_check(_ret_config)); @@ -184,7 +176,7 @@ int main(int argc, char **argv) { #endif z_drop(z_move(_ret_sconfig)); - sleep(SLEEP); + z_sleep_s(SLEEP); _ret_sconfig = z_scouting_config_from(z_loan(_ret_config)); z_owned_closure_hello_t _ret_closure_hello = z_closure(hello_handler, NULL, NULL); @@ -192,8 +184,8 @@ int main(int argc, char **argv) { assert(_ret_int8 == 0); assert(hellos == 1); - sleep(atoi(SCOUTING_TIMEOUT) / 1000); - sleep(SLEEP); + z_sleep_s(atoi(SCOUTING_TIMEOUT) / 1000); + z_sleep_s(SLEEP); z_owned_session_t s1 = z_open(z_move(_ret_config)); assert(z_check(s1)); @@ -207,13 +199,13 @@ int main(int argc, char **argv) { z_owned_closure_zid_t _ret_closure_zid = z_closure(zid_handler, NULL, NULL); _ret_int8 = z_info_peers_zid(z_loan(s1), z_move(_ret_closure_zid)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(zids == 0); _ret_int8 = z_info_routers_zid(z_loan(s1), z_move(_ret_closure_zid)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(zids == 1); #ifdef ZENOH_PICO @@ -223,7 +215,7 @@ int main(int argc, char **argv) { zp_start_lease_task(z_loan(s1), &_ret_lease_opt); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); _ret_config = z_config_default(); #ifdef ZENOH_PICO @@ -248,7 +240,7 @@ int main(int argc, char **argv) { zp_start_lease_task(z_loan(s2), NULL); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); z_session_t ls1 = z_loan(s1); z_owned_closure_sample_t _ret_closure_sample = z_closure(data_handler, NULL, &ls1); @@ -257,7 +249,7 @@ int main(int argc, char **argv) { z_declare_subscriber(z_loan(s2), z_keyexpr(keyexpr_str), z_move(_ret_closure_sample), &_ret_sub_opt); assert(z_check(_ret_sub)); - sleep(SLEEP); + z_sleep_s(SLEEP); char s1_res[64]; sprintf(s1_res, "%s/chunk/%d", keyexpr_str, 1); @@ -271,14 +263,14 @@ int main(int argc, char **argv) { _ret_int8 = z_put(z_loan(s1), z_loan(_ret_expr), (const uint8_t *)value, strlen(value), &_ret_put_opt); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(datas == 1); z_delete_options_t _ret_delete_opt = z_delete_options_default(); _ret_int8 = z_delete(z_loan(s1), z_loan(_ret_expr), &_ret_delete_opt); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(datas == 2); _ret_int8 = z_undeclare_keyexpr(z_loan(s1), z_move(_ret_expr)); @@ -303,23 +295,23 @@ int main(int argc, char **argv) { _ret_int8 = z_publisher_put(z_loan(_ret_pub), (const uint8_t *)value, strlen(value), &_ret_pput_opt); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); _ret_int8 = z_subscriber_pull(z_loan(_ret_psub)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(datas == 3); z_publisher_delete_options_t _ret_pdelete_opt = z_publisher_delete_options_default(); _ret_int8 = z_publisher_delete(z_loan(_ret_pub), &_ret_pdelete_opt); - sleep(SLEEP); + z_sleep_s(SLEEP); _ret_int8 = z_subscriber_pull(z_loan(_ret_psub)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(datas == 4); _ret_int8 = z_undeclare_publisher(z_move(_ret_pub)); @@ -328,7 +320,7 @@ int main(int argc, char **argv) { _ret_int8 = z_undeclare_pull_subscriber(z_move(_ret_psub)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); z_owned_closure_query_t _ret_closure_query = z_closure(query_handler, NULL, &ls1); z_queryable_options_t _ret_qle_opt = z_queryable_options_default(); @@ -336,7 +328,7 @@ int main(int argc, char **argv) { z_declare_queryable(z_loan(s1), z_keyexpr(s1_res), z_move(_ret_closure_query), &_ret_qle_opt); assert(z_check(qle)); - sleep(SLEEP); + z_sleep_s(SLEEP); z_session_t ls2 = z_loan(s2); z_owned_closure_reply_t _ret_closure_reply = z_closure(reply_handler, NULL, &ls2); @@ -350,7 +342,7 @@ int main(int argc, char **argv) { _ret_int8 = z_get(z_loan(s2), z_keyexpr(s1_res), "", z_move(_ret_closure_reply), &_ret_get_opt); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(queries == 1); assert(replies == 1); @@ -372,7 +364,7 @@ int main(int argc, char **argv) { _ret_int8 = z_close(z_move(s2)); assert(_ret_int8 == 0); - sleep(SLEEP * 5); + z_sleep_s(SLEEP * 5); z_free(keyexpr_str); diff --git a/tests/z_api_attachment_test.c b/tests/z_api_attachment_test.c index c11abcbfe..737048e9b 100644 --- a/tests/z_api_attachment_test.c +++ b/tests/z_api_attachment_test.c @@ -29,6 +29,11 @@ void writting_through_map_by_alias_read_by_get() { z_attachment_t attachment = z_bytes_map_as_attachment(&map); // Elements check + + assert(z_bytes_map_len(&map) == 2); + assert(z_attachment_len(attachment) == 2); + assert(!z_attachment_is_empty(attachment)); + z_bytes_t a1 = z_attachment_get(attachment, z_bytes_from_str("k1")); ASSERT_STR_BYTES_EQUAL("v1", a1); @@ -61,6 +66,10 @@ void writting_through_map_by_copy_read_by_iter() { z_attachment_t attachment = z_bytes_map_as_attachment(&map); // Elements check + assert(z_bytes_map_len(&map) == 2); + assert(z_attachment_len(attachment) == 2); + assert(!z_attachment_is_empty(attachment)); + int res = z_attachment_iterate(attachment, _attachment_reader, (void*)42); assert(res == 24); @@ -81,6 +90,9 @@ void writting_no_map_read_by_get() { z_attachment_t attachment = {.data = NULL, .iteration_driver = &_iteration_driver}; // Elements check + assert(z_attachment_len(attachment) == 2); + assert(!z_attachment_is_empty(attachment)); + z_bytes_t a1 = z_attachment_get(attachment, z_bytes_from_str("k1")); ASSERT_STR_BYTES_EQUAL("v1", a1); @@ -94,6 +106,8 @@ void writting_no_map_read_by_get() { void invalid_attachment_safety() { z_attachment_t attachment = z_attachment_null(); + assert(z_attachment_is_empty(attachment)); + assert(z_attachment_len(attachment) == 0); z_bytes_t a_non = z_attachment_get(attachment, z_bytes_from_str("k_non")); assert(a_non.start == NULL); diff --git a/tests/z_api_keyexpr_test.c b/tests/z_api_keyexpr_test.c index b5cdeaad1..cb3c234b3 100644 --- a/tests/z_api_keyexpr_test.c +++ b/tests/z_api_keyexpr_test.c @@ -41,6 +41,22 @@ void canonize() { printf("'%s', err = %d\n", keyexpr, err); assert(err == 0); assert(strcmp(keyexpr, "a/**/c") == 0); + + strcpy(keyexpr, "a/**/**/c"); + z_keyexpr_t key_expr_canonized = z_keyexpr_autocanonize(keyexpr); + assert(z_keyexpr_check(keyexpr) == true); + assert(strcmp(keyexpr, "a/**/c") == 0); + assert(z_keyexpr_as_bytes(key_expr_canonized).len == len_new); + assert(strncmp(z_keyexpr_as_bytes(key_expr_canonized).start, "a/**/c", len_new) == 0); + + strcpy(keyexpr, "a/**/**/c"); + len_new = len_old; + key_expr_canonized = zc_keyexpr_from_slice_autocanonize(keyexpr, &len_new); + assert(z_keyexpr_check(keyexpr) == true); + assert(len_new == len_old - 3); + assert(strncmp(keyexpr, "a/**/c", len_new) == 0); + assert(z_keyexpr_as_bytes(key_expr_canonized).len == len_new); + assert(strncmp(z_keyexpr_as_bytes(key_expr_canonized).start, "a/**/c", len_new) == 0); } void includes() { @@ -73,9 +89,23 @@ void undeclare() { assert(!z_keyexpr_check(&ke)); } +void relation_to() { + z_keyexpr_t nul = z_keyexpr(NULL); + z_keyexpr_t foobar = z_keyexpr("foo/bar"); + z_keyexpr_t foostar = z_keyexpr("foo/*"); + z_keyexpr_t barstar = z_keyexpr("bar/*"); + assert(z_keyexpr_relation_to(foostar, foobar) == Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES); + assert(z_keyexpr_relation_to(foobar, foostar) == Z_KEYEXPR_INTERSECTION_LEVEL_INTERSECTS); + assert(z_keyexpr_relation_to(foostar, foostar) == Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS); + assert(z_keyexpr_relation_to(barstar, foobar) == Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT); + assert(z_keyexpr_relation_to(nul, foobar) == Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT); + assert(z_keyexpr_relation_to(foobar, nul) == Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT); +} + int main(int argc, char **argv) { canonize(); includes(); intersects(); undeclare(); + relation_to(); } diff --git a/tests/z_int_pub_cache_query_sub_test.c b/tests/z_int_pub_cache_query_sub_test.c index 7495939f2..868b3878e 100644 --- a/tests/z_int_pub_cache_query_sub_test.c +++ b/tests/z_int_pub_cache_query_sub_test.c @@ -122,7 +122,7 @@ int run_subscriber() { } SEM_POST(sem_sub); - sleep(10); + z_sleep_s(10); z_drop(z_move(sub)); z_close(z_move(s)); diff --git a/tests/z_int_pub_sub_attachment_test.c b/tests/z_int_pub_sub_attachment_test.c index 554d1fd57..bafdd87ca 100644 --- a/tests/z_int_pub_sub_attachment_test.c +++ b/tests/z_int_pub_sub_attachment_test.c @@ -107,7 +107,7 @@ int run_subscriber() { } SEM_POST(sem); - sleep(10); + z_sleep_s(10); z_undeclare_subscriber(z_move(sub)); z_close(z_move(s)); diff --git a/tests/z_int_queryable_attachment_test.c b/tests/z_int_queryable_attachment_test.c index 836f8d988..1de9de788 100644 --- a/tests/z_int_queryable_attachment_test.c +++ b/tests/z_int_queryable_attachment_test.c @@ -76,7 +76,7 @@ int run_queryable() { } SEM_POST(sem); - sleep(10); + z_sleep_s(10); z_drop(z_move(qable)); z_close(z_move(s)); diff --git a/tests/z_int_queryable_test.c b/tests/z_int_queryable_test.c index 67c690f8e..9bcc16cc1 100644 --- a/tests/z_int_queryable_test.c +++ b/tests/z_int_queryable_test.c @@ -59,7 +59,7 @@ int run_queryable() { } SEM_POST(sem); - sleep(10); + z_sleep_s(10); z_drop(z_move(qable)); z_close(z_move(s)); From a2cfa7ff963b62792cd4d50577ffbc5010c76f46 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 28 Mar 2024 12:32:31 +0100 Subject: [PATCH 13/30] merge --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c62eb1df..d29080bad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -417,9 +417,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", From dbc88773fdc34ec32b86e667a6369880ccbc84b8 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 28 Mar 2024 12:38:03 +0100 Subject: [PATCH 14/30] removed cargo channel parameter by default (#301) --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00aa5cac2..d236e99fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ declare_cache_var_true_if_vscode(ZENOHC_BUILD_IN_SOURCE_TREE "Do build inside so declare_cache_var(ZENOHC_BUILD_WITH_LOGGER_AUTOINIT TRUE BOOL "Enable logger-autoinit zenoh-c feature") declare_cache_var(ZENOHC_BUILD_WITH_SHARED_MEMORY TRUE BOOL "Enable shared-memory zenoh-c feature") declare_cache_var(ZENOHC_CUSTOM_TARGET "" STRING "Rust target for cross compilation, 'aarch64-unknown-linux-gnu' for example") -declare_cache_var(ZENOHC_CARGO_CHANNEL "stable" STRING "Cargo channel selected: stable or nightly") +declare_cache_var(ZENOHC_CARGO_CHANNEL "" STRING "Cargo channel parameter. Should be '+stable', '+nightly' or empty value") declare_cache_var(ZENOHC_CARGO_FLAGS "" STRING "Additional cargo flags") declare_cache_var(ZENOHC_LIB_STATIC FALSE BOOL "Alias zenohc::lib target to zenohc::static if TRUE, to zenohc::shared if FALSE") @@ -198,8 +198,8 @@ file(GLOB_RECURSE rust_sources "Cargo.toml.in" "src/*.rs" "build.rs" "splitguide add_custom_command( OUTPUT ${libs} COMMAND ${CMAKE_COMMAND} -E echo \"RUSTFLAGS = $$RUSTFLAGS\" - COMMAND ${CMAKE_COMMAND} -E echo \"cargo +${ZENOHC_CARGO_CHANNEL} build ${cargo_flags}\" - COMMAND cargo +${ZENOHC_CARGO_CHANNEL} build ${cargo_flags} + COMMAND ${CMAKE_COMMAND} -E echo \"cargo ${ZENOHC_CARGO_CHANNEL} build ${cargo_flags}\" + COMMAND cargo ${ZENOHC_CARGO_CHANNEL} build ${cargo_flags} VERBATIM COMMAND_EXPAND_LISTS DEPENDS "${rust_sources}" From c1498fcaf08d3dad15e49b1ac15cd380c0dc175c Mon Sep 17 00:00:00 2001 From: eclipse-zenoh-bot <61247838+eclipse-zenoh-bot@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:54:47 +0200 Subject: [PATCH 15/30] chore: Sync Cargo lockfile with Zenoh's (#307) Co-authored-by: eclipse-zenoh-bot --- Cargo.lock | 69 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d29080bad..959b85749 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2953,7 +2953,7 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "zenoh" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "base64", @@ -2996,6 +2996,7 @@ dependencies = [ "zenoh-runtime", "zenoh-shm", "zenoh-sync", + "zenoh-task", "zenoh-transport", "zenoh-util", ] @@ -3003,7 +3004,7 @@ dependencies = [ [[package]] name = "zenoh-buffers" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "zenoh-collections", ] @@ -3035,7 +3036,7 @@ dependencies = [ [[package]] name = "zenoh-codec" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "log", "serde", @@ -3048,12 +3049,12 @@ dependencies = [ [[package]] name = "zenoh-collections" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" [[package]] name = "zenoh-config" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "flume", "json5", @@ -3073,7 +3074,7 @@ dependencies = [ [[package]] name = "zenoh-core" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-global-executor", "lazy_static", @@ -3085,7 +3086,7 @@ dependencies = [ [[package]] name = "zenoh-crypto" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "aes", "hmac", @@ -3098,7 +3099,7 @@ dependencies = [ [[package]] name = "zenoh-ext" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "bincode", "env_logger 0.11.2", @@ -3113,13 +3114,14 @@ dependencies = [ "zenoh-result", "zenoh-runtime", "zenoh-sync", + "zenoh-task", "zenoh-util", ] [[package]] name = "zenoh-keyexpr" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "hashbrown 0.14.0", "keyed-set", @@ -3133,7 +3135,7 @@ dependencies = [ [[package]] name = "zenoh-link" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "zenoh-config", @@ -3151,7 +3153,7 @@ dependencies = [ [[package]] name = "zenoh-link-commons" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "flume", @@ -3174,7 +3176,7 @@ dependencies = [ [[package]] name = "zenoh-link-quic" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "base64", @@ -3202,7 +3204,7 @@ dependencies = [ [[package]] name = "zenoh-link-tcp" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "log", @@ -3220,7 +3222,7 @@ dependencies = [ [[package]] name = "zenoh-link-tls" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "base64", @@ -3248,7 +3250,7 @@ dependencies = [ [[package]] name = "zenoh-link-udp" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "log", @@ -3269,7 +3271,7 @@ dependencies = [ [[package]] name = "zenoh-link-unixsock_stream" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "futures", @@ -3289,7 +3291,7 @@ dependencies = [ [[package]] name = "zenoh-link-ws" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "futures-util", @@ -3310,7 +3312,7 @@ dependencies = [ [[package]] name = "zenoh-macros" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "proc-macro2", "quote", @@ -3321,7 +3323,7 @@ dependencies = [ [[package]] name = "zenoh-plugin-trait" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "const_format", "libloading", @@ -3337,7 +3339,7 @@ dependencies = [ [[package]] name = "zenoh-protocol" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "const_format", "rand", @@ -3351,7 +3353,7 @@ dependencies = [ [[package]] name = "zenoh-result" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "anyhow", ] @@ -3359,8 +3361,9 @@ dependencies = [ [[package]] name = "zenoh-runtime" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ + "futures", "lazy_static", "tokio", "zenoh-collections", @@ -3370,7 +3373,7 @@ dependencies = [ [[package]] name = "zenoh-shm" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "log", "serde", @@ -3382,7 +3385,7 @@ dependencies = [ [[package]] name = "zenoh-sync" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "event-listener 4.0.0", "futures", @@ -3393,10 +3396,23 @@ dependencies = [ "zenoh-runtime", ] +[[package]] +name = "zenoh-task" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" +dependencies = [ + "futures", + "log", + "tokio", + "tokio-util", + "zenoh-core", + "zenoh-runtime", +] + [[package]] name = "zenoh-transport" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-trait", "flume", @@ -3422,13 +3438,14 @@ dependencies = [ "zenoh-runtime", "zenoh-shm", "zenoh-sync", + "zenoh-task", "zenoh-util", ] [[package]] name = "zenoh-util" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#02d4783042d50110ccfb79aada420ff5231ae840" dependencies = [ "async-std", "async-trait", From 206983ecb23142bda6dc43e00aaec1e89c2d80c9 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Wed, 3 Apr 2024 22:34:30 +0200 Subject: [PATCH 16/30] put and get with owned payload --- .gitignore | 5 +- CMakeLists.txt | 5 + Cargo.lock | 1 + Cargo.toml | 1 + Cargo.toml.in | 1 + build-resources/opaque-types/Cargo.lock | 2624 +++++++++++++++++++++++ build-resources/opaque-types/Cargo.toml | 10 + build-resources/opaque-types/src/lib.rs | 38 + build.rs | 57 +- examples/z_get.c | 9 +- examples/z_non_blocking_get.c | 7 +- examples/z_ping.c | 5 +- examples/z_pong.c | 6 +- examples/z_pub.c | 3 +- examples/z_pub_attachment.c | 3 +- examples/z_pub_cache.c | 3 +- examples/z_pub_shm.c | 2 +- examples/z_pub_thr.c | 3 +- examples/z_pull.c | 7 +- examples/z_put.c | 3 +- examples/z_query_sub.c | 7 +- examples/z_queryable.c | 10 +- examples/z_queryable_with_channels.c | 10 +- examples/z_sub.c | 7 +- examples/z_sub_attachment.c | 6 +- include/zenoh_commons.h | 185 +- src/collections.rs | 79 +- src/commons.rs | 152 +- src/get.rs | 136 +- src/lib.rs | 2 + src/liveliness.rs | 7 +- src/opaque_types/mod.rs | 15 + src/publisher.rs | 59 +- src/pull_subscriber.rs | 6 +- src/put.rs | 68 +- src/queryable.rs | 19 +- src/querying_subscriber.rs | 6 +- src/subscriber.rs | 6 +- tests/z_api_alignment_test.c | 6 +- tests/z_int_pub_cache_query_sub_test.c | 15 +- tests/z_int_pub_sub_attachment_test.c | 9 +- tests/z_int_pub_sub_test.c | 9 +- tests/z_int_queryable_attachment_test.c | 9 +- tests/z_int_queryable_test.c | 9 +- 44 files changed, 3200 insertions(+), 430 deletions(-) create mode 100644 build-resources/opaque-types/Cargo.lock create mode 100644 build-resources/opaque-types/Cargo.toml create mode 100644 build-resources/opaque-types/src/lib.rs create mode 100644 src/opaque_types/mod.rs diff --git a/.gitignore b/.gitignore index d7a6cf967..8aaf37e32 100644 --- a/.gitignore +++ b/.gitignore @@ -70,4 +70,7 @@ dkms.conf .cache # Platform dependent generated files -include/zenoh_configure.h \ No newline at end of file +include/zenoh_configure.h + +# Build resources +.build_resources* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 00aa5cac2..aac66278b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,6 +179,10 @@ set_genexpr_condition(cargo_flags DEBUG $ "--manifest-path=${cargo_toml_dir_debug}/Cargo.toml" "--release;--manifest-path=${cargo_toml_dir_release}/Cargo.toml") set(cargo_flags ${cargo_flags} ${ZENOHC_CARGO_FLAGS}) +set_genexpr_condition(cargo_dep_flags DEBUG $ + "--manifest-path=${CMAKE_CURRENT_SOURCE_DIR}/build-resources/opaque-types/Cargo.toml" + "--release;--manifest-path=${CMAKE_CURRENT_SOURCE_DIR}/build-resources/opaque-types/Cargo.toml") +set(cargo_dep_flags ${cargo_dep_flags} ${ZENOHC_CARGO_FLAGS}) if(ZENOHC_BUILD_WITH_LOGGER_AUTOINIT) set(cargo_flags ${cargo_flags} --features=logger-autoinit) @@ -199,6 +203,7 @@ add_custom_command( OUTPUT ${libs} COMMAND ${CMAKE_COMMAND} -E echo \"RUSTFLAGS = $$RUSTFLAGS\" COMMAND ${CMAKE_COMMAND} -E echo \"cargo +${ZENOHC_CARGO_CHANNEL} build ${cargo_flags}\" + COMMAND cargo +${ZENOHC_CARGO_CHANNEL} build ${cargo_dep_flags} &> ${CMAKE_CURRENT_SOURCE_DIR}/.build_resources_opaque_types.txt || echo "" COMMAND cargo +${ZENOHC_CARGO_CHANNEL} build ${cargo_flags} VERBATIM COMMAND_EXPAND_LISTS diff --git a/Cargo.lock b/Cargo.lock index d29080bad..7bf87ae6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3024,6 +3024,7 @@ dependencies = [ "libc", "log", "rand", + "regex", "serde_yaml", "spin 0.9.8", "zenoh", diff --git a/Cargo.toml b/Cargo.toml index 95867f95f..8e0541888 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ zenoh-ext = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/ze [build-dependencies] cbindgen = "0.24.3" fs2 = "0.4.3" +regex = "1.7.1" serde_yaml = "0.9.19" [lib] diff --git a/Cargo.toml.in b/Cargo.toml.in index f434df3a1..a8123bcd5 100644 --- a/Cargo.toml.in +++ b/Cargo.toml.in @@ -59,6 +59,7 @@ zenoh-ext = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/ze [build-dependencies] cbindgen = "0.24.3" fs2 = "0.4.3" +regex = "1.7.1" serde_yaml = "0.9.19" [lib] diff --git a/build-resources/opaque-types/Cargo.lock b/build-resources/opaque-types/Cargo.lock new file mode 100644 index 000000000..a6f37dab3 --- /dev/null +++ b/build-resources/opaque-types/Cargo.lock @@ -0,0 +1,2624 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +dependencies = [ + "concurrent-queue", + "event-listener 5.2.0", + "event-listener-strategy 0.5.0", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +dependencies = [ + "async-lock 3.3.0", + "async-task", + "concurrent-queue", + "fastrand 2.0.2", + "futures-lite 2.3.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.2.0", + "async-executor", + "async-io 2.3.2", + "async-lock 3.3.0", + "blocking", + "futures-lite 2.3.0", + "once_cell", + "tokio", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +dependencies = [ + "async-lock 3.3.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.6.0", + "rustix 0.38.32", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.32", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-signal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +dependencies = [ + "async-io 2.3.2", + "async-lock 2.8.0", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.32", + "signal-hook-registry", + "slab", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 1.13.0", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" + +[[package]] +name = "async-trait" +version = "0.1.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +dependencies = [ + "async-channel 2.2.0", + "async-lock 3.3.0", + "async-task", + "fastrand 2.0.2", + "futures-io", + "futures-lite 2.3.0", + "piper", + "tracing", +] + +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cache-padded" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "981520c98f422fcc584dc1a95c334e6953900b9106bc47a9839b81790009eb21" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "concurrent-queue" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +dependencies = [ + "event-listener 5.2.0", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.0.2", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "git-version" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad568aa3db0fcbc81f2f116137f263d7304f512a1209b35b85150d3ef88ad19" +dependencies = [ + "git-version-macro", +] + +[[package]] +name = "git-version-macro" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ipnetwork" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" +dependencies = [ + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keyed-set" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b79e110283e09081809ca488cf3a9709270c6d4d4c4a32674c39cc438366615a" +dependencies = [ + "hashbrown 0.13.2", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets 0.52.4", +] + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.5.0", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +dependencies = [ + "value-bag", +] + +[[package]] +name = "lz4_flex" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-types" +version = "0.1.0" +dependencies = [ + "zenoh", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-float" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "pest_meta" +version = "2.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.2", + "futures-io", +] + +[[package]] +name = "pnet_base" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c" +dependencies = [ + "no-std-net", +] + +[[package]] +name = "pnet_datalink" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad5854abf0067ebbd3967f7d45ebc8976ff577ff0c7bd101c4973ae3c70f98fe" +dependencies = [ + "ipnetwork", + "libc", + "pnet_base", + "pnet_sys", + "winapi", +] + +[[package]] +name = "pnet_sys" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417c0becd1b573f6d544f73671070b039051e5ad819cc64aa96377b536128d00" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 0.38.32", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ringbuffer-spsc" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1938faa63a2362ee1747afb2d10567d0fb1413b9cbd6198a8541485c4f773" +dependencies = [ + "array-init", + "cache-padded", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys 0.4.13", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" + +[[package]] +name = "rustls-webpki" +version = "0.102.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "serde", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "shared_memory" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba8593196da75d9dc4f69349682bd4c2099f8cde114257d1ef7ef1b33d1aba54" +dependencies = [ + "cfg-if", + "libc", + "nix", + "rand", + "win-sys", +] + +[[package]] +name = "shellexpand" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +dependencies = [ + "dirs", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stop-token" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af91f480ee899ab2d9f8435bfdfc14d08a5754bd9d3fef1f1a1c23336aad6c8b" +dependencies = [ + "async-channel 1.9.0", + "cfg-if", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "token-cell" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a2b964fdb303b08a4eab04d7c1bad2bca33f8eee334ccd28802f1041c6eb87" +dependencies = [ + "paste", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2 0.5.6", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "futures-util", + "hashbrown 0.14.3", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "uhlc" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b6df3f3e948b40e20c38a6d1fd6d8f91b3573922fc164e068ad3331560487e" +dependencies = [ + "humantime", + "lazy_static", + "log", + "rand", + "serde", + "spin", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "unzip-n" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7e85a0596447f0f2ac090e16bc4c516c6fe91771fb0c0ccf7fa3dae896b9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "getrandom", +] + +[[package]] +name = "validated_struct" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feef04c049b4beae3037a2a31b8da40d8cebec0b97456f24c7de0ede4ed9efed" +dependencies = [ + "json5", + "serde", + "serde_json", + "validated_struct_macros", +] + +[[package]] +name = "validated_struct_macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d4444a980afa9ef0d29c2a3f4d952ec0495a7a996a9c78b52698b71bc21edb4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unzip-n", +] + +[[package]] +name = "value-bag" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74797339c3b98616c009c7c3eb53a0ce41e85c8ec66bd3db96ed132d20cfdee8" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.55", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "win-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b7b128a98c1cfa201b09eb49ba285887deb3cbe7466a98850eb1adabb452be5" +dependencies = [ + "windows", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" +dependencies = [ + "windows_aarch64_msvc 0.34.0", + "windows_i686_gnu 0.34.0", + "windows_i686_msvc 0.34.0", + "windows_x86_64_gnu 0.34.0", + "windows_x86_64_msvc 0.34.0", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "zenoh" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "async-trait", + "base64", + "const_format", + "env_logger", + "event-listener 4.0.3", + "flume", + "form_urlencoded", + "futures", + "git-version", + "lazy_static", + "log", + "ordered-float", + "paste", + "petgraph", + "rand", + "regex", + "rustc_version", + "serde", + "serde_json", + "socket2 0.5.6", + "stop-token", + "tokio", + "tokio-util", + "uhlc", + "uuid", + "vec_map", + "zenoh-buffers", + "zenoh-codec", + "zenoh-collections", + "zenoh-config", + "zenoh-core", + "zenoh-crypto", + "zenoh-keyexpr", + "zenoh-link", + "zenoh-macros", + "zenoh-plugin-trait", + "zenoh-protocol", + "zenoh-result", + "zenoh-runtime", + "zenoh-shm", + "zenoh-sync", + "zenoh-transport", + "zenoh-util", +] + +[[package]] +name = "zenoh-buffers" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "zenoh-collections", +] + +[[package]] +name = "zenoh-codec" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "log", + "serde", + "uhlc", + "zenoh-buffers", + "zenoh-protocol", + "zenoh-shm", +] + +[[package]] +name = "zenoh-collections" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" + +[[package]] +name = "zenoh-config" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "flume", + "json5", + "log", + "num_cpus", + "secrecy", + "serde", + "serde_json", + "serde_yaml", + "validated_struct", + "zenoh-core", + "zenoh-protocol", + "zenoh-result", + "zenoh-util", +] + +[[package]] +name = "zenoh-core" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "async-global-executor", + "lazy_static", + "tokio", + "zenoh-result", + "zenoh-runtime", +] + +[[package]] +name = "zenoh-crypto" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "aes", + "hmac", + "rand", + "rand_chacha", + "sha3", + "zenoh-result", +] + +[[package]] +name = "zenoh-keyexpr" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "hashbrown 0.14.3", + "keyed-set", + "rand", + "schemars", + "serde", + "token-cell", + "zenoh-result", +] + +[[package]] +name = "zenoh-link" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "async-trait", + "zenoh-config", + "zenoh-link-commons", + "zenoh-protocol", + "zenoh-result", +] + +[[package]] +name = "zenoh-link-commons" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "async-trait", + "flume", + "futures", + "log", + "rustls", + "rustls-webpki", + "serde", + "tokio", + "tokio-util", + "zenoh-buffers", + "zenoh-codec", + "zenoh-core", + "zenoh-protocol", + "zenoh-result", + "zenoh-runtime", + "zenoh-util", +] + +[[package]] +name = "zenoh-macros" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", + "zenoh-keyexpr", +] + +[[package]] +name = "zenoh-plugin-trait" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "const_format", + "libloading", + "log", + "serde", + "serde_json", + "zenoh-keyexpr", + "zenoh-macros", + "zenoh-result", + "zenoh-util", +] + +[[package]] +name = "zenoh-protocol" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "const_format", + "rand", + "serde", + "uhlc", + "zenoh-buffers", + "zenoh-keyexpr", + "zenoh-result", +] + +[[package]] +name = "zenoh-result" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "anyhow", +] + +[[package]] +name = "zenoh-runtime" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "lazy_static", + "tokio", + "zenoh-collections", + "zenoh-result", +] + +[[package]] +name = "zenoh-shm" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "log", + "serde", + "shared_memory", + "zenoh-buffers", + "zenoh-result", +] + +[[package]] +name = "zenoh-sync" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "event-listener 4.0.3", + "futures", + "tokio", + "zenoh-buffers", + "zenoh-collections", + "zenoh-core", + "zenoh-runtime", +] + +[[package]] +name = "zenoh-transport" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "async-trait", + "flume", + "log", + "lz4_flex", + "paste", + "rand", + "ringbuffer-spsc", + "serde", + "sha3", + "tokio", + "tokio-util", + "zenoh-buffers", + "zenoh-codec", + "zenoh-collections", + "zenoh-config", + "zenoh-core", + "zenoh-crypto", + "zenoh-link", + "zenoh-protocol", + "zenoh-result", + "zenoh-runtime", + "zenoh-shm", + "zenoh-sync", + "zenoh-util", +] + +[[package]] +name = "zenoh-util" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#e04c8613d3c33472edcbde6fde5bd4beeb24f2bf" +dependencies = [ + "async-std", + "async-trait", + "flume", + "home", + "humantime", + "lazy_static", + "libc", + "libloading", + "log", + "pnet_datalink", + "shellexpand", + "tokio", + "winapi", + "zenoh-core", + "zenoh-result", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/build-resources/opaque-types/Cargo.toml b/build-resources/opaque-types/Cargo.toml new file mode 100644 index 000000000..6e8319bb0 --- /dev/null +++ b/build-resources/opaque-types/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "opaque-types" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# shared-memory enabled for zenoh even if zenoh-c "shared-memory" feature is disabled. This is to make "std::mem::transmute" work for `ZSLice` +zenoh = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["shared-memory", "unstable"], default-features = false } \ No newline at end of file diff --git a/build-resources/opaque-types/src/lib.rs b/build-resources/opaque-types/src/lib.rs new file mode 100644 index 000000000..8ef08035c --- /dev/null +++ b/build-resources/opaque-types/src/lib.rs @@ -0,0 +1,38 @@ +use zenoh::sample::Sample; +use zenoh::buffers::ZBuf; + +#[macro_export] +macro_rules! get_opaque_type_data { +($src_type:ty, $expr:expr) => { + const _: () = { + let align = std::mem::align_of::<$src_type>(); + let size = std::mem::size_of::<$src_type>(); + let mut msg: [u8; 61] = *b"type: , align: , size: "; + let mut i = 0; + while i < 4 { + msg[i as usize + 46] = b'0' + ((align / 10u32.pow(3 - i) as usize) % 10) as u8; + msg[i as usize + 57] = b'0' + ((size / 10u32.pow(3 - i) as usize) % 10) as u8; + i += 1; + } + let mut i: usize = 0; + while i < $expr.len() { + msg[i as usize + 5] = $expr.as_bytes()[i]; + i += 1; + } + panic!("{}", unsafe { + std::str::from_utf8_unchecked(msg.as_slice()) + }); + }; + } +} + +/// A split buffer that owns all of its data. +/// +/// To minimize copies and reallocations, Zenoh may provide you data in split buffers. +get_opaque_type_data!(Option, "z_owned_buffer_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`. +get_opaque_type_data!(Option, "zc_owned_sample_t"); \ No newline at end of file diff --git a/build.rs b/build.rs index 17dde1894..03a271817 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,5 @@ use fs2::FileExt; +use regex::Regex; use std::io::{Read, Write}; use std::{borrow::Cow, collections::HashMap, io::BufWriter, path::Path}; @@ -24,6 +25,7 @@ const HEADER: &str = r"// "; fn main() { + generate_opaque_types(); cbindgen::generate(std::env::var("CARGO_MANIFEST_DIR").unwrap()) .expect("Unable to generate bindings") .write_to_file(GENERATION_PATH); @@ -36,7 +38,60 @@ fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=src"); println!("cargo:rerun-if-changed=splitguide.yaml"); - println!("cargo:rerun-if-changed=cbindgen.toml") + println!("cargo:rerun-if-changed=cbindgen.toml"); + println!("cargo:rerun-if-changed=build-resources") +} + +fn generate_opaque_types() { + let current_folder = std::env::current_dir().unwrap(); + let path_in = current_folder.join("./.build_resources_opaque_types.txt"); + let path_out = current_folder.join("./src/opaque_types/mod.rs"); + + let data_in = std::fs::read_to_string(path_in).unwrap(); + let mut data_out = String::new(); + let docs = get_opaque_type_docs(); + + let re = Regex::new(r"type:(\w+) *, align:0*(\d+), size:0*(\d+)").unwrap(); + for (_, [type_name, align, size]) in re.captures_iter(&data_in).map(|c| c.extract()) { + let s = format!( + "#[repr(C, align({align}))] +pub struct {type_name} {{ + _0: [u8; {size}] +}} +" + ); + if let Some(doc) = docs.get(type_name) { + for d in doc { + data_out += d; + data_out += "\r\n"; + } + } + data_out += &s; + } + std::fs::write(path_out, data_out).unwrap(); +} + +fn get_opaque_type_docs() -> HashMap> { + let current_folder = std::env::current_dir().unwrap(); + let path_in = current_folder.join("./build-resources/opaque-types/src/lib.rs"); + let re = Regex::new(r#"get_opaque_type_data!\(.*, "(\w+)"\)"#).unwrap(); + let mut comments = std::vec::Vec::::new(); + let mut res = HashMap::>::new(); + + for line in std::fs::read_to_string(path_in).unwrap().lines() { + if line.starts_with("///") { + comments.push(line.to_string()); + continue; + } + if comments.is_empty() { + continue; + } + if let Some(c) = re.captures(line) { + res.insert(c[1].to_string(), comments.clone()); + } + comments.clear(); + } + res } fn configure() { diff --git a/examples/z_get.c b/examples/z_get.c index 853366210..e5a1de104 100644 --- a/examples/z_get.c +++ b/examples/z_get.c @@ -57,17 +57,18 @@ int main(int argc, char **argv) { z_owned_reply_channel_t channel = zc_reply_fifo_new(16); z_get_options_t opts = z_get_options_default(); if (value != NULL) { - opts.value.payload = z_bytes_from_str(value); + opts.value.payload = zc_payload_encode_from_string(value); } z_get(z_loan(s), keyexpr, "", z_move(channel.send), - &opts); // here, the send is moved and will be dropped by zenoh when adequate + z_move(opts)); // here, the send is moved and will be dropped by zenoh when adequate z_owned_reply_t reply = z_reply_null(); 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(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_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(&sample)); + printf(">> Received ('%s': '%s')\n", z_loan(keystr), z_loan(payload)); + z_drop(z_move(payload)); z_drop(z_move(keystr)); } else { printf("Received an error\n"); diff --git a/examples/z_non_blocking_get.c b/examples/z_non_blocking_get.c index a741d6071..21437199c 100644 --- a/examples/z_non_blocking_get.c +++ b/examples/z_non_blocking_get.c @@ -49,7 +49,7 @@ int main(int argc, char **argv) { opts.target = Z_QUERY_TARGET_ALL; z_owned_reply_channel_t channel = zc_reply_non_blocking_fifo_new(16); z_get(z_loan(s), keyexpr, "", z_move(channel.send), - &opts); // here, the send is moved and will be dropped by zenoh when adequate + z_move(opts)); // here, the send is moved and will be dropped by zenoh when adequate z_owned_reply_t reply = z_reply_null(); for (bool call_success = z_call(channel.recv, &reply); !call_success || z_check(reply); call_success = z_call(channel.recv, &reply)) { @@ -59,8 +59,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(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_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(&sample)); + printf(">> Received ('%s': '%s')\n", z_loan(keystr), z_loan(payload)); + z_drop(z_move(payload)); z_drop(z_move(keystr)); } else { printf("Received an error\n"); diff --git a/examples/z_ping.c b/examples/z_ping.c index fdc08f71d..a5c0954d0 100644 --- a/examples/z_ping.c +++ b/examples/z_ping.c @@ -54,6 +54,7 @@ int main(int argc, char** argv) { for (int i = 0; i < args.size; i++) { data[i] = i % 10; } + zc_owned_payload_t payload = zc_payload_encode_from_bytes((z_bytes_t){.start = data, .len = args.size}); z_mutex_lock(&mutex); if (args.warmup_ms) { printf("Warming up for %dms...\n", args.warmup_ms); @@ -61,7 +62,7 @@ int main(int argc, char** argv) { unsigned long elapsed_us = 0; while (elapsed_us < args.warmup_ms * 1000) { - z_publisher_put(z_loan(pub), data, args.size, NULL); + z_publisher_put(z_loan(pub), z_move(payload), NULL); int s = z_condvar_wait(&cond, &mutex); if (s != 0) { handle_error_en(s, "z_condvar_wait"); @@ -72,7 +73,7 @@ int main(int argc, char** argv) { unsigned long* results = z_malloc(sizeof(unsigned long) * args.number_of_pings); for (int i = 0; i < args.number_of_pings; i++) { z_clock_t measure_start = z_clock_now(); - z_publisher_put(z_loan(pub), data, args.size, NULL); + z_publisher_put(z_loan(pub), z_move(payload), NULL); int s = z_condvar_wait(&cond, &mutex); if (s != 0) { handle_error_en(s, "z_condvar_wait"); diff --git a/examples/z_pong.c b/examples/z_pong.c index 4047ff3d2..772280696 100644 --- a/examples/z_pong.c +++ b/examples/z_pong.c @@ -6,10 +6,8 @@ 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. - 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); + zc_owned_payload_t payload = z_sample_owned_payload(sample); + z_publisher_put(pub, z_move(payload), NULL); #endif } void drop(void* context) { diff --git a/examples/z_pub.c b/examples/z_pub.c index ecc95e42d..9dd496153 100644 --- a/examples/z_pub.c +++ b/examples/z_pub.c @@ -71,7 +71,8 @@ int main(int argc, char **argv) { printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); z_publisher_put_options_t options = z_publisher_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), &options); + zc_owned_payload_t payload = zc_payload_encode_from_string(buf); + z_publisher_put(z_loan(pub), z_move(payload), &options); } z_undeclare_publisher(z_move(pub)); diff --git a/examples/z_pub_attachment.c b/examples/z_pub_attachment.c index a24133e91..530d9dc29 100644 --- a/examples/z_pub_attachment.c +++ b/examples/z_pub_attachment.c @@ -71,7 +71,8 @@ int main(int argc, char **argv) { sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), &options); + zc_owned_payload_t payload = zc_payload_encode_from_string(buf); + z_publisher_put(z_loan(pub), z_move(payload), &options); } z_undeclare_publisher(z_move(pub)); diff --git a/examples/z_pub_cache.c b/examples/z_pub_cache.c index 770bf9d93..622896948 100644 --- a/examples/z_pub_cache.c +++ b/examples/z_pub_cache.c @@ -63,7 +63,8 @@ int main(int argc, char **argv) { z_sleep_s(1); sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)buf, strlen(buf), NULL); + zc_owned_payload_t payload = zc_payload_encode_from_string(buf); + z_put(z_loan(s), z_keyexpr(keyexpr), z_move(payload), NULL); } z_drop(z_move(pub_cache)); diff --git a/examples/z_pub_shm.c b/examples/z_pub_shm.c index 10970bf62..3c032e02f 100644 --- a/examples/z_pub_shm.c +++ b/examples/z_pub_shm.c @@ -84,7 +84,7 @@ int main(int argc, char **argv) { z_publisher_put_options_t options = z_publisher_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); zc_owned_payload_t payload = zc_shmbuf_into_payload(z_move(shmbuf)); - zc_publisher_put_owned(z_loan(pub), z_move(payload), &options); + z_publisher_put(z_loan(pub), z_move(payload), &options); } z_undeclare_publisher(z_move(pub)); diff --git a/examples/z_pub_thr.c b/examples/z_pub_thr.c index 8686c33eb..e0568973c 100644 --- a/examples/z_pub_thr.c +++ b/examples/z_pub_thr.c @@ -54,7 +54,8 @@ int main(int argc, char **argv) { } while (1) { - z_publisher_put(z_loan(pub), (const uint8_t *)value, len, NULL); + zc_owned_payload_t payload = zc_payload_encode_from_bytes((z_bytes_t){.start = value, .len = len}); + z_publisher_put(z_loan(pub), z_move(payload), NULL); } z_undeclare_publisher(z_move(pub)); diff --git a/examples/z_pull.c b/examples/z_pull.c index 4f2de7945..c7daf1172 100644 --- a/examples/z_pull.c +++ b/examples/z_pull.c @@ -18,9 +18,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(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_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + z_loan(payload)); + z_drop(z_move(payload)); z_drop(z_move(keystr)); } diff --git a/examples/z_put.c b/examples/z_put.c index 498d1e958..503fb5c36 100644 --- a/examples/z_put.c +++ b/examples/z_put.c @@ -48,7 +48,8 @@ int main(int argc, char **argv) { z_put_options_t options = z_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); options.attachment = z_bytes_map_as_attachment(&attachment); - int res = z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)value, strlen(value), &options); + zc_owned_payload_t payload = zc_payload_encode_from_string(value); + int res = z_put(z_loan(s), z_keyexpr(keyexpr), z_move(payload), &options); if (res < 0) { printf("Put failed...\n"); } diff --git a/examples/z_query_sub.c b/examples/z_query_sub.c index d60bc2bf1..a5b2ec1f9 100644 --- a/examples/z_query_sub.c +++ b/examples/z_query_sub.c @@ -18,9 +18,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(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_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + z_loan(payload)); + z_drop(z_move(payload)); z_drop(z_move(keystr)); } diff --git a/examples/z_queryable.c b/examples/z_queryable.c index 9d6ec7702..25d8a959d 100644 --- a/examples/z_queryable.c +++ b/examples/z_queryable.c @@ -22,10 +22,12 @@ z_keyexpr_t keyexpr; void query_handler(const z_query_t *query, void *context) { z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); z_bytes_t pred = z_query_parameters(query); - z_value_t payload_value = z_query_value(query); - if (payload_value.payload.len > 0) { - printf(">> [Queryable ] Received Query '%s?%.*s' with value '%.*s'\n", z_loan(keystr), (int)pred.len, - pred.start, (int)payload_value.payload.len, payload_value.payload.start); + zc_payload_t payload = z_query_value(query).payload; + if (zc_payload_len(payload) > 0) { + z_owned_str_t payload_string = zc_payload_decode_into_string(payload); + printf(">> [Queryable ] Received Query '%s?%.*s' with value '%s'\n", z_loan(keystr), (int)pred.len, + pred.start, z_loan(payload_string)); + z_drop(z_move(payload_string)); } else { printf(">> [Queryable ] Received Query '%s?%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); } diff --git a/examples/z_queryable_with_channels.c b/examples/z_queryable_with_channels.c index 672ddd607..dfef42532 100644 --- a/examples/z_queryable_with_channels.c +++ b/examples/z_queryable_with_channels.c @@ -68,10 +68,12 @@ int main(int argc, char **argv) { z_query_t query = z_loan(oquery); z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(&query)); z_bytes_t pred = z_query_parameters(&query); - z_value_t payload_value = z_query_value(&query); - if (payload_value.payload.len > 0) { - printf(">> [Queryable ] Received Query '%s?%.*s' with value '%.*s'\n", z_loan(keystr), (int)pred.len, - pred.start, (int)payload_value.payload.len, payload_value.payload.start); + zc_payload_t payload = z_query_value(&query).payload; + if (zc_payload_len(payload) > 0) { + z_owned_str_t payload_string = zc_payload_decode_into_string(payload); + printf(">> [Queryable ] Received Query '%s?%.*s' with value '%s'\n", z_loan(keystr), (int)pred.len, + pred.start, z_loan(payload_string)); + z_drop(z_move(payload_string)); } else { printf(">> [Queryable ] Received Query '%s?%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); } diff --git a/examples/z_sub.c b/examples/z_sub.c index 378a717e6..c7ea05c9a 100644 --- a/examples/z_sub.c +++ b/examples/z_sub.c @@ -18,9 +18,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(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_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + z_loan(payload)); + z_drop(z_move(payload)); z_drop(z_move(keystr)); } diff --git a/examples/z_sub_attachment.c b/examples/z_sub_attachment.c index 2031d1155..b3be1f672 100644 --- a/examples/z_sub_attachment.c +++ b/examples/z_sub_attachment.c @@ -24,9 +24,8 @@ 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(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_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), z_loan(payload)); z_attachment_t attachment = z_sample_attachment(sample); // checks if attachment exists @@ -40,6 +39,7 @@ void data_handler(const z_sample_t *sample, void *arg) { printf(" message number: %.*s\n", (int)index.len, index.start); } } + z_drop(z_move(payload)); z_drop(z_move(keystr)); } diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 55a52f82d..26c428c29 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -207,13 +207,9 @@ typedef struct z_attachment_t { * 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]; +typedef struct ALIGN(8) z_owned_buffer_t { + uint8_t _0[40]; } z_owned_buffer_t; /** * A loan of a `z_owned_buffer_t`. @@ -221,7 +217,7 @@ typedef struct 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; + struct z_owned_buffer_t *_inner; } z_buffer_t; /** * A map of maybe-owned vector of bytes to owned vector of bytes. @@ -617,7 +613,7 @@ typedef struct z_delete_options_t { * 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; + enum z_encoding_prefix_t prefix; struct z_bytes_t suffix; } z_encoding_t; /** @@ -634,7 +630,7 @@ typedef struct 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. */ typedef struct z_owned_encoding_t { - uint64_t prefix; + enum z_encoding_prefix_t prefix; struct z_bytes_t suffix; bool _dropped; } z_owned_encoding_t; @@ -645,16 +641,22 @@ typedef struct z_query_consolidation_t { enum z_consolidation_mode_t mode; } z_query_consolidation_t; /** - * A zenoh value. + * An owned payload, backed by a reference counted owner. + * + * The `payload` field may be modified, and Zenoh will take the new values into account. + */ +typedef struct z_owned_buffer_t zc_owned_payload_t; +/** + * An owned zenoh value. * * Members: - * z_bytes_t payload: The payload of this zenoh value. - * z_encoding_t encoding: The encoding of this zenoh value `payload`. + * zc_owned_payload_t payload: The payload of this zenoh value. + * z_owned_encoding_t encoding: The encoding of this zenoh value `payload`. */ -typedef struct z_value_t { - struct z_bytes_t payload; - struct z_encoding_t encoding; -} z_value_t; +typedef struct z_owned_value_t { + zc_owned_payload_t payload; + struct z_owned_encoding_t encoding; +} z_owned_value_t; /** * Options passed to the :c:func:`z_get` function. * @@ -668,7 +670,7 @@ typedef struct z_value_t { typedef struct z_get_options_t { enum z_query_target_t target; struct z_query_consolidation_t consolidation; - struct z_value_t value; + struct z_owned_value_t value; struct z_attachment_t attachment; uint64_t timeout_ms; } z_get_options_t; @@ -792,6 +794,18 @@ typedef struct z_query_reply_options_t { struct z_encoding_t encoding; struct z_attachment_t attachment; } z_query_reply_options_t; +typedef struct z_buffer_t zc_payload_t; +/** + * A zenoh value. + * + * Members: + * zc_payload_t payload: The payload of this zenoh value. + * z_encoding_t encoding: The encoding of this zenoh value `payload`. + */ +typedef struct z_value_t { + zc_payload_t payload; + struct z_encoding_t encoding; +} z_value_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. @@ -877,30 +891,14 @@ typedef struct zc_owned_liveliness_token_t { typedef struct zc_liveliness_get_options_t { uint32_t timeout_ms; } zc_liveliness_get_options_t; -/** - * An owned payload, backed by a reference counted owner. - * - * The `payload` field may be modified, and Zenoh will take the new values into account, - * however, assuming `ostart` and `olen` are the respective values of `payload.start` and - * `payload.len` when constructing the `zc_owned_payload_t payload` value was created, - * then `payload.start` MUST remain within the `[ostart, ostart + olen[` interval, and - * `payload.len` must remain within `[0, olen -(payload.start - ostart)]`. - * - * 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 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; - struct z_owned_buffer_t _2; - size_t _3[12]; +typedef struct ALIGN(8) zc_owned_sample_t { + uint8_t _0[224]; } zc_owned_sample_t; typedef struct zc_owned_shmbuf_t { size_t _0[9]; @@ -1083,19 +1081,16 @@ 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); +/** + * Returns total number bytes in the buffer. + */ +ZENOHC_API size_t z_buffer_len(struct z_buffer_t buffer); /** * Loans the buffer, allowing you to call functions that only need a loan of it. */ @@ -1104,12 +1099,6 @@ 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. * @@ -1119,10 +1108,9 @@ ZENOHC_API struct z_bytes_t z_buffer_slice_at(struct z_buffer_t buffer, size_t i /** * 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. + * If the return value is 0 or 1, then the buffer's data is contiguous in memory. */ -ZENOHC_API -size_t z_buffer_slice_count(struct z_buffer_t buffer); +ZENOHC_API size_t z_buffer_slice_count(struct z_buffer_t buffer); /** * Returns ``true`` if `b` is initialized. */ @@ -1581,7 +1569,7 @@ int8_t z_get(struct z_session_t session, struct z_keyexpr_t keyexpr, const char *parameters, struct z_owned_closure_reply_t *callback, - const struct z_get_options_t *options); + struct z_get_options_t *options); ZENOHC_API struct z_get_options_t z_get_options_default(void); /** * Returns ``true`` if `hello` is valid. @@ -1819,22 +1807,24 @@ ZENOHC_API struct z_owned_publisher_t z_publisher_null(void); */ ZENOHC_API struct z_publisher_options_t z_publisher_options_default(void); /** - * Sends a `PUT` message onto the publisher's key expression. + * Sends a `PUT` message onto the publisher's key expression, transfering the payload ownership. + * + * This is avoids copies when transfering data that was either: + * - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher + * - constructed from a `zc_owned_shmbuf_t` * * The payload's encoding can be sepcified through the options. * * Parameters: * session: The zenoh session. * payload: The value to put. - * len: The length of the value to put. * options: The publisher put options. * Returns: * ``0`` in case of success, negative values in case of failure. */ ZENOHC_API int8_t z_publisher_put(struct z_publisher_t publisher, - const uint8_t *payload, - size_t len, + zc_owned_payload_t *payload, const struct z_publisher_put_options_t *options); /** * Constructs the default value for :c:type:`z_publisher_put_options_t`. @@ -1858,7 +1848,11 @@ ZENOHC_API struct z_owned_pull_subscriber_t z_pull_subscriber_null(void); */ ZENOHC_API struct z_pull_subscriber_options_t z_pull_subscriber_options_default(void); /** - * Put data. + * Put data, transfering the buffer ownership. + * + * This is avoids copies when transfering data that was either: + * - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher + * - constructed from a `zc_owned_shmbuf_t` * * The payload's encoding can be sepcified through the options. * @@ -1866,7 +1860,6 @@ ZENOHC_API struct z_pull_subscriber_options_t z_pull_subscriber_options_default( * session: The zenoh session. * keyexpr: The key expression to put. * payload: The value to put. - * len: The length of the value to put. * options: The put options. * Returns: * ``0`` in case of success, negative values in case of failure. @@ -1874,8 +1867,7 @@ ZENOHC_API struct z_pull_subscriber_options_t z_pull_subscriber_options_default( ZENOHC_API int8_t z_put(struct z_session_t session, struct z_keyexpr_t keyexpr, - const uint8_t *payload, - size_t len, + zc_owned_payload_t *payload, const struct z_put_options_t *opts); /** * Constructs the default value for :c:type:`z_put_options_t`. @@ -2133,7 +2125,7 @@ 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); +ZENOHC_API struct z_buffer_t z_sample_payload(const struct z_sample_t *sample); /** * The qos with which the sample was received. */ @@ -2280,6 +2272,10 @@ ZENOHC_API int8_t z_undeclare_queryable(struct z_owned_queryable_t *qable); */ ZENOHC_API int8_t z_undeclare_subscriber(struct z_owned_subscriber_t *sub); +ZENOHC_API bool z_value_check(const struct z_owned_value_t *value); +ZENOHC_API void z_value_drop(struct z_owned_value_t *value); +ZENOHC_API struct z_value_t z_value_loan(const struct z_owned_value_t *value); +ZENOHC_API struct z_owned_value_t z_value_null(void); /** * Converts the kind of zenoh entity into a string. * @@ -2466,61 +2462,42 @@ 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 zc_owned_payload_t *payload); +/** + * Increments internal payload reference count, returning owned payload. + */ +ZENOHC_API zc_owned_payload_t zc_payload_clone(zc_payload_t payload); +/** + * Decodes payload into null-terminated string + */ +ZENOHC_API struct z_owned_str_t zc_payload_decode_into_string(zc_payload_t payload); /** * Decrements `payload`'s backing refcount, releasing the memory if appropriate. */ ZENOHC_API void zc_payload_drop(zc_owned_payload_t *payload); /** - * Constructs `zc_owned_payload_t`'s gravestone value. + * Encodes byte sequence by aliasing. */ -ZENOHC_API zc_owned_payload_t zc_payload_null(void); +ZENOHC_API zc_owned_payload_t zc_payload_encode_from_bytes(struct z_bytes_t bytes); /** - * Clones the `payload` by incrementing its reference counter. + * Encodes a null-terminated string by aliasing. */ -ZENOHC_API zc_owned_payload_t zc_payload_rcinc(const zc_owned_payload_t *payload); +ZENOHC_API zc_owned_payload_t zc_payload_encode_from_string(const char *cstr); /** - * Sends a `PUT` message onto the publisher's key expression, transfering the buffer ownership. - * - * This is avoids copies when transfering data that was either: - * - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher - * - constructed from a `zc_owned_shmbuf_t` - * - * The payload's encoding can be sepcified through the options. - * - * Parameters: - * session: The zenoh session. - * payload: The value to put. - * len: The length of the value to put. - * options: The publisher put options. - * Returns: - * ``0`` in case of success, negative values in case of failure. + * Returns total number bytes in the payload. */ -ZENOHC_API -int8_t zc_publisher_put_owned(struct z_publisher_t publisher, - zc_owned_payload_t *payload, - const struct z_publisher_put_options_t *options); +ZENOHC_API size_t zc_payload_len(zc_payload_t payload); /** - * Put data, transfering the buffer ownership. - * - * This is avoids copies when transfering data that was either: - * - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher - * - constructed from a `zc_owned_shmbuf_t` - * - * The payload's encoding can be sepcified through the options. - * - * Parameters: - * session: The zenoh session. - * keyexpr: The key expression to put. - * payload: The value to put. - * options: The put options. - * Returns: - * ``0`` in case of success, negative values in case of failure. + * Returns a :c:type:`zc_payload_t` loaned from `payload`. */ -ZENOHC_API -int8_t zc_put_owned(struct z_session_t session, - struct z_keyexpr_t keyexpr, - zc_owned_payload_t *payload, - const struct z_put_options_t *opts); +ZENOHC_API zc_payload_t zc_payload_loan(const zc_owned_payload_t *payload); +/** + * Constructs `zc_owned_payload_t`'s gravestone value. + */ +ZENOHC_API zc_owned_payload_t zc_payload_null(void); +/** + * Clones the `payload` by incrementing its reference counter. + */ +ZENOHC_API zc_owned_payload_t zc_payload_rcinc(const zc_owned_payload_t *payload); /** * Creates a new blocking fifo channel, returned as a pair of closures. * diff --git a/src/collections.rs b/src/collections.rs index 89c0e0438..e0f2e7afe 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -13,12 +13,14 @@ // use libc::{c_char, size_t}; +use std::ops::Deref; +use std::ptr::NonNull; use zenoh::{ buffers::{buffer::SplitBuffer, ZBuf}, prelude::ZenohId, }; -use crate::impl_guarded_transmute; +use crate::{impl_guarded_transmute, GuardedTransmute}; /// A contiguous view of bytes owned by some other entity. /// @@ -162,17 +164,7 @@ impl From<&[u8]> for z_bytes_t { } } -/// 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], -} +pub use crate::z_owned_buffer_t; impl_guarded_transmute!(noderefs Option, z_owned_buffer_t); impl Default for z_owned_buffer_t { fn default() -> Self { @@ -181,13 +173,10 @@ impl Default for z_owned_buffer_t { } 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)) } + Some(value).transmute() } } + impl From> for z_owned_buffer_t { fn from(value: Option) -> Self { match value { @@ -239,12 +228,18 @@ pub extern "C" fn z_buffer_loan(buffer: &z_owned_buffer_t) -> z_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> { - _inner: &'a (), +#[derive(Clone, Copy, Default)] +pub struct z_buffer_t { + _inner: Option>, } -impl_guarded_transmute!(Option<&'a ZBuf>, z_buffer_t<'a>, 'a); -impl<'a> From> for Option<&'a ZBuf> { + +impl From> for z_buffer_t { + fn from(value: Option<&ZBuf>) -> Self { + unsafe { core::mem::transmute(value) } + } +} + +impl From for Option<&'static ZBuf> { fn from(value: z_buffer_t) -> Self { unsafe { core::mem::transmute(value) } } @@ -253,45 +248,29 @@ 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 { - return z_bytes_null(); - }; - match buffer.contiguous() { - std::borrow::Cow::Borrowed(buffer) => buffer.into(), - std::borrow::Cow::Owned(_) => z_bytes_null(), + match buffer._inner { + Some(b) => unsafe { b.as_ref().deref().clone().transmute() }, + None => ZBuf::empty().into(), } } -/// Returns an owned version of this buffer whose data is guaranteed to be contiguous in memory. +/// Returns the number of slices in the buffer. /// -/// 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. +/// If the return value is 0 or 1, then the buffer's data is contiguous in memory. #[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(), +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 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. +/// Returns total number bytes in the buffer. #[no_mangle] -pub extern "C" fn z_buffer_slice_count(buffer: z_buffer_t) -> usize { +pub extern "C" fn z_buffer_len(buffer: z_buffer_t) -> usize { match buffer.into() { None => 0, - Some(buf) => ZBuf::slices(buf).len(), + Some(buf) => ZBuf::slices(buf).fold(0, |acc, s| acc + s.len()), } } diff --git a/src/commons.rs b/src/commons.rs index d23618846..249333d66 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -12,7 +12,9 @@ // ZettaScale Zenoh team, // +use std::any::Any; use std::ops::Deref; +use std::slice; use crate::collections::*; use crate::keyexpr::*; @@ -22,8 +24,10 @@ use crate::z_priority_t; use crate::{impl_guarded_transmute, GuardedTransmute}; use libc::c_void; use libc::{c_char, c_ulong}; +use zenoh::buffers::buffer::SplitBuffer; +use zenoh::buffers::ZBuf; +use zenoh::buffers::ZSliceBuffer; use zenoh::prelude::SampleKind; -use zenoh::prelude::SplitBuffer; use zenoh::query::ReplyKeyExpr; use zenoh::sample::Locality; use zenoh::sample::QoS; @@ -93,14 +97,7 @@ impl From> for z_timestamp_t { /// An owned payload, backed by a reference counted owner. /// -/// The `payload` field may be modified, and Zenoh will take the new values into account, -/// however, assuming `ostart` and `olen` are the respective values of `payload.start` and -/// `payload.len` when constructing the `zc_owned_payload_t payload` value was created, -/// then `payload.start` MUST remain within the `[ostart, ostart + olen[` interval, and -/// `payload.len` must remain within `[0, olen -(payload.start - ostart)]`. -/// -/// 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). +/// The `payload` field may be modified, and Zenoh will take the new values into account. #[allow(non_camel_case_types)] pub type zc_owned_payload_t = z_owned_buffer_t; @@ -125,6 +122,81 @@ pub extern "C" fn zc_payload_null() -> zc_owned_payload_t { z_buffer_null() } +/// Returns a :c:type:`zc_payload_t` loaned from `payload`. +#[no_mangle] +pub extern "C" fn zc_payload_loan(payload: &zc_owned_payload_t) -> zc_payload_t { + z_buffer_loan(payload) +} + +#[allow(non_camel_case_types)] +pub type zc_payload_t = z_buffer_t; + +/// Increments internal payload reference count, returning owned payload. +#[no_mangle] +pub extern "C" fn zc_payload_clone(payload: zc_payload_t) -> zc_owned_payload_t { + z_buffer_clone(payload) +} + +/// Decodes payload into null-terminated string +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_decode_into_string(payload: zc_payload_t) -> z_owned_str_t { + let payload: Option<&ZBuf> = payload.into(); + if payload.is_none() { + return z_str_null(); + } + let mut cstr = z_owned_str_t::preallocate(zc_payload_len(payload.into())); + let payload = payload.unwrap(); + + let mut pos = 0; + for s in payload.slices() { + cstr.insert_unchecked(pos, s); + pos += s.len(); + } + cstr +} + +unsafe impl Send for z_bytes_t {} +unsafe impl Sync for z_bytes_t {} + +impl ZSliceBuffer for z_bytes_t { + fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.start, self.len) } + } + fn as_mut_slice(&mut self) -> &mut [u8] { + unsafe { slice::from_raw_parts_mut(self.start as *mut u8, self.len) } + } + fn as_any(&self) -> &dyn Any { + self + } +} + +/// Encodes byte sequence by aliasing. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_encode_from_bytes(bytes: z_bytes_t) -> zc_owned_payload_t { + ZBuf::from(bytes).into() +} + +/// Encodes a null-terminated string by aliasing. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_encode_from_string( + cstr: *const libc::c_char, +) -> zc_owned_payload_t { + let bytes = z_bytes_t { + start: cstr as *const u8, + len: libc::strlen(cstr), + }; + zc_payload_encode_from_bytes(bytes) +} + +/// Returns total number bytes in the payload. +#[no_mangle] +pub extern "C" fn zc_payload_len(payload: zc_payload_t) -> usize { + z_buffer_len(payload) +} + /// QoS settings of zenoh message. /// #[repr(C)] @@ -191,8 +263,8 @@ pub extern "C" fn z_sample_encoding(sample: &z_sample_t) -> z_encoding_t { /// /// 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() +pub extern "C" fn z_sample_payload(sample: &z_sample_t) -> z_buffer_t { + Some(&sample.payload).into() } /// Returns the sample's payload after incrementing its internal reference count. /// @@ -231,18 +303,7 @@ 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, - _1: z_owned_buffer_t, - _2: z_owned_buffer_t, - _3: [usize; 12], -} - +pub use crate::zc_owned_sample_t; impl_guarded_transmute!(Option, zc_owned_sample_t); /// Clone a sample in the cheapest way available. @@ -422,24 +483,21 @@ impl From for z_encoding_prefix_t { #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct z_encoding_t { - pub prefix: u64, + pub prefix: z_encoding_prefix_t, 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 as u8).try_into().unwrap()) + zenoh_protocol::core::Encoding::Exact(enc.prefix.into()) } 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 as u8).try_into().unwrap(), - suffix.into(), - ) + zenoh_protocol::core::Encoding::WithSuffix(enc.prefix.into(), suffix.into()) } } } @@ -448,7 +506,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: u8::from(*val.prefix()) as u64, + prefix: (*val.prefix()).into(), suffix: z_bytes_t { start: suffix.as_ptr(), len: suffix.len(), @@ -470,7 +528,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: u64, + pub prefix: z_encoding_prefix_t, pub suffix: z_bytes_t, pub _dropped: bool, } @@ -478,7 +536,7 @@ pub struct z_owned_encoding_t { impl z_owned_encoding_t { pub fn null() -> Self { z_owned_encoding_t { - prefix: 0, + prefix: z_encoding_prefix_t::Empty, suffix: z_bytes_t::default(), _dropped: true, } @@ -506,10 +564,7 @@ pub unsafe extern "C" fn z_encoding( len: libc::strlen(suffix), } }; - z_encoding_t { - prefix: prefix as u64, - suffix, - } + z_encoding_t { prefix, suffix } } /// Constructs a default :c:type:`z_encoding_t`. @@ -562,13 +617,30 @@ pub struct z_owned_str_t { pub _cstr: *mut libc::c_char, } +impl z_owned_str_t { + #[allow(clippy::missing_safety_doc)] + pub unsafe fn preallocate(len: usize) -> z_owned_str_t { + let cstr = libc::malloc(len + 1) as *mut libc::c_char; + *cstr.add(len) = 0; + z_owned_str_t { _cstr: cstr } + } + + #[allow(clippy::missing_safety_doc)] + pub unsafe fn insert_unchecked(&mut self, start: usize, value: &[u8]) { + std::ptr::copy_nonoverlapping( + value.as_ptr(), + (self._cstr as *mut u8).add(start), + value.len(), + ); + } +} + impl From<&[u8]> for z_owned_str_t { fn from(value: &[u8]) -> Self { unsafe { - let cstr = libc::malloc(value.len() + 1) as *mut libc::c_char; - std::ptr::copy_nonoverlapping(value.as_ptr(), cstr as _, value.len()); - *cstr.add(value.len()) = 0; - z_owned_str_t { _cstr: cstr } + let mut cstr = Self::preallocate(value.len()); + cstr.insert_unchecked(0, value); + cstr } } } diff --git a/src/get.rs b/src/get.rs index bc37d7039..17ed9ccbe 100644 --- a/src/get.rs +++ b/src/get.rs @@ -15,14 +15,14 @@ use libc::c_char; use libc::c_void; use std::{ - borrow::Cow, convert::TryFrom, ffi::CStr, ops::{Deref, DerefMut}, }; +use zenoh::buffers::ZBuf; use zenoh::{ - prelude::{ConsolidationMode, KeyExpr, QueryTarget, SplitBuffer}, + prelude::{ConsolidationMode, KeyExpr, QueryTarget}, query::{Mode, QueryConsolidation, Reply}, sample::AttachmentBuilder, value::Value, @@ -33,10 +33,20 @@ use crate::attachment::{ insert_in_attachment_builder, z_attachment_check, z_attachment_iterate, z_attachment_null, z_attachment_t, }; +use crate::z_encoding_check; +use crate::z_encoding_drop; +use crate::z_encoding_loan; +use crate::z_encoding_null; +use crate::z_owned_encoding_t; +use crate::zc_owned_payload_t; +use crate::zc_payload_check; +use crate::zc_payload_drop; +use crate::zc_payload_loan; +use crate::zc_payload_null; +use crate::zc_payload_t; use crate::{ - impl_guarded_transmute, z_bytes_t, z_closure_reply_call, z_encoding_default, z_encoding_t, - z_keyexpr_t, z_owned_closure_reply_t, z_sample_t, z_session_t, GuardedTransmute, - LOG_INVALID_SESSION, + impl_guarded_transmute, z_closure_reply_call, z_encoding_t, z_keyexpr_t, + z_owned_closure_reply_t, z_sample_t, z_session_t, GuardedTransmute, LOG_INVALID_SESSION, }; type ReplyInner = Option; @@ -59,13 +69,7 @@ pub struct z_owned_reply_t([u64; 19]); impl_guarded_transmute!(noderefs ReplyInner, z_owned_reply_t); impl From for z_owned_reply_t { - fn from(mut val: ReplyInner) -> Self { - if let Some(val) = &mut val { - match &mut val.sample { - Ok(inner) => inner.payload = inner.payload.contiguous().into_owned().into(), - Err(inner) => inner.payload = inner.payload.contiguous().into_owned().into(), - }; - } + fn from(val: ReplyInner) -> Self { val.transmute() } } @@ -101,9 +105,6 @@ pub unsafe extern "C" fn z_reply_is_ok(reply: &z_owned_reply_t) -> bool { #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn z_reply_ok(reply: &z_owned_reply_t) -> z_sample_t { if let Some(sample) = reply.as_ref().and_then(|s| s.sample.as_ref().ok()) { - 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) } else { panic!("Assertion failed: tried to treat `z_owned_reply_t` as Ok despite that not being the case") @@ -113,14 +114,53 @@ pub unsafe extern "C" fn z_reply_ok(reply: &z_owned_reply_t) -> z_sample_t { /// A zenoh value. /// /// Members: -/// z_bytes_t payload: The payload of this zenoh value. +/// zc_payload_t payload: The payload of this zenoh value. /// z_encoding_t encoding: The encoding of this zenoh value `payload`. #[repr(C)] pub struct z_value_t { - pub payload: z_bytes_t, + pub payload: zc_payload_t, pub encoding: z_encoding_t, } +/// An owned zenoh value. +/// +/// Members: +/// zc_owned_payload_t payload: The payload of this zenoh value. +/// z_owned_encoding_t encoding: The encoding of this zenoh value `payload`. +#[repr(C)] +pub struct z_owned_value_t { + pub payload: zc_owned_payload_t, + pub encoding: z_owned_encoding_t, +} + +#[no_mangle] +pub extern "C" fn z_value_null() -> z_owned_value_t { + z_owned_value_t { + payload: zc_payload_null(), + encoding: z_encoding_null(), + } +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_value_drop(value: &mut z_owned_value_t) { + z_encoding_drop(&mut value.encoding); + zc_payload_drop(&mut value.payload); +} + +#[no_mangle] +pub extern "C" fn z_value_loan(value: &z_owned_value_t) -> z_value_t { + z_value_t { + payload: zc_payload_loan(&value.payload), + encoding: z_encoding_loan(&value.encoding), + } +} + +#[no_mangle] +pub extern "C" fn z_value_check(value: &z_owned_value_t) -> bool { + zc_payload_check(&value.payload) && z_encoding_check(&value.encoding) +} + /// Yields the contents of the reply by asserting it indicates a failure. /// /// You should always make sure that :c:func:`z_reply_is_ok` returns ``false`` before calling this function. @@ -129,10 +169,7 @@ pub struct z_value_t { pub unsafe extern "C" fn z_reply_err(reply: &z_owned_reply_t) -> z_value_t { if let Some(inner) = reply.as_ref().and_then(|s| s.sample.as_ref().err()) { z_value_t { - payload: match &inner.payload.contiguous() { - Cow::Borrowed(payload) => crate::z_bytes_t { start: payload.as_ptr(), len: payload.len() }, - Cow::Owned(_) => unreachable!("z_reply_err found a payload that wasn't contiguous by the time it was reached, which breaks some crate assertions."), - }, + payload: Some(&inner.payload).into(), encoding: (&inner.encoding).into(), } } else { @@ -165,7 +202,7 @@ pub extern "C" fn z_reply_null() -> z_owned_reply_t { pub struct z_get_options_t { pub target: z_query_target_t, pub consolidation: z_query_consolidation_t, - pub value: z_value_t, + pub value: z_owned_value_t, pub attachment: z_attachment_t, pub timeout_ms: u64, } @@ -175,12 +212,7 @@ pub extern "C" fn z_get_options_default() -> z_get_options_t { target: QueryTarget::default().into(), consolidation: QueryConsolidation::default().into(), timeout_ms: 0, - value: { - z_value_t { - payload: z_bytes_t::empty(), - encoding: z_encoding_default(), - } - }, + value: z_value_null(), attachment: z_attachment_null(), } } @@ -206,7 +238,7 @@ pub unsafe extern "C" fn z_get( keyexpr: z_keyexpr_t, parameters: *const c_char, callback: &mut z_owned_closure_reply_t, - options: Option<&z_get_options_t>, + options: Option<&mut z_get_options_t>, ) -> i8 { let mut closure = z_owned_closure_reply_t::empty(); std::mem::swap(callback, &mut closure); @@ -223,8 +255,25 @@ pub unsafe extern "C" fn z_get( if let Some(options) = options { q = q .consolidation(options.consolidation) - .target(options.target.into()) - .with_value(&options.value); + .target(options.target.into()); + + if let Some(payload) = options.value.payload.take() { + let mut value = Value::new(payload); + if z_encoding_check(&options.value.encoding) { + value = value.encoding(z_encoding_loan(&options.value.encoding).into()); + } + q = q.with_value(value); + } + z_encoding_drop(&mut options.value.encoding); + if zc_payload_check(&options.value.payload) { + let buf: ZBuf = options.value.payload.as_ref().unwrap().clone(); + let mut value = Value::new(buf); + if z_encoding_check(&options.value.encoding) { + value = value.encoding(z_encoding_loan(&options.value.encoding).into()); + } + q = q.with_value(value); + z_value_drop(&mut options.value); + } if options.timeout_ms != 0 { q = q.timeout(std::time::Duration::from_millis(options.timeout_ms)); } @@ -302,30 +351,29 @@ impl From for QueryTarget { impl From<&z_value_t> for Value { #[inline] fn from(val: &z_value_t) -> Value { - unsafe { - let value: Value = - std::slice::from_raw_parts(val.payload.start, val.payload.len).into(); - let encoding = std::str::from_utf8(std::slice::from_raw_parts( + let payload: Option<&ZBuf> = val.payload.into(); + let payload = match payload { + Some(b) => b.clone(), + None => ZBuf::empty(), + }; + let encoding = unsafe { + std::str::from_utf8(std::slice::from_raw_parts( val.encoding.suffix.start, val.encoding.suffix.len, )) - .expect("encodings must be UTF8"); - value.encoding( - zenoh::prelude::Encoding::new(val.encoding.prefix as u8, encoding).unwrap(), - ) - } + .expect("encodings must be UTF8") + }; + let v = Value::new(payload); + v.encoding(zenoh::prelude::Encoding::new(val.encoding.prefix as u8, encoding).unwrap()) } } impl From<&Value> for z_value_t { #[inline] fn from(val: &Value) -> z_value_t { - let std::borrow::Cow::Borrowed(payload) = val.payload.contiguous() else { - panic!("Would have returned a reference to a temporary, make sure you the Value's payload is contiguous BEFORE calling this constructor.") - }; z_value_t { encoding: (&val.encoding).into(), - payload: payload.into(), + payload: Some(&val.payload).into(), } } } diff --git a/src/lib.rs b/src/lib.rs index 5019a0713..96cc4bd76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,6 +55,8 @@ pub use querying_subscriber::*; pub mod attachment; pub use platform::*; pub mod platform; +pub use opaque_types::*; +pub mod opaque_types; #[cfg(feature = "shared-memory")] mod shm; diff --git a/src/liveliness.rs b/src/liveliness.rs index d66508cd5..b3c61a7de 100644 --- a/src/liveliness.rs +++ b/src/liveliness.rs @@ -14,7 +14,7 @@ use zenoh::{ liveliness::{Liveliness, LivelinessToken}, - prelude::{SessionDeclarations, SplitBuffer}, + prelude::SessionDeclarations, }; use zenoh_util::core::{zresult::ErrNo, SyncResolve}; @@ -176,10 +176,7 @@ pub extern "C" fn zc_liveliness_declare_subscriber( match session .liveliness() .declare_subscriber(key) - .callback(move |mut sample| { - if let std::borrow::Cow::Owned(v) = sample.payload.contiguous() { - sample.payload = v.into(); - } + .callback(move |sample| { let sample = z_sample_t::new(&sample); z_closure_sample_call(&callback, &sample) }) diff --git a/src/opaque_types/mod.rs b/src/opaque_types/mod.rs new file mode 100644 index 000000000..0327b0943 --- /dev/null +++ b/src/opaque_types/mod.rs @@ -0,0 +1,15 @@ +/// A split buffer that owns all of its data. +/// +/// To minimize copies and reallocations, Zenoh may provide you data in split buffers. +#[repr(C, align(8))] +pub struct z_owned_buffer_t { + _0: [u8; 40] +} +/// 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, align(8))] +pub struct zc_owned_sample_t { + _0: [u8; 224] +} diff --git a/src/publisher.rs b/src/publisher.rs index f49d8cd31..6647655bd 100644 --- a/src/publisher.rs +++ b/src/publisher.rs @@ -234,14 +234,17 @@ pub extern "C" fn z_publisher_put_options_default() -> z_publisher_put_options_t } } -/// Sends a `PUT` message onto the publisher's key expression. +/// Sends a `PUT` message onto the publisher's key expression, transfering the payload ownership. +/// +/// This is avoids copies when transfering data that was either: +/// - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher +/// - constructed from a `zc_owned_shmbuf_t` /// /// The payload's encoding can be sepcified through the options. /// /// Parameters: /// session: The zenoh session. /// payload: The value to put. -/// len: The length of the value to put. /// options: The publisher put options. /// Returns: /// ``0`` in case of success, negative values in case of failure. @@ -249,12 +252,15 @@ pub extern "C" fn z_publisher_put_options_default() -> z_publisher_put_options_t #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn z_publisher_put( publisher: z_publisher_t, - payload: *const u8, - len: usize, + payload: Option<&mut zc_owned_payload_t>, options: Option<&z_publisher_put_options_t>, ) -> i8 { if let Some(p) = publisher.as_ref() { - let value: Value = std::slice::from_raw_parts(payload, len).into(); + let Some(payload) = payload.and_then(|p| p.take()) else { + log::debug!("Attempted to put without a payload"); + return i8::MIN; + }; + let value: Value = payload.into(); let put = match options { Some(options) => { let mut put = p.put(value.encoding(options.encoding.into())); @@ -282,49 +288,6 @@ pub unsafe extern "C" fn z_publisher_put( } } -/// Sends a `PUT` message onto the publisher's key expression, transfering the buffer ownership. -/// -/// This is avoids copies when transfering data that was either: -/// - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher -/// - constructed from a `zc_owned_shmbuf_t` -/// -/// The payload's encoding can be sepcified through the options. -/// -/// Parameters: -/// session: The zenoh session. -/// payload: The value to put. -/// len: The length of the value to put. -/// options: The publisher put options. -/// Returns: -/// ``0`` in case of success, negative values in case of failure. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_publisher_put_owned( - publisher: z_publisher_t, - payload: Option<&mut zc_owned_payload_t>, - options: Option<&z_publisher_put_options_t>, -) -> i8 { - if let Some(p) = publisher.as_ref() { - let Some(payload) = payload.and_then(|p| p.take()) else { - log::debug!("Attempted to put without a payload"); - return i8::MIN; - }; - let value: Value = payload.into(); - let put = match options { - Some(options) => p.put(value.encoding(options.encoding.into())), - None => p.put(value), - }; - if let Err(e) = put.res_sync() { - log::error!("{}", e); - e.errno().get() - } else { - 0 - } - } else { - i8::MIN - } -} - /// Represents the set of options that can be applied to the delete operation by a previously declared publisher, /// whenever issued via :c:func:`z_publisher_delete`. #[repr(C)] diff --git a/src/pull_subscriber.rs b/src/pull_subscriber.rs index 247484cb1..ebef7064b 100644 --- a/src/pull_subscriber.rs +++ b/src/pull_subscriber.rs @@ -22,7 +22,6 @@ use crate::z_reliability_t; use crate::LOG_INVALID_SESSION; use zenoh::prelude::sync::SyncResolve; use zenoh::prelude::SessionDeclarations; -use zenoh::prelude::SplitBuffer; use zenoh_protocol::core::SubInfo; use zenoh_util::core::zresult::ErrNo; @@ -149,10 +148,7 @@ pub extern "C" fn z_declare_pull_subscriber( Some(s) => { 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(); - } + .callback(move |sample| { let sample = z_sample_t::new(&sample); z_closure_sample_call(&closure, &sample) }) diff --git a/src/put.rs b/src/put.rs index b5d9f2f94..5c8b8d807 100644 --- a/src/put.rs +++ b/src/put.rs @@ -16,7 +16,6 @@ use crate::keyexpr::*; use crate::session::*; use crate::LOG_INVALID_SESSION; use libc::c_void; -use libc::size_t; use zenoh::prelude::{sync::SyncResolve, Priority, SampleKind}; use zenoh::publication::CongestionControl; use zenoh::sample::AttachmentBuilder; @@ -135,62 +134,6 @@ pub extern "C" fn z_put_options_default() -> z_put_options_t { } } -/// Put data. -/// -/// The payload's encoding can be sepcified through the options. -/// -/// Parameters: -/// session: The zenoh session. -/// keyexpr: The key expression to put. -/// payload: The value to put. -/// len: The length of the value to put. -/// options: The put options. -/// Returns: -/// ``0`` in case of success, negative values in case of failure. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_put( - session: z_session_t, - keyexpr: z_keyexpr_t, - payload: *const u8, - len: size_t, - opts: Option<&z_put_options_t>, -) -> i8 { - match session.upgrade() { - Some(s) => { - let mut res = s - .put(keyexpr, std::slice::from_raw_parts(payload, len)) - .kind(SampleKind::Put); - if let Some(opts) = opts { - res = res - .encoding(opts.encoding) - .congestion_control(opts.congestion_control.into()) - .priority(opts.priority.into()); - if z_attachment_check(&opts.attachment) { - let mut attachment_builder = AttachmentBuilder::new(); - z_attachment_iterate( - opts.attachment, - insert_in_attachment_builder, - &mut attachment_builder as *mut AttachmentBuilder as *mut c_void, - ); - res = res.with_attachment(attachment_builder.build()); - }; - } - match res.res_sync() { - Err(e) => { - log::error!("{}", e); - e.errno().get() - } - Ok(()) => 0, - } - } - None => { - log::debug!("{}", LOG_INVALID_SESSION); - i8::MIN - } - } -} - /// Put data, transfering the buffer ownership. /// /// This is avoids copies when transfering data that was either: @@ -208,7 +151,7 @@ pub unsafe extern "C" fn z_put( /// ``0`` in case of success, negative values in case of failure. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn zc_put_owned( +pub extern "C" fn z_put( session: z_session_t, keyexpr: z_keyexpr_t, payload: Option<&mut zc_owned_payload_t>, @@ -223,6 +166,15 @@ pub extern "C" fn zc_put_owned( .encoding(opts.encoding) .congestion_control(opts.congestion_control.into()) .priority(opts.priority.into()); + if z_attachment_check(&opts.attachment) { + let mut attachment_builder = AttachmentBuilder::new(); + z_attachment_iterate( + opts.attachment, + insert_in_attachment_builder, + &mut attachment_builder as *mut AttachmentBuilder as *mut c_void, + ); + res = res.with_attachment(attachment_builder.build()); + }; } match res.res_sync() { Err(e) => { diff --git a/src/queryable.rs b/src/queryable.rs index 1906dc735..f5b647473 100644 --- a/src/queryable.rs +++ b/src/queryable.rs @@ -16,17 +16,17 @@ use crate::attachment::{ z_attachment_iterate, z_attachment_null, z_attachment_t, }; 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, LOG_INVALID_SESSION, + impl_guarded_transmute, z_buffer_t, 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, + LOG_INVALID_SESSION, }; use libc::c_void; use std::ops::{Deref, DerefMut}; use zenoh::prelude::SessionDeclarations; use zenoh::{ - prelude::{Sample, SplitBuffer}, + prelude::Sample, queryable::{Query, Queryable as CallbackQueryable}, sample::AttachmentBuilder, - value::Value, }; use zenoh_util::core::{zresult::ErrNo, SyncResolve}; @@ -346,14 +346,15 @@ pub extern "C" fn z_query_parameters(query: &z_query_t) -> z_bytes_t { #[no_mangle] pub unsafe extern "C" fn z_query_value(query: &z_query_t) -> z_value_t { match query.as_ref().and_then(|q| q.value()) { - Some(value) => { + Some(value) => + { #[allow(mutable_transmutes)] - if let std::borrow::Cow::Owned(payload) = value.payload.contiguous() { - unsafe { std::mem::transmute::<_, &mut Value>(value).payload = payload.into() } - } value.into() } - None => (&Value::empty()).into(), + None => z_value_t { + payload: z_buffer_t::default(), + encoding: z_encoding_default(), + }, } } diff --git a/src/querying_subscriber.rs b/src/querying_subscriber.rs index a4681b4e9..910f1b89b 100644 --- a/src/querying_subscriber.rs +++ b/src/querying_subscriber.rs @@ -15,7 +15,6 @@ use zenoh::prelude::sync::SyncResolve; use zenoh::prelude::KeyExpr; use zenoh::prelude::SessionDeclarations; -use zenoh::prelude::SplitBuffer; use zenoh_ext::*; use zenoh_protocol::core::SubInfo; use zenoh_util::core::zresult::ErrNo; @@ -185,10 +184,7 @@ pub unsafe extern "C" fn ze_declare_querying_subscriber( } } match sub - .callback(move |mut sample| { - if let std::borrow::Cow::Owned(v) = sample.payload.contiguous() { - sample.payload = v.into(); - } + .callback(move |sample| { let sample = z_sample_t::new(&sample); z_closure_sample_call(&closure, &sample) }) diff --git a/src/subscriber.rs b/src/subscriber.rs index 7d15e740a..d82086f7f 100644 --- a/src/subscriber.rs +++ b/src/subscriber.rs @@ -21,7 +21,6 @@ use crate::z_owned_closure_sample_t; use crate::LOG_INVALID_SESSION; use zenoh::prelude::sync::SyncResolve; use zenoh::prelude::SessionDeclarations; -use zenoh::prelude::SplitBuffer; use zenoh::subscriber::Reliability; use zenoh_protocol::core::SubInfo; use zenoh_util::core::zresult::ErrNo; @@ -179,10 +178,7 @@ pub extern "C" fn z_declare_subscriber( match session.upgrade() { Some(s) => { - 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 mut res = s.declare_subscriber(keyexpr).callback(move |sample| { let sample = z_sample_t::new(&sample); z_closure_sample_call(&closure, &sample) }); diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index 9ade440f3..49827e148 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -260,7 +260,8 @@ int main(int argc, char **argv) { z_encoding_t _ret_encoding = z_encoding_default(); _ret_encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); _ret_put_opt.encoding = _ret_encoding; - _ret_int8 = z_put(z_loan(s1), z_loan(_ret_expr), (const uint8_t *)value, strlen(value), &_ret_put_opt); + zc_owned_payload_t payload = zc_payload_encode_from_string(value); + _ret_int8 = z_put(z_loan(s1), z_loan(_ret_expr), z_move(payload), &_ret_put_opt); assert(_ret_int8 == 0); z_sleep_s(SLEEP); @@ -292,7 +293,8 @@ int main(int argc, char **argv) { assert(z_check(_ret_pub)); z_publisher_put_options_t _ret_pput_opt = z_publisher_put_options_default(); - _ret_int8 = z_publisher_put(z_loan(_ret_pub), (const uint8_t *)value, strlen(value), &_ret_pput_opt); + payload = zc_payload_encode_from_string(value); + _ret_int8 = z_publisher_put(z_loan(_ret_pub), z_move(payload), &_ret_pput_opt); assert(_ret_int8 == 0); z_sleep_s(SLEEP); diff --git a/tests/z_int_pub_cache_query_sub_test.c b/tests/z_int_pub_cache_query_sub_test.c index 868b3878e..789a00ffc 100644 --- a/tests/z_int_pub_cache_query_sub_test.c +++ b/tests/z_int_pub_cache_query_sub_test.c @@ -61,7 +61,8 @@ int run_publisher() { // values for cache for (int i = 0; i < values_count / 2; ++i) { - z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)values[i], strlen(values[i]), NULL); + zc_owned_payload_t payload = zc_payload_encode_from_string(values[i]); + z_put(z_loan(s), z_keyexpr(keyexpr), z_move(payload), NULL); } SEM_POST(sem_pub); @@ -70,7 +71,8 @@ int run_publisher() { // values for subscribe for (int i = values_count / 2; i < values_count; ++i) { - z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)values[i], strlen(values[i]), NULL); + zc_owned_payload_t payload = zc_payload_encode_from_string(values[i]); + z_put(z_loan(s), z_keyexpr(keyexpr), z_move(payload), NULL); } printf("wait: sem_sub\n"); @@ -91,8 +93,13 @@ void data_handler(const z_sample_t *sample, void *arg) { exit(-1); } z_drop(z_move(keystr)); - - ASSERT_STR_BYTES_EQUAL(values[val_num], z_sample_payload(sample)); + z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + if (strcmp(values[val_num], z_loan(payload))) { + perror("Unexpected value received"); + z_drop(z_move(payload)); + exit(-1); + } + z_drop(z_move(payload)); 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 bafdd87ca..a665ad19b 100644 --- a/tests/z_int_pub_sub_attachment_test.c +++ b/tests/z_int_pub_sub_attachment_test.c @@ -55,7 +55,8 @@ int run_publisher() { options.attachment = z_bytes_map_as_attachment(&map); for (int i = 0; i < values_count; ++i) { z_bytes_map_insert_by_copy(&map, z_bytes_from_str(K_VAR), z_bytes_from_str(values[i])); - z_publisher_put(z_loan(pub), (const uint8_t *)values[i], strlen(values[i]), &options); + zc_owned_payload_t payload = zc_payload_encode_from_string(values[i]); + z_publisher_put(z_loan(pub), z_move(payload), &options); } z_undeclare_publisher(z_move(pub)); @@ -73,11 +74,13 @@ void data_handler(const z_sample_t *sample, void *arg) { } z_drop(z_move(keystr)); - z_bytes_t payload = z_sample_payload(sample); - if (strncmp(values[val_num], (const char *)payload.start, (int)payload.len)) { + z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + if (strcmp(values[val_num], z_loan(payload))) { perror("Unexpected value received"); + z_drop(z_move(payload)); exit(-1); } + z_drop(z_move(payload)); 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); diff --git a/tests/z_int_pub_sub_test.c b/tests/z_int_pub_sub_test.c index 6e48fef5a..06d5c87ba 100644 --- a/tests/z_int_pub_sub_test.c +++ b/tests/z_int_pub_sub_test.c @@ -49,7 +49,8 @@ int run_publisher() { for (int i = 0; i < values_count; ++i) { z_publisher_put_options_t options = z_publisher_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_publisher_put(z_loan(pub), (const uint8_t *)values[i], strlen(values[i]), &options); + zc_owned_payload_t payload = zc_payload_encode_from_string(values[i]); + z_publisher_put(z_loan(pub), z_move(payload), &options); } z_undeclare_publisher(z_move(pub)); @@ -66,11 +67,13 @@ void data_handler(const z_sample_t *sample, void *arg) { } z_drop(z_move(keystr)); - z_bytes_t payload = z_sample_payload(sample); - if (strncmp(values[val_num], (const char *)payload.start, (int)payload.len)) { + z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + if (strcmp(values[val_num], z_loan(payload))) { perror("Unexpected value received"); + z_drop(z_move(payload)); exit(-1); } + z_drop(z_move(payload)); 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) { diff --git a/tests/z_int_queryable_attachment_test.c b/tests/z_int_queryable_attachment_test.c index 1de9de788..deb28658e 100644 --- a/tests/z_int_queryable_attachment_test.c +++ b/tests/z_int_queryable_attachment_test.c @@ -110,13 +110,18 @@ int run_get() { z_sample_t sample = z_reply_ok(&reply); z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(&sample)); - - ASSERT_STR_BYTES_EQUAL(values[val_num], z_sample_payload(&sample)); + z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(&sample)); + if (strcmp(values[val_num], z_loan(payload))) { + perror("Unexpected value received"); + z_drop(z_move(payload)); + exit(-1); + } 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)); + z_drop(z_move(payload)); } z_drop(z_move(reply)); z_drop(z_move(channel)); diff --git a/tests/z_int_queryable_test.c b/tests/z_int_queryable_test.c index 9bcc16cc1..dc587e292 100644 --- a/tests/z_int_queryable_test.c +++ b/tests/z_int_queryable_test.c @@ -86,10 +86,15 @@ int run_get() { z_sample_t sample = z_reply_ok(&reply); z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(&sample)); - - ASSERT_STR_BYTES_EQUAL(values[val_num], z_sample_payload(&sample)); + z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(&sample)); + if (strcmp(values[val_num], z_loan(payload))) { + perror("Unexpected value received"); + z_drop(z_move(payload)); + exit(-1); + } z_drop(z_move(keystr)); + z_drop(z_move(payload)); } z_drop(z_move(reply)); z_drop(z_move(channel)); From ed3a164b56b0e55fc17d0826c3aa12bdaf89450e Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Wed, 3 Apr 2024 22:49:47 +0200 Subject: [PATCH 17/30] reply with owned payload --- examples/z_queryable.c | 3 +- examples/z_queryable_with_channels.c | 3 +- include/zenoh_commons.h | 4 +-- src/queryable.rs | 48 ++++++++++++------------- tests/z_api_alignment_test.c | 3 +- tests/z_int_queryable_attachment_test.c | 4 +-- tests/z_int_queryable_test.c | 4 +-- 7 files changed, 33 insertions(+), 36 deletions(-) diff --git a/examples/z_queryable.c b/examples/z_queryable.c index 25d8a959d..5c4ef6dfb 100644 --- a/examples/z_queryable.c +++ b/examples/z_queryable.c @@ -33,7 +33,8 @@ void query_handler(const z_query_t *query, void *context) { } z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(query, z_keyexpr((const char *)context), (const unsigned char *)value, strlen(value), &options); + zc_owned_payload_t reply_payload = zc_payload_encode_from_string(value); + z_query_reply(query, z_keyexpr((const char *)context), z_move(reply_payload), &options); z_drop(z_move(keystr)); } diff --git a/examples/z_queryable_with_channels.c b/examples/z_queryable_with_channels.c index dfef42532..e68577d2e 100644 --- a/examples/z_queryable_with_channels.c +++ b/examples/z_queryable_with_channels.c @@ -79,7 +79,8 @@ int main(int argc, char **argv) { } z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(&query, keyexpr, (const unsigned char *)value, strlen(value), &options); + zc_owned_payload_t reply_payload = zc_payload_encode_from_string(value); + z_query_reply(&query, keyexpr, z_move(reply_payload), &options); z_drop(z_move(keystr)); z_drop(z_move(oquery)); } diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 26c428c29..a24a9c0b4 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -1994,14 +1994,12 @@ struct z_bytes_t z_query_parameters(const struct z_query_t *query); * query: The query to reply to. * key: The key of this reply. * payload: The value of this reply. - * len: The length of the value of this reply. * options: The options of this reply. */ ZENOHC_API int8_t z_query_reply(const struct z_query_t *query, struct z_keyexpr_t key, - const uint8_t *payload, - size_t len, + zc_owned_payload_t *payload, const struct z_query_reply_options_t *options); /** * Constructs the default value for :c:type:`z_query_reply_options_t`. diff --git a/src/queryable.rs b/src/queryable.rs index f5b647473..c55820227 100644 --- a/src/queryable.rs +++ b/src/queryable.rs @@ -17,7 +17,7 @@ use crate::attachment::{ }; use crate::{ impl_guarded_transmute, z_buffer_t, 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, + z_encoding_t, z_keyexpr_t, z_owned_closure_query_t, z_session_t, z_value_t, zc_owned_payload_t, LOG_INVALID_SESSION, }; use libc::c_void; @@ -273,15 +273,13 @@ pub extern "C" fn z_queryable_check(qable: &z_owned_queryable_t) -> bool { /// query: The query to reply to. /// key: The key of this reply. /// payload: The value of this reply. -/// len: The length of the value of this reply. /// options: The options of this reply. #[allow(clippy::missing_safety_doc)] #[no_mangle] pub unsafe extern "C" fn z_query_reply( query: &z_query_t, key: z_keyexpr_t, - payload: *const u8, - len: usize, + payload: Option<&mut zc_owned_payload_t>, options: Option<&z_query_reply_options_t>, ) -> i8 { let Some(query) = query.as_ref() else { @@ -289,30 +287,28 @@ pub unsafe extern "C" fn z_query_reply( return i8::MIN; }; if let Some(key) = &*key { - let mut s = Sample::new( - key.clone().into_owned(), - std::slice::from_raw_parts(payload, len), - ); - if let Some(o) = options { - s.encoding = o.encoding.into(); - if z_attachment_check(&o.attachment) { - let mut attachment_builder = AttachmentBuilder::new(); - z_attachment_iterate( - o.attachment, - insert_in_attachment_builder, - &mut attachment_builder as *mut AttachmentBuilder as *mut c_void, - ); - s = s.with_attachment(attachment_builder.build()); - }; + if let Some(payload) = payload.and_then(|p| p.take()) { + let mut s = Sample::new(key.clone().into_owned(), payload); + if let Some(o) = options { + s.encoding = o.encoding.into(); + if z_attachment_check(&o.attachment) { + let mut attachment_builder = AttachmentBuilder::new(); + z_attachment_iterate( + o.attachment, + insert_in_attachment_builder, + &mut attachment_builder as *mut AttachmentBuilder as *mut c_void, + ); + s = s.with_attachment(attachment_builder.build()); + }; + } + if let Err(e) = query.reply(Ok(s)).res_sync() { + log::error!("{}", e); + return e.errno().get(); + } + return 0; } - if let Err(e) = query.reply(Ok(s)).res_sync() { - log::error!("{}", e); - return e.errno().get(); - } - 0 - } else { - i8::MIN } + i8::MIN } /// Get a query's key by aliasing it. diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index 49827e148..e7b72ef96 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -56,7 +56,8 @@ void query_handler(const z_query_t *query, void *arg) { z_value_t payload_value = z_query_value(query); (void)(payload_value); z_query_reply_options_t _ret_qreply_opt = z_query_reply_options_default(); - z_query_reply(query, z_keyexpr(z_loan(k_str)), (const uint8_t *)value, strlen(value), &_ret_qreply_opt); + zc_owned_payload_t payload = zc_payload_encode_from_string(value); + z_query_reply(query, z_keyexpr(z_loan(k_str)), z_move(payload), &_ret_qreply_opt); z_drop(z_move(k_str)); } diff --git a/tests/z_int_queryable_attachment_test.c b/tests/z_int_queryable_attachment_test.c index deb28658e..26645ad29 100644 --- a/tests/z_int_queryable_attachment_test.c +++ b/tests/z_int_queryable_attachment_test.c @@ -50,8 +50,8 @@ void query_handler(const z_query_t *query, void *context) { z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); options.attachment = z_bytes_map_as_attachment(&map); - z_query_reply(query, z_keyexpr((const char *)context), (const uint8_t *)values[value_num], - strlen(values[value_num]), &options); + zc_owned_payload_t payload = zc_payload_encode_from_string(values[value_num]); + z_query_reply(query, z_keyexpr((const char *)context), z_move(payload), &options); z_drop(z_move(keystr)); z_drop(z_move(map)); diff --git a/tests/z_int_queryable_test.c b/tests/z_int_queryable_test.c index dc587e292..7cc7f3bfc 100644 --- a/tests/z_int_queryable_test.c +++ b/tests/z_int_queryable_test.c @@ -34,8 +34,8 @@ void query_handler(const z_query_t *query, void *context) { z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(query, z_keyexpr((const char *)context), (const uint8_t *)values[value_num], - strlen(values[value_num]), &options); + zc_owned_payload_t payload = zc_payload_encode_from_string(values[value_num]); + z_query_reply(query, z_keyexpr((const char *)context), z_move(payload), &options); z_drop(z_move(keystr)); if (++value_num == values_count) { From 6d005bb1e86eebc48a2f5eab187c448345d103eb Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Thu, 4 Apr 2024 23:38:42 +0200 Subject: [PATCH 18/30] modified payload decoding functions to return error and take value by pointer --- examples/z_get.c | 9 ++- examples/z_non_blocking_get.c | 7 +- examples/z_pull.c | 7 +- examples/z_query_sub.c | 7 +- examples/z_queryable.c | 8 +- examples/z_queryable_with_channels.c | 7 +- examples/z_sub.c | 7 +- examples/z_sub_attachment.c | 10 ++- include/zenoh_commons.h | 52 +++++++------ include/zenoh_macros.h | 4 +- src/attachment.rs | 10 +-- src/collections.rs | 99 ++++++++++++++++++++++--- src/commons.rs | 40 ++++++++-- src/get.rs | 70 ++--------------- tests/z_int_pub_cache_query_sub_test.c | 9 ++- tests/z_int_pub_sub_attachment_test.c | 9 ++- tests/z_int_pub_sub_test.c | 9 ++- tests/z_int_queryable_attachment_test.c | 9 ++- tests/z_int_queryable_test.c | 9 ++- 19 files changed, 223 insertions(+), 159 deletions(-) diff --git a/examples/z_get.c b/examples/z_get.c index e5a1de104..9866212f7 100644 --- a/examples/z_get.c +++ b/examples/z_get.c @@ -57,18 +57,19 @@ int main(int argc, char **argv) { z_owned_reply_channel_t channel = zc_reply_fifo_new(16); z_get_options_t opts = z_get_options_default(); if (value != NULL) { - opts.value.payload = zc_payload_encode_from_string(value); + opts.payload = zc_payload_encode_from_string(value); } z_get(z_loan(s), keyexpr, "", z_move(channel.send), z_move(opts)); // here, the send is moved and will be dropped by zenoh when adequate z_owned_reply_t reply = z_reply_null(); + z_owned_str_t payload_value = z_str_null(); 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(z_sample_keyexpr(&sample)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(&sample)); - printf(">> Received ('%s': '%s')\n", z_loan(keystr), z_loan(payload)); - z_drop(z_move(payload)); + zc_payload_decode_into_string(z_sample_payload(&sample), &payload_value); + printf(">> Received ('%s': '%s')\n", z_loan(keystr), z_loan(payload_value)); + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } else { printf("Received an error\n"); diff --git a/examples/z_non_blocking_get.c b/examples/z_non_blocking_get.c index 21437199c..471f7e227 100644 --- a/examples/z_non_blocking_get.c +++ b/examples/z_non_blocking_get.c @@ -51,6 +51,7 @@ int main(int argc, char **argv) { z_get(z_loan(s), keyexpr, "", z_move(channel.send), z_move(opts)); // here, the send is moved and will be dropped by zenoh when adequate z_owned_reply_t reply = z_reply_null(); + z_owned_str_t payload_value = z_str_null(); for (bool call_success = z_call(channel.recv, &reply); !call_success || z_check(reply); call_success = z_call(channel.recv, &reply)) { if (!call_success) { @@ -59,9 +60,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(z_sample_keyexpr(&sample)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(&sample)); - printf(">> Received ('%s': '%s')\n", z_loan(keystr), z_loan(payload)); - z_drop(z_move(payload)); + zc_payload_decode_into_string(z_sample_payload(&sample), &payload_value); + printf(">> Received ('%s': '%s')\n", z_loan(keystr), z_loan(payload_value)); + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } else { printf("Received an error\n"); diff --git a/examples/z_pull.c b/examples/z_pull.c index c7daf1172..094dc0a6b 100644 --- a/examples/z_pull.c +++ b/examples/z_pull.c @@ -18,10 +18,11 @@ 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(z_sample_keyexpr(sample)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(z_sample_payload(sample), &payload_value); printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), - z_loan(payload)); - z_drop(z_move(payload)); + z_loan(payload_value)); + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } diff --git a/examples/z_query_sub.c b/examples/z_query_sub.c index a5b2ec1f9..620dd9594 100644 --- a/examples/z_query_sub.c +++ b/examples/z_query_sub.c @@ -18,10 +18,11 @@ 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(z_sample_keyexpr(sample)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(z_sample_payload(sample), &payload_value); printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), - z_loan(payload)); - z_drop(z_move(payload)); + z_loan(payload_value)); + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } diff --git a/examples/z_queryable.c b/examples/z_queryable.c index 5c4ef6dfb..577ef146e 100644 --- a/examples/z_queryable.c +++ b/examples/z_queryable.c @@ -24,15 +24,17 @@ void query_handler(const z_query_t *query, void *context) { z_bytes_t pred = z_query_parameters(query); zc_payload_t payload = z_query_value(query).payload; if (zc_payload_len(payload) > 0) { - z_owned_str_t payload_string = zc_payload_decode_into_string(payload); + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(payload, &payload_value); printf(">> [Queryable ] Received Query '%s?%.*s' with value '%s'\n", z_loan(keystr), (int)pred.len, - pred.start, z_loan(payload_string)); - z_drop(z_move(payload_string)); + pred.start, z_loan(payload_value)); + z_drop(z_move(payload_value)); } else { printf(">> [Queryable ] Received Query '%s?%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); } z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); + zc_owned_payload_t reply_payload = zc_payload_encode_from_string(value); z_query_reply(query, z_keyexpr((const char *)context), z_move(reply_payload), &options); z_drop(z_move(keystr)); diff --git a/examples/z_queryable_with_channels.c b/examples/z_queryable_with_channels.c index e68577d2e..6c3ca0df1 100644 --- a/examples/z_queryable_with_channels.c +++ b/examples/z_queryable_with_channels.c @@ -70,10 +70,11 @@ int main(int argc, char **argv) { z_bytes_t pred = z_query_parameters(&query); zc_payload_t payload = z_query_value(&query).payload; if (zc_payload_len(payload) > 0) { - z_owned_str_t payload_string = zc_payload_decode_into_string(payload); + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(payload, &payload_value); printf(">> [Queryable ] Received Query '%s?%.*s' with value '%s'\n", z_loan(keystr), (int)pred.len, - pred.start, z_loan(payload_string)); - z_drop(z_move(payload_string)); + pred.start, z_loan(payload_value)); + z_drop(z_move(payload_value)); } else { printf(">> [Queryable ] Received Query '%s?%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); } diff --git a/examples/z_sub.c b/examples/z_sub.c index c7ea05c9a..ffa63703b 100644 --- a/examples/z_sub.c +++ b/examples/z_sub.c @@ -18,10 +18,11 @@ 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(z_sample_keyexpr(sample)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(z_sample_payload(sample), &payload_value); printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), - z_loan(payload)); - z_drop(z_move(payload)); + z_loan(payload_value)); + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } diff --git a/examples/z_sub_attachment.c b/examples/z_sub_attachment.c index b3be1f672..b703e6ad6 100644 --- a/examples/z_sub_attachment.c +++ b/examples/z_sub_attachment.c @@ -24,8 +24,10 @@ 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(z_sample_keyexpr(sample)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); - printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), z_loan(payload)); + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(z_sample_payload(sample), &payload_value); + printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + z_loan(payload_value)); z_attachment_t attachment = z_sample_attachment(sample); // checks if attachment exists @@ -35,11 +37,11 @@ void data_handler(const z_sample_t *sample, void *arg) { // reads particular attachment item z_bytes_t index = z_attachment_get(attachment, z_bytes_from_str("index")); - if (z_check(index)) { + if (z_bytes_is_initialized(&index)) { printf(" message number: %.*s\n", (int)index.len, index.start); } } - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index a24a9c0b4..fe2b58959 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -219,6 +219,10 @@ typedef struct ALIGN(8) z_owned_buffer_t { typedef struct z_buffer_t { struct z_owned_buffer_t *_inner; } z_buffer_t; +typedef struct z_owned_bytes_t { + uint8_t *start; + size_t len; +} z_owned_bytes_t; /** * A map of maybe-owned vector of bytes to owned vector of bytes. * @@ -631,7 +635,7 @@ typedef struct z_encoding_t { */ typedef struct z_owned_encoding_t { enum z_encoding_prefix_t prefix; - struct z_bytes_t suffix; + struct z_owned_bytes_t suffix; bool _dropped; } z_owned_encoding_t; /** @@ -646,17 +650,6 @@ typedef struct z_query_consolidation_t { * The `payload` field may be modified, and Zenoh will take the new values into account. */ typedef struct z_owned_buffer_t zc_owned_payload_t; -/** - * An owned zenoh value. - * - * Members: - * zc_owned_payload_t payload: The payload of this zenoh value. - * z_owned_encoding_t encoding: The encoding of this zenoh value `payload`. - */ -typedef struct z_owned_value_t { - zc_owned_payload_t payload; - struct z_owned_encoding_t encoding; -} z_owned_value_t; /** * Options passed to the :c:func:`z_get` function. * @@ -670,7 +663,8 @@ typedef struct z_owned_value_t { typedef struct z_get_options_t { enum z_query_target_t target; struct z_query_consolidation_t consolidation; - struct z_owned_value_t value; + zc_owned_payload_t payload; + struct z_encoding_t encoding; struct z_attachment_t attachment; uint64_t timeout_ms; } z_get_options_t; @@ -1102,7 +1096,7 @@ ZENOHC_API struct z_owned_buffer_t z_buffer_null(void); /** * Returns the `index`th slice of the buffer, aliasing it. * - * Out of bounds accesses will return `z_bytes_null`. + * Out of bounds accesses will return `z_bytes_empty`. */ ZENOHC_API struct z_bytes_t z_buffer_slice_at(struct z_buffer_t buffer, size_t index); /** @@ -1114,13 +1108,23 @@ ZENOHC_API size_t z_buffer_slice_count(struct z_buffer_t buffer); /** * Returns ``true`` if `b` is initialized. */ -ZENOHC_API bool z_bytes_check(const struct z_bytes_t *b); +ZENOHC_API bool z_bytes_check(const struct z_owned_bytes_t *b); +ZENOHC_API struct z_owned_bytes_t z_bytes_clone(const struct z_bytes_t *b); +/** + * Returns the gravestone value for `z_bytes_t` + */ +ZENOHC_API struct z_bytes_t z_bytes_empty(void); /** * Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). * - * `str == NULL` will cause this to return `z_bytes_null()` + * `str == NULL` will cause this to return `z_bytes_empty()` */ ZENOHC_API struct z_bytes_t z_bytes_from_str(const char *str); +/** + * Returns ``true`` if `b` is initialized. + */ +ZENOHC_API bool z_bytes_is_initialized(const struct z_bytes_t *b); +ZENOHC_API struct z_bytes_t z_bytes_loan(const struct z_owned_bytes_t *b); /** * Aliases `this` into a generic `z_attachment_t`, allowing it to be passed to corresponding APIs. */ @@ -1211,14 +1215,14 @@ ZENOHC_API struct z_owned_bytes_map_t z_bytes_map_null(void); /** * Deprecated in favor of `z_bytes_from_str`: Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). * - * `str == NULL` will cause this to return `z_bytes_null()` + * `str == NULL` will cause this to return `z_bytes_empty()` */ ZENOHC_API struct z_bytes_t z_bytes_new(const char *str); /** - * Returns the gravestone value for `z_bytes_t` + * Returns the gravestone value for `z_owned_bytes_t` */ -ZENOHC_API struct z_bytes_t z_bytes_null(void); +ZENOHC_API struct z_owned_bytes_t z_bytes_null(void); /** * Constructs a `len` bytes long view starting at `start`. */ @@ -2270,10 +2274,6 @@ ZENOHC_API int8_t z_undeclare_queryable(struct z_owned_queryable_t *qable); */ ZENOHC_API int8_t z_undeclare_subscriber(struct z_owned_subscriber_t *sub); -ZENOHC_API bool z_value_check(const struct z_owned_value_t *value); -ZENOHC_API void z_value_drop(struct z_owned_value_t *value); -ZENOHC_API struct z_value_t z_value_loan(const struct z_owned_value_t *value); -ZENOHC_API struct z_owned_value_t z_value_null(void); /** * Converts the kind of zenoh entity into a string. * @@ -2467,7 +2467,11 @@ ZENOHC_API zc_owned_payload_t zc_payload_clone(zc_payload_t payload); /** * Decodes payload into null-terminated string */ -ZENOHC_API struct z_owned_str_t zc_payload_decode_into_string(zc_payload_t payload); +ZENOHC_API int8_t zc_payload_decode_into_bytes(zc_payload_t payload, struct z_owned_bytes_t *b); +/** + * Decodes payload into null-terminated string + */ +ZENOHC_API int8_t zc_payload_decode_into_string(zc_payload_t payload, struct z_owned_str_t *cstr); /** * Decrements `payload`'s backing refcount, releasing the memory if appropriate. */ diff --git a/include/zenoh_macros.h b/include/zenoh_macros.h index dba68f29a..bb50476a5 100644 --- a/include/zenoh_macros.h +++ b/include/zenoh_macros.h @@ -89,7 +89,7 @@ z_keyexpr_t : z_keyexpr_is_initialized, \ z_owned_config_t : z_config_check, \ z_owned_scouting_config_t : z_scouting_config_check, \ - z_bytes_t : z_bytes_check, \ + z_owned_bytes_t : z_bytes_check, \ z_owned_subscriber_t : z_subscriber_check, \ z_owned_pull_subscriber_t : z_pull_subscriber_check, \ z_owned_queryable_t : z_queryable_check, \ @@ -257,7 +257,7 @@ inline bool z_check(const z_owned_keyexpr_t& v) { return z_keyexpr_check(&v); } inline bool z_check(const z_keyexpr_t& v) { return z_keyexpr_is_initialized(&v); } inline bool z_check(const z_owned_config_t& v) { return z_config_check(&v); } inline bool z_check(const z_owned_scouting_config_t& v) { return z_scouting_config_check(&v); } -inline bool z_check(const z_bytes_t& v) { return z_bytes_check(&v); } +inline bool z_check(const z_owned_bytes_t& v) { return z_bytes_check(&v); } inline bool z_check(const zc_owned_payload_t& v) { return zc_payload_check(&v); } inline bool z_check(const zc_owned_shmbuf_t& v) { return zc_shmbuf_check(&v); } inline bool z_check(const zc_owned_shm_manager_t& v) { return zc_shm_manager_check(&v); } diff --git a/src/attachment.rs b/src/attachment.rs index 7b456a9c1..045596c47 100644 --- a/src/attachment.rs +++ b/src/attachment.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, cell::UnsafeCell, collections::HashMap}; use libc::c_void; -use crate::{impl_guarded_transmute, z_bytes_null, z_bytes_t}; +use crate::{impl_guarded_transmute, z_bytes_empty, z_bytes_t}; use zenoh::sample::{Attachment, AttachmentBuilder}; @@ -101,7 +101,7 @@ pub extern "C" fn z_attachment_get(this: z_attachment_t, key: z_bytes_t) -> z_by let mut context = attachment_get_iterator_context { key, - value: z_bytes_null(), + value: z_bytes_empty(), }; if this.iteration_driver.map_or(false, |iteration_driver| { @@ -113,7 +113,7 @@ pub extern "C" fn z_attachment_get(this: z_attachment_t, key: z_bytes_t) -> z_by }) { context.value } else { - z_bytes_null() + z_bytes_empty() } } @@ -237,12 +237,12 @@ pub extern "C" fn z_bytes_map_is_empty(this: &mut z_owned_bytes_map_t) -> bool { pub extern "C" fn z_bytes_map_get(this: &z_owned_bytes_map_t, key: z_bytes_t) -> z_bytes_t { let this = unsafe { &*this.get() }; let (Some(this), Some(key)) = (this.as_ref(), key.as_slice()) else { - return z_bytes_null(); + return z_bytes_empty(); }; if let Some(value) = this.get(key) { value.as_ref().into() } else { - z_bytes_null() + z_bytes_empty() } } diff --git a/src/collections.rs b/src/collections.rs index e0f2e7afe..2990f1a3a 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -54,15 +54,58 @@ impl Default for z_bytes_t { } } +#[repr(C)] +#[derive(Clone, Debug)] +pub struct z_owned_bytes_t { + pub start: *mut u8, + pub len: size_t, +} + +impl Drop for z_owned_bytes_t { + fn drop(&mut self) { + unsafe { z_bytes_drop(self) } + } +} + +impl z_owned_bytes_t { + pub fn new(data: &[u8]) ->z_owned_bytes_t { + if data.len() == 0 { + return z_bytes_null(); + } + let data = data.to_vec().into_boxed_slice(); + z_owned_bytes_t { + len: data.len(), + start: Box::leak(data).as_mut_ptr(), + } + } + + pub fn preallocate(len: usize) -> z_owned_bytes_t { + let data = vec![0u8; len].into_boxed_slice(); + z_owned_bytes_t { + len, + start: Box::leak(data).as_mut_ptr(), + } + } + + #[allow(clippy::missing_safety_doc)] + pub unsafe fn insert_unchecked(&mut self, start: usize, value: &[u8]) { + std::ptr::copy_nonoverlapping( + value.as_ptr(), + (self.start as *mut u8).add(start), + value.len(), + ); + } +} + /// Returns ``true`` if `b` is initialized. #[no_mangle] -pub extern "C" fn z_bytes_check(b: &z_bytes_t) -> bool { +pub extern "C" fn z_bytes_is_initialized(b: &z_bytes_t) -> bool { !b.start.is_null() } /// Returns the gravestone value for `z_bytes_t` #[no_mangle] -pub const extern "C" fn z_bytes_null() -> z_bytes_t { +pub const extern "C" fn z_bytes_empty() -> z_bytes_t { z_bytes_t { len: 0, start: core::ptr::null(), @@ -71,12 +114,12 @@ pub const extern "C" fn z_bytes_null() -> z_bytes_t { /// Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). /// -/// `str == NULL` will cause this to return `z_bytes_null()` +/// `str == NULL` will cause this to return `z_bytes_empty()` #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn z_bytes_from_str(str: *const c_char) -> z_bytes_t { if str.is_null() { - z_bytes_null() + z_bytes_empty() } else { let len = unsafe { libc::strlen(str) }; z_bytes_t { @@ -89,7 +132,7 @@ pub unsafe extern "C" fn z_bytes_from_str(str: *const c_char) -> z_bytes_t { #[deprecated = "Renamed to z_bytes_from_str"] /// Deprecated in favor of `z_bytes_from_str`: Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). /// -/// `str == NULL` will cause this to return `z_bytes_null()` +/// `str == NULL` will cause this to return `z_bytes_empty()` #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn z_bytes_new(str: *const c_char) -> z_bytes_t { @@ -101,7 +144,7 @@ pub unsafe extern "C" fn z_bytes_new(str: *const c_char) -> z_bytes_t { #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn z_bytes_wrap(start: *const u8, len: usize) -> z_bytes_t { if start.is_null() { - z_bytes_null() + z_bytes_empty() } else { z_bytes_t { len, start } } @@ -109,15 +152,49 @@ pub unsafe extern "C" fn z_bytes_wrap(start: *const u8, len: usize) -> z_bytes_t /// Frees `b` and invalidates it for double-drop safety. #[allow(clippy::missing_safety_doc)] -pub(crate) unsafe fn z_bytes_drop(b: &mut z_bytes_t) { +pub unsafe extern "C" fn z_bytes_drop(b: &mut z_owned_bytes_t) { if !b.start.is_null() { std::mem::drop(Box::from_raw( core::ptr::slice_from_raw_parts(b.start, b.len).cast_mut(), )); - b.start = std::ptr::null(); + b.start = std::ptr::null_mut(); + b.len = 0; } } +/// Returns the gravestone value for `z_owned_bytes_t` +#[no_mangle] +pub const extern "C" fn z_bytes_null() -> z_owned_bytes_t { + z_owned_bytes_t { + len: 0, + start: core::ptr::null_mut(), + } +} + +#[no_mangle] +pub const extern "C" fn z_bytes_loan(b: &z_owned_bytes_t) -> z_bytes_t { + z_bytes_t { + len: b.len, + start: b.start, + } +} + +#[no_mangle] +pub extern "C" fn z_bytes_clone(b: &z_bytes_t) -> z_owned_bytes_t { + if !z_bytes_is_initialized(b) { + return z_bytes_null(); + } else { + return z_owned_bytes_t::new(unsafe { std::slice::from_raw_parts(b.start, b.len) } ) + } +} + +/// Returns ``true`` if `b` is initialized. +#[no_mangle] +pub extern "C" fn z_bytes_check(b: &z_owned_bytes_t) -> bool { + !b.start.is_null() +} + + impl From for z_bytes_t { #[inline] fn from(pid: ZenohId) -> Self { @@ -276,13 +353,13 @@ pub extern "C" fn z_buffer_len(buffer: z_buffer_t) -> usize { /// Returns the `index`th slice of the buffer, aliasing it. /// -/// Out of bounds accesses will return `z_bytes_null`. +/// Out of bounds accesses will return `z_bytes_empty`. #[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(), + None => z_bytes_empty(), Some(buf) => ZBuf::slices(buf) .nth(index) - .map_or(z_bytes_null(), |slice| slice.into()), + .map_or(z_bytes_empty(), |slice| slice.into()), } } diff --git a/src/commons.rs b/src/commons.rs index 249333d66..e8a6bc5d6 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -140,12 +140,13 @@ pub extern "C" fn zc_payload_clone(payload: zc_payload_t) -> zc_owned_payload_t /// Decodes payload into null-terminated string #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_payload_decode_into_string(payload: zc_payload_t) -> z_owned_str_t { +pub unsafe extern "C" fn zc_payload_decode_into_string(payload: zc_payload_t, cstr: &mut z_owned_str_t) -> i8 { let payload: Option<&ZBuf> = payload.into(); if payload.is_none() { - return z_str_null(); + *cstr = z_str_null(); + return 0; } - let mut cstr = z_owned_str_t::preallocate(zc_payload_len(payload.into())); + *cstr = z_owned_str_t::preallocate(zc_payload_len(payload.into())); let payload = payload.unwrap(); let mut pos = 0; @@ -153,7 +154,27 @@ pub unsafe extern "C" fn zc_payload_decode_into_string(payload: zc_payload_t) -> cstr.insert_unchecked(pos, s); pos += s.len(); } - cstr + return 0; +} + +/// Decodes payload into null-terminated string +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_decode_into_bytes(payload: zc_payload_t, b: &mut z_owned_bytes_t) -> i8 { + let payload: Option<&ZBuf> = payload.into(); + if payload.is_none() { + *b = z_bytes_null(); + return 0; + } + *b = z_owned_bytes_t::preallocate(zc_payload_len(payload.into())); + let payload = payload.unwrap(); + + let mut pos = 0; + for s in payload.slices() { + b.insert_unchecked(pos, s); + pos += s.len(); + } + return 0; } unsafe impl Send for z_bytes_t {} @@ -529,7 +550,7 @@ impl From<&zenoh_protocol::core::Encoding> for z_encoding_t { #[repr(C)] pub struct z_owned_encoding_t { pub prefix: z_encoding_prefix_t, - pub suffix: z_bytes_t, + pub suffix: z_owned_bytes_t, pub _dropped: bool, } @@ -537,7 +558,7 @@ impl z_owned_encoding_t { pub fn null() -> Self { z_owned_encoding_t { prefix: z_encoding_prefix_t::Empty, - suffix: z_bytes_t::default(), + suffix: z_bytes_null(), _dropped: true, } } @@ -595,7 +616,7 @@ pub extern "C" fn z_encoding_check(encoding: &z_owned_encoding_t) -> bool { pub extern "C" fn z_encoding_loan(encoding: &z_owned_encoding_t) -> z_encoding_t { z_encoding_t { prefix: encoding.prefix, - suffix: encoding.suffix, + suffix: z_bytes_loan(&encoding.suffix), } } @@ -603,7 +624,7 @@ impl From for z_owned_encoding_t { fn from(val: z_encoding_t) -> Self { z_owned_encoding_t { prefix: val.prefix, - suffix: val.suffix, + suffix: z_bytes_clone(&val.suffix), _dropped: false, } } @@ -655,6 +676,9 @@ impl Drop for z_owned_str_t { #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn z_str_drop(s: &mut z_owned_str_t) { + if s._cstr.is_null() { + return; + } libc::free(std::mem::transmute(s._cstr)); s._cstr = std::ptr::null_mut(); } diff --git a/src/get.rs b/src/get.rs index 17ed9ccbe..3e9e4ded4 100644 --- a/src/get.rs +++ b/src/get.rs @@ -33,15 +33,8 @@ use crate::attachment::{ insert_in_attachment_builder, z_attachment_check, z_attachment_iterate, z_attachment_null, z_attachment_t, }; -use crate::z_encoding_check; -use crate::z_encoding_drop; -use crate::z_encoding_loan; -use crate::z_encoding_null; -use crate::z_owned_encoding_t; +use crate::z_encoding_default; use crate::zc_owned_payload_t; -use crate::zc_payload_check; -use crate::zc_payload_drop; -use crate::zc_payload_loan; use crate::zc_payload_null; use crate::zc_payload_t; use crate::{ @@ -122,45 +115,6 @@ pub struct z_value_t { pub encoding: z_encoding_t, } -/// An owned zenoh value. -/// -/// Members: -/// zc_owned_payload_t payload: The payload of this zenoh value. -/// z_owned_encoding_t encoding: The encoding of this zenoh value `payload`. -#[repr(C)] -pub struct z_owned_value_t { - pub payload: zc_owned_payload_t, - pub encoding: z_owned_encoding_t, -} - -#[no_mangle] -pub extern "C" fn z_value_null() -> z_owned_value_t { - z_owned_value_t { - payload: zc_payload_null(), - encoding: z_encoding_null(), - } -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_value_drop(value: &mut z_owned_value_t) { - z_encoding_drop(&mut value.encoding); - zc_payload_drop(&mut value.payload); -} - -#[no_mangle] -pub extern "C" fn z_value_loan(value: &z_owned_value_t) -> z_value_t { - z_value_t { - payload: zc_payload_loan(&value.payload), - encoding: z_encoding_loan(&value.encoding), - } -} - -#[no_mangle] -pub extern "C" fn z_value_check(value: &z_owned_value_t) -> bool { - zc_payload_check(&value.payload) && z_encoding_check(&value.encoding) -} - /// Yields the contents of the reply by asserting it indicates a failure. /// /// You should always make sure that :c:func:`z_reply_is_ok` returns ``false`` before calling this function. @@ -202,7 +156,8 @@ pub extern "C" fn z_reply_null() -> z_owned_reply_t { pub struct z_get_options_t { pub target: z_query_target_t, pub consolidation: z_query_consolidation_t, - pub value: z_owned_value_t, + pub payload: zc_owned_payload_t, + pub encoding: z_encoding_t, pub attachment: z_attachment_t, pub timeout_ms: u64, } @@ -212,7 +167,8 @@ pub extern "C" fn z_get_options_default() -> z_get_options_t { target: QueryTarget::default().into(), consolidation: QueryConsolidation::default().into(), timeout_ms: 0, - value: z_value_null(), + payload: zc_payload_null(), + encoding: z_encoding_default(), attachment: z_attachment_null(), } } @@ -257,22 +213,10 @@ pub unsafe extern "C" fn z_get( .consolidation(options.consolidation) .target(options.target.into()); - if let Some(payload) = options.value.payload.take() { + if let Some(payload) = options.payload.take() { let mut value = Value::new(payload); - if z_encoding_check(&options.value.encoding) { - value = value.encoding(z_encoding_loan(&options.value.encoding).into()); - } - q = q.with_value(value); - } - z_encoding_drop(&mut options.value.encoding); - if zc_payload_check(&options.value.payload) { - let buf: ZBuf = options.value.payload.as_ref().unwrap().clone(); - let mut value = Value::new(buf); - if z_encoding_check(&options.value.encoding) { - value = value.encoding(z_encoding_loan(&options.value.encoding).into()); - } + value = value.encoding(options.encoding.into()); q = q.with_value(value); - z_value_drop(&mut options.value); } if options.timeout_ms != 0 { q = q.timeout(std::time::Duration::from_millis(options.timeout_ms)); diff --git a/tests/z_int_pub_cache_query_sub_test.c b/tests/z_int_pub_cache_query_sub_test.c index 789a00ffc..03a6d893c 100644 --- a/tests/z_int_pub_cache_query_sub_test.c +++ b/tests/z_int_pub_cache_query_sub_test.c @@ -93,13 +93,14 @@ void data_handler(const z_sample_t *sample, void *arg) { exit(-1); } z_drop(z_move(keystr)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); - if (strcmp(values[val_num], z_loan(payload))) { + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(z_sample_payload(sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { perror("Unexpected value received"); - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); exit(-1); } - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); 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 a665ad19b..ccb2c1e82 100644 --- a/tests/z_int_pub_sub_attachment_test.c +++ b/tests/z_int_pub_sub_attachment_test.c @@ -74,13 +74,14 @@ void data_handler(const z_sample_t *sample, void *arg) { } z_drop(z_move(keystr)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); - if (strcmp(values[val_num], z_loan(payload))) { + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(z_sample_payload(sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { perror("Unexpected value received"); - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); exit(-1); } - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); 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); diff --git a/tests/z_int_pub_sub_test.c b/tests/z_int_pub_sub_test.c index 06d5c87ba..ad5969fa2 100644 --- a/tests/z_int_pub_sub_test.c +++ b/tests/z_int_pub_sub_test.c @@ -67,13 +67,14 @@ void data_handler(const z_sample_t *sample, void *arg) { } z_drop(z_move(keystr)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(sample)); - if (strcmp(values[val_num], z_loan(payload))) { + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(z_sample_payload(sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { perror("Unexpected value received"); - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); exit(-1); } - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); 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) { diff --git a/tests/z_int_queryable_attachment_test.c b/tests/z_int_queryable_attachment_test.c index 26645ad29..909da8c24 100644 --- a/tests/z_int_queryable_attachment_test.c +++ b/tests/z_int_queryable_attachment_test.c @@ -110,10 +110,11 @@ int run_get() { z_sample_t sample = z_reply_ok(&reply); z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(&sample)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(&sample)); - if (strcmp(values[val_num], z_loan(payload))) { + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(z_sample_payload(&sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { perror("Unexpected value received"); - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); exit(-1); } @@ -121,7 +122,7 @@ int run_get() { ASSERT_STR_BYTES_EQUAL(V_CONST, v_const); z_drop(z_move(keystr)); - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); } z_drop(z_move(reply)); z_drop(z_move(channel)); diff --git a/tests/z_int_queryable_test.c b/tests/z_int_queryable_test.c index 7cc7f3bfc..3b3abad94 100644 --- a/tests/z_int_queryable_test.c +++ b/tests/z_int_queryable_test.c @@ -86,15 +86,16 @@ int run_get() { z_sample_t sample = z_reply_ok(&reply); z_owned_str_t keystr = z_keyexpr_to_string(z_sample_keyexpr(&sample)); - z_owned_str_t payload = zc_payload_decode_into_string(z_sample_payload(&sample)); - if (strcmp(values[val_num], z_loan(payload))) { + z_owned_str_t payload_value = z_str_null(); + zc_payload_decode_into_string(z_sample_payload(&sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { perror("Unexpected value received"); - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); exit(-1); } z_drop(z_move(keystr)); - z_drop(z_move(payload)); + z_drop(z_move(payload_value)); } z_drop(z_move(reply)); z_drop(z_move(channel)); From b957f98a304bb870c5715c5bfe8a5d71525706c3 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Fri, 5 Apr 2024 12:31:48 +0200 Subject: [PATCH 19/30] generate opaque types data inside build.rs instead of cmake --- CMakeLists.txt | 5 ----- build.rs | 28 ++++++++++++++++++++++++++-- src/collections.rs | 17 ++++++----------- src/commons.rs | 14 ++++++++++---- src/opaque_types/mod.rs | 15 --------------- 5 files changed, 42 insertions(+), 37 deletions(-) delete mode 100644 src/opaque_types/mod.rs diff --git a/CMakeLists.txt b/CMakeLists.txt index aac66278b..00aa5cac2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,10 +179,6 @@ set_genexpr_condition(cargo_flags DEBUG $ "--manifest-path=${cargo_toml_dir_debug}/Cargo.toml" "--release;--manifest-path=${cargo_toml_dir_release}/Cargo.toml") set(cargo_flags ${cargo_flags} ${ZENOHC_CARGO_FLAGS}) -set_genexpr_condition(cargo_dep_flags DEBUG $ - "--manifest-path=${CMAKE_CURRENT_SOURCE_DIR}/build-resources/opaque-types/Cargo.toml" - "--release;--manifest-path=${CMAKE_CURRENT_SOURCE_DIR}/build-resources/opaque-types/Cargo.toml") -set(cargo_dep_flags ${cargo_dep_flags} ${ZENOHC_CARGO_FLAGS}) if(ZENOHC_BUILD_WITH_LOGGER_AUTOINIT) set(cargo_flags ${cargo_flags} --features=logger-autoinit) @@ -203,7 +199,6 @@ add_custom_command( OUTPUT ${libs} COMMAND ${CMAKE_COMMAND} -E echo \"RUSTFLAGS = $$RUSTFLAGS\" COMMAND ${CMAKE_COMMAND} -E echo \"cargo +${ZENOHC_CARGO_CHANNEL} build ${cargo_flags}\" - COMMAND cargo +${ZENOHC_CARGO_CHANNEL} build ${cargo_dep_flags} &> ${CMAKE_CURRENT_SOURCE_DIR}/.build_resources_opaque_types.txt || echo "" COMMAND cargo +${ZENOHC_CARGO_CHANNEL} build ${cargo_flags} VERBATIM COMMAND_EXPAND_LISTS diff --git a/build.rs b/build.rs index 03a271817..b14bdc4cd 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,8 @@ use fs2::FileExt; use regex::Regex; use std::io::{Read, Write}; +use std::path::PathBuf; +use std::process::{Command, Stdio}; use std::{borrow::Cow, collections::HashMap, io::BufWriter, path::Path}; const GENERATION_PATH: &str = "include/zenoh-gen.h"; @@ -24,6 +26,8 @@ const HEADER: &str = r"// #endif "; +use std::env; + fn main() { generate_opaque_types(); cbindgen::generate(std::env::var("CARGO_MANIFEST_DIR").unwrap()) @@ -42,9 +46,29 @@ fn main() { println!("cargo:rerun-if-changed=build-resources") } +fn produce_opaque_types_data() -> PathBuf { + let target = env::var("TARGET").unwrap(); + let current_folder = std::env::current_dir().unwrap(); + let manifest_path = current_folder.join("./build-resources/opaque-types/Cargo.toml"); + let output_file_path = current_folder.join("./.build_resources_opaque_types.txt"); + let out_file = std::fs::File::create(output_file_path.clone()).unwrap(); + let stdio = Stdio::from(out_file); + let _ = Command::new("cargo") + .arg("build") + .arg("--target") + .arg(target) + .arg("--manifest-path") + .arg(manifest_path) + .stderr(stdio) + .output() + .unwrap(); + + output_file_path +} + fn generate_opaque_types() { let current_folder = std::env::current_dir().unwrap(); - let path_in = current_folder.join("./.build_resources_opaque_types.txt"); + let path_in = produce_opaque_types_data(); let path_out = current_folder.join("./src/opaque_types/mod.rs"); let data_in = std::fs::read_to_string(path_in).unwrap(); @@ -56,7 +80,7 @@ fn generate_opaque_types() { let s = format!( "#[repr(C, align({align}))] pub struct {type_name} {{ - _0: [u8; {size}] + _0: [u8; {size}], }} " ); diff --git a/src/collections.rs b/src/collections.rs index 2990f1a3a..363c30a89 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -68,8 +68,8 @@ impl Drop for z_owned_bytes_t { } impl z_owned_bytes_t { - pub fn new(data: &[u8]) ->z_owned_bytes_t { - if data.len() == 0 { + pub fn new(data: &[u8]) -> z_owned_bytes_t { + if data.is_empty() { return z_bytes_null(); } let data = data.to_vec().into_boxed_slice(); @@ -83,17 +83,13 @@ impl z_owned_bytes_t { let data = vec![0u8; len].into_boxed_slice(); z_owned_bytes_t { len, - start: Box::leak(data).as_mut_ptr(), + start: Box::leak(data).as_mut_ptr(), } } #[allow(clippy::missing_safety_doc)] pub unsafe fn insert_unchecked(&mut self, start: usize, value: &[u8]) { - std::ptr::copy_nonoverlapping( - value.as_ptr(), - (self.start as *mut u8).add(start), - value.len(), - ); + std::ptr::copy_nonoverlapping(value.as_ptr(), self.start.add(start), value.len()); } } @@ -182,9 +178,9 @@ pub const extern "C" fn z_bytes_loan(b: &z_owned_bytes_t) -> z_bytes_t { #[no_mangle] pub extern "C" fn z_bytes_clone(b: &z_bytes_t) -> z_owned_bytes_t { if !z_bytes_is_initialized(b) { - return z_bytes_null(); + z_bytes_null() } else { - return z_owned_bytes_t::new(unsafe { std::slice::from_raw_parts(b.start, b.len) } ) + z_owned_bytes_t::new(unsafe { std::slice::from_raw_parts(b.start, b.len) }) } } @@ -194,7 +190,6 @@ pub extern "C" fn z_bytes_check(b: &z_owned_bytes_t) -> bool { !b.start.is_null() } - impl From for z_bytes_t { #[inline] fn from(pid: ZenohId) -> Self { diff --git a/src/commons.rs b/src/commons.rs index e8a6bc5d6..5f8ede970 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -140,7 +140,10 @@ pub extern "C" fn zc_payload_clone(payload: zc_payload_t) -> zc_owned_payload_t /// Decodes payload into null-terminated string #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_payload_decode_into_string(payload: zc_payload_t, cstr: &mut z_owned_str_t) -> i8 { +pub unsafe extern "C" fn zc_payload_decode_into_string( + payload: zc_payload_t, + cstr: &mut z_owned_str_t, +) -> i8 { let payload: Option<&ZBuf> = payload.into(); if payload.is_none() { *cstr = z_str_null(); @@ -154,13 +157,16 @@ pub unsafe extern "C" fn zc_payload_decode_into_string(payload: zc_payload_t, cs cstr.insert_unchecked(pos, s); pos += s.len(); } - return 0; + 0 } /// Decodes payload into null-terminated string #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_payload_decode_into_bytes(payload: zc_payload_t, b: &mut z_owned_bytes_t) -> i8 { +pub unsafe extern "C" fn zc_payload_decode_into_bytes( + payload: zc_payload_t, + b: &mut z_owned_bytes_t, +) -> i8 { let payload: Option<&ZBuf> = payload.into(); if payload.is_none() { *b = z_bytes_null(); @@ -174,7 +180,7 @@ pub unsafe extern "C" fn zc_payload_decode_into_bytes(payload: zc_payload_t, b: b.insert_unchecked(pos, s); pos += s.len(); } - return 0; + 0 } unsafe impl Send for z_bytes_t {} diff --git a/src/opaque_types/mod.rs b/src/opaque_types/mod.rs deleted file mode 100644 index 0327b0943..000000000 --- a/src/opaque_types/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -/// A split buffer that owns all of its data. -/// -/// To minimize copies and reallocations, Zenoh may provide you data in split buffers. -#[repr(C, align(8))] -pub struct z_owned_buffer_t { - _0: [u8; 40] -} -/// 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, align(8))] -pub struct zc_owned_sample_t { - _0: [u8; 224] -} From f73599feb336f94dc029eb6958abcfbcba47abd6 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Fri, 5 Apr 2024 12:36:30 +0200 Subject: [PATCH 20/30] .gitignore update --- .gitignore | 3 ++- src/opaque_types/.gitkeep | 0 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 src/opaque_types/.gitkeep diff --git a/.gitignore b/.gitignore index 8aaf37e32..49b20fcc2 100644 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,5 @@ dkms.conf include/zenoh_configure.h # Build resources -.build_resources* \ No newline at end of file +.build_resources* +src/opaque_types/mod.rs \ No newline at end of file diff --git a/src/opaque_types/.gitkeep b/src/opaque_types/.gitkeep new file mode 100644 index 000000000..e69de29bb From a3cc34a1c1f54eb9fcfc1d9ff5d9fc3c9d454024 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Fri, 5 Apr 2024 16:04:59 +0200 Subject: [PATCH 21/30] extract build.rs instad of current folder to allow build outside of crate root --- build.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/build.rs b/build.rs index b14bdc4cd..51d44a615 100644 --- a/build.rs +++ b/build.rs @@ -46,10 +46,18 @@ fn main() { println!("cargo:rerun-if-changed=build-resources") } +fn get_build_rs_path() -> PathBuf { + let file_path = file!(); + let mut path_buf = PathBuf::new(); + path_buf.push(file_path); + path_buf.parent().unwrap().to_path_buf() +} + fn produce_opaque_types_data() -> PathBuf { let target = env::var("TARGET").unwrap(); - let current_folder = std::env::current_dir().unwrap(); + let current_folder = get_build_rs_path(); let manifest_path = current_folder.join("./build-resources/opaque-types/Cargo.toml"); + println!("cargo:warning={}", current_folder.to_str().unwrap()); let output_file_path = current_folder.join("./.build_resources_opaque_types.txt"); let out_file = std::fs::File::create(output_file_path.clone()).unwrap(); let stdio = Stdio::from(out_file); @@ -67,7 +75,7 @@ fn produce_opaque_types_data() -> PathBuf { } fn generate_opaque_types() { - let current_folder = std::env::current_dir().unwrap(); + let current_folder = get_build_rs_path(); let path_in = produce_opaque_types_data(); let path_out = current_folder.join("./src/opaque_types/mod.rs"); @@ -96,7 +104,7 @@ pub struct {type_name} {{ } fn get_opaque_type_docs() -> HashMap> { - let current_folder = std::env::current_dir().unwrap(); + let current_folder = get_build_rs_path(); let path_in = current_folder.join("./build-resources/opaque-types/src/lib.rs"); let re = Regex::new(r#"get_opaque_type_data!\(.*, "(\w+)"\)"#).unwrap(); let mut comments = std::vec::Vec::::new(); From 142b75299e7e4610328650cd18cf608749c9e0fa Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Fri, 5 Apr 2024 16:28:54 +0200 Subject: [PATCH 22/30] remove println! --- build.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/build.rs b/build.rs index 51d44a615..703bde4c1 100644 --- a/build.rs +++ b/build.rs @@ -57,7 +57,6 @@ fn produce_opaque_types_data() -> PathBuf { let target = env::var("TARGET").unwrap(); let current_folder = get_build_rs_path(); let manifest_path = current_folder.join("./build-resources/opaque-types/Cargo.toml"); - println!("cargo:warning={}", current_folder.to_str().unwrap()); let output_file_path = current_folder.join("./.build_resources_opaque_types.txt"); let out_file = std::fs::File::create(output_file_path.clone()).unwrap(); let stdio = Stdio::from(out_file); From 4932ddff7c708380ca8177d7a844981182397ed8 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Fri, 5 Apr 2024 17:36:13 +0200 Subject: [PATCH 23/30] move Payload/zBuf-related functionality into separate file --- include/zenoh_commons.h | 4 +- src/collections.rs | 132 +------------------- src/commons.rs | 140 +-------------------- src/lib.rs | 2 + src/payload.rs | 261 ++++++++++++++++++++++++++++++++++++++++ src/put.rs | 1 + 6 files changed, 271 insertions(+), 269 deletions(-) create mode 100644 src/payload.rs diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index fe2b58959..7e6060df7 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -2121,13 +2121,13 @@ ZENOHC_API enum z_sample_kind_t z_sample_kind(const struct z_sample_t *sample); * 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); +ZENOHC_API zc_owned_payload_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_buffer_t z_sample_payload(const struct z_sample_t *sample); +ZENOHC_API zc_payload_t z_sample_payload(const struct z_sample_t *sample); /** * The qos with which the sample was received. */ diff --git a/src/collections.rs b/src/collections.rs index 363c30a89..d55a9fa1b 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -13,14 +13,7 @@ // use libc::{c_char, size_t}; -use std::ops::Deref; -use std::ptr::NonNull; -use zenoh::{ - buffers::{buffer::SplitBuffer, ZBuf}, - prelude::ZenohId, -}; - -use crate::{impl_guarded_transmute, GuardedTransmute}; +use zenoh::prelude::ZenohId; /// A contiguous view of bytes owned by some other entity. /// @@ -235,126 +228,3 @@ impl From<&[u8]> for z_bytes_t { } } } - -pub use crate::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 { - Some(value).transmute() - } -} - -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) } - } -} - -/// 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, Default)] -pub struct z_buffer_t { - _inner: Option>, -} - -impl From> for z_buffer_t { - fn from(value: Option<&ZBuf>) -> Self { - unsafe { core::mem::transmute(value) } - } -} - -impl From for Option<&'static ZBuf> { - fn from(value: z_buffer_t) -> Self { - unsafe { core::mem::transmute(value) } - } -} - -/// 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 { - match buffer._inner { - Some(b) => unsafe { b.as_ref().deref().clone().transmute() }, - None => ZBuf::empty().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. -#[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 total number bytes in the buffer. -#[no_mangle] -pub extern "C" fn z_buffer_len(buffer: z_buffer_t) -> usize { - match buffer.into() { - None => 0, - Some(buf) => ZBuf::slices(buf).fold(0, |acc, s| acc + s.len()), - } -} - -/// Returns the `index`th slice of the buffer, aliasing it. -/// -/// Out of bounds accesses will return `z_bytes_empty`. -#[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_empty(), - Some(buf) => ZBuf::slices(buf) - .nth(index) - .map_or(z_bytes_empty(), |slice| slice.into()), - } -} diff --git a/src/commons.rs b/src/commons.rs index 5f8ede970..ed0f9dbf0 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -12,21 +12,18 @@ // ZettaScale Zenoh team, // -use std::any::Any; use std::ops::Deref; -use std::slice; use crate::collections::*; use crate::keyexpr::*; use crate::z_congestion_control_t; use crate::z_id_t; use crate::z_priority_t; +use crate::zc_owned_payload_t; +use crate::zc_payload_t; use crate::{impl_guarded_transmute, GuardedTransmute}; use libc::c_void; use libc::{c_char, c_ulong}; -use zenoh::buffers::buffer::SplitBuffer; -use zenoh::buffers::ZBuf; -use zenoh::buffers::ZSliceBuffer; use zenoh::prelude::SampleKind; use zenoh::query::ReplyKeyExpr; use zenoh::sample::Locality; @@ -95,135 +92,6 @@ impl From> for z_timestamp_t { } } -/// An owned payload, backed by a reference counted owner. -/// -/// The `payload` field may be modified, and Zenoh will take the new values into account. -#[allow(non_camel_case_types)] -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 { - 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 { - 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) { - 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 { - z_buffer_null() -} - -/// Returns a :c:type:`zc_payload_t` loaned from `payload`. -#[no_mangle] -pub extern "C" fn zc_payload_loan(payload: &zc_owned_payload_t) -> zc_payload_t { - z_buffer_loan(payload) -} - -#[allow(non_camel_case_types)] -pub type zc_payload_t = z_buffer_t; - -/// Increments internal payload reference count, returning owned payload. -#[no_mangle] -pub extern "C" fn zc_payload_clone(payload: zc_payload_t) -> zc_owned_payload_t { - z_buffer_clone(payload) -} - -/// Decodes payload into null-terminated string -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_payload_decode_into_string( - payload: zc_payload_t, - cstr: &mut z_owned_str_t, -) -> i8 { - let payload: Option<&ZBuf> = payload.into(); - if payload.is_none() { - *cstr = z_str_null(); - return 0; - } - *cstr = z_owned_str_t::preallocate(zc_payload_len(payload.into())); - let payload = payload.unwrap(); - - let mut pos = 0; - for s in payload.slices() { - cstr.insert_unchecked(pos, s); - pos += s.len(); - } - 0 -} - -/// Decodes payload into null-terminated string -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_payload_decode_into_bytes( - payload: zc_payload_t, - b: &mut z_owned_bytes_t, -) -> i8 { - let payload: Option<&ZBuf> = payload.into(); - if payload.is_none() { - *b = z_bytes_null(); - return 0; - } - *b = z_owned_bytes_t::preallocate(zc_payload_len(payload.into())); - let payload = payload.unwrap(); - - let mut pos = 0; - for s in payload.slices() { - b.insert_unchecked(pos, s); - pos += s.len(); - } - 0 -} - -unsafe impl Send for z_bytes_t {} -unsafe impl Sync for z_bytes_t {} - -impl ZSliceBuffer for z_bytes_t { - fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.start, self.len) } - } - fn as_mut_slice(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.start as *mut u8, self.len) } - } - fn as_any(&self) -> &dyn Any { - self - } -} - -/// Encodes byte sequence by aliasing. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_payload_encode_from_bytes(bytes: z_bytes_t) -> zc_owned_payload_t { - ZBuf::from(bytes).into() -} - -/// Encodes a null-terminated string by aliasing. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_payload_encode_from_string( - cstr: *const libc::c_char, -) -> zc_owned_payload_t { - let bytes = z_bytes_t { - start: cstr as *const u8, - len: libc::strlen(cstr), - }; - zc_payload_encode_from_bytes(bytes) -} - -/// Returns total number bytes in the payload. -#[no_mangle] -pub extern "C" fn zc_payload_len(payload: zc_payload_t) -> usize { - z_buffer_len(payload) -} - /// QoS settings of zenoh message. /// #[repr(C)] @@ -290,7 +158,7 @@ pub extern "C" fn z_sample_encoding(sample: &z_sample_t) -> z_encoding_t { /// /// 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_buffer_t { +pub extern "C" fn z_sample_payload(sample: &z_sample_t) -> zc_payload_t { Some(&sample.payload).into() } /// Returns the sample's payload after incrementing its internal reference count. @@ -298,7 +166,7 @@ pub extern "C" fn z_sample_payload(sample: &z_sample_t) -> z_buffer_t { /// 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 { +pub extern "C" fn z_sample_owned_payload(sample: &z_sample_t) -> zc_owned_payload_t { sample.payload.clone().into() } /// The sample's kind (put or delete). diff --git a/src/lib.rs b/src/lib.rs index 96cc4bd76..20f766352 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,8 @@ mod config; pub use crate::config::*; mod commons; pub use crate::commons::*; +mod payload; +pub use crate::payload::*; mod keyexpr; pub use crate::keyexpr::*; mod info; diff --git a/src/payload.rs b/src/payload.rs new file mode 100644 index 000000000..ba28eb3e4 --- /dev/null +++ b/src/payload.rs @@ -0,0 +1,261 @@ +use core::slice; +use std::{any::Any, ops::Deref, ptr::NonNull}; + +use zenoh::buffers::{buffer::SplitBuffer, ZBuf, ZSliceBuffer}; + +use crate::{ + impl_guarded_transmute, z_bytes_empty, z_bytes_null, z_bytes_t, z_owned_bytes_t, z_owned_str_t, + z_str_null, GuardedTransmute, +}; + +pub use crate::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 { + Some(value).transmute() + } +} + +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) } + } +} + +/// 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, Default)] +pub struct z_buffer_t { + _inner: Option>, +} + +impl From> for z_buffer_t { + fn from(value: Option<&ZBuf>) -> Self { + unsafe { core::mem::transmute(value) } + } +} + +impl From for Option<&'static ZBuf> { + fn from(value: z_buffer_t) -> Self { + unsafe { core::mem::transmute(value) } + } +} + +/// 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 { + match buffer._inner { + Some(b) => unsafe { b.as_ref().deref().clone().transmute() }, + None => ZBuf::empty().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. +#[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 total number bytes in the buffer. +#[no_mangle] +pub extern "C" fn z_buffer_len(buffer: z_buffer_t) -> usize { + match buffer.into() { + None => 0, + Some(buf) => ZBuf::slices(buf).fold(0, |acc, s| acc + s.len()), + } +} + +/// Returns the `index`th slice of the buffer, aliasing it. +/// +/// Out of bounds accesses will return `z_bytes_empty`. +#[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_empty(), + Some(buf) => ZBuf::slices(buf) + .nth(index) + .map_or(z_bytes_empty(), |slice| slice.into()), + } +} + +/// An owned payload, backed by a reference counted owner. +/// +/// The `payload` field may be modified, and Zenoh will take the new values into account. +#[allow(non_camel_case_types)] +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 { + 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 { + 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) { + 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 { + z_buffer_null() +} + +/// Returns a :c:type:`zc_payload_t` loaned from `payload`. +#[no_mangle] +pub extern "C" fn zc_payload_loan(payload: &zc_owned_payload_t) -> zc_payload_t { + z_buffer_loan(payload) +} + +#[allow(non_camel_case_types)] +pub type zc_payload_t = z_buffer_t; + +/// Increments internal payload reference count, returning owned payload. +#[no_mangle] +pub extern "C" fn zc_payload_clone(payload: zc_payload_t) -> zc_owned_payload_t { + z_buffer_clone(payload) +} + +/// Decodes payload into null-terminated string +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_decode_into_string( + payload: zc_payload_t, + cstr: &mut z_owned_str_t, +) -> i8 { + let payload: Option<&ZBuf> = payload.into(); + if payload.is_none() { + *cstr = z_str_null(); + return 0; + } + *cstr = z_owned_str_t::preallocate(zc_payload_len(payload.into())); + let payload = payload.unwrap(); + + let mut pos = 0; + for s in payload.slices() { + cstr.insert_unchecked(pos, s); + pos += s.len(); + } + 0 +} + +/// Decodes payload into null-terminated string +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_decode_into_bytes( + payload: zc_payload_t, + b: &mut z_owned_bytes_t, +) -> i8 { + let payload: Option<&ZBuf> = payload.into(); + if payload.is_none() { + *b = z_bytes_null(); + return 0; + } + *b = z_owned_bytes_t::preallocate(zc_payload_len(payload.into())); + let payload = payload.unwrap(); + + let mut pos = 0; + for s in payload.slices() { + b.insert_unchecked(pos, s); + pos += s.len(); + } + 0 +} + +unsafe impl Send for z_bytes_t {} +unsafe impl Sync for z_bytes_t {} + +impl ZSliceBuffer for z_bytes_t { + fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.start, self.len) } + } + fn as_mut_slice(&mut self) -> &mut [u8] { + unsafe { slice::from_raw_parts_mut(self.start as *mut u8, self.len) } + } + fn as_any(&self) -> &dyn Any { + self + } +} + +/// Encodes byte sequence by aliasing. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_encode_from_bytes(bytes: z_bytes_t) -> zc_owned_payload_t { + ZBuf::from(bytes).into() +} + +/// Encodes a null-terminated string by aliasing. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_encode_from_string( + cstr: *const libc::c_char, +) -> zc_owned_payload_t { + let bytes = z_bytes_t { + start: cstr as *const u8, + len: libc::strlen(cstr), + }; + zc_payload_encode_from_bytes(bytes) +} + +/// Returns total number bytes in the payload. +#[no_mangle] +pub extern "C" fn zc_payload_len(payload: zc_payload_t) -> usize { + z_buffer_len(payload) +} diff --git a/src/put.rs b/src/put.rs index 5c8b8d807..5e2d59aec 100644 --- a/src/put.rs +++ b/src/put.rs @@ -14,6 +14,7 @@ use crate::commons::*; use crate::keyexpr::*; use crate::session::*; +use crate::zc_owned_payload_t; use crate::LOG_INVALID_SESSION; use libc::c_void; use zenoh::prelude::{sync::SyncResolve, Priority, SampleKind}; From 90f25783bf5607303aa749b08af228243e0db12a Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Fri, 5 Apr 2024 18:24:20 +0200 Subject: [PATCH 24/30] replace unsafe transmutes with safe ones --- src/payload.rs | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/src/payload.rs b/src/payload.rs index ba28eb3e4..2bc82e699 100644 --- a/src/payload.rs +++ b/src/payload.rs @@ -9,7 +9,8 @@ use crate::{ }; pub use crate::z_owned_buffer_t; -impl_guarded_transmute!(noderefs Option, z_owned_buffer_t); +impl_guarded_transmute!(Option, z_owned_buffer_t); + impl Default for z_owned_buffer_t { fn default() -> Self { z_buffer_null() @@ -21,31 +22,10 @@ impl From for z_owned_buffer_t { } } -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) } - } -} - /// 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::) } + None::.transmute() } /// Decrements the buffer's reference counter, destroying it if applicable. @@ -77,15 +57,18 @@ pub struct z_buffer_t { _inner: Option>, } +impl_guarded_transmute!(noderefs Option<&ZBuf>, z_buffer_t); +impl_guarded_transmute!(noderefs z_buffer_t, Option<&'static ZBuf>); + impl From> for z_buffer_t { fn from(value: Option<&ZBuf>) -> Self { - unsafe { core::mem::transmute(value) } + value.transmute() } } impl From for Option<&'static ZBuf> { fn from(value: z_buffer_t) -> Self { - unsafe { core::mem::transmute(value) } + value.transmute() } } From 32ac0af172334bccb9f480053b7e15bd30f04a3d Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Mon, 8 Apr 2024 13:26:49 +0200 Subject: [PATCH 25/30] add payload reader --- build-resources/opaque-types/src/lib.rs | 7 ++-- include/zenoh_commons.h | 27 ++++++++++++++++ src/payload.rs | 42 ++++++++++++++++++++++++ tests/z_api_payload_test.c | 43 +++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 tests/z_api_payload_test.c diff --git a/build-resources/opaque-types/src/lib.rs b/build-resources/opaque-types/src/lib.rs index 8ef08035c..354e8d999 100644 --- a/build-resources/opaque-types/src/lib.rs +++ b/build-resources/opaque-types/src/lib.rs @@ -1,5 +1,5 @@ use zenoh::sample::Sample; -use zenoh::buffers::ZBuf; +use zenoh::buffers::{ZBuf, ZBufReader}; #[macro_export] macro_rules! get_opaque_type_data { @@ -35,4 +35,7 @@ get_opaque_type_data!(Option, "z_owned_buffer_t"); /// /// 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`. -get_opaque_type_data!(Option, "zc_owned_sample_t"); \ No newline at end of file +get_opaque_type_data!(Option, "zc_owned_sample_t"); + +/// A reader for payload data. +get_opaque_type_data!(ZBufReader, "zc_payload_reader"); \ No newline at end of file diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 7e6060df7..41129a653 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -885,6 +885,12 @@ typedef struct zc_owned_liveliness_token_t { typedef struct zc_liveliness_get_options_t { uint32_t timeout_ms; } zc_liveliness_get_options_t; +/** + * A reader for payload data. + */ +typedef struct ALIGN(8) zc_payload_reader { + uint8_t _0[24]; +} zc_payload_reader; /** * An owned sample. * @@ -2500,6 +2506,27 @@ ZENOHC_API zc_owned_payload_t zc_payload_null(void); * Clones the `payload` by incrementing its reference counter. */ ZENOHC_API zc_owned_payload_t zc_payload_rcinc(const zc_owned_payload_t *payload); +/** + * Creates a reader for the specified `payload`. + * + * Returns 0 in case of success, -1 if `payload` is not valid. + */ +ZENOHC_API int8_t zc_payload_reader_init(zc_payload_t payload, struct zc_payload_reader *reader); +/** + * Reads data into specified destination. + * + * Will read at most `len` bytes. + * Returns number of bytes read. If return value is smaller than `len`, it means that end of the payload was reached. + */ +ZENOHC_API +size_t zc_payload_reader_read(struct zc_payload_reader *reader, + uint8_t *dest, + size_t len); +/** + * Returns number of the remaining bytes in the payload + * + */ +ZENOHC_API size_t zc_payload_reader_remaining(const struct zc_payload_reader *reader); /** * Creates a new blocking fifo channel, returned as a pair of closures. * diff --git a/src/payload.rs b/src/payload.rs index 2bc82e699..e43124bbb 100644 --- a/src/payload.rs +++ b/src/payload.rs @@ -1,6 +1,10 @@ use core::slice; +use std::slice::from_raw_parts_mut; use std::{any::Any, ops::Deref, ptr::NonNull}; +use zenoh::buffers::reader::HasReader; +use zenoh::buffers::reader::Reader; +use zenoh::buffers::ZBufReader; use zenoh::buffers::{buffer::SplitBuffer, ZBuf, ZSliceBuffer}; use crate::{ @@ -242,3 +246,41 @@ pub unsafe extern "C" fn zc_payload_encode_from_string( pub extern "C" fn zc_payload_len(payload: zc_payload_t) -> usize { z_buffer_len(payload) } + + + +pub use crate::zc_payload_reader; +impl_guarded_transmute!(ZBufReader<'static>, zc_payload_reader); +impl_guarded_transmute!(noderefs zc_payload_reader, ZBufReader<'static>); + +/// Creates a reader for the specified `payload`. +/// +/// Returns 0 in case of success, -1 if `payload` is not valid. +#[no_mangle] +pub unsafe extern "C" fn zc_payload_reader_init(payload: zc_payload_t, reader: *mut zc_payload_reader) -> i8 { + if payload._inner.is_none() { + return -1; + } + *reader = payload.transmute().unwrap().reader().transmute(); + 0 +} + + +/// Reads data into specified destination. +/// +/// Will read at most `len` bytes. +/// Returns number of bytes read. If return value is smaller than `len`, it means that end of the payload was reached. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_reader_read(reader: *mut zc_payload_reader, dest: *mut u8, len: usize) -> usize { + let buf = unsafe { from_raw_parts_mut(dest, len) } ; + reader.as_mut().unwrap().read(buf).map(|n| n.get()).unwrap_or(0) +} + +/// Returns number of the remaining bytes in the payload +/// +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_reader_remaining(reader: *const zc_payload_reader) -> usize { + reader.as_ref().unwrap().remaining() +} \ No newline at end of file diff --git a/tests/z_api_payload_test.c b/tests/z_api_payload_test.c new file mode 100644 index 000000000..d2d5da4d4 --- /dev/null +++ b/tests/z_api_payload_test.c @@ -0,0 +1,43 @@ +// +// Copyright (c) 2022 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, + +#include +#include +#include +#include + +#include "zenoh.h" + +#undef NDEBUG +#include + +void test_reader() { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t data_out[10] = {}; + z_bytes_t bytes = {.start = data, .len = 10 }; + + zc_owned_payload_t payload = zc_payload_encode_from_bytes(bytes); + zc_payload_reader reader; + zc_payload_reader_init(z_loan(payload), &reader); + assert(zc_payload_reader_remaining(&reader) == 10); + + zc_payload_reader_read(&reader, data_out, 5); + assert(zc_payload_reader_remaining(&reader) == 5); + zc_payload_reader_read(&reader, data_out, 5); + assert(zc_payload_reader_remaining(&reader) == 0); + assert(memcmp(data, data_out, 10)); +} + +int main(int argc, char **argv) { + test_reader(); +} From f1cdeda3375a415f7c3fc76b1f9606c8a8a1f1a4 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Mon, 8 Apr 2024 14:33:47 +0200 Subject: [PATCH 26/30] fmt and clippy --- src/payload.rs | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/payload.rs b/src/payload.rs index e43124bbb..f7a737ef5 100644 --- a/src/payload.rs +++ b/src/payload.rs @@ -247,17 +247,19 @@ pub extern "C" fn zc_payload_len(payload: zc_payload_t) -> usize { z_buffer_len(payload) } - - pub use crate::zc_payload_reader; impl_guarded_transmute!(ZBufReader<'static>, zc_payload_reader); impl_guarded_transmute!(noderefs zc_payload_reader, ZBufReader<'static>); -/// Creates a reader for the specified `payload`. +/// Creates a reader for the specified `payload`. /// /// Returns 0 in case of success, -1 if `payload` is not valid. #[no_mangle] -pub unsafe extern "C" fn zc_payload_reader_init(payload: zc_payload_t, reader: *mut zc_payload_reader) -> i8 { +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_payload_reader_init( + payload: zc_payload_t, + reader: *mut zc_payload_reader, +) -> i8 { if payload._inner.is_none() { return -1; } @@ -265,22 +267,30 @@ pub unsafe extern "C" fn zc_payload_reader_init(payload: zc_payload_t, reader: * 0 } - /// Reads data into specified destination. -/// -/// Will read at most `len` bytes. +/// +/// Will read at most `len` bytes. /// Returns number of bytes read. If return value is smaller than `len`, it means that end of the payload was reached. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_payload_reader_read(reader: *mut zc_payload_reader, dest: *mut u8, len: usize) -> usize { - let buf = unsafe { from_raw_parts_mut(dest, len) } ; - reader.as_mut().unwrap().read(buf).map(|n| n.get()).unwrap_or(0) +pub unsafe extern "C" fn zc_payload_reader_read( + reader: *mut zc_payload_reader, + dest: *mut u8, + len: usize, +) -> usize { + let buf = unsafe { from_raw_parts_mut(dest, len) }; + reader + .as_mut() + .unwrap() + .read(buf) + .map(|n| n.get()) + .unwrap_or(0) } /// Returns number of the remaining bytes in the payload -/// +/// #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn zc_payload_reader_remaining(reader: *const zc_payload_reader) -> usize { reader.as_ref().unwrap().remaining() -} \ No newline at end of file +} From e2df814c1e4ebc5d8f79867a686ff0e1d63769c7 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Mon, 8 Apr 2024 14:46:40 +0200 Subject: [PATCH 27/30] make all references to z_buffer_t private --- include/zenoh_commons.h | 70 ++++++++++------------------------------- include/zenoh_macros.h | 22 ++++++------- src/payload.rs | 16 +++++----- 3 files changed, 35 insertions(+), 73 deletions(-) diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 41129a653..4326d856f 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -203,22 +203,6 @@ typedef struct z_attachment_t { const void *data; z_attachment_iter_driver_t iteration_driver; } z_attachment_t; -/** - * A split buffer that owns all of its data. - * - * To minimize copies and reallocations, Zenoh may provide you data in split buffers. - */ -typedef struct ALIGN(8) z_owned_buffer_t { - uint8_t _0[40]; -} 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 { - struct z_owned_buffer_t *_inner; -} z_buffer_t; typedef struct z_owned_bytes_t { uint8_t *start; size_t len; @@ -644,6 +628,14 @@ typedef struct z_owned_encoding_t { typedef struct z_query_consolidation_t { enum z_consolidation_mode_t mode; } z_query_consolidation_t; +/** + * A split buffer that owns all of its data. + * + * To minimize copies and reallocations, Zenoh may provide you data in split buffers. + */ +typedef struct ALIGN(8) z_owned_buffer_t { + uint8_t _0[40]; +} z_owned_buffer_t; /** * An owned payload, backed by a reference counted owner. * @@ -788,6 +780,14 @@ typedef struct z_query_reply_options_t { struct z_encoding_t encoding; struct z_attachment_t attachment; } z_query_reply_options_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 { + struct z_owned_buffer_t *_inner; +} z_buffer_t; typedef struct z_buffer_t zc_payload_t; /** * A zenoh value. @@ -1073,44 +1073,6 @@ ZENOHC_API size_t z_attachment_len(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); -/** - * 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); -/** - * Returns total number bytes in the buffer. - */ -ZENOHC_API size_t z_buffer_len(struct z_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 `index`th slice of the buffer, aliasing it. - * - * Out of bounds accesses will return `z_bytes_empty`. - */ -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. - */ -ZENOHC_API size_t z_buffer_slice_count(struct z_buffer_t buffer); /** * Returns ``true`` if `b` is initialized. */ diff --git a/include/zenoh_macros.h b/include/zenoh_macros.h index bb50476a5..815b2df85 100644 --- a/include/zenoh_macros.h +++ b/include/zenoh_macros.h @@ -14,7 +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, \ + zc_owned_payload_t : zc_payload_loan, \ ze_owned_querying_subscriber_t : ze_querying_subscriber_loan \ )(&x) @@ -43,7 +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, \ zc_owned_liveliness_token_t * : zc_liveliness_undeclare_token, \ @@ -74,7 +74,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, \ + zc_owned_payload_t * : zc_payload_null, \ z_attachment_t * : z_attachment_null, \ zc_owned_shmbuf_t * : zc_shmbuf_null, \ zc_owned_shm_manager_t * : zc_shm_manager_null, \ @@ -89,7 +89,7 @@ z_keyexpr_t : z_keyexpr_is_initialized, \ z_owned_config_t : z_config_check, \ z_owned_scouting_config_t : z_scouting_config_check, \ - z_owned_bytes_t : z_bytes_check, \ + z_owned_bytes_t : z_bytes_check, \ z_owned_subscriber_t : z_subscriber_check, \ z_owned_pull_subscriber_t : z_pull_subscriber_check, \ z_owned_queryable_t : z_queryable_check, \ @@ -99,7 +99,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, \ + zc_owned_payload_t: zc_payload_check, \ z_attachment_t : z_attachment_check, \ zc_owned_shmbuf_t : zc_shmbuf_check, \ zc_owned_shm_manager_t : zc_shm_manager_check, \ @@ -142,7 +142,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 zc_payload_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); } @@ -155,7 +155,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 zc_payload_t z_loan(const zc_owned_payload& x) { return zc_payload_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; }; @@ -174,7 +174,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; }; template<> struct zenoh_drop_type { typedef void type; }; @@ -204,7 +204,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* v) { zc_payload_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); } @@ -234,7 +234,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& v) { v = zc_payload_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(); } @@ -269,7 +269,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 zc_owned_payload& v) { return zc_payload_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/payload.rs b/src/payload.rs index f7a737ef5..a1745ba36 100644 --- a/src/payload.rs +++ b/src/payload.rs @@ -28,7 +28,7 @@ impl From 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 { +extern "C" fn z_buffer_null() -> z_owned_buffer_t { None::.transmute() } @@ -36,19 +36,19 @@ pub extern "C" fn z_buffer_null() -> z_owned_buffer_t { /// /// `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) { +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 { +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 { +extern "C" fn z_buffer_loan(buffer: &z_owned_buffer_t) -> z_buffer_t { buffer.as_ref().into() } @@ -78,7 +78,7 @@ impl From for Option<&'static 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 { +extern "C" fn z_buffer_clone(buffer: z_buffer_t) -> z_owned_buffer_t { match buffer._inner { Some(b) => unsafe { b.as_ref().deref().clone().transmute() }, None => ZBuf::empty().into(), @@ -89,7 +89,7 @@ pub extern "C" fn z_buffer_clone(buffer: z_buffer_t) -> z_owned_buffer_t { /// /// If the return value is 0 or 1, then the buffer's data is contiguous in memory. #[no_mangle] -pub extern "C" fn z_buffer_slice_count(buffer: z_buffer_t) -> usize { +extern "C" fn z_buffer_slice_count(buffer: z_buffer_t) -> usize { match buffer.into() { None => 0, Some(buf) => ZBuf::slices(buf).len(), @@ -98,7 +98,7 @@ pub extern "C" fn z_buffer_slice_count(buffer: z_buffer_t) -> usize { /// Returns total number bytes in the buffer. #[no_mangle] -pub extern "C" fn z_buffer_len(buffer: z_buffer_t) -> usize { +extern "C" fn z_buffer_len(buffer: z_buffer_t) -> usize { match buffer.into() { None => 0, Some(buf) => ZBuf::slices(buf).fold(0, |acc, s| acc + s.len()), @@ -109,7 +109,7 @@ pub extern "C" fn z_buffer_len(buffer: z_buffer_t) -> usize { /// /// Out of bounds accesses will return `z_bytes_empty`. #[no_mangle] -pub extern "C" fn z_buffer_slice_at(buffer: z_buffer_t, index: usize) -> z_bytes_t { +extern "C" fn z_buffer_slice_at(buffer: z_buffer_t, index: usize) -> z_bytes_t { match buffer.into() { None => z_bytes_empty(), Some(buf) => ZBuf::slices(buf) From 05401fed3b493641e5034453a760fbae7a6cba0a Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Mon, 8 Apr 2024 14:49:46 +0200 Subject: [PATCH 28/30] remove reference to z_buffer_t --- src/queryable.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/queryable.rs b/src/queryable.rs index c55820227..3c62fba4d 100644 --- a/src/queryable.rs +++ b/src/queryable.rs @@ -16,7 +16,7 @@ use crate::attachment::{ z_attachment_iterate, z_attachment_null, z_attachment_t, }; use crate::{ - impl_guarded_transmute, z_buffer_t, z_bytes_t, z_closure_query_call, z_encoding_default, + impl_guarded_transmute, zc_payload_t, 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, zc_owned_payload_t, LOG_INVALID_SESSION, }; @@ -348,7 +348,7 @@ pub unsafe extern "C" fn z_query_value(query: &z_query_t) -> z_value_t { value.into() } None => z_value_t { - payload: z_buffer_t::default(), + payload: zc_payload_t::default(), encoding: z_encoding_default(), }, } From 7a94a55dc296673d49d65d756d9c6f0fcbb13b21 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Mon, 8 Apr 2024 14:56:56 +0200 Subject: [PATCH 29/30] fmt --- src/queryable.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/queryable.rs b/src/queryable.rs index 3c62fba4d..dd932188c 100644 --- a/src/queryable.rs +++ b/src/queryable.rs @@ -16,8 +16,8 @@ use crate::attachment::{ z_attachment_iterate, z_attachment_null, z_attachment_t, }; use crate::{ - impl_guarded_transmute, zc_payload_t, 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, zc_owned_payload_t, + 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, zc_owned_payload_t, zc_payload_t, LOG_INVALID_SESSION, }; use libc::c_void; From 0275363057328894f013cf101c3d3c1fa9d202b2 Mon Sep 17 00:00:00 2001 From: Denis Biryukov Date: Mon, 8 Apr 2024 15:17:41 +0200 Subject: [PATCH 30/30] explicit zero-intialization --- tests/z_api_payload_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/z_api_payload_test.c b/tests/z_api_payload_test.c index d2d5da4d4..10b1a3177 100644 --- a/tests/z_api_payload_test.c +++ b/tests/z_api_payload_test.c @@ -23,7 +23,7 @@ void test_reader() { uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - uint8_t data_out[10] = {}; + uint8_t data_out[10] = {0}; z_bytes_t bytes = {.start = data, .len = 10 }; zc_owned_payload_t payload = zc_payload_encode_from_bytes(bytes);