diff --git a/build-resources/opaque-types/src/lib.rs b/build-resources/opaque-types/src/lib.rs index c6941a3c6..ba7aa95f7 100644 --- a/build-resources/opaque-types/src/lib.rs +++ b/build-resources/opaque-types/src/lib.rs @@ -6,13 +6,6 @@ use std::{ thread::JoinHandle, }; -#[cfg(feature = "unstable")] -use zenoh::{ - pubsub::MatchingListener, - liveliness::LivelinessToken, - session::{EntityGlobalId, ZenohId}, - sample::SourceInfo, -}; use zenoh::{ bytes::{Encoding, ZBytes, ZBytesIterator, ZBytesReader, ZBytesWriter}, config::Config, @@ -25,13 +18,20 @@ use zenoh::{ session::Session, time::Timestamp, }; +#[cfg(feature = "unstable")] +use zenoh::{ + liveliness::LivelinessToken, + pubsub::MatchingListener, + sample::SourceInfo, + session::{EntityGlobalId, ZenohId}, +}; #[cfg(all(feature = "shared-memory", feature = "unstable"))] use zenoh::{ shm::zshm, shm::zshmmut, shm::AllocLayout, shm::BufAllocResult, shm::ChunkAllocResult, shm::ChunkDescriptor, shm::DynamicProtocolID, shm::MemoryLayout, shm::PosixShmProviderBackend, shm::ProtocolID, shm::ShmClient, shm::ShmClientStorage, shm::ShmProvider, - shm::ShmProviderBackend, shm::StaticProtocolID, shm::ZShm, shm::ZShmMut, - shm::POSIX_PROTOCOL_ID, shm::ZLayoutError, + shm::ShmProviderBackend, shm::StaticProtocolID, shm::ZLayoutError, shm::ZShm, shm::ZShmMut, + shm::POSIX_PROTOCOL_ID, }; #[macro_export] @@ -56,7 +56,7 @@ get_opaque_type_data!(ZBytes, z_owned_bytes_t); /// A loaned serialized Zenoh data. get_opaque_type_data!(ZBytes, z_loaned_bytes_t); -type CSlice = (usize, isize); +type CSlice = (usize, usize, usize, usize); /// A contiguous owned sequence of bytes allocated by Zenoh. get_opaque_type_data!(CSlice, z_owned_slice_t); diff --git a/docs/api.rst b/docs/api.rst index fd1f24e46..1a0a400e4 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -38,8 +38,10 @@ Functions .. doxygenfunction:: z_slice_drop .. doxygenfunction:: z_slice_empty +.. doxygenfunction:: z_slice_copy_from_buf +.. doxygenfunction:: z_slice_from_buf .. doxygenfunction:: z_view_slice_empty -.. doxygenfunction:: z_view_slice_wrap +.. doxygenfunction:: z_view_slice_from_buf .. doxygenfunction:: z_slice_data .. doxygenfunction:: z_slice_len .. doxygenfunction:: z_slice_is_empty @@ -66,9 +68,10 @@ Functions .. doxygenfunction:: z_string_empty .. doxygenfunction:: z_view_string_empty +.. doxygenfunction:: z_string_copy_from_str +.. doxygenfunction:: z_view_string_from_str +.. doxygenfunction:: z_string_copy_from_substr .. doxygenfunction:: z_string_from_str -.. doxygenfunction:: z_view_string_wrap -.. doxygenfunction:: z_string_from_substr .. doxygenfunction:: z_string_data .. doxygenfunction:: z_string_len .. doxygenfunction:: z_string_is_empty @@ -108,9 +111,17 @@ Functions ^^^^^^^^^ .. doxygenfunction:: z_bytes_len .. doxygenfunction:: z_bytes_serialize_from_slice +.. doxygenfunction:: z_bytes_from_slice +.. doxygenfunction:: z_bytes_serialize_from_buf +.. doxygenfunction:: z_bytes_from_buf +.. doxygenfunction:: z_bytes_from_static_buf +.. doxygenfunction:: z_bytes_serialize_from_string +.. doxygenfunction:: z_bytes_from_string .. doxygenfunction:: z_bytes_serialize_from_str -.. doxygenfunction:: z_bytes_serialize_from_iter -.. doxygenfunction:: z_bytes_serialize_from_pair +.. doxygenfunction:: z_bytes_from_str +.. doxygenfunction:: z_bytes_from_static_str +.. doxygenfunction:: z_bytes_from_iter +.. doxygenfunction:: z_bytes_from_pair .. doxygenfunction:: z_bytes_serialize_from_uint8 .. doxygenfunction:: z_bytes_serialize_from_uint16 diff --git a/docs/examples.rst b/docs/examples.rst index bf826e4f1..f7d27b7f3 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -34,7 +34,7 @@ Publish } z_owned_bytes_t payload; - z_bytes_serialize_from_str(&payload, "value"); + z_bytes_from_static_str(&payload, "value"); z_view_keyexpr_t key_expr; z_view_keyexpr_from_string(&key_expr, "key/expression"); @@ -171,7 +171,7 @@ Queryable } z_owned_bytes_t reply_payload; - z_bytes_serialize_from_str(&reply_payload, "reply"); + z_bytes_from_static_str(&reply_payload, "reply"); z_view_keyexpr_t reply_keyexpr; z_view_keyexpr_from_string(&reply_keyexpr, (const char *)context); diff --git a/examples/z_get.c b/examples/z_get.c index e9c5e1457..486700e35 100644 --- a/examples/z_get.c +++ b/examples/z_get.c @@ -64,7 +64,7 @@ int main(int argc, char **argv) { z_owned_bytes_t payload; if (value != NULL) { - z_bytes_serialize_from_str(&payload, value); + z_bytes_from_static_str(&payload, value); opts.payload = &payload; } z_get(z_loan(s), z_loan(keyexpr), "", z_move(closure), diff --git a/examples/z_ping.c b/examples/z_ping.c index bfb6d2c79..c5ab59364 100644 --- a/examples/z_ping.c +++ b/examples/z_ping.c @@ -78,7 +78,7 @@ int main(int argc, char** argv) { unsigned long elapsed_us = 0; while (elapsed_us < args.warmup_ms * 1000) { - z_bytes_serialize_from_slice(&payload, data, args.size); + z_bytes_from_buf(&payload, data, args.size, NULL, NULL); z_publisher_put(z_loan(pub), z_move(payload), NULL); int s = z_condvar_wait(z_loan(cond), z_loan_mut(mutex)); if (s != 0) { @@ -89,7 +89,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_bytes_serialize_from_slice(&payload, data, args.size); + z_bytes_from_buf(&payload, data, args.size, NULL, NULL); z_clock_t measure_start = z_clock_now(); z_publisher_put(z_loan(pub), z_move(payload), NULL); int s = z_condvar_wait(z_loan(cond), z_loan_mut(mutex)); diff --git a/examples/z_pong.c b/examples/z_pong.c index af060546a..d63916733 100644 --- a/examples/z_pong.c +++ b/examples/z_pong.c @@ -5,11 +5,9 @@ void callback(const z_loaned_sample_t* sample, void* context) { const z_loaned_publisher_t* pub = z_loan(*(z_owned_publisher_t*)context); -#ifdef ZENOH_C // The z_owned_bytes_t API is exclusive to zenoh-c, but allows avoiding some copies. z_owned_bytes_t payload; z_bytes_clone(&payload, z_sample_payload(sample)); z_publisher_put(pub, z_move(payload), NULL); -#endif } void drop(void* context) { z_owned_publisher_t* pub = (z_owned_publisher_t*)context; diff --git a/examples/z_pub_attachment.c b/examples/z_pub_attachment.c index 99868aecd..86fa49732 100644 --- a/examples/z_pub_attachment.c +++ b/examples/z_pub_attachment.c @@ -34,7 +34,7 @@ bool create_attachment_iter(z_owned_bytes_t* kv_pair, void* context) { z_owned_bytes_t k, v; z_bytes_serialize_from_str(&k, it->current->key); z_bytes_serialize_from_str(&v, it->current->value); - z_bytes_serialize_from_pair(kv_pair, z_move(k), z_move(v)); + z_bytes_from_pair(kv_pair, z_move(k), z_move(v)); it->current++; return true; }; @@ -93,7 +93,7 @@ int main(int argc, char** argv) { sprintf(buf_ind, "%d", idx); kvs[1] = (kv_pair_t){.key = "index", .value = buf_ind}; kv_it it = {.current = kvs, .end = kvs + 2}; - z_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void*)&it); + z_bytes_from_iter(&attachment, create_attachment_iter, (void*)&it); options.attachment = &attachment; sprintf(buf, "[%4d] %s", idx, value); diff --git a/examples/z_pub_thr.c b/examples/z_pub_thr.c index 40734a41a..83601ef5d 100644 --- a/examples/z_pub_thr.c +++ b/examples/z_pub_thr.c @@ -59,7 +59,7 @@ int main(int argc, char **argv) { z_owned_bytes_t payload; while (1) { - z_bytes_serialize_from_slice(&payload, value, len); + z_bytes_from_buf(&payload, value, len, NULL, NULL); z_publisher_put(z_loan(pub), z_move(payload), NULL); } diff --git a/examples/z_put.c b/examples/z_put.c index 04644c3cd..f58225d05 100644 --- a/examples/z_put.c +++ b/examples/z_put.c @@ -49,12 +49,12 @@ int main(int argc, char **argv) { z_view_keyexpr_from_str(&ke, keyexpr); z_owned_bytes_t payload; - z_bytes_serialize_from_str(&payload, value); + z_bytes_from_static_str(&payload, value); z_owned_bytes_t attachment, key, val; - z_bytes_serialize_from_str(&key, "hello"); - z_bytes_serialize_from_str(&val, "there"); - z_bytes_serialize_from_pair(&attachment, z_move(key), z_move(val)); + z_bytes_from_static_str(&key, (char *)"hello"); + z_bytes_from_static_str(&val, (char *)"there"); + z_bytes_from_pair(&attachment, z_move(key), z_move(val)); z_put_options_t options; z_put_options_default(&options); diff --git a/examples/z_queryable.c b/examples/z_queryable.c index ad352a785..7b86fcab2 100644 --- a/examples/z_queryable.c +++ b/examples/z_queryable.c @@ -44,7 +44,7 @@ void query_handler(const z_loaned_query_t *query, void *context) { z_query_reply_options_default(&options); z_owned_bytes_t reply_payload; - z_bytes_serialize_from_str(&reply_payload, value); + z_bytes_from_static_str(&reply_payload, (char *)value); z_view_keyexpr_t reply_keyexpr; z_view_keyexpr_from_str(&reply_keyexpr, (const char *)context); diff --git a/examples/z_queryable_with_channels.c b/examples/z_queryable_with_channels.c index 1580f8dec..45805e406 100644 --- a/examples/z_queryable_with_channels.c +++ b/examples/z_queryable_with_channels.c @@ -88,7 +88,7 @@ int main(int argc, char **argv) { z_query_reply_options_default(&options); z_owned_bytes_t reply_payload; - z_bytes_serialize_from_str(&reply_payload, value); + z_bytes_from_static_str(&reply_payload, value); z_query_reply(query, z_loan(ke), z_move(reply_payload), &options); z_drop(z_move(oquery)); } diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 82d96fd0f..e53405f05 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -1195,6 +1195,81 @@ ZENOHC_API void z_bytes_drop(struct z_owned_bytes_t *this_); * Constructs an empty instance of `z_owned_bytes_t`. */ ZENOHC_API void z_bytes_empty(struct z_owned_bytes_t *this_); +/** + * Serializes a data from buffer. + * @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. + * @param data: A pointer to the buffer containing data. `this_` will take ownership of the buffer. + * @param len: Length of the buffer. + * @param deleter: A thread-safe function, that will be called on `data` when `this_` is dropped. Can be `NULL` if `data` is located in static memory and does not require a drop. + * @param context: An optional context to be passed to `deleter`. + * @return 0 in case of success, negative error code otherwise. + */ +ZENOHC_API +z_result_t z_bytes_from_buf(struct z_owned_bytes_t *this_, + uint8_t *data, + size_t len, + void (*deleter)(void *data, void *context), + void *context); +/** + * Constructs payload from an iterator to `z_owned_bytes_t`. + * @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. + * @param iterator_body: Iterator body function, providing data items. Returning false is treated as iteration end. + * @param context: Arbitrary context that will be passed to iterator_body. + * @return 0 in case of success, negative error code otherwise. + */ +ZENOHC_API +z_result_t z_bytes_from_iter(struct z_owned_bytes_t *this_, + bool (*iterator_body)(struct z_owned_bytes_t *data, void *context), + void *context); +/** + * Serializes a pair of `z_owned_bytes_t` objects which are consumed in the process. + * @return 0 in case of success, negative error code otherwise. + */ +ZENOHC_API +z_result_t z_bytes_from_pair(struct z_owned_bytes_t *this_, + struct z_owned_bytes_t *first, + struct z_owned_bytes_t *second); +/** + * Serializes a slice. + * The slice is consumed upon function return. + */ +ZENOHC_API void z_bytes_from_slice(struct z_owned_bytes_t *this_, struct z_owned_slice_t *slice); +/** + * Serializes a statically allocated constant data. + * @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. + * @param data: A pointer to the statically allocated constant data. + * @param len: Number of bytes to serialize. + * @return 0 in case of success, negative error code otherwise. + */ +ZENOHC_API +z_result_t z_bytes_from_static_buf(struct z_owned_bytes_t *this_, + uint8_t *data, + size_t len); +/** + * Serializes a statically allocated constant null-terminated string by aliasing. + * @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. + * @param str: a pointer to the statically allocated constant string. + * @return 0 in case of success, negative error code otherwise. + */ +ZENOHC_API z_result_t z_bytes_from_static_str(struct z_owned_bytes_t *this_, const char *str); +/** + * Serializes a null-terminated string. + * @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. + * @param str: a pointer to the string. `this_` will take ownership of the buffer. + * @param deleter: A thread-safe function, that will be called on `str` when `this_` is dropped. Can be `NULL` if `str` is located in static memory and does not require a drop. + * @param context: An optional context to be passed to `deleter`. + * @return 0 in case of success, negative error code otherwise. + */ +ZENOHC_API +z_result_t z_bytes_from_str(struct z_owned_bytes_t *this_, + char *str, + void (*deleter)(void *data, void *context), + void *context); +/** + * Serializes a string. + * The string is consumed upon function return. + */ +ZENOHC_API void z_bytes_from_string(struct z_owned_bytes_t *this_, struct z_owned_string_t *s); /** * Returns an iterator for multi-element serialized data. * @@ -1267,6 +1342,17 @@ z_result_t z_bytes_reader_seek(struct z_bytes_reader_t *this_, * @return read position indicator on success or -1L if failure occurs. */ ZENOHC_API int64_t z_bytes_reader_tell(struct z_bytes_reader_t *this_); +/** + * Serializes a data from buffer by copying. + * @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. + * @param data: A pointer to the buffer containing data. + * @param len: Length of the buffer. + * @return 0 in case of success, negative error code otherwise. + */ +ZENOHC_API +z_result_t z_bytes_serialize_from_buf(struct z_owned_bytes_t *this_, + const uint8_t *data, + size_t len); /** * Serializes a double. */ @@ -1291,26 +1377,6 @@ ZENOHC_API void z_bytes_serialize_from_int64(struct z_owned_bytes_t *this_, int6 * Serializes a signed integer. */ ZENOHC_API void z_bytes_serialize_from_int8(struct z_owned_bytes_t *this_, int8_t val); -/** - * Constructs payload from an iterator to `z_owned_bytes_t`. - * @param this_: An uninitialized location in memory for `z_owned_bytes_t` will be constructed. - * @param iterator_body: Iterator body function, providing data items. Returning false is treated as iteration end. - * @param context: Arbitrary context that will be passed to iterator_body. - * @return 0 in case of success, negative error code otherwise. - */ -ZENOHC_API -z_result_t z_bytes_serialize_from_iter(struct z_owned_bytes_t *this_, - bool (*iterator_body)(struct z_owned_bytes_t *data, - void *context), - void *context); -/** - * Serializes a pair of `z_owned_bytes_t` objects which are consumed in the process. - * @return 0 in case of success, negative error code otherwise. - */ -ZENOHC_API -z_result_t z_bytes_serialize_from_pair(struct z_owned_bytes_t *this_, - struct z_owned_bytes_t *first, - struct z_owned_bytes_t *second); /** * Serializes from an immutable SHM buffer consuming it */ @@ -1325,28 +1391,25 @@ ZENOHC_API z_result_t z_bytes_serialize_from_shm_mut(struct z_owned_bytes_t *this_, z_owned_shm_mut_t *shm); #endif -/** - * Serializes a slice by aliasing. - */ -ZENOHC_API -void z_bytes_serialize_from_slice(struct z_owned_bytes_t *this_, - const uint8_t *data, - size_t len); /** * Serializes a slice by copying. */ ZENOHC_API -void z_bytes_serialize_from_slice_copy(struct z_owned_bytes_t *this_, - const uint8_t *data, - size_t len); +void z_bytes_serialize_from_slice(struct z_owned_bytes_t *this_, + const struct z_loaned_slice_t *slice); /** - * Serializes a null-terminated string by aliasing. + * Serializes a null-terminated string by copying. + * @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. + * @param str: a pointer to the null-terminated string. `this_` will take ownership of the string. + * @return 0 in case of success, negative error code otherwise. */ -ZENOHC_API void z_bytes_serialize_from_str(struct z_owned_bytes_t *this_, const char *s); +ZENOHC_API z_result_t z_bytes_serialize_from_str(struct z_owned_bytes_t *this_, const char *str); /** - * Serializes a null-terminated string by copying. + * Serializes a string by copying. */ -ZENOHC_API void z_bytes_serialize_from_str_copy(struct z_owned_bytes_t *this_, const char *s); +ZENOHC_API +void z_bytes_serialize_from_string(struct z_owned_bytes_t *this_, + const struct z_loaned_string_t *str); /** * Serializes an unsigned integer. */ @@ -3628,6 +3691,15 @@ ZENOHC_API bool z_slice_check(const struct z_owned_slice_t *this_); * Constructs an owned copy of a slice. */ ZENOHC_API void z_slice_clone(struct z_owned_slice_t *dst, const struct z_loaned_slice_t *this_); +/** + * Constructs a slice by copying a `len` bytes long sequence starting at `start`. + * + * @return -1 if `start == NULL` and `len > 0` (creating an empty slice), 0 otherwise. + */ +ZENOHC_API +z_result_t z_slice_copy_from_buf(struct z_owned_slice_t *this_, + const uint8_t *start, + size_t len); /** * @return the pointer to the slice data. */ @@ -3640,6 +3712,22 @@ ZENOHC_API void z_slice_drop(struct z_owned_slice_t *this_); * Constructs an empty `z_owned_slice_t`. */ ZENOHC_API void z_slice_empty(struct z_owned_slice_t *this_); +/** + * Constructs a slice by transferring ownership of `data` to it. + * @param this_: Pointer to an uninitialized memoery location where slice will be constructed. + * @param data: Pointer to the data to be owned by `this_`. + * @param len: Number of bytes in `data`. + * @param deleter: A thread-safe delete function to free the `data`. Will be called once when `this_` is dropped. Can be NULL, in case if `data` is allocated in static memory. + * @param context: An optional context to be passed to the `deleter`. + * + * @return -1 if `start == NULL` and `len > 0` (creating an empty slice), 0 otherwise. + */ +ZENOHC_API +z_result_t z_slice_from_buf(struct z_owned_slice_t *this_, + uint8_t *data, + size_t len, + void (*drop)(void *data, void *context), + void *context); /** * @return ``true`` if slice is empty, ``false`` otherwise. */ @@ -3768,6 +3856,23 @@ ZENOHC_API bool z_string_check(const struct z_owned_string_t *this_); * Constructs an owned copy of a string. */ ZENOHC_API void z_string_clone(struct z_owned_string_t *dst, const struct z_loaned_string_t *this_); +/** + * Constructs an owned string by copying `str` into it (including terminating 0), using `strlen` (this should therefore not be used with untrusted inputs). + * + * @return -1 if `str == NULL` (and creates a string in a gravestone state), 0 otherwise. + */ +ZENOHC_API +z_result_t z_string_copy_from_str(struct z_owned_string_t *this_, + const char *str); +/** + * Constructs an owned string by copying a `str` substring of length `len`. + * + * @return -1 if `str == NULL` and `len > 0` (and creates a string in a gravestone state), 0 otherwise. + */ +ZENOHC_API +z_result_t z_string_copy_from_substr(struct z_owned_string_t *this_, + const char *str, + size_t len); /** * @return the pointer of the string data. */ @@ -3781,22 +3886,18 @@ ZENOHC_API void z_string_drop(struct z_owned_string_t *this_); */ ZENOHC_API void z_string_empty(struct z_owned_string_t *this_); /** - * Constructs an owned string by copying `str` into it (including terminating 0), using `strlen` (this should therefore not be used with untrusted inputs). - * - * @return -1 if `str == NULL` (and creates a string in a gravestone state), 0 otherwise. - */ -ZENOHC_API -z_result_t z_string_from_str(struct z_owned_string_t *this_, - const char *str); -/** - * Constructs an owned string by copying a `str` substring of length `len`. - * + * Constructs an owned string by transferring ownership of a null-terminated string `str` to it. + * @param this_: Pointer to an uninitialized memory location where an owned string will be constructed. + * @param value: Pointer to a null terminated string to be owned by `this_`. + * @param deleter: A thread-safe delete function to free the `str`. Will be called once when `str` is dropped. Can be NULL, in case if `str` is allocated in static memory. + * @param context: An optional context to be passed to the `deleter`. * @return -1 if `str == NULL` and `len > 0` (and creates a string in a gravestone state), 0 otherwise. */ ZENOHC_API -z_result_t z_string_from_substr(struct z_owned_string_t *this_, - const char *str, - size_t len); +z_result_t z_string_from_str(struct z_owned_string_t *this_, + char *str, + void (*drop)(void *value, void *context), + void *context); /** * @return ``true`` if string is empty, ``false`` otherwise. */ @@ -4032,13 +4133,14 @@ ZENOHC_API bool z_view_slice_check(const struct z_view_slice_t *this_); */ ZENOHC_API void z_view_slice_empty(struct z_view_slice_t *this_); /** - * Constructs a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). + * Constructs a `len` bytes long view starting at `start`. * - * @return -1 if `str == NULL` (and creates an empty view slice), 0 otherwise. + * @return -1 if `start == NULL` and `len > 0` (and creates an empty view slice), 0 otherwise. */ ZENOHC_API -z_result_t z_view_slice_from_str(struct z_view_slice_t *this_, - const char *str); +z_result_t z_view_slice_from_buf(struct z_view_slice_t *this_, + const uint8_t *start, + size_t len); /** * Borrows view slice. */ @@ -4047,15 +4149,6 @@ ZENOHC_API const struct z_loaned_slice_t *z_view_slice_loan(const struct z_view_ * Constructs an empty view slice. */ ZENOHC_API void z_view_slice_null(struct z_view_slice_t *this_); -/** - * Constructs a `len` bytes long view starting at `start`. - * - * @return -1 if `start == NULL` and `len > 0` (and creates an empty view slice), 0 otherwise. - */ -ZENOHC_API -z_result_t z_view_slice_wrap(struct z_view_slice_t *this_, - const uint8_t *start, - size_t len); /** * @return ``true`` if view string is valid, ``false`` if it is in a gravestone state. */ @@ -4064,6 +4157,14 @@ ZENOHC_API bool z_view_string_check(const struct z_view_string_t *this_); * Constructs an empty view string. */ ZENOHC_API void z_view_string_empty(struct z_view_string_t *this_); +/** + * Constructs a view string of `str`, using `strlen` (this should therefore not be used with untrusted inputs). + * + * @return -1 if `str == NULL` (and creates a string in a gravestone state), 0 otherwise. + */ +ZENOHC_API +z_result_t z_view_string_from_str(struct z_view_string_t *this_, + const char *str); /** * Constructs a view string to a specified substring of length `len`. * @@ -4081,14 +4182,6 @@ ZENOHC_API const struct z_loaned_string_t *z_view_string_loan(const struct z_vie * Constructs view string in a gravestone state. */ ZENOHC_API void z_view_string_null(struct z_view_string_t *this_); -/** - * Constructs a view string of `str`, using `strlen` (this should therefore not be used with untrusted inputs). - * - * @return -1 if `str == NULL` (and creates a string in a gravestone state), 0 otherwise. - */ -ZENOHC_API -z_result_t z_view_string_wrap(struct z_view_string_t *this_, - const char *str); /** * Constructs a non-owned non-null-terminated string from the kind of zenoh entity. * diff --git a/src/collections.rs b/src/collections.rs index ae1013e43..37262f382 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -12,24 +12,38 @@ // ZettaScale Zenoh team, // +use core::ffi::c_void; use std::{ hash::Hash, mem::MaybeUninit, ops::{Deref, DerefMut}, - ptr::{null, slice_from_raw_parts}, + ptr::{null, null_mut, slice_from_raw_parts}, slice::from_raw_parts, }; -use libc::{c_char, strlen}; +use libc::strlen; use crate::{ result::{self, z_result_t}, transmute::{LoanedCTypeRef, RustTypeRef, RustTypeRefUninit}, }; -pub struct CSlice(*const u8, isize); +pub struct CSlice { + data: *const u8, + len: usize, + drop: Option, + context: *mut c_void, +} + +pub extern "C" fn _z_drop_c_slice_default(data: *mut c_void, context: *mut c_void) { + let ptr = data as *const u8; + let len = context as usize; + let b = unsafe { Box::from_raw(slice_from_raw_parts(ptr, len).cast_mut()) }; + std::mem::drop(b); +} + #[derive(Default, Clone)] -pub struct CSliceOwned(CSlice); +pub struct CSliceOwned(pub CSlice); #[derive(Default)] pub struct CSliceView(CSlice); @@ -82,12 +96,47 @@ impl CSliceOwned { pub unsafe fn new(data: *const u8, len: usize) -> Result { Ok(Self(CSlice::new_owned(data, len)?)) } + #[allow(clippy::missing_safety_doc)] + pub unsafe fn wrap( + data: *mut u8, + len: usize, + drop: Option, + context: *mut c_void, + ) -> Result { + Ok(CSliceOwned(CSlice::new(data, len, drop, context)?)) + } } impl CSlice { + pub fn new_unchecked( + data: *const u8, + len: usize, + drop: Option, + context: *mut c_void, + ) -> Self { + Self { + data, + len, + drop, + context, + } + } + pub fn new_borrowed_unchecked(data: *const u8, len: usize) -> Self { - let len: isize = len as isize; - Self(data, -len) + Self::new_unchecked(data, len, None, null_mut()) + } + + pub fn new( + data: *mut u8, + len: usize, + drop: Option, + context: *mut c_void, + ) -> Result { + if data.is_null() && len > 0 { + Err(result::Z_EINVAL) + } else { + Ok(Self::new_unchecked(data, len, drop, context)) + } } pub fn new_borrowed(data: *const u8, len: usize) -> Result { @@ -109,7 +158,11 @@ impl CSlice { } let b = unsafe { from_raw_parts(data, len).to_vec().into_boxed_slice() }; let slice = Box::leak(b); - Self(slice.as_ptr(), slice.len() as isize) + CSlice::wrap(slice.as_ptr(), len) + } + + pub fn wrap(data: *const u8, len: usize) -> Self { + Self::new_unchecked(data, len, Some(_z_drop_c_slice_default), len as *mut c_void) } #[allow(clippy::missing_safety_doc)] @@ -122,30 +175,30 @@ impl CSlice { } pub fn slice(&self) -> &'static [u8] { - if self.1 == 0 { + if self.len == 0 { return &[0u8; 0]; } - unsafe { from_raw_parts(self.0, self.1.unsigned_abs()) } + unsafe { from_raw_parts(self.data, self.len) } } pub fn data(&self) -> *const u8 { - self.0 + self.data } pub fn len(&self) -> usize { - self.1.unsigned_abs() + self.len } pub fn is_empty(&self) -> bool { - self.1 == 0 + self.len == 0 } pub fn is_owned(&self) -> bool { - self.1 > 0 + self.drop.is_some() } - pub fn shallow_copy(&self) -> Self { - Self(self.0, self.1) + pub fn clone_to_borrowed(&self) -> Self { + Self::new_borrowed_unchecked(self.data, self.len) } pub fn clone_to_owned(&self) -> CSliceOwned { @@ -161,17 +214,20 @@ impl Clone for CSlice { impl Default for CSlice { fn default() -> Self { - Self(null(), 0) + Self { + data: null(), + len: 0, + drop: None, + context: null_mut(), + } } } impl Drop for CSlice { fn drop(&mut self) { - if !self.is_owned() { - return; + if let Some(drop) = self.drop { + drop(self.data as *mut c_void, self.context); } - let b = unsafe { Box::from_raw(slice_from_raw_parts(self.data(), self.len()).cast_mut()) }; - std::mem::drop(b); } } @@ -190,7 +246,7 @@ impl PartialEq for CSlice { impl From> for CSliceOwned { fn from(value: Vec) -> Self { let slice = Box::leak(value.into_boxed_slice()); - CSliceOwned(CSlice(slice.as_ptr(), slice.len() as isize)) + CSliceOwned(CSlice::wrap(slice.as_ptr(), slice.len())) } } @@ -223,30 +279,12 @@ pub extern "C" fn z_view_slice_null(this: &mut MaybeUninit) { this.as_rust_type_mut_uninit().write(CSliceView::default()); } -/// Constructs a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). -/// -/// @return -1 if `str == NULL` (and creates an empty view slice), 0 otherwise. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_view_slice_from_str( - this: &mut MaybeUninit, - str: *const c_char, -) -> z_result_t { - if str.is_null() { - z_view_slice_empty(this); - result::Z_EINVAL - } else { - z_view_slice_wrap(this, str as *const u8, libc::strlen(str)); - result::Z_OK - } -} - /// Constructs a `len` bytes long view starting at `start`. /// /// @return -1 if `start == NULL` and `len > 0` (and creates an empty view slice), 0 otherwise. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_view_slice_wrap( +pub unsafe extern "C" fn z_view_slice_from_buf( this: &mut MaybeUninit, start: *const u8, len: usize, @@ -332,14 +370,67 @@ pub extern "C" fn z_slice_is_empty(this: &z_loaned_slice_t) -> bool { this.as_rust_type_ref().is_empty() } +/// Constructs a slice by copying a `len` bytes long sequence starting at `start`. +/// +/// @return -1 if `start == NULL` and `len > 0` (creating an empty slice), 0 otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_slice_copy_from_buf( + this: &mut MaybeUninit, + start: *const u8, + len: usize, +) -> z_result_t { + let this = this.as_rust_type_mut_uninit(); + match CSliceOwned::new(start, len) { + Ok(slice) => { + this.write(slice); + result::Z_OK + } + Err(e) => { + this.write(CSliceOwned::default()); + e + } + } +} + +/// Constructs a slice by transferring ownership of `data` to it. +/// @param this_: Pointer to an uninitialized memoery location where slice will be constructed. +/// @param data: Pointer to the data to be owned by `this_`. +/// @param len: Number of bytes in `data`. +/// @param deleter: A thread-safe delete function to free the `data`. Will be called once when `this_` is dropped. Can be NULL, in case if `data` is allocated in static memory. +/// @param context: An optional context to be passed to the `deleter`. +/// +/// @return -1 if `start == NULL` and `len > 0` (creating an empty slice), 0 otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_slice_from_buf( + this: &mut MaybeUninit, + data: *mut u8, + len: usize, + drop: Option, + context: *mut c_void, +) -> z_result_t { + let this = this.as_rust_type_mut_uninit(); + match CSliceOwned::wrap(data, len, drop, context) { + Ok(slice) => { + this.write(slice); + result::Z_OK + } + Err(e) => { + this.write(CSliceOwned::default()); + e + } + } +} + pub use crate::opaque_types::{z_loaned_string_t, z_owned_string_t, z_view_string_t}; #[derive(Default)] -pub struct CString(CSlice); +pub struct CString(pub CSlice); #[derive(Default)] -pub struct CStringOwned(CString); +pub struct CStringOwned(pub CString); #[derive(Default)] -pub struct CStringView(CString); +pub struct CStringView(pub CString); impl CString { pub fn new_borrowed_from_slice(slice: &[u8]) -> Self { @@ -349,9 +440,21 @@ impl CString { impl CStringOwned { #[allow(clippy::missing_safety_doc)] - pub unsafe fn new_owned(data: *const libc::c_char, len: usize) -> Result { + pub unsafe fn new(data: *const libc::c_char, len: usize) -> Result { Ok(CStringOwned(CString(CSlice::new_owned(data as _, len)?))) } + + #[allow(clippy::missing_safety_doc)] + pub unsafe fn wrap( + data: *mut libc::c_char, + len: usize, + drop: Option, + context: *mut c_void, + ) -> Result { + Ok(CStringOwned(CString(CSlice::new( + data as _, len, drop, context, + )?))) + } } impl CStringView { @@ -406,7 +509,7 @@ impl AsRef for CStringView { impl From for CStringOwned { fn from(value: String) -> Self { let slice = Box::leak(value.into_boxed_str()); - CStringOwned(CString(CSlice(slice.as_ptr(), slice.len() as isize))) + CStringOwned(CString(CSlice::wrap(slice.as_ptr(), slice.len()))) } } @@ -480,11 +583,11 @@ pub extern "C" fn z_view_string_loan(this: &z_view_string_t) -> &z_loaned_string /// @return -1 if `str == NULL` (and creates a string in a gravestone state), 0 otherwise. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_string_from_str( +pub unsafe extern "C" fn z_string_copy_from_str( this: &mut MaybeUninit, str: *const libc::c_char, ) -> z_result_t { - z_string_from_substr(this, str, strlen(str)) + z_string_copy_from_substr(this, str, strlen(str)) } /// Constructs an owned string by copying a `str` substring of length `len`. @@ -492,13 +595,40 @@ pub unsafe extern "C" fn z_string_from_str( /// @return -1 if `str == NULL` and `len > 0` (and creates a string in a gravestone state), 0 otherwise. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_string_from_substr( +pub unsafe extern "C" fn z_string_copy_from_substr( this: &mut MaybeUninit, str: *const libc::c_char, len: usize, ) -> z_result_t { let this = this.as_rust_type_mut_uninit(); - match CStringOwned::new_owned(str, len) { + match CStringOwned::new(str, len) { + Ok(slice) => { + this.write(slice); + result::Z_OK + } + Err(e) => { + this.write(CStringOwned::default()); + e + } + } +} + +/// Constructs an owned string by transferring ownership of a null-terminated string `str` to it. +/// @param this_: Pointer to an uninitialized memory location where an owned string will be constructed. +/// @param value: Pointer to a null terminated string to be owned by `this_`. +/// @param deleter: A thread-safe delete function to free the `str`. Will be called once when `str` is dropped. Can be NULL, in case if `str` is allocated in static memory. +/// @param context: An optional context to be passed to the `deleter`. +/// @return -1 if `str == NULL` and `len > 0` (and creates a string in a gravestone state), 0 otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_string_from_str( + this: &mut MaybeUninit, + str: *mut libc::c_char, + drop: Option, + context: *mut c_void, +) -> z_result_t { + let this = this.as_rust_type_mut_uninit(); + match CStringOwned::wrap(str, libc::strlen(str), drop, context) { Ok(slice) => { this.write(slice); result::Z_OK @@ -515,7 +645,7 @@ pub unsafe extern "C" fn z_string_from_substr( /// @return -1 if `str == NULL` (and creates a string in a gravestone state), 0 otherwise. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_view_string_wrap( +pub unsafe extern "C" fn z_view_string_from_str( this: &mut MaybeUninit, str: *const libc::c_char, ) -> z_result_t { @@ -698,7 +828,7 @@ pub extern "C" fn z_string_array_push_by_alias( ) -> usize { let this = this.as_rust_type_mut(); let v = value.as_rust_type_ref(); - this.push(CString(v.shallow_copy())); + this.push(CString(v.clone_to_borrowed())); this.len() } diff --git a/src/config.rs b/src/config.rs index dae51f35f..1407758f6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,7 +19,7 @@ use zenoh::config::{Config, Locator, ValidatedMap, WhatAmI}; use crate::{ result::{self, z_result_t, Z_OK}, transmute::{LoanedCTypeRef, RustTypeRef, RustTypeRefUninit}, - z_owned_string_t, z_string_from_substr, z_string_null, + z_owned_string_t, z_string_copy_from_substr, z_string_null, }; #[no_mangle] @@ -148,7 +148,7 @@ pub unsafe extern "C" fn zc_config_get_from_substr( let val = config.get_json(key).ok(); match val { Some(val) => { - z_string_from_substr( + z_string_copy_from_substr( out_value_string, val.as_ptr() as *const libc::c_char, val.len(), @@ -252,7 +252,7 @@ pub unsafe extern "C" fn zc_config_to_string( match json5::to_string(config) { Ok(s) => { unsafe { - z_string_from_substr( + z_string_copy_from_substr( out_config_string, s.as_ptr() as *const libc::c_char, s.len(), diff --git a/src/encoding.rs b/src/encoding.rs index 9465a0f79..2f25e37c7 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -27,7 +27,7 @@ pub use crate::opaque_types::{z_loaned_encoding_t, z_owned_encoding_t}; use crate::{ result::{self, z_result_t}, transmute::{LoanedCTypeRef, RustTypeRef, RustTypeRefUninit}, - z_owned_string_t, z_string_from_substr, + z_owned_string_t, z_string_copy_from_substr, }; decl_c_type!( @@ -124,7 +124,7 @@ pub unsafe extern "C" fn z_encoding_to_string( out_str: &mut MaybeUninit, ) { let s: Cow<'static, str> = this.as_rust_type_ref().into(); - z_string_from_substr(out_str, s.as_bytes().as_ptr() as _, s.as_bytes().len()); + z_string_copy_from_substr(out_str, s.as_bytes().as_ptr() as _, s.as_bytes().len()); } /// Returns a loaned default `z_loaned_encoding_t`. diff --git a/src/payload.rs b/src/payload.rs index 69ecfbf0d..09a0c5b25 100644 --- a/src/payload.rs +++ b/src/payload.rs @@ -18,6 +18,7 @@ use std::{ io::{Read, Seek, SeekFrom, Write}, mem::MaybeUninit, os::raw::c_void, + ptr::null_mut, slice::{from_raw_parts, from_raw_parts_mut}, }; @@ -30,9 +31,10 @@ pub use crate::opaque_types::{z_loaned_bytes_t, z_owned_bytes_t}; #[cfg(all(feature = "shared-memory", feature = "unstable"))] use crate::result::Z_ENULL; use crate::{ - result::{self, z_result_t, Z_EIO, Z_EPARSE, Z_OK}, - transmute::{LoanedCTypeRef, RustTypeRef, RustTypeRefUninit}, - z_owned_slice_t, z_owned_string_t, CSlice, CSliceOwned, CStringOwned, + result::{self, z_result_t, Z_EINVAL, Z_EIO, Z_EPARSE, Z_OK}, + transmute::{LoanedCTypeRef, OwnedCTypeRef, RustTypeRef, RustTypeRefUninit}, + z_loaned_slice_t, z_loaned_string_t, z_owned_slice_t, z_owned_string_t, z_slice_clone, + z_string_clone, CSlice, CSliceOwned, CStringOwned, }; #[cfg(all(feature = "shared-memory", feature = "unstable"))] use crate::{z_loaned_shm_t, z_owned_shm_mut_t, z_owned_shm_t}; @@ -438,56 +440,187 @@ pub extern "C" fn z_bytes_deserialize_into_double( z_bytes_deserialize_into_arithmetic::(this, dst) } -/// Serializes a slice by aliasing. +fn _z_bytes_serialize_from_cslice(this: &mut MaybeUninit, s: CSlice) { + let payload = ZBytes::from(ZSlice::from(s)); + this.as_rust_type_mut_uninit().write(payload); +} + +/// Serializes a slice. +/// The slice is consumed upon function return. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_bytes_serialize_from_slice( +pub unsafe extern "C" fn z_bytes_from_slice( this: &mut MaybeUninit, - data: *const u8, - len: usize, + slice: &mut z_owned_slice_t, ) { - let s = CSlice::new_borrowed_unchecked(data, len); - let payload = ZBytes::from(ZSlice::from(s)); - this.as_rust_type_mut_uninit().write(payload); + _z_bytes_serialize_from_cslice(this, std::mem::take(slice.as_rust_type_mut())) } /// Serializes a slice by copying. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_bytes_serialize_from_slice_copy( +pub unsafe extern "C" fn z_bytes_serialize_from_slice( + this: &mut MaybeUninit, + slice: &z_loaned_slice_t, +) { + let mut s = MaybeUninit::::uninit(); + z_slice_clone(&mut s, slice); + let mut s_clone = s.assume_init(); + z_bytes_from_slice(this, &mut s_clone) +} + +/// Serializes a data from buffer. +/// @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. +/// @param data: A pointer to the buffer containing data. `this_` will take ownership of the buffer. +/// @param len: Length of the buffer. +/// @param deleter: A thread-safe function, that will be called on `data` when `this_` is dropped. Can be `NULL` if `data` is located in static memory and does not require a drop. +/// @param context: An optional context to be passed to `deleter`. +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_from_buf( + this: &mut MaybeUninit, + data: *mut u8, + len: usize, + deleter: Option, + context: *mut c_void, +) -> z_result_t { + if let Ok(mut s) = CSliceOwned::wrap(data, len, deleter, context) { + z_bytes_from_slice(this, s.as_owned_c_type_mut()); + Z_OK + } else { + Z_EINVAL + } +} + +/// Serializes a statically allocated constant data. +/// @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. +/// @param data: A pointer to the statically allocated constant data. +/// @param len: Number of bytes to serialize. +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_from_static_buf( + this: &mut MaybeUninit, + data: *mut u8, + len: usize, +) -> z_result_t { + if let Ok(mut s) = CSliceOwned::wrap(data as _, len, None, null_mut()) { + z_bytes_from_slice(this, s.as_owned_c_type_mut()); + Z_OK + } else { + Z_EINVAL + } +} + +/// Serializes a data from buffer by copying. +/// @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. +/// @param data: A pointer to the buffer containing data. +/// @param len: Length of the buffer. +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_serialize_from_buf( this: &mut MaybeUninit, data: *const u8, len: usize, +) -> z_result_t { + if let Ok(mut s) = CSliceOwned::new(data, len) { + z_bytes_from_slice(this, s.as_owned_c_type_mut()); + Z_OK + } else { + Z_EINVAL + } +} + +/// Serializes a string. +/// The string is consumed upon function return. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_from_string( + this: &mut MaybeUninit, + s: &mut z_owned_string_t, ) { - let s = CSlice::new_owned_unchecked(data, len); - let payload = ZBytes::from(ZSlice::from(s)); - this.as_rust_type_mut_uninit().write(payload); + // TODO: verify that string is a valid utf-8 string ? + let cs = std::mem::take(&mut s.as_rust_type_mut().0 .0); + _z_bytes_serialize_from_cslice(this, cs) } -/// Serializes a null-terminated string by aliasing. +/// Serializes a string by copying. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_bytes_serialize_from_str( +pub unsafe extern "C" fn z_bytes_serialize_from_string( this: &mut MaybeUninit, - s: *const libc::c_char, + str: &z_loaned_string_t, ) { - z_bytes_serialize_from_slice(this, s as *const u8, libc::strlen(s)); + let mut s = MaybeUninit::::uninit(); + z_string_clone(&mut s, str); + let mut s_clone = s.assume_init(); + z_bytes_from_string(this, &mut s_clone) +} + +/// Serializes a null-terminated string. +/// @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. +/// @param str: a pointer to the string. `this_` will take ownership of the buffer. +/// @param deleter: A thread-safe function, that will be called on `str` when `this_` is dropped. Can be `NULL` if `str` is located in static memory and does not require a drop. +/// @param context: An optional context to be passed to `deleter`. +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_from_str( + this: &mut MaybeUninit, + str: *mut libc::c_char, + deleter: Option, + context: *mut c_void, +) -> z_result_t { + if let Ok(mut s) = CStringOwned::wrap(str, libc::strlen(str), deleter, context) { + z_bytes_from_string(this, s.as_owned_c_type_mut()); + Z_OK + } else { + Z_EINVAL + } +} + +/// Serializes a statically allocated constant null-terminated string by aliasing. +/// @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. +/// @param str: a pointer to the statically allocated constant string. +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_from_static_str( + this: &mut MaybeUninit, + str: *const libc::c_char, +) -> z_result_t { + if let Ok(mut s) = CStringOwned::wrap(str as _, libc::strlen(str), None, null_mut()) { + z_bytes_from_string(this, s.as_owned_c_type_mut()); + Z_OK + } else { + Z_EINVAL + } } /// Serializes a null-terminated string by copying. +/// @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. +/// @param str: a pointer to the null-terminated string. `this_` will take ownership of the string. +/// @return 0 in case of success, negative error code otherwise. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_bytes_serialize_from_str_copy( +pub unsafe extern "C" fn z_bytes_serialize_from_str( this: &mut MaybeUninit, - s: *const libc::c_char, -) { - z_bytes_serialize_from_slice_copy(this, s as *const u8, libc::strlen(s)); + str: *const libc::c_char, +) -> z_result_t { + if let Ok(mut s) = CStringOwned::new(str, libc::strlen(str)) { + z_bytes_from_string(this, s.as_owned_c_type_mut()); + Z_OK + } else { + Z_EINVAL + } } /// Serializes a pair of `z_owned_bytes_t` objects which are consumed in the process. /// @return 0 in case of success, negative error code otherwise. #[no_mangle] -pub extern "C" fn z_bytes_serialize_from_pair( +pub extern "C" fn z_bytes_from_pair( this: &mut MaybeUninit, first: &mut z_owned_bytes_t, second: &mut z_owned_bytes_t, @@ -542,12 +675,12 @@ impl Iterator for ZBytesInIterator { } /// Constructs payload from an iterator to `z_owned_bytes_t`. -/// @param this_: An uninitialized location in memory for `z_owned_bytes_t` will be constructed. +/// @param this_: An uninitialized location in memory where `z_owned_bytes_t` is to be constructed. /// @param iterator_body: Iterator body function, providing data items. Returning false is treated as iteration end. /// @param context: Arbitrary context that will be passed to iterator_body. /// @return 0 in case of success, negative error code otherwise. #[no_mangle] -pub extern "C" fn z_bytes_serialize_from_iter( +pub extern "C" fn z_bytes_from_iter( this: &mut MaybeUninit, iterator_body: extern "C" fn( data: &mut MaybeUninit, diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index 7ab3d47ae..52a46c9b2 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -66,7 +66,7 @@ void query_handler(const z_loaned_query_t *query, void *arg) { z_query_reply_options_default(&_ret_qreply_opt); z_owned_bytes_t payload; - z_bytes_serialize_from_str(&payload, value); + z_bytes_from_static_str(&payload, value); z_query_reply(query, query_ke, z_move(payload), &_ret_qreply_opt); } diff --git a/tests/z_api_payload_test.c b/tests/z_api_payload_test.c index 1edae0125..6c03133cc 100644 --- a/tests/z_api_payload_test.c +++ b/tests/z_api_payload_test.c @@ -26,7 +26,7 @@ void test_reader_seek() { uint8_t data_out[10] = {0}; z_owned_bytes_t payload; - z_bytes_serialize_from_slice(&payload, data, 10); + z_bytes_from_buf(&payload, data, 10, NULL, NULL); z_bytes_reader_t reader = z_bytes_get_reader(z_loan(payload)); assert(z_bytes_reader_tell(&reader) == 0); @@ -57,7 +57,7 @@ void test_reader_read() { uint8_t data_out[10] = {0}; z_owned_bytes_t payload; - z_bytes_serialize_from_slice(&payload, data, 10); + z_bytes_from_buf(&payload, data, 10, NULL, NULL); z_bytes_reader_t reader = z_bytes_get_reader(z_loan(payload)); assert(5 == z_bytes_reader_read(&reader, data_out, 5)); @@ -102,30 +102,60 @@ void test_writer() { z_drop(z_move(payload)); } -void test_slice() { +void custom_deleter(void *data, void *context) { + (void)data; + size_t *cnt = (size_t *)context; + (*cnt)++; +} + +bool z_check_and_drop_payload(z_owned_bytes_t *payload, uint8_t *data, size_t len) { + z_owned_slice_t out; + z_bytes_deserialize_into_slice(z_loan(*payload), &out); + z_drop(z_move(*payload)); + bool res = memcmp(data, z_slice_data(z_loan(out)), len) == 0; + z_drop(z_move(out)); + + return res; +} + +void test_slice(void) { uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + size_t cnt = 0; z_owned_bytes_t payload; - z_bytes_serialize_from_slice(&payload, data, 10); + z_bytes_from_buf(&payload, data, 10, custom_deleter, (void *)&cnt); z_owned_slice_t out; - data[5] = 0; z_bytes_deserialize_into_slice(z_loan(payload), &out); + assert(cnt == 0); + z_drop(z_move(payload)); + assert(cnt == 1); + assert(!memcmp(data, z_slice_data(z_loan(out)), 10)); + z_drop(z_move(out)); z_owned_bytes_t payload2; - z_bytes_serialize_from_slice_copy(&payload2, data, 10); - data[5] = 5; - z_owned_slice_t out2; - z_bytes_deserialize_into_slice(z_loan(payload2), &out2); - data[5] = 0; - assert(!memcmp(data, z_slice_data(z_loan(out2)), 10)); - - z_drop(z_move(payload)); - z_drop(z_move(payload2)); - z_drop(z_move(out)); - z_drop(z_move(out2)); + z_owned_slice_t s; + z_slice_copy_from_buf(&s, data, 10); + z_bytes_serialize_from_slice(&payload2, z_loan(s)); + assert(z_check(s)); + z_drop(z_move(s)); + assert(z_check_and_drop_payload(&payload2, data, 10)); + + z_owned_bytes_t payload3; + z_slice_copy_from_buf(&s, data, 10); + z_bytes_from_slice(&payload3, z_move(s)); + assert(!z_check(s)); + assert(z_check_and_drop_payload(&payload3, data, 10)); + + z_owned_bytes_t payload4; + z_bytes_serialize_from_buf(&payload4, data, 10); + assert(z_check_and_drop_payload(&payload4, data, 10)); + + z_owned_bytes_t payload5; + z_bytes_from_static_buf(&payload5, data, 10); + assert(z_check_and_drop_payload(&payload5, data, 10)); } #define TEST_ARITHMETIC(TYPE, EXT, VAL) \ @@ -153,8 +183,8 @@ void test_arithmetic() { TEST_ARITHMETIC(double, double, -105.001); } -bool iter_body(z_owned_bytes_t* b, void* context) { - uint8_t* val = (uint8_t*)context; +bool iter_body(z_owned_bytes_t *b, void *context) { + uint8_t *val = (uint8_t *)context; if (*val >= 10) { return false; } else { @@ -169,7 +199,7 @@ void test_iter() { z_owned_bytes_t payload; uint8_t context = 0; - z_bytes_serialize_from_iter(&payload, iter_body, (void*)(&context)); + z_bytes_from_iter(&payload, iter_body, (void *)(&context)); z_bytes_iterator_t it = z_bytes_get_iterator(z_loan(payload)); @@ -190,7 +220,7 @@ void test_pair() { z_owned_bytes_t payload, payload1, payload2, payload1_out, payload2_out; z_bytes_serialize_from_int16(&payload1, -500); z_bytes_serialize_from_double(&payload2, 123.45); - z_bytes_serialize_from_pair(&payload, z_move(payload1), z_move(payload2)); + z_bytes_from_pair(&payload, z_move(payload1), z_move(payload2)); z_bytes_deserialize_into_pair(z_loan(payload), &payload1_out, &payload2_out); @@ -203,7 +233,7 @@ void test_pair() { assert(d == 123.45); } -int main(int argc, char** argv) { +int main(int argc, char **argv) { test_reader_seek(); test_reader_read(); test_writer(); diff --git a/tests/z_int_pub_cache_query_sub_test.c b/tests/z_int_pub_cache_query_sub_test.c index a49cff577..25209bbea 100644 --- a/tests/z_int_pub_cache_query_sub_test.c +++ b/tests/z_int_pub_cache_query_sub_test.c @@ -66,7 +66,7 @@ int run_publisher() { // values for cache for (int i = 0; i < values_count / 2; ++i) { z_owned_bytes_t payload; - z_bytes_serialize_from_str(&payload, values[i]); + z_bytes_from_static_str(&payload, values[i]); z_put(z_loan(s), z_loan(ke), z_move(payload), NULL); } @@ -77,7 +77,7 @@ int run_publisher() { // values for subscribe for (int i = values_count / 2; i < values_count; ++i) { z_owned_bytes_t payload; - z_bytes_serialize_from_str(&payload, values[i]); + z_bytes_from_static_str(&payload, values[i]); z_put(z_loan(s), z_loan(ke), z_move(payload), NULL); } diff --git a/tests/z_int_pub_sub_attachment_test.c b/tests/z_int_pub_sub_attachment_test.c index 41f075e62..5cd81f758 100644 --- a/tests/z_int_pub_sub_attachment_test.c +++ b/tests/z_int_pub_sub_attachment_test.c @@ -49,7 +49,7 @@ bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context) { z_owned_bytes_t k, v; z_bytes_serialize_from_str(&k, it->current->key); z_bytes_serialize_from_str(&v, it->current->value); - z_bytes_serialize_from_pair(kv_pair, z_move(k), z_move(v)); + z_bytes_from_pair(kv_pair, z_move(k), z_move(v)); it->current++; return true; }; @@ -117,14 +117,12 @@ int run_publisher() { z_owned_bytes_t attachment; kv_it it = {kvs, kvs + 2}; - z_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&it); + z_bytes_from_iter(&attachment, create_attachment_iter, (void *)&it); options.attachment = &attachment; - z_view_slice_t v_var; - z_view_slice_from_str(&v_var, values[i]); z_owned_bytes_t payload; - z_bytes_serialize_from_slice(&payload, z_slice_data(z_loan(v_var)), z_slice_len(z_loan(v_var))); + z_bytes_from_static_str(&payload, values[i]); z_publisher_put(z_loan(pub), z_move(payload), &options); } diff --git a/tests/z_int_pub_sub_test.c b/tests/z_int_pub_sub_test.c index ca86183d3..cac4fbe6d 100644 --- a/tests/z_int_pub_sub_test.c +++ b/tests/z_int_pub_sub_test.c @@ -71,7 +71,7 @@ int run_publisher() { options.timestamp = &ts; z_owned_bytes_t payload; - z_bytes_serialize_from_str(&payload, values[i]); + z_bytes_from_static_str(&payload, values[i]); z_publisher_put(z_loan(pub), z_move(payload), &options); } diff --git a/tests/z_int_queryable_attachment_test.c b/tests/z_int_queryable_attachment_test.c index 9ab767638..02a24dd34 100644 --- a/tests/z_int_queryable_attachment_test.c +++ b/tests/z_int_queryable_attachment_test.c @@ -47,7 +47,7 @@ bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context) { z_owned_bytes_t k, v; z_bytes_serialize_from_str(&k, it->current->key); z_bytes_serialize_from_str(&v, it->current->value); - z_bytes_serialize_from_pair(kv_pair, z_move(k), z_move(v)); + z_bytes_from_pair(kv_pair, z_move(k), z_move(v)); it->current++; return true; }; @@ -111,12 +111,12 @@ void query_handler(const z_loaned_query_t *query, void *context) { z_owned_bytes_t reply_attachment; kv_pair_t kvs_out[1] = {(kv_pair_t){K_CONST, V_CONST}}; kv_it it_out = {.current = kvs_out, .end = kvs_out + 1}; - z_bytes_serialize_from_iter(&reply_attachment, create_attachment_iter, (void *)&it_out); + z_bytes_from_iter(&reply_attachment, create_attachment_iter, (void *)&it_out); options.attachment = &reply_attachment; z_owned_bytes_t payload; - z_bytes_serialize_from_str(&payload, values[value_num]); + z_bytes_from_static_str(&payload, values[value_num]); z_view_keyexpr_t reply_ke; z_view_keyexpr_from_str(&reply_ke, (const char *)context); @@ -185,7 +185,7 @@ int run_get() { z_owned_bytes_t attachment; kv_it it = {.current = kvs, .end = kvs + 2}; - z_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&it); + z_bytes_from_iter(&attachment, create_attachment_iter, (void *)&it); opts.attachment = &attachment; z_get(z_loan(s), z_loan(ke), "", z_move(closure), &opts); diff --git a/tests/z_int_queryable_test.c b/tests/z_int_queryable_test.c index 2a62e636e..cee948803 100644 --- a/tests/z_int_queryable_test.c +++ b/tests/z_int_queryable_test.c @@ -48,7 +48,7 @@ void query_handler(const z_loaned_query_t *query, void *context) { // options.source_info = &source_info; z_owned_bytes_t payload; - z_bytes_serialize_from_str(&payload, values[value_num]); + z_bytes_from_static_str(&payload, values[value_num]); z_view_keyexpr_t reply_ke; z_view_keyexpr_from_str(&reply_ke, (const char *)context);