diff --git a/CMakeLists.txt b/CMakeLists.txt index 306c62b3d..7d35cb139 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -374,6 +374,8 @@ if(UNIX OR MSVC) add_executable(z_test_fragment_rx ${PROJECT_SOURCE_DIR}/tests/z_test_fragment_rx.c) add_executable(z_perf_tx ${PROJECT_SOURCE_DIR}/tests/z_perf_tx.c) add_executable(z_perf_rx ${PROJECT_SOURCE_DIR}/tests/z_perf_rx.c) + add_executable(z_bytes_test ${PROJECT_SOURCE_DIR}/tests/z_bytes_test.c) + add_executable(z_api_bytes_test ${PROJECT_SOURCE_DIR}/tests/z_api_bytes_test.c) target_link_libraries(z_data_struct_test ${Libname}) target_link_libraries(z_channels_test ${Libname}) @@ -388,6 +390,8 @@ if(UNIX OR MSVC) target_link_libraries(z_test_fragment_rx ${Libname}) target_link_libraries(z_perf_tx ${Libname}) target_link_libraries(z_perf_rx ${Libname}) + target_link_libraries(z_bytes_test ${Libname}) + target_link_libraries(z_api_bytes_test ${Libname}) configure_file(${PROJECT_SOURCE_DIR}/tests/modularity.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/modularity.py COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/raweth.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/raweth.py COPYONLY) @@ -405,6 +409,8 @@ if(UNIX OR MSVC) add_test(z_keyexpr_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_keyexpr_test) add_test(z_api_null_drop_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_api_null_drop_test) add_test(z_api_double_drop_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_api_double_drop_test) + add_test(z_bytes_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_bytes_test) + add_test(z_api_bytes_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_api_bytes_test) endif() if(BUILD_MULTICAST) diff --git a/docs/api.rst b/docs/api.rst index 10cce4f84..c51bb4e07 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -54,6 +54,9 @@ Data Structures .. autoctype:: types.h::zp_send_keep_alive_options_t .. autoctype:: types.h::zp_send_join_options_t .. autoctype:: types.h::z_qos_t +.. autoctype:: types.h::z_bytes_reader_t +.. autoctype:: types.h::z_bytes_iterator_t + Owned Types ~~~~~~~~~~~ @@ -128,6 +131,10 @@ TODO: owned type description Represents an array of non null-terminated string. +.. c:type:: z_owned_bytes_writer_t + + Represents a writer for serialized data. + Loaned Types ~~~~~~~~~~~ @@ -201,6 +208,10 @@ TODO: loaned type description Represents an array of non null-terminated string. +.. c:type:: z_loaned_bytes_writer_t + + Represents a writer for serialized data. + View Types ~~~~~~~~~~~ @@ -319,6 +330,17 @@ Primitives .. autocfunction:: primitives.h::z_bytes_serialize_from_slice_copy .. autocfunction:: primitives.h::z_bytes_serialize_from_string .. autocfunction:: primitives.h::z_bytes_serialize_from_string_copy +.. autocfunction:: primitives.h::z_bytes_empty +.. autocfunction:: primitives.h::z_bytes_len +.. autocfunction:: primitives.h::z_bytes_is_empty +.. autocfunction:: primitives.h::z_bytes_get_iterator +.. autocfunction:: primitives.h::z_bytes_iterator_next +.. autocfunction:: primitives.h::z_bytes_get_reader +.. autocfunction:: primitives.h::z_bytes_reader_read +.. autocfunction:: primitives.h::z_bytes_reader_seek +.. autocfunction:: primitives.h::z_bytes_reader_tell +.. autocfunction:: primitives.h::z_bytes_get_writer +.. autocfunction:: primitives.h::z_bytes_writer_write .. autocfunction:: primitives.h::z_timestamp_check .. autocfunction:: primitives.h::z_query_target_default .. autocfunction:: primitives.h::z_query_consolidation_auto diff --git a/examples/unix/c11/z_get_attachment.c b/examples/unix/c11/z_get_attachment.c index f807ee51b..83fab15ea 100644 --- a/examples/unix/c11/z_get_attachment.c +++ b/examples/unix/c11/z_get_attachment.c @@ -46,18 +46,7 @@ typedef struct kv_pairs_rx_t { static z_condvar_t cond; static z_mutex_t mutex; -size_t kv_pairs_size(kv_pairs_tx_t *kvp) { - size_t ret = 0; - for (size_t i = 0; i < kvp->len; i++) { - // Size fields - ret += 2 * sizeof(uint32_t); - // Data size - ret += strlen(kvp->data[i].key) + strlen(kvp->data[i].value); - } - return ret; -} - -_Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context, size_t *curr_idx) { +_Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context) { kv_pairs_tx_t *kvs = (kv_pairs_tx_t *)(context); z_owned_bytes_t k, v; if (kvs->current_idx >= kvs->len) { @@ -65,17 +54,18 @@ _Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context, size_t *cu } else { z_bytes_serialize_from_string(&k, kvs->data[kvs->current_idx].key); z_bytes_serialize_from_string(&v, kvs->data[kvs->current_idx].value); - zp_bytes_serialize_from_pair(kv_pair, z_move(k), z_move(v), curr_idx); + z_bytes_serialize_from_pair(kv_pair, z_move(k), z_move(v)); kvs->current_idx++; return true; } } void parse_attachment(kv_pairs_rx_t *kvp, const z_loaned_bytes_t *attachment) { - size_t curr_idx = 0; - z_owned_bytes_t first, second; - while ((kvp->current_idx < kvp->len) && - (zp_bytes_deserialize_into_pair(attachment, &first, &second, &curr_idx) == 0)) { + z_owned_bytes_t kv, first, second; + z_bytes_iterator_t iter = z_bytes_get_iterator(attachment); + + while (kvp->current_idx < kvp->len && z_bytes_iterator_next(&iter, &kv)) { + z_bytes_deserialize_into_pair(z_loan(kv), &first, &second); z_bytes_deserialize_into_string(z_loan(first), &kvp->data[kvp->current_idx].key); z_bytes_deserialize_into_string(z_loan(second), &kvp->data[kvp->current_idx].value); z_bytes_drop(&first); @@ -220,7 +210,7 @@ int main(int argc, char **argv) { kvs[0] = (kv_pair_t){.key = "test_key", .value = "test_value"}; kv_pairs_tx_t ctx = (kv_pairs_tx_t){.data = kvs, .current_idx = 0, .len = 1}; z_owned_bytes_t attachment; - zp_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&ctx, kv_pairs_size(&ctx)); + z_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&ctx); opts.attachment = z_move(attachment); z_owned_closure_reply_t callback; diff --git a/examples/unix/c11/z_pub_attachment.c b/examples/unix/c11/z_pub_attachment.c index cad72d9de..b9e793e2e 100644 --- a/examples/unix/c11/z_pub_attachment.c +++ b/examples/unix/c11/z_pub_attachment.c @@ -35,19 +35,7 @@ typedef struct kv_pairs_t { #if Z_FEATURE_PUBLICATION == 1 -// Return the total serialized size of the key value pairs -size_t kv_pairs_size(kv_pairs_t *kvp) { - size_t ret = 0; - for (size_t i = 0; i < kvp->len; i++) { - // Size fields - ret += 2 * sizeof(uint32_t); - // Data size - ret += strlen(kvp->data[i].key) + strlen(kvp->data[i].value); - } - return ret; -} - -_Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context, size_t *curr_idx) { +_Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context) { kv_pairs_t *kvs = (kv_pairs_t *)(context); z_owned_bytes_t k, v; if (kvs->current_idx >= kvs->len) { @@ -55,7 +43,7 @@ _Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context, size_t *cu } else { z_bytes_serialize_from_string(&k, kvs->data[kvs->current_idx].key); z_bytes_serialize_from_string(&v, kvs->data[kvs->current_idx].value); - zp_bytes_serialize_from_pair(kv_pair, z_move(k), z_move(v), curr_idx); + z_bytes_serialize_from_pair(kv_pair, z_move(k), z_move(v)); kvs->current_idx++; return true; } @@ -172,7 +160,7 @@ int main(int argc, char **argv) { sprintf(buf_ind, "%d", idx); kvs[1] = (kv_pair_t){.key = "index", .value = buf_ind}; kv_pairs_t ctx = (kv_pairs_t){.data = kvs, .current_idx = 0, .len = 2}; - zp_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&ctx, kv_pairs_size(&ctx)); + z_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&ctx); options.attachment = z_move(attachment); // Add encoding value diff --git a/examples/unix/c11/z_queryable_attachment.c b/examples/unix/c11/z_queryable_attachment.c index 7715e28ef..dba0810e8 100644 --- a/examples/unix/c11/z_queryable_attachment.c +++ b/examples/unix/c11/z_queryable_attachment.c @@ -58,7 +58,7 @@ size_t kv_pairs_size(kv_pairs_tx_t *kvp) { return ret; } -_Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context, size_t *curr_idx) { +_Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context) { kv_pairs_tx_t *kvs = (kv_pairs_tx_t *)(context); z_owned_bytes_t k, v; if (kvs->current_idx >= kvs->len) { @@ -66,17 +66,18 @@ _Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context, size_t *cu } else { z_bytes_serialize_from_string(&k, kvs->data[kvs->current_idx].key); z_bytes_serialize_from_string(&v, kvs->data[kvs->current_idx].value); - zp_bytes_serialize_from_pair(kv_pair, z_move(k), z_move(v), curr_idx); + z_bytes_serialize_from_pair(kv_pair, z_move(k), z_move(v)); kvs->current_idx++; return true; } } void parse_attachment(kv_pairs_rx_t *kvp, const z_loaned_bytes_t *attachment) { - size_t curr_idx = 0; - z_owned_bytes_t first, second; - while ((kvp->current_idx < kvp->len) && - (zp_bytes_deserialize_into_pair(attachment, &first, &second, &curr_idx) == 0)) { + z_owned_bytes_t kv, first, second; + z_bytes_iterator_t iter = z_bytes_get_iterator(attachment); + + while (kvp->current_idx < kvp->len && z_bytes_iterator_next(&iter, &kv)) { + z_bytes_deserialize_into_pair(z_loan(kv), &first, &second); z_bytes_deserialize_into_string(z_loan(first), &kvp->data[kvp->current_idx].key); z_bytes_deserialize_into_string(z_loan(second), &kvp->data[kvp->current_idx].value); z_bytes_drop(&first); @@ -134,7 +135,7 @@ void query_handler(const z_loaned_query_t *query, void *ctx) { kvs[0] = (kv_pair_t){.key = "reply_key", .value = "reply_value"}; kv_pairs_tx_t kv_ctx = (kv_pairs_tx_t){.data = kvs, .current_idx = 0, .len = 1}; z_owned_bytes_t attachment; - zp_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&kv_ctx, kv_pairs_size(&kv_ctx)); + z_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&kv_ctx); z_query_reply_options_t options; z_query_reply_options_default(&options); diff --git a/examples/unix/c11/z_sub_attachment.c b/examples/unix/c11/z_sub_attachment.c index 92854d2c6..5038c2ae6 100644 --- a/examples/unix/c11/z_sub_attachment.c +++ b/examples/unix/c11/z_sub_attachment.c @@ -38,10 +38,11 @@ typedef struct kv_pairs_t { static int msg_nb = 0; void parse_attachment(kv_pairs_t *kvp, const z_loaned_bytes_t *attachment) { - size_t curr_idx = 0; - z_owned_bytes_t first, second; - while ((kvp->current_idx < kvp->len) && - (zp_bytes_deserialize_into_pair(attachment, &first, &second, &curr_idx) == 0)) { + z_owned_bytes_t kv, first, second; + z_bytes_iterator_t iter = z_bytes_get_iterator(attachment); + + while (kvp->current_idx < kvp->len && z_bytes_iterator_next(&iter, &kv)) { + z_bytes_deserialize_into_pair(z_loan(kv), &first, &second); z_bytes_deserialize_into_string(z_loan(first), &kvp->data[kvp->current_idx].key); z_bytes_deserialize_into_string(z_loan(second), &kvp->data[kvp->current_idx].value); z_bytes_drop(&first); diff --git a/include/zenoh-pico/api/olv_macros.h b/include/zenoh-pico/api/olv_macros.h index bae04c382..8c93f8010 100644 --- a/include/zenoh-pico/api/olv_macros.h +++ b/include/zenoh-pico/api/olv_macros.h @@ -73,6 +73,29 @@ } \ } +#define _Z_OWNED_FUNCTIONS_PTR_TRIVIAL_IMPL(type, name) \ + _Bool z_##name##_check(const z_owned_##name##_t *obj) { return obj->_val != NULL; } \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *obj) { return obj->_val; } \ + z_loaned_##name##_t *z_##name##_loan_mut(z_owned_##name##_t *obj) { return obj->_val; } \ + void z_##name##_null(z_owned_##name##_t *obj) { obj->_val = NULL; } \ + z_owned_##name##_t *z_##name##_move(z_owned_##name##_t *obj) { return obj; } \ + int8_t z_##name##_clone(z_owned_##name##_t *obj, const z_loaned_##name##_t *src) { \ + int8_t ret = _Z_RES_OK; \ + obj->_val = (type *)z_malloc(sizeof(type)); \ + if (obj->_val != NULL) { \ + *obj->_val = *src; \ + } else { \ + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; \ + } \ + return ret; \ + } \ + void z_##name##_drop(z_owned_##name##_t *obj) { \ + if ((obj != NULL) && (obj->_val != NULL)) { \ + z_free(obj->_val); \ + obj->_val = NULL; \ + } \ + } + #define _Z_OWNED_FUNCTIONS_RC_IMPL(name) \ _Bool z_##name##_check(const z_owned_##name##_t *val) { return val->_rc.in != NULL; } \ const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *val) { return &val->_rc; } \ @@ -132,6 +155,9 @@ // Gets internal value from refcounted type (e.g. z_loaned_session_t, z_query_t) #define _Z_RC_IN_VAL(arg) ((arg)->in->val) +// Checks if refcounted type is initialized +#define _Z_RC_IS_NULL(arg) ((arg)->in == NULL) + // Gets internal value from refcounted owned type (e.g. z_owned_session_t, z_owned_query_t) #define _Z_OWNED_RC_IN_VAL(arg) ((arg)->_rc.in->val) diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index 2974b333f..c5f680025 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -613,13 +613,11 @@ int8_t z_bytes_deserialize_into_string(const z_loaned_bytes_t *bytes, z_owned_st * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. * first: Pointer to an uninitialized :c:type:`z_owned_bytes_t` to contain the first element. * second: Pointer to an uninitialized :c:type:`z_owned_bytes_t` to contain the second element. - * curr_idx: Pointer to the current decoding index. * * Return: * ``0`` if decode successful, or a ``negative value`` otherwise. */ -int8_t zp_bytes_deserialize_into_pair(const z_loaned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second, - size_t *curr_idx); +int8_t z_bytes_deserialize_into_pair(const z_loaned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second); /** * Encodes a signed integer into a :c:type:`z_owned_bytes_t` @@ -795,29 +793,152 @@ int8_t z_bytes_serialize_from_string_copy(z_owned_bytes_t *bytes, const char *s) * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded payload. * iterator_body: Iterator body function, providing data items. Returning false is treated as iteration end. * context: Arbitrary context that will be passed to iterator_body. - * total_len: The length of all the items to encode. * * Return: * ``0`` if encode successful, ``negative value`` otherwise. */ -int8_t zp_bytes_serialize_from_iter(z_owned_bytes_t *bytes, - _Bool (*iterator_body)(z_owned_bytes_t *data, void *context, size_t *curr_idx), - void *context, size_t total_len); +int8_t z_bytes_serialize_from_iter(z_owned_bytes_t *bytes, _Bool (*iterator_body)(z_owned_bytes_t *data, void *context), + void *context); /** * Append a pair of `z_owned_bytes` objects which are consumed in the process. * * Parameters: - * bytes: An pre-initialized :c:type:`z_owned_bytes_t` to contain the encoded pair. + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded pair. * first: Pointer to the first `z_owned_bytes` to encode. * second: Pointer to the second `z_owned_bytes` to encode. - * curr_idx: Pointer to the current encoding index value. * * Return: * ``0`` if encode successful, ``negative value`` otherwise. */ -int8_t zp_bytes_serialize_from_pair(z_owned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second, - size_t *curr_idx); +int8_t z_bytes_serialize_from_pair(z_owned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second); + +/** + * Parameters: + * bytes: Pointer to an unitialized :c:type:`z_lowned_bytes_t` instance. + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_empty(z_owned_bytes_t *bytes); + +/** + * Returns total number of bytes in the container. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * Return: + * Number of bytes in the container. + */ +size_t z_bytes_len(const z_loaned_bytes_t *bytes); + +/** + * Checks if container is empty + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * Return: + * ``true`` if conainer is empty, ``false`` otherwise. + */ +_Bool z_bytes_is_empty(const z_loaned_bytes_t *bytes); + +/** + * Returns an iterator for multi-element serialized data. + * + * Parameters: + * bytes: Data to iterate over. + * + * Return: + * The constructed :c:type:`z_bytes_iterator_t`. + */ +z_bytes_iterator_t z_bytes_get_iterator(const z_loaned_bytes_t *bytes); + +/** + * Constructs :c:type:`z_owned_bytes_t` object corresponding to the next element of serialized data. + * + * Will construct null-state `z_owned_bytes_t` when iterator reaches the end (or in case of error). + * + * Parameters: + * iter: An iterator over multi-element serialized data. + * out: An uninitialized :c:type:`z_owned_bytes_t` that will contained next serialized element. + * Return: + * ``false`` when iterator reaches the end, ``true`` otherwise. + */ +_Bool z_bytes_iterator_next(z_bytes_iterator_t *iter, z_owned_bytes_t *out); + +/** + * Returns a reader for the `bytes`. + * + * The `bytes` should outlive the reader and should not be modified, while reader is in use. + * + * Parameters: + * bytes: Data to read. + * + * Return: + * The constructed :c:type:`z_bytes_reader_t`. + */ +z_bytes_reader_t z_bytes_get_reader(const z_loaned_bytes_t *bytes); + +/** + * Reads data into specified destination. + * + * Parameters: + * reader: Data reader to read from. + * dst: Buffer where the read data is written. + * len: Maximum number of bytes to read. + * + * Return: + * Number of bytes read. If return value is smaller than `len`, it means that the end of the data was reached. + */ +size_t z_bytes_reader_read(z_bytes_reader_t *reader, uint8_t *dst, size_t len); +/** + * Sets the `reader` position indicator for the payload to the value pointed to by offset. + * The new position is exactly `offset` bytes measured from the beginning of the payload if origin is `SEEK_SET`, + * from the current reader position if origin is `SEEK_CUR`, and from the end of the payload if origin is `SEEK_END`. + * + * Parameters: + * reader: Data reader to reposition. + * offset: New position ffset in bytes. + * origin: Origin for the new position. + * + * Return: + * ​0​ upon success, negative error code otherwise. + */ +int8_t z_bytes_reader_seek(z_bytes_reader_t *reader, int64_t offset, int origin); +/** + * Gets the read position indicator. + * + * Parameters: + * reader: Data reader to get position of. + * + * Return: + * Read position indicator on success or -1L if failure occurs. + */ +int64_t z_bytes_reader_tell(z_bytes_reader_t *reader); + +/** + * Constructs writer for :c:type:`z_loaned_bytes_t`. + * + * Parameters: + * bytes: Data container to write to. + * writer: Uninitialized memory location where writer is to be constructed. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_get_writer(z_loaned_bytes_t *bytes, z_owned_bytes_writer_t *writer); + +/** + * Writes `len` bytes from `src` into underlying :c:type:`z_loaned_bytes_t. + * + * Parameters: + * writer: A data writer + * src: Buffer to write from. + * len: Number of bytes to write. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_writer_write(z_loaned_bytes_writer_t *writer, const uint8_t *src, size_t len); /** * Checks validity of a timestamp @@ -1077,6 +1198,7 @@ _Z_OWNED_FUNCTIONS_DEF(z_loaned_sample_t, z_owned_sample_t, sample) _Z_OWNED_FUNCTIONS_DEF(z_loaned_query_t, z_owned_query_t, query) _Z_OWNED_FUNCTIONS_DEF(z_loaned_slice_t, z_owned_slice_t, slice) _Z_OWNED_FUNCTIONS_DEF(z_loaned_bytes_t, z_owned_bytes_t, bytes) +_Z_OWNED_FUNCTIONS_DEF(z_loaned_bytes_writer_t, z_owned_bytes_writer_t, bytes_writer) _Z_OWNED_FUNCTIONS_DEF(z_loaned_reply_err_t, z_owned_reply_err_t, reply_err) _Z_OWNED_FUNCTIONS_CLOSURE_DEF(z_owned_closure_sample_t, closure_sample) diff --git a/include/zenoh-pico/api/types.h b/include/zenoh-pico/api/types.h index 7c20bd47f..305dacbc7 100644 --- a/include/zenoh-pico/api/types.h +++ b/include/zenoh-pico/api/types.h @@ -16,6 +16,7 @@ #define INCLUDE_ZENOH_PICO_API_TYPES_H #include "olv_macros.h" +#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/list.h" #include "zenoh-pico/collections/slice.h" @@ -74,6 +75,22 @@ _Z_LOANED_TYPE(_z_slice_t, slice) _Z_OWNED_TYPE_PTR(_z_bytes_t, bytes) _Z_LOANED_TYPE(_z_bytes_t, bytes) +/** + * Represents a writer for serialized data. + */ +_Z_OWNED_TYPE_PTR(_z_bytes_writer_t, bytes_writer) +_Z_LOANED_TYPE(_z_bytes_writer_t, bytes_writer) + +/** + * An iterator over multi-element serialized data. + */ +typedef _z_bytes_iterator_t z_bytes_iterator_t; + +/** + * A reader for serialized data. + */ +typedef _z_bytes_reader_t z_bytes_reader_t; + /** * Represents a string without null-terminator. * diff --git a/include/zenoh-pico/collections/arc_slice.h b/include/zenoh-pico/collections/arc_slice.h new file mode 100644 index 000000000..2e6c1bf67 --- /dev/null +++ b/include/zenoh-pico/collections/arc_slice.h @@ -0,0 +1,55 @@ +// +// Copyright (c) 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 +// 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, +// + +#ifndef ZENOH_PICO_COLLECTIONS_ARC_SLICE_H +#define ZENOH_PICO_COLLECTIONS_ARC_SLICE_H + +#include +#include +#include +#include + +#include "refcount.h" +#include "slice.h" +#include "zenoh-pico/system/platform-common.h" + +_Z_REFCOUNT_DEFINE(_z_slice, _z_slice) + +/*-------- ArcSlice --------*/ +/** + * An atomically reference counted subslice. + * + * Members: + * _z_slice_rc_t len: Rc counted slice. + * size_t start: Offset to the subslice start. + * size_t len: Length of the subslice. + */ + +typedef struct { + _z_slice_rc_t slice; + size_t start; + size_t len; +} _z_arc_slice_t; + +_z_arc_slice_t _z_arc_slice_empty(void); +_z_arc_slice_t _z_arc_slice_wrap(_z_slice_t s, size_t offset, size_t len); +_z_arc_slice_t _z_arc_slice_get_subslice(const _z_arc_slice_t* s, size_t offset, size_t len); +size_t _z_arc_slice_len(const _z_arc_slice_t* s); +_Bool _z_arc_slice_is_empty(const _z_arc_slice_t* s); +const uint8_t* _z_arc_slice_data(const _z_arc_slice_t* s); +int8_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src); +int8_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src); +int8_t _z_arc_slice_drop(_z_arc_slice_t* s); + +#endif /* ZENOH_PICO_COLLECTIONS_ARC_SLICE_H */ diff --git a/include/zenoh-pico/collections/bytes.h b/include/zenoh-pico/collections/bytes.h new file mode 100644 index 000000000..56672879c --- /dev/null +++ b/include/zenoh-pico/collections/bytes.h @@ -0,0 +1,117 @@ +// +// Copyright (c) 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 +// 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, +// + +#ifndef ZENOH_PICO_COLLECTIONS_BYTES_H +#define ZENOH_PICO_COLLECTIONS_BYTES_H + +#include +#include +#include + +#include "arc_slice.h" +#include "vec.h" +#include "zenoh-pico/protocol/iobuf.h" + +inline size_t _z_arc_slice_size(const _z_arc_slice_t *s) { + (void)s; + return sizeof(_z_arc_slice_t); +} +static inline void _z_arc_slice_elem_move(void *dst, void *src) { + _z_arc_slice_move((_z_arc_slice_t *)dst, (_z_arc_slice_t *)src); +} +_Z_ELEM_DEFINE(_z_arc_slice, _z_arc_slice_t, _z_arc_slice_size, _z_arc_slice_drop, _z_arc_slice_copy) +_Z_SVEC_DEFINE(_z_arc_slice, _z_arc_slice_t) + +/*-------- Bytes --------*/ +/** + * A container for slices. + * + * Members: + * _z_slice_vec_t _slices: contents of the container. + */ + +typedef struct { + _z_arc_slice_svec_t _slices; +} _z_bytes_t; + +_Bool _z_bytes_check(const _z_bytes_t *bytes); +_z_bytes_t _z_bytes_null(void); +int8_t _z_bytes_append_bytes(_z_bytes_t *dst, _z_bytes_t *src); +int8_t _z_bytes_append_slice(_z_bytes_t *dst, _z_arc_slice_t *s); +int8_t _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src); +_z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src); +void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src); +void _z_bytes_drop(_z_bytes_t *bytes); +void _z_bytes_free(_z_bytes_t **bs); +size_t _z_bytes_num_slices(const _z_bytes_t *bs); +_z_arc_slice_t *_z_bytes_get_slice(const _z_bytes_t *bs, size_t i); +size_t _z_bytes_len(const _z_bytes_t *bs); +_Bool _z_bytes_is_empty(const _z_bytes_t *bs); +int8_t _z_bytes_to_uint8(const _z_bytes_t *bs, uint8_t *u); +int8_t _z_bytes_to_uint16(const _z_bytes_t *bs, uint16_t *u); +int8_t _z_bytes_to_uint32(const _z_bytes_t *bs, uint32_t *u); +int8_t _z_bytes_to_uint64(const _z_bytes_t *bs, uint64_t *u); +int8_t _z_bytes_to_float(const _z_bytes_t *bs, float *f); +int8_t _z_bytes_to_double(const _z_bytes_t *bs, double *d); +int8_t _z_bytes_to_slice(const _z_bytes_t *bytes, _z_slice_t *s); +int8_t _z_bytes_from_slice(_z_bytes_t *b, _z_slice_t s); +int8_t _z_bytes_from_uint8(_z_bytes_t *b, uint8_t val); +int8_t _z_bytes_from_uint16(_z_bytes_t *b, uint16_t val); +int8_t _z_bytes_from_uint32(_z_bytes_t *b, uint32_t val); +int8_t _z_bytes_from_uint64(_z_bytes_t *b, uint64_t val); +int8_t _z_bytes_from_float(_z_bytes_t *b, float val); +int8_t _z_bytes_from_double(_z_bytes_t *b, double val); +size_t _z_bytes_to_buf(const _z_bytes_t *bytes, uint8_t *dst, size_t len); +int8_t _z_bytes_from_buf(_z_bytes_t *b, const uint8_t *src, size_t len); +int8_t _z_bytes_serialize_from_pair(_z_bytes_t *out, _z_bytes_t *first, _z_bytes_t *second); +int8_t _z_bytes_deserialize_into_pair(const _z_bytes_t *bs, _z_bytes_t *first_out, _z_bytes_t *second_out); +_z_slice_t _z_bytes_try_get_contiguous(const _z_bytes_t *bs); + +typedef struct { + size_t slice_idx; + size_t in_slice_idx; + size_t byte_idx; + const _z_bytes_t *bytes; +} _z_bytes_reader_t; + +_z_bytes_reader_t _z_bytes_get_reader(const _z_bytes_t *bytes); +int8_t _z_bytes_reader_seek(_z_bytes_reader_t *reader, int64_t offset, int origin); +int64_t _z_bytes_reader_tell(const _z_bytes_reader_t *reader); +int8_t _z_bytes_reader_read_slices(_z_bytes_reader_t *reader, size_t len, _z_bytes_t *out); +size_t _z_bytes_reader_read(_z_bytes_reader_t *reader, uint8_t *buf, size_t len); + +typedef struct { + _z_bytes_reader_t _reader; +} _z_bytes_iterator_t; + +_z_bytes_iterator_t _z_bytes_get_iterator(const _z_bytes_t *bytes); +int8_t _z_bytes_iterator_next(_z_bytes_iterator_t *iter, _z_bytes_t *b); + +typedef struct { + uint8_t *cache; + size_t cache_size; + _z_bytes_t *bytes; +} _z_bytes_writer_t; + +_z_bytes_writer_t _z_bytes_get_writer(_z_bytes_t *bytes, size_t cache_size); +int8_t _z_bytes_writer_write(_z_bytes_writer_t *writer, const uint8_t *src, size_t len); +int8_t _z_bytes_writer_ensure_cache(_z_bytes_writer_t *writer); + +typedef struct { + _z_bytes_writer_t writer; +} _z_bytes_iterator_writer_t; + +_z_bytes_iterator_writer_t _z_bytes_get_iterator_writer(_z_bytes_t *bytes); +int8_t _z_bytes_iterator_writer_write(_z_bytes_iterator_writer_t *writer, _z_bytes_t *bytes); +#endif /* ZENOH_PICO_COLLECTIONS_BYTES_H */ diff --git a/include/zenoh-pico/collections/element.h b/include/zenoh-pico/collections/element.h index 5f1bfd7b0..94a71403d 100644 --- a/include/zenoh-pico/collections/element.h +++ b/include/zenoh-pico/collections/element.h @@ -19,6 +19,7 @@ #include #include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/result.h" /*-------- element functions --------*/ typedef size_t (*z_element_size_f)(void *e); @@ -62,8 +63,13 @@ static inline void _z_noop_clear(void *s) { (void)(s); } static inline void _z_noop_free(void **s) { (void)(s); } static inline void _z_noop_copy(void *dst, const void *src) { - (void)(dst); - (void)(src); + _ZP_UNUSED(dst); + _ZP_UNUSED(src); +} + +static inline void _z_noop_move(void *dst, void *src) { + _ZP_UNUSED(dst); + _ZP_UNUSED(src); } _Z_ELEM_DEFINE(_z_noop, _z_noop_t, _z_noop_size, _z_noop_clear, _z_noop_copy) diff --git a/include/zenoh-pico/collections/slice.h b/include/zenoh-pico/collections/slice.h index e491a2041..c9c25945a 100644 --- a/include/zenoh-pico/collections/slice.h +++ b/include/zenoh-pico/collections/slice.h @@ -39,8 +39,9 @@ inline static _Bool _z_slice_check(_z_slice_t value) { return value.start != NUL int8_t _z_slice_init(_z_slice_t *bs, size_t capacity); _z_slice_t _z_slice_make(size_t capacity); _z_slice_t _z_slice_wrap(const uint8_t *bs, size_t len); +_z_slice_t _z_slice_wrap_copy(const uint8_t *bs, size_t len); _z_slice_t _z_slice_steal(_z_slice_t *b); -void _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src); +int8_t _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src); _z_slice_t _z_slice_duplicate(const _z_slice_t *src); void _z_slice_move(_z_slice_t *dst, _z_slice_t *src); void _z_slice_reset(_z_slice_t *bs); @@ -49,37 +50,4 @@ _Bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right); void _z_slice_clear(_z_slice_t *bs); void _z_slice_free(_z_slice_t **bs); -/*-------- Bytes --------*/ -/** - * A container for slices. - * - * Members: - * _z_slice_t slice: content of the container. - */ -typedef struct { - _z_slice_t _slice; -} _z_bytes_t; - -_Bool _z_bytes_check(_z_bytes_t bytes); -_z_bytes_t _z_bytes_null(void); -_z_bytes_t _z_bytes_make(size_t capacity); -void _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src); -_z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src); -void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src); -void _z_bytes_clear(_z_bytes_t *bytes); -void _z_bytes_free(_z_bytes_t **bs); -uint8_t _z_bytes_to_uint8(const _z_bytes_t *bs); -uint16_t _z_bytes_to_uint16(const _z_bytes_t *bs); -uint32_t _z_bytes_to_uint32(const _z_bytes_t *bs); -uint64_t _z_bytes_to_uint64(const _z_bytes_t *bs); -float _z_bytes_to_float(const _z_bytes_t *bs); -double _z_bytes_to_double(const _z_bytes_t *bs); -_z_slice_t _z_bytes_to_slice(const _z_bytes_t *bytes); -_z_bytes_t _z_bytes_from_uint8(uint8_t val); -_z_bytes_t _z_bytes_from_uint16(uint16_t val); -_z_bytes_t _z_bytes_from_uint32(uint32_t val); -_z_bytes_t _z_bytes_from_uint64(uint64_t val); -_z_bytes_t _z_bytes_from_float(float val); -_z_bytes_t _z_bytes_from_double(double val); - #endif /* ZENOH_PICO_COLLECTIONS_SLICE_H */ diff --git a/include/zenoh-pico/collections/string.h b/include/zenoh-pico/collections/string.h index d304bbd73..a37ffa110 100644 --- a/include/zenoh-pico/collections/string.h +++ b/include/zenoh-pico/collections/string.h @@ -84,6 +84,7 @@ void _z_string_free(_z_string_t **s); void _z_string_reset(_z_string_t *s); _z_string_t _z_string_convert_bytes(const _z_slice_t *bs); _z_string_t _z_string_from_bytes(const _z_slice_t *bs); +_z_string_t _z_string_preallocate(const size_t len); _Z_ELEM_DEFINE(_z_string, _z_string_t, _z_string_size, _z_string_clear, _z_string_copy) diff --git a/include/zenoh-pico/collections/vec.h b/include/zenoh-pico/collections/vec.h index a6bcdb71d..07ecd9c68 100644 --- a/include/zenoh-pico/collections/vec.h +++ b/include/zenoh-pico/collections/vec.h @@ -43,6 +43,7 @@ void _z_vec_remove(_z_vec_t *sv, size_t pos, z_element_free_f f); void _z_vec_reset(_z_vec_t *v, z_element_free_f f); void _z_vec_clear(_z_vec_t *v, z_element_free_f f); void _z_vec_free(_z_vec_t **v, z_element_free_f f); +void _z_vec_release(_z_vec_t *v); #define _Z_VEC_DEFINE(name, type) \ typedef _z_vec_t name##_vec_t; \ @@ -60,6 +61,57 @@ void _z_vec_free(_z_vec_t **v, z_element_free_f f); } \ static inline void name##_vec_reset(name##_vec_t *v) { _z_vec_reset(v, name##_elem_free); } \ static inline void name##_vec_clear(name##_vec_t *v) { _z_vec_clear(v, name##_elem_free); } \ - static inline void name##_vec_free(name##_vec_t **v) { _z_vec_free(v, name##_elem_free); } + static inline void name##_vec_free(name##_vec_t **v) { _z_vec_free(v, name##_elem_free); } \ + static inline void name##_vec_release(name##_vec_t *v) { _z_vec_release(v); } + +/*-------- Dynamically allocated sized vector --------*/ +/** + * A dynamically allocate vector. + */ +typedef struct { + size_t _capacity; + size_t _len; + void *_val; +} _z_svec_t; + +_z_svec_t _z_svec_make(size_t capacity, size_t element_size); +void _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size); + +size_t _z_svec_len(const _z_svec_t *v); +_Bool _z_svec_is_empty(const _z_svec_t *v); + +bool _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f m, size_t element_size); +void *_z_svec_get(const _z_svec_t *v, size_t pos, size_t element_size); +void _z_svec_set(_z_svec_t *sv, size_t pos, void *e, z_element_clear_f f, size_t element_size); +void _z_svec_remove(_z_svec_t *sv, size_t pos, z_element_clear_f f, z_element_move_f m, size_t element_size); + +void _z_svec_reset(_z_svec_t *v, z_element_clear_f f, size_t element_size); +void _z_svec_clear(_z_svec_t *v, z_element_clear_f f, size_t element_size); +void _z_svec_free(_z_svec_t **v, z_element_clear_f f, size_t element_size); +void _z_svec_release(_z_svec_t *v); + +#define _Z_SVEC_DEFINE(name, type) \ + typedef _z_svec_t name##_svec_t; \ + static inline name##_svec_t name##_svec_make(size_t capacity) { return _z_svec_make(capacity, sizeof(type)); } \ + static inline size_t name##_svec_len(const name##_svec_t *v) { return _z_svec_len(v); } \ + static inline _Bool name##_svec_is_empty(const name##_svec_t *v) { return _z_svec_is_empty(v); } \ + static inline _Bool name##_svec_append(name##_svec_t *v, type *e) { \ + return _z_svec_append(v, e, name##_elem_move, sizeof(type)); \ + } \ + static inline type *name##_svec_get(const name##_svec_t *v, size_t pos) { \ + return (type *)_z_svec_get(v, pos, sizeof(type)); \ + } \ + static inline void name##_svec_set(name##_svec_t *v, size_t pos, type *e) { \ + _z_svec_set(v, pos, e, name##_elem_clear, sizeof(type)); \ + } \ + static inline void name##_svec_remove(name##_svec_t *v, size_t pos) { \ + _z_svec_remove(v, pos, name##_elem_clear, name##_elem_move, sizeof(type)); \ + } \ + static inline void name##_svec_copy(name##_svec_t *dst, const name##_svec_t *src) { \ + _z_svec_copy(dst, src, name##_elem_copy, sizeof(type)); \ + } \ + static inline void name##_svec_reset(name##_svec_t *v) { _z_svec_reset(v, name##_elem_clear, sizeof(type)); } \ + static inline void name##_svec_clear(name##_svec_t *v) { _z_svec_clear(v, name##_elem_clear, sizeof(type)); } \ + static inline void name##_svec_free(name##_svec_t **v) { _z_svec_free(v, name##_elem_clear, sizeof(type)); } #endif /* ZENOH_PICO_COLLECTIONS_VECTOR_H */ diff --git a/include/zenoh-pico/net/primitives.h b/include/zenoh-pico/net/primitives.h index ed9ef6989..46342bac8 100644 --- a/include/zenoh-pico/net/primitives.h +++ b/include/zenoh-pico/net/primitives.h @@ -108,8 +108,7 @@ int8_t _z_undeclare_publisher(_z_publisher_t *pub); * Parameters: * zn: The zenoh-net session. The caller keeps its ownership. * keyexpr: The resource key to write. The caller keeps its ownership. - * payload: The value to write. - * len: The length of the value to write. + * payload: The data to write. * encoding: The encoding of the payload. The callee gets the ownership of * any allocated value. * kind: The kind of the value. @@ -119,9 +118,9 @@ int8_t _z_undeclare_publisher(_z_publisher_t *pub); * Returns: * ``0`` in case of success, ``-1`` in case of failure. */ -int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, const size_t len, - const _z_encoding_t encoding, const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, - z_priority_t priority, const _z_bytes_t attachment); +int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, _z_bytes_t payload, const _z_encoding_t encoding, + const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, z_priority_t priority, + const _z_bytes_t attachment); #endif #if Z_FEATURE_SUBSCRIPTION == 1 diff --git a/include/zenoh-pico/net/query.h b/include/zenoh-pico/net/query.h index e04cc6f88..e34d587a2 100644 --- a/include/zenoh-pico/net/query.h +++ b/include/zenoh-pico/net/query.h @@ -17,6 +17,7 @@ #include #include "zenoh-pico/api/constants.h" +#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" diff --git a/include/zenoh-pico/net/reply.h b/include/zenoh-pico/net/reply.h index f8ad26449..3a14a58a3 100644 --- a/include/zenoh-pico/net/reply.h +++ b/include/zenoh-pico/net/reply.h @@ -61,7 +61,7 @@ _z_reply_t _z_reply_null(void); void _z_reply_clear(_z_reply_t *src); void _z_reply_free(_z_reply_t **hello); void _z_reply_copy(_z_reply_t *dst, _z_reply_t *src); -_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, z_reply_tag_t tag, _z_id_t id, const _z_slice_t *payload, +_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, z_reply_tag_t tag, _z_id_t id, const _z_bytes_t payload, const _z_timestamp_t *timestamp, _z_encoding_t encoding, z_sample_kind_t kind, const _z_bytes_t attachment); diff --git a/include/zenoh-pico/net/sample.h b/include/zenoh-pico/net/sample.h index 13b1023dd..0817d9d1e 100644 --- a/include/zenoh-pico/net/sample.h +++ b/include/zenoh-pico/net/sample.h @@ -56,7 +56,7 @@ void _z_sample_free(_z_sample_t **sample); void _z_sample_copy(_z_sample_t *dst, const _z_sample_t *src); _z_sample_t _z_sample_duplicate(const _z_sample_t *src); -_z_sample_t _z_sample_create(const _z_keyexpr_t *key, const _z_slice_t *payload, _z_timestamp_t timestamp, +_z_sample_t _z_sample_create(const _z_keyexpr_t *key, const _z_bytes_t payload, _z_timestamp_t timestamp, const _z_encoding_t encoding, const z_sample_kind_t kind, const _z_qos_t qos, const _z_bytes_t attachment); diff --git a/include/zenoh-pico/protocol/codec/core.h b/include/zenoh-pico/protocol/codec/core.h index 60fea8290..e4354aade 100644 --- a/include/zenoh-pico/protocol/codec/core.h +++ b/include/zenoh-pico/protocol/codec/core.h @@ -24,23 +24,7 @@ #include "zenoh-pico/utils/config.h" #include "zenoh-pico/utils/result.h" -#define _Z_RETURN_IF_ERR(expr) \ - { \ - int8_t __res = expr; \ - if (__res != _Z_RES_OK) { \ - return __res; \ - } \ - } - -#define _Z_CLEAN_RETURN_IF_ERR(base_expr, clean_expr) \ - { \ - int8_t __res = base_expr; \ - if (__res != _Z_RES_OK) { \ - clean_expr; \ - return __res; \ - } \ - } - +typedef int8_t (*__z_single_byte_reader_t)(uint8_t *, void *context); /*------------------ Internal Zenoh-net Macros ------------------*/ int8_t _z_consolidation_mode_encode(_z_wbuf_t *wbf, z_consolidation_mode_t en); int8_t _z_consolidation_mode_decode(z_consolidation_mode_t *en, _z_zbuf_t *zbf); @@ -56,11 +40,16 @@ int8_t _z_uint16_encode(_z_wbuf_t *buf, uint16_t v); int8_t _z_uint16_decode(uint16_t *u16, _z_zbuf_t *buf); uint8_t _z_zint_len(uint64_t v); +uint8_t _z_zint64_encode_buf(uint8_t *buf, uint64_t v); +static inline uint8_t _z_zsize_encode_buf(uint8_t *buf, _z_zint_t v) { return _z_zint64_encode_buf(buf, (uint64_t)v); } + int8_t _z_zsize_encode(_z_wbuf_t *buf, _z_zint_t v); int8_t _z_zint64_encode(_z_wbuf_t *buf, uint64_t v); int8_t _z_zint16_decode(uint16_t *zint, _z_zbuf_t *buf); int8_t _z_zint32_decode(uint32_t *zint, _z_zbuf_t *buf); int8_t _z_zint64_decode(uint64_t *zint, _z_zbuf_t *buf); +int8_t _z_zint64_decode_with_reader(uint64_t *zint, __z_single_byte_reader_t reader, void *context); +int8_t _z_zsize_decode_with_reader(_z_zint_t *zint, __z_single_byte_reader_t reader, void *context); int8_t _z_zsize_decode(_z_zint_t *zint, _z_zbuf_t *buf); int8_t _z_slice_val_encode(_z_wbuf_t *buf, const _z_slice_t *bs); @@ -82,6 +71,9 @@ size_t _z_encoding_len(const _z_encoding_t *en); int8_t _z_encoding_encode(_z_wbuf_t *wbf, const _z_encoding_t *en); int8_t _z_encoding_decode(_z_encoding_t *en, _z_zbuf_t *zbf); +int8_t _z_value_encode(_z_wbuf_t *wbf, const _z_value_t *en); +int8_t _z_value_decode(_z_value_t *en, _z_zbuf_t *zbf); + int8_t _z_keyexpr_encode(_z_wbuf_t *buf, _Bool has_suffix, const _z_keyexpr_t *ke); int8_t _z_keyexpr_decode(_z_keyexpr_t *ke, _z_zbuf_t *buf, _Bool has_suffix); diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index 99377f0e0..b24c933c4 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -20,6 +20,7 @@ #include #include "zenoh-pico/api/constants.h" +#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/refcount.h" #include "zenoh-pico/collections/slice.h" diff --git a/include/zenoh-pico/protocol/definitions/message.h b/include/zenoh-pico/protocol/definitions/message.h index 36dd0f2bf..2dec35a53 100644 --- a/include/zenoh-pico/protocol/definitions/message.h +++ b/include/zenoh-pico/protocol/definitions/message.h @@ -55,7 +55,7 @@ typedef struct { _z_encoding_t encoding; _z_source_info_t _ext_source_info; - _z_slice_t _payload; + _z_bytes_t _payload; } _z_msg_err_t; void _z_msg_err_clear(_z_msg_err_t *err); @@ -73,7 +73,7 @@ static inline void _z_msg_del_clear(_z_msg_del_t *del) { (void)del; } typedef struct { _z_m_push_commons_t _commons; - _z_slice_t _payload; + _z_bytes_t _payload; _z_encoding_t _encoding; _z_bytes_t _attachment; } _z_msg_put_t; diff --git a/include/zenoh-pico/session/subscription.h b/include/zenoh-pico/session/subscription.h index 0635a9572..03e0535d9 100644 --- a/include/zenoh-pico/session/subscription.h +++ b/include/zenoh-pico/session/subscription.h @@ -19,15 +19,15 @@ #include "zenoh-pico/net/session.h" /*------------------ Subscription ------------------*/ -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, - _z_zint_t payload_len, const _z_n_qos_t qos, const _z_bytes_t att); +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, + const _z_n_qos_t qos, const _z_bytes_t attachment); #if Z_FEATURE_SUBSCRIPTION == 1 _z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id); _z_subscription_rc_list_t *_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr); _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *sub); -int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_slice_t payload, +int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, const _z_encoding_t encoding, const _z_zint_t kind, const _z_timestamp_t timestamp, const _z_n_qos_t qos, const _z_bytes_t attachment); void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub); diff --git a/include/zenoh-pico/utils/result.h b/include/zenoh-pico/utils/result.h index 68d735dc3..af31d8db8 100644 --- a/include/zenoh-pico/utils/result.h +++ b/include/zenoh-pico/utils/result.h @@ -68,7 +68,29 @@ typedef enum { _Z_ERR_CONNECTION_CLOSED = -77, + _Z_ERR_DID_NOT_READ = -76, + _Z_ERR_GENERIC = -128 } _z_res_t; +#define _Z_RETURN_IF_ERR(expr) \ + { \ + int8_t __res = expr; \ + if (__res != _Z_RES_OK) { \ + return __res; \ + } \ + } + +#define _Z_CLEAN_RETURN_IF_ERR(base_expr, clean_expr) \ + { \ + int8_t __res = base_expr; \ + if (__res != _Z_RES_OK) { \ + clean_expr; \ + return __res; \ + } \ + } + +#define _Z_IS_OK(expr) (expr == _Z_RES_OK) +#define _Z_IS_ERR(expr) (expr != _Z_RES_OK) + #endif /* ZENOH_PICO_UTILS_RESULT_H */ diff --git a/src/api/api.c b/src/api/api.c index 91f6a6f39..bd7ca283c 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -425,53 +425,43 @@ const uint8_t *z_slice_data(const z_loaned_slice_t *slice) { return slice->start size_t z_slice_len(const z_loaned_slice_t *slice) { return slice->len; } int8_t z_bytes_deserialize_into_int8(const z_loaned_bytes_t *bytes, int8_t *dst) { - *dst = (int8_t)_z_bytes_to_uint8(bytes); - return _Z_RES_OK; + return _z_bytes_to_uint8(bytes, (uint8_t *)dst); } int8_t z_bytes_deserialize_into_int16(const z_loaned_bytes_t *bytes, int16_t *dst) { - *dst = (int16_t)_z_bytes_to_uint16(bytes); - return _Z_RES_OK; + return _z_bytes_to_uint16(bytes, (uint16_t *)dst); } int8_t z_bytes_deserialize_into_int32(const z_loaned_bytes_t *bytes, int32_t *dst) { - *dst = (int32_t)_z_bytes_to_uint32(bytes); - return _Z_RES_OK; + return _z_bytes_to_uint32(bytes, (uint32_t *)dst); } int8_t z_bytes_deserialize_into_int64(const z_loaned_bytes_t *bytes, int64_t *dst) { - *dst = (int64_t)_z_bytes_to_uint64(bytes); - return _Z_RES_OK; + return _z_bytes_to_uint64(bytes, (uint64_t *)dst); } int8_t z_bytes_deserialize_into_uint8(const z_loaned_bytes_t *bytes, uint8_t *dst) { - *dst = _z_bytes_to_uint8(bytes); - return _Z_RES_OK; + return _z_bytes_to_uint8(bytes, dst); } int8_t z_bytes_deserialize_into_uint16(const z_loaned_bytes_t *bytes, uint16_t *dst) { - *dst = _z_bytes_to_uint16(bytes); - return _Z_RES_OK; + return _z_bytes_to_uint16(bytes, dst); } int8_t z_bytes_deserialize_into_uint32(const z_loaned_bytes_t *bytes, uint32_t *dst) { - *dst = _z_bytes_to_uint32(bytes); - return _Z_RES_OK; + return _z_bytes_to_uint32(bytes, dst); } int8_t z_bytes_deserialize_into_uint64(const z_loaned_bytes_t *bytes, uint64_t *dst) { - *dst = _z_bytes_to_uint64(bytes); - return _Z_RES_OK; + return _z_bytes_to_uint64(bytes, dst); } int8_t z_bytes_deserialize_into_float(const z_loaned_bytes_t *bytes, float *dst) { - *dst = _z_bytes_to_float(bytes); - return _Z_RES_OK; + return _z_bytes_to_float(bytes, dst); } int8_t z_bytes_deserialize_into_double(const z_loaned_bytes_t *bytes, double *dst) { - *dst = _z_bytes_to_double(bytes); - return _Z_RES_OK; + return _z_bytes_to_double(bytes, dst); } int8_t z_bytes_deserialize_into_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t *dst) { @@ -482,8 +472,7 @@ int8_t z_bytes_deserialize_into_slice(const z_loaned_bytes_t *bytes, z_owned_sli return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } // Convert bytes to slice - *dst->_val = _z_bytes_to_slice(bytes); - return _Z_RES_OK; + return _z_bytes_to_slice(bytes, dst->_val); } int8_t z_bytes_deserialize_into_string(const z_loaned_bytes_t *bytes, z_owned_string_t *s) { @@ -494,48 +483,18 @@ int8_t z_bytes_deserialize_into_string(const z_loaned_bytes_t *bytes, z_owned_st return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } // Convert bytes to string - *s->_val = _z_string_from_bytes(&bytes->_slice); + size_t len = _z_bytes_len(bytes); + *s->_val = _z_string_preallocate(len); + if (s->_val->len != len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + _z_bytes_to_buf(bytes, (uint8_t *)s->_val->val, len); return _Z_RES_OK; } -int8_t zp_bytes_deserialize_into_pair(const z_loaned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second, - size_t *curr_idx) { - // Check bound size - if (*curr_idx >= bytes->_slice.len) { - return _Z_ERR_GENERIC; - } +int8_t z_bytes_deserialize_into_pair(const z_loaned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second) { // Init pair of owned bytes - z_bytes_null(first); - z_bytes_null(second); - first->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - second->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if ((first->_val == NULL) || (second->_val == NULL)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - // Extract first item size - size_t first_len = _z_host_le_load32(&bytes->_slice.start[*curr_idx]); - *curr_idx += sizeof(uint32_t); - // Allocate first item bytes - *first->_val = _z_bytes_make(first_len); - if (!_z_bytes_check(*first->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - // Extract first item data - memcpy((uint8_t *)first->_val->_slice.start, &bytes->_slice.start[*curr_idx], first_len); - *curr_idx += first_len; - - // Extract second item size - size_t second_len = _z_host_le_load32(&bytes->_slice.start[*curr_idx]); - *curr_idx += sizeof(uint32_t); - // Allocate second item bytes - *second->_val = _z_bytes_make(second_len); - if (!_z_bytes_check(*second->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - // Extract second item data - memcpy((uint8_t *)second->_val->_slice.start, &bytes->_slice.start[*curr_idx], second_len); - *curr_idx += second_len; - return _Z_RES_OK; + _Z_RETURN_IF_ERR(z_bytes_empty(first)); + _Z_CLEAN_RETURN_IF_ERR(z_bytes_empty(second), z_bytes_drop(first)); + return _z_bytes_deserialize_into_pair(bytes, first->_val, second->_val); } int8_t z_bytes_serialize_from_int8(z_owned_bytes_t *bytes, int8_t val) { @@ -556,194 +515,156 @@ int8_t z_bytes_serialize_from_int64(z_owned_bytes_t *bytes, int64_t val) { int8_t z_bytes_serialize_from_uint8(z_owned_bytes_t *bytes, uint8_t val) { // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_RETURN_IF_ERR(z_bytes_empty(bytes)); // Encode data - *bytes->_val = _z_bytes_from_uint8(val); - if (!_z_bytes_check(*bytes->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_from_uint8(bytes->_val, val), z_bytes_drop(bytes)); return _Z_RES_OK; } int8_t z_bytes_serialize_from_uint16(z_owned_bytes_t *bytes, uint16_t val) { // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_RETURN_IF_ERR(z_bytes_empty(bytes)); // Encode data - *bytes->_val = _z_bytes_from_uint16(val); - if (!_z_bytes_check(*bytes->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_from_uint16(bytes->_val, val), z_bytes_drop(bytes)); return _Z_RES_OK; } int8_t z_bytes_serialize_from_uint32(z_owned_bytes_t *bytes, uint32_t val) { // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_RETURN_IF_ERR(z_bytes_empty(bytes)); // Encode data - *bytes->_val = _z_bytes_from_uint32(val); - if (!_z_bytes_check(*bytes->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_from_uint32(bytes->_val, val), z_bytes_drop(bytes)); return _Z_RES_OK; } int8_t z_bytes_serialize_from_uint64(z_owned_bytes_t *bytes, uint64_t val) { // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_RETURN_IF_ERR(z_bytes_empty(bytes)); // Encode data - *bytes->_val = _z_bytes_from_uint64(val); - if (!_z_bytes_check(*bytes->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_from_uint64(bytes->_val, val), z_bytes_drop(bytes)); return _Z_RES_OK; } int8_t z_bytes_serialize_from_float(z_owned_bytes_t *bytes, float val) { // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_RETURN_IF_ERR(z_bytes_empty(bytes)); // Encode data - *bytes->_val = _z_bytes_from_float(val); - if (!_z_bytes_check(*bytes->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_from_float(bytes->_val, val), z_bytes_drop(bytes)); return _Z_RES_OK; } int8_t z_bytes_serialize_from_double(z_owned_bytes_t *bytes, double val) { // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_RETURN_IF_ERR(z_bytes_empty(bytes)); // Encode data - *bytes->_val = _z_bytes_from_double(val); - if (!_z_bytes_check(*bytes->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_from_double(bytes->_val, val), z_bytes_drop(bytes)); return _Z_RES_OK; } int8_t z_bytes_serialize_from_slice(z_owned_bytes_t *bytes, const uint8_t *data, size_t len) { // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + _Z_RETURN_IF_ERR(z_bytes_empty(bytes)); // Encode data - bytes->_val->_slice = _z_slice_wrap((uint8_t *)data, len); + _z_slice_t s = _z_slice_wrap((uint8_t *)data, len); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_from_slice(bytes->_val, s), z_bytes_drop(bytes)); return _Z_RES_OK; } int8_t z_bytes_serialize_from_slice_copy(z_owned_bytes_t *bytes, const uint8_t *data, size_t len) { - // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } // Allocate bytes - *bytes->_val = _z_bytes_make(len); - if (!_z_bytes_check(*bytes->_val)) { + _z_slice_t s = _z_slice_wrap_copy((uint8_t *)data, len); + if (!_z_slice_check(s) && len > 0) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - // Copy data - memcpy((uint8_t *)bytes->_val->_slice.start, data, len); + + // Init owned bytes + _Z_CLEAN_RETURN_IF_ERR(z_bytes_empty(bytes), _z_slice_clear(&s)); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_from_slice(bytes->_val, s), _z_slice_clear(&s); z_bytes_drop(bytes)); return _Z_RES_OK; } int8_t z_bytes_serialize_from_string(z_owned_bytes_t *bytes, const char *s) { - // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } // Encode string without null terminator size_t len = strlen(s); - bytes->_val->_slice = _z_slice_wrap((uint8_t *)s, len); - return _Z_RES_OK; + return z_bytes_serialize_from_slice(bytes, (uint8_t *)s, len); } int8_t z_bytes_serialize_from_string_copy(z_owned_bytes_t *bytes, const char *s) { - // Init owned bytes - z_bytes_null(bytes); - bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); - if (bytes->_val == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - // Allocate bytes + // Encode string without null terminator size_t len = strlen(s); - *bytes->_val = _z_bytes_make(len); - if (!_z_bytes_check(*bytes->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + return z_bytes_serialize_from_slice_copy(bytes, (uint8_t *)s, len); +} + +int8_t z_bytes_serialize_from_iter(z_owned_bytes_t *bytes, _Bool (*iterator_body)(z_owned_bytes_t *data, void *context), + void *context) { + // Init owned bytes + _Z_RETURN_IF_ERR(z_bytes_empty(bytes)); + z_owned_bytes_t data; + _z_bytes_iterator_writer_t iter_writer = _z_bytes_get_iterator_writer(bytes->_val); + while (iterator_body(&data, context)) { + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_iterator_writer_write(&iter_writer, data._val), z_bytes_drop(bytes)); } - // Copy string without null terminator - memcpy((uint8_t *)bytes->_val->_slice.start, s, len); return _Z_RES_OK; } -int8_t zp_bytes_serialize_from_iter(z_owned_bytes_t *bytes, - _Bool (*iterator_body)(z_owned_bytes_t *data, void *context, size_t *curr_idx), - void *context, size_t total_len) { - // Init owned bytes - z_bytes_null(bytes); +int8_t z_bytes_serialize_from_pair(z_owned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second) { + _Z_CLEAN_RETURN_IF_ERR(z_bytes_empty(bytes), z_bytes_drop(first); z_bytes_drop(second)); + int8_t res = _z_bytes_serialize_from_pair(bytes->_val, first->_val, second->_val); + first->_val = NULL; + second->_val = NULL; + if (res != _Z_RES_OK) z_bytes_drop(bytes); + return res; +} + +int8_t z_bytes_empty(z_owned_bytes_t *bytes) { bytes->_val = (_z_bytes_t *)z_malloc(sizeof(_z_bytes_t)); if (bytes->_val == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - // Allocate bytes - *bytes->_val = _z_bytes_make(total_len); - if (!_z_bytes_check(*bytes->_val)) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - size_t curr_idx = 0; - while (iterator_body(bytes, context, &curr_idx)) - ; + *bytes->_val = _z_bytes_null(); return _Z_RES_OK; } -int8_t zp_bytes_serialize_from_pair(z_owned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second, - size_t *curr_idx) { - // Calculate pair size - size_t first_len = z_slice_len(&first->_val->_slice); - size_t second_len = z_slice_len(&second->_val->_slice); - // Copy data - _z_host_le_store32((uint32_t)first_len, (uint8_t *)&bytes->_val->_slice.start[*curr_idx]); - *curr_idx += sizeof(uint32_t); - memcpy((uint8_t *)&bytes->_val->_slice.start[*curr_idx], z_slice_data(&first->_val->_slice), first_len); - *curr_idx += first_len; - _z_host_le_store32((uint32_t)second_len, (uint8_t *)&bytes->_val->_slice.start[*curr_idx]); - *curr_idx += sizeof(uint32_t); - memcpy((uint8_t *)&bytes->_val->_slice.start[*curr_idx], z_slice_data(&second->_val->_slice), second_len); - *curr_idx += second_len; - // Clean up - z_bytes_drop(first); - z_bytes_drop(second); +size_t z_bytes_len(const z_loaned_bytes_t *bytes) { return _z_bytes_len(bytes); } + +_Bool z_bytes_is_empty(const z_loaned_bytes_t *bytes) { return _z_bytes_is_empty(bytes); } + +z_bytes_reader_t z_bytes_get_reader(const z_loaned_bytes_t *bytes) { return _z_bytes_get_reader(bytes); } + +size_t z_bytes_reader_read(z_bytes_reader_t *reader, uint8_t *dst, size_t len) { + return _z_bytes_reader_read(reader, dst, len); +} + +int8_t z_bytes_reader_seek(z_bytes_reader_t *reader, int64_t offset, int origin) { + return _z_bytes_reader_seek(reader, offset, origin); +} + +int64_t z_bytes_reader_tell(z_bytes_reader_t *reader) { return _z_bytes_reader_tell(reader); } + +z_bytes_iterator_t z_bytes_get_iterator(const z_loaned_bytes_t *bytes) { return _z_bytes_get_iterator(bytes); } + +_Bool z_bytes_iterator_next(z_bytes_iterator_t *iter, z_owned_bytes_t *bytes) { + z_bytes_null(bytes); + bytes->_val = (z_loaned_bytes_t *)z_malloc(sizeof(z_loaned_bytes_t)); + if (bytes->_val == NULL) return false; + if (_z_bytes_iterator_next(iter, bytes->_val) != _Z_RES_OK) { + z_bytes_drop(bytes); + return false; + } + return true; +} + +int8_t z_bytes_get_writer(z_loaned_bytes_t *bytes, z_owned_bytes_writer_t *writer) { + writer->_val = (z_loaned_bytes_writer_t *)z_malloc(sizeof(z_loaned_bytes_writer_t)); + if (writer->_val == NULL) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + *writer->_val = _z_bytes_get_writer(bytes, Z_IOSLICE_SIZE); return _Z_RES_OK; } +int8_t z_bytes_writer_write(z_loaned_bytes_writer_t *writer, const uint8_t *src, size_t len) { + return _z_bytes_writer_write(writer, src, len); +} + _Bool z_timestamp_check(z_timestamp_t ts) { return _z_timestamp_check(&ts); } z_query_target_t z_query_target_default(void) { return Z_QUERY_TARGET_DEFAULT; } @@ -845,15 +766,16 @@ _Z_OWNED_FUNCTIONS_PTR_IMPL(_z_string_vec_t, string_array, _z_owner_noop_copy, _ _Z_VIEW_FUNCTIONS_PTR_IMPL(_z_string_vec_t, string_array) _Z_OWNED_FUNCTIONS_PTR_IMPL(_z_slice_t, slice, _z_slice_copy, _z_slice_free) _Z_OWNED_FUNCTIONS_PTR_IMPL(_z_bytes_t, bytes, _z_bytes_copy, _z_bytes_free) +_Z_OWNED_FUNCTIONS_PTR_TRIVIAL_IMPL(_z_bytes_writer_t, bytes_writer) #if Z_FEATURE_PUBLICATION == 1 || Z_FEATURE_QUERYABLE == 1 || Z_FEATURE_QUERY == 1 // Convert a user owned bytes payload to an internal bytes payload, returning an empty one if value invalid static _z_bytes_t _z_bytes_from_owned_bytes(z_owned_bytes_t *bytes) { - _z_bytes_t b = _z_bytes_null(); if ((bytes != NULL) && (bytes->_val != NULL)) { - b._slice = _z_slice_wrap(bytes->_val->_slice.start, bytes->_val->_slice.len); + return *bytes->_val; + } else { + return _z_bytes_null(); } - return b; } // Convert a user owned encoding to an internal encoding, return default encoding if value invalid @@ -1067,12 +989,12 @@ int8_t z_put(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, z_ opt.attachment = options->attachment; } - ret = _z_write(&_Z_RC_IN_VAL(zs), *keyexpr, payload->_val->_slice.start, payload->_val->_slice.len, - _z_encoding_from_owned(opt.encoding), Z_SAMPLE_KIND_PUT, opt.congestion_control, opt.priority, - _z_bytes_from_owned_bytes(opt.attachment)); + ret = + _z_write(&_Z_RC_IN_VAL(zs), *keyexpr, _z_bytes_from_owned_bytes(payload), _z_encoding_from_owned(opt.encoding), + Z_SAMPLE_KIND_PUT, opt.congestion_control, opt.priority, _z_bytes_from_owned_bytes(opt.attachment)); // Trigger local subscriptions - _z_trigger_local_subscriptions(&_Z_RC_IN_VAL(zs), *keyexpr, payload->_val->_slice.start, payload->_val->_slice.len, + _z_trigger_local_subscriptions(&_Z_RC_IN_VAL(zs), *keyexpr, _z_bytes_from_owned_bytes(payload), _z_n_qos_make(0, opt.congestion_control == Z_CONGESTION_CONTROL_BLOCK, opt.priority), _z_bytes_from_owned_bytes(opt.attachment)); // Clean-up @@ -1091,7 +1013,7 @@ int8_t z_delete(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, opt.congestion_control = options->congestion_control; opt.priority = options->priority; } - ret = _z_write(&_Z_RC_IN_VAL(zs), *keyexpr, NULL, 0, _z_encoding_null(), Z_SAMPLE_KIND_DELETE, + ret = _z_write(&_Z_RC_IN_VAL(zs), *keyexpr, _z_bytes_null(), _z_encoding_null(), Z_SAMPLE_KIND_DELETE, opt.congestion_control, opt.priority, _z_bytes_null()); return ret; @@ -1166,13 +1088,13 @@ int8_t z_publisher_put(const z_loaned_publisher_t *pub, z_owned_bytes_t *payload // Check if write filter is active before writing if (!_z_write_filter_active(pub)) { // Write value - ret = _z_write(&pub->_zn.in->val, pub->_key, payload->_val->_slice.start, payload->_val->_slice.len, + ret = _z_write(&pub->_zn.in->val, pub->_key, _z_bytes_from_owned_bytes(payload), _z_encoding_from_owned(opt.encoding), Z_SAMPLE_KIND_PUT, pub->_congestion_control, pub->_priority, _z_bytes_from_owned_bytes(opt.attachment)); } // Trigger local subscriptions - _z_trigger_local_subscriptions(&pub->_zn.in->val, pub->_key, payload->_val->_slice.start, payload->_val->_slice.len, - _Z_N_QOS_DEFAULT, _z_bytes_from_owned_bytes(opt.attachment)); + _z_trigger_local_subscriptions(&pub->_zn.in->val, pub->_key, _z_bytes_from_owned_bytes(payload), _Z_N_QOS_DEFAULT, + _z_bytes_from_owned_bytes(opt.attachment)); // Clean-up z_encoding_drop(opt.encoding); z_bytes_drop(opt.attachment); @@ -1182,7 +1104,7 @@ int8_t z_publisher_put(const z_loaned_publisher_t *pub, z_owned_bytes_t *payload int8_t z_publisher_delete(const z_loaned_publisher_t *pub, const z_publisher_delete_options_t *options) { (void)(options); - return _z_write(&pub->_zn.in->val, pub->_key, NULL, 0, _z_encoding_null(), Z_SAMPLE_KIND_DELETE, + return _z_write(&pub->_zn.in->val, pub->_key, _z_bytes_null(), _z_encoding_null(), Z_SAMPLE_KIND_DELETE, pub->_congestion_control, pub->_priority, _z_bytes_null()); } diff --git a/src/collections/arc_slice.c b/src/collections/arc_slice.c new file mode 100644 index 000000000..ac0e7bc9d --- /dev/null +++ b/src/collections/arc_slice.c @@ -0,0 +1,84 @@ +// +// Copyright (c) 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 +// 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 "zenoh-pico/collections/arc_slice.h" + +#include +#include +#include +#include + +_z_arc_slice_t _z_arc_slice_empty(void) { + _z_arc_slice_t s; + s.len = 0; + s.start = 0; + s.slice.in = NULL; + return s; +} + +_z_arc_slice_t _z_arc_slice_wrap(_z_slice_t s, size_t offset, size_t len) { + assert(offset + len <= s.len); + + _z_arc_slice_t arc_s; + arc_s.slice = _z_slice_rc_new_from_val(s); + arc_s.len = len; + arc_s.start = offset; + return arc_s; +} + +_z_arc_slice_t _z_arc_slice_get_subslice(const _z_arc_slice_t* s, size_t offset, size_t len) { + assert(offset + len <= s->len); + assert(s->slice.in != NULL || (len == 0 && offset == 0)); + + _z_arc_slice_t out; + if (s->slice.in == NULL) { + out.slice.in = NULL; + out.start = 0; + out.len = 0; + } else { + out.slice = _z_slice_rc_clone(&s->slice); + out.len = len; + out.start = s->start + offset; + } + return out; +} + +size_t _z_arc_slice_len(const _z_arc_slice_t* s) { return s->len; } + +_Bool _z_arc_slice_is_empty(const _z_arc_slice_t* s) { return _z_arc_slice_len(s) == 0; } + +const uint8_t* _z_arc_slice_data(const _z_arc_slice_t* s) { return s->slice.in->val.start + s->start; } + +int8_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src) { + _z_slice_rc_copy(&dst->slice, &src->slice); + dst->len = src->len; + dst->start = src->start; + return _Z_RES_OK; +} + +int8_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src) { + dst->slice = src->slice; + dst->len = src->len; + dst->start = src->start; + src->len = 0; + src->start = 0; + src->slice.in = NULL; + return _Z_RES_OK; +} + +int8_t _z_arc_slice_drop(_z_arc_slice_t* s) { + _z_slice_rc_drop(&s->slice); + *s = _z_arc_slice_empty(); + return _Z_RES_OK; +} diff --git a/src/collections/bytes.c b/src/collections/bytes.c new file mode 100644 index 000000000..2298090d4 --- /dev/null +++ b/src/collections/bytes.c @@ -0,0 +1,491 @@ +// +// Copyright (c) 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 +// 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 "zenoh-pico/collections/bytes.h" + +#include +#include +#include + +#include "zenoh-pico/api/olv_macros.h" +#include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/endianness.h" +#include "zenoh-pico/utils/result.h" + +/*-------- Bytes --------*/ +_Bool _z_bytes_check(const _z_bytes_t *bytes) { return !_z_bytes_is_empty(bytes); } + +_z_bytes_t _z_bytes_null(void) { + _z_bytes_t b; + b._slices = _z_arc_slice_svec_make(0); + return b; +} + +int8_t _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src) { + _z_arc_slice_svec_copy(&dst->_slices, &src->_slices); + if (_z_arc_slice_svec_len(&dst->_slices) == _z_arc_slice_svec_len(&src->_slices)) { + return _Z_RES_OK; + } else { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } +} + +_z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src) { + _z_bytes_t dst = _z_bytes_null(); + _z_bytes_copy(&dst, src); + return dst; +} + +size_t _z_bytes_len(const _z_bytes_t *bs) { + size_t len = 0; + for (size_t i = 0; i < _z_arc_slice_svec_len(&bs->_slices); ++i) { + const _z_arc_slice_t *s = _z_arc_slice_svec_get(&bs->_slices, i); + len += _z_arc_slice_len(s); + } + return len; +} + +_Bool _z_bytes_is_empty(const _z_bytes_t *bs) { + for (size_t i = 0; i < _z_arc_slice_svec_len(&bs->_slices); i++) { + const _z_arc_slice_t *s = _z_arc_slice_svec_get(&bs->_slices, i); + if (_z_arc_slice_len(s) > 0) return false; + } + return true; +} + +size_t _z_bytes_num_slices(const _z_bytes_t *bs) { return _z_arc_slice_svec_len(&bs->_slices); } + +_z_arc_slice_t *_z_bytes_get_slice(const _z_bytes_t *bs, size_t i) { + if (i >= _z_bytes_num_slices(bs)) return NULL; + return _z_arc_slice_svec_get(&bs->_slices, i); +} + +void _z_bytes_drop(_z_bytes_t *bytes) { _z_arc_slice_svec_clear(&bytes->_slices); } + +void _z_bytes_free(_z_bytes_t **bs) { + _z_bytes_t *ptr = *bs; + + if (ptr != NULL) { + _z_bytes_drop(ptr); + + z_free(ptr); + *bs = NULL; + } +} + +size_t _z_bytes_to_buf(const _z_bytes_t *bytes, uint8_t *dst, size_t len) { + uint8_t *start = dst; + size_t remaining = len; + for (size_t i = 0; i < _z_bytes_num_slices(bytes) && remaining > 0; ++i) { + // Recopy data + _z_arc_slice_t *s = _z_bytes_get_slice(bytes, i); + size_t s_len = _z_arc_slice_len(s); + size_t len_to_copy = remaining >= s_len ? s_len : remaining; + memcpy(start, _z_arc_slice_data(s), len_to_copy); + start += len_to_copy; + remaining -= len_to_copy; + } + + return len - remaining; +} +int8_t _z_bytes_from_slice(_z_bytes_t *b, _z_slice_t s) { + *b = _z_bytes_null(); + _z_arc_slice_t arc_s = _z_arc_slice_wrap(s, 0, s.len); + if (_z_arc_slice_len(&arc_s) != s.len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + return _z_arc_slice_svec_append(&b->_slices, &arc_s) ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY; +} + +int8_t _z_bytes_from_buf(_z_bytes_t *b, const uint8_t *src, size_t len) { + *b = _z_bytes_null(); + _z_slice_t s = _z_slice_wrap_copy(src, len); + if (s.len != len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + return _z_bytes_from_slice(b, s); +} + +int8_t _z_bytes_to_slice(const _z_bytes_t *bytes, _z_slice_t *s) { + // Allocate slice + size_t len = _z_bytes_len(bytes); + *s = _z_slice_make(len); + if (!_z_slice_check(*s) && len > 0) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + uint8_t *start = (uint8_t *)s->start; + for (size_t i = 0; i < _z_bytes_num_slices(bytes); ++i) { + // Recopy data + _z_arc_slice_t *arc_s = _z_bytes_get_slice(bytes, i); + size_t s_len = _z_arc_slice_len(arc_s); + memcpy(start, _z_arc_slice_data(arc_s), s_len); + start += s_len; + } + + return _Z_RES_OK; +} + +int8_t _z_bytes_append_slice(_z_bytes_t *dst, _z_arc_slice_t *s) { + _Z_CLEAN_RETURN_IF_ERR(_z_arc_slice_svec_append(&dst->_slices, s) ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY, + _z_arc_slice_drop(s)); + return _Z_RES_OK; +} + +int8_t _z_bytes_append_bytes(_z_bytes_t *dst, _z_bytes_t *src) { + int8_t res = _Z_RES_OK; + for (size_t i = 0; i < _z_bytes_num_slices(src); ++i) { + _z_arc_slice_t s; + _z_arc_slice_move(&s, _z_bytes_get_slice(src, i)); + res = _z_bytes_append_slice(dst, &s); + if (res != _Z_RES_OK) { + break; + } + } + + _z_bytes_drop(src); + return res; +} + +int8_t _z_bytes_serialize_from_pair(_z_bytes_t *out, _z_bytes_t *first, _z_bytes_t *second) { + *out = _z_bytes_null(); + _z_bytes_iterator_writer_t writer = _z_bytes_get_iterator_writer(out); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_iterator_writer_write(&writer, first), _z_bytes_drop(second)); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_iterator_writer_write(&writer, second), _z_bytes_drop(out)); + + return _Z_RES_OK; +} + +int8_t _z_bytes_deserialize_into_pair(const _z_bytes_t *bs, _z_bytes_t *first_out, _z_bytes_t *second_out) { + _z_bytes_iterator_t iter = _z_bytes_get_iterator(bs); + int8_t res = _z_bytes_iterator_next(&iter, first_out); + if (res != _Z_RES_OK) return res; + res = _z_bytes_iterator_next(&iter, second_out); + if (res != _Z_RES_OK) { + _z_bytes_drop(first_out); + }; + return res; +} + +int8_t _z_bytes_to_uint8(const _z_bytes_t *bs, uint8_t *val) { + *val = 0; + return _z_bytes_to_buf(bs, val, sizeof(uint8_t)) == sizeof(uint8_t) ? _Z_RES_OK : _Z_ERR_DID_NOT_READ; +} + +int8_t _z_bytes_to_uint16(const _z_bytes_t *bs, uint16_t *val) { + *val = 0; + uint8_t buf[sizeof(uint16_t)]; + if (_z_bytes_to_buf(bs, buf, sizeof(uint16_t)) != sizeof(uint16_t)) { + return _Z_ERR_DID_NOT_READ; + } + *val = _z_host_le_load16(buf); + return _Z_RES_OK; +} + +int8_t _z_bytes_to_uint32(const _z_bytes_t *bs, uint32_t *val) { + *val = 0; + uint8_t buf[sizeof(uint32_t)]; + if (_z_bytes_to_buf(bs, buf, sizeof(uint32_t)) != sizeof(uint32_t)) { + return _Z_ERR_DID_NOT_READ; + } + *val = _z_host_le_load32(buf); + return _Z_RES_OK; +} + +int8_t _z_bytes_to_uint64(const _z_bytes_t *bs, uint64_t *val) { + *val = 0; + uint8_t buf[sizeof(uint64_t)]; + if (_z_bytes_to_buf(bs, buf, sizeof(uint64_t)) != sizeof(uint64_t)) { + return _Z_ERR_DID_NOT_READ; + } + *val = _z_host_le_load64(buf); + return _Z_RES_OK; +} + +int8_t _z_bytes_to_float(const _z_bytes_t *bs, float *val) { + *val = 0; + return _z_bytes_to_buf(bs, (uint8_t *)val, sizeof(float)) == sizeof(float) ? _Z_RES_OK : _Z_ERR_DID_NOT_READ; +} + +int8_t _z_bytes_to_double(const _z_bytes_t *bs, double *val) { + *val = 0; + return _z_bytes_to_buf(bs, (uint8_t *)val, sizeof(double)) == sizeof(double) ? _Z_RES_OK : _Z_ERR_DID_NOT_READ; +} + +int8_t _z_bytes_from_uint8(_z_bytes_t *b, uint8_t val) { return _z_bytes_from_buf(b, &val, sizeof(val)); } + +int8_t _z_bytes_from_uint16(_z_bytes_t *b, uint16_t val) { + uint8_t buf[sizeof(uint16_t)]; + _z_host_le_store16(val, buf); + return _z_bytes_from_buf(b, buf, sizeof(uint16_t)); +} + +int8_t _z_bytes_from_uint32(_z_bytes_t *b, uint32_t val) { + uint8_t buf[sizeof(uint32_t)]; + _z_host_le_store32(val, buf); + return _z_bytes_from_buf(b, buf, sizeof(uint32_t)); +} + +int8_t _z_bytes_from_uint64(_z_bytes_t *b, uint64_t val) { + uint8_t buf[sizeof(uint64_t)]; + _z_host_le_store64(val, buf); + return _z_bytes_from_buf(b, buf, sizeof(uint64_t)); +} + +int8_t _z_bytes_from_float(_z_bytes_t *b, float val) { return _z_bytes_from_buf(b, (uint8_t *)&val, sizeof(val)); } + +int8_t _z_bytes_from_double(_z_bytes_t *b, double val) { return _z_bytes_from_buf(b, (uint8_t *)&val, sizeof(val)); } + +_z_slice_t _z_bytes_try_get_contiguous(const _z_bytes_t *bs) { + if (_z_bytes_num_slices(bs) == 1) { + _z_arc_slice_t *arc_s = _z_bytes_get_slice(bs, 0); + return _z_slice_wrap(_z_arc_slice_data(arc_s), _z_arc_slice_len(arc_s)); + } + return _z_slice_empty(); +} + +void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src) { + dst->_slices = src->_slices; + *src = _z_bytes_null(); +} + +_z_bytes_reader_t _z_bytes_get_reader(const _z_bytes_t *bytes) { + _z_bytes_reader_t r; + r.bytes = bytes; + r.slice_idx = 0; + r.byte_idx = 0; + r.in_slice_idx = 0; + return r; +} + +int8_t _z_bytes_reader_seek_forward(_z_bytes_reader_t *reader, size_t offset) { + size_t start_slice = reader->slice_idx; + for (size_t i = start_slice; i < _z_bytes_num_slices(reader->bytes); ++i) { + _z_arc_slice_t *s = _z_bytes_get_slice(reader->bytes, i); + size_t remaining = _z_arc_slice_len(s) - reader->in_slice_idx; + if (offset >= remaining) { + reader->slice_idx += 1; + reader->in_slice_idx = 0; + reader->byte_idx += remaining; + offset -= remaining; + } else { + reader->in_slice_idx += offset; + reader->byte_idx += offset; + offset = 0; + } + if (offset == 0) break; + } + + if (offset > 0) return _Z_ERR_DID_NOT_READ; + return _Z_RES_OK; +} + +int8_t _z_bytes_reader_seek_backward(_z_bytes_reader_t *reader, size_t offset) { + while (offset != 0) { + if (reader->in_slice_idx == 0) { + if (reader->slice_idx == 0) return _Z_ERR_DID_NOT_READ; + reader->slice_idx--; + _z_arc_slice_t *s = _z_bytes_get_slice(reader->bytes, reader->slice_idx); + reader->in_slice_idx = _z_arc_slice_len(s); + } + + if (offset > reader->in_slice_idx) { + offset -= reader->in_slice_idx; + reader->byte_idx -= reader->in_slice_idx; + reader->in_slice_idx = 0; + } else { + reader->byte_idx -= offset; + reader->in_slice_idx -= offset; + offset = 0; + } + } + return _Z_RES_OK; +} + +int8_t _z_bytes_reader_seek(_z_bytes_reader_t *reader, int64_t offset, int origin) { + switch (origin) { + case SEEK_SET: { + reader->byte_idx = 0; + reader->in_slice_idx = 0; + reader->slice_idx = 0; + if (offset < 0) return _Z_ERR_DID_NOT_READ; + return _z_bytes_reader_seek_forward(reader, offset); + } + case SEEK_CUR: { + if (offset >= 0) + return _z_bytes_reader_seek_forward(reader, offset); + else + return _z_bytes_reader_seek_backward(reader, -offset); + } + case SEEK_END: { + reader->byte_idx = _z_bytes_len(reader->bytes); + reader->in_slice_idx = 0; + reader->slice_idx = _z_bytes_num_slices(reader->bytes); + if (offset > 0) + return _Z_ERR_DID_NOT_READ; + else + return _z_bytes_reader_seek_backward(reader, -offset); + } + default: + return _Z_ERR_GENERIC; + } +} + +int64_t _z_bytes_reader_tell(const _z_bytes_reader_t *reader) { return reader->byte_idx; } + +size_t _z_bytes_reader_read(_z_bytes_reader_t *reader, uint8_t *buf, size_t len) { + uint8_t *buf_start = buf; + size_t to_read = len; + for (size_t i = reader->slice_idx; i < _z_bytes_num_slices(reader->bytes); ++i) { + _z_arc_slice_t *s = _z_bytes_get_slice(reader->bytes, i); + size_t remaining = _z_arc_slice_len(s) - reader->in_slice_idx; + if (len >= remaining) { + memcpy(buf_start, _z_arc_slice_data(s) + reader->in_slice_idx, remaining); + reader->slice_idx += 1; + reader->in_slice_idx = 0; + reader->byte_idx += remaining; + len -= remaining; + buf_start += remaining; + } else { + memcpy(buf_start, _z_arc_slice_data(s) + reader->in_slice_idx, len); + reader->in_slice_idx += len; + reader->byte_idx += len; + len = 0; + } + if (len == 0) break; + } + + return to_read - len; +} + +int8_t __read_single_byte(uint8_t *b, void *context) { + _z_bytes_reader_t *reader = (_z_bytes_reader_t *)context; + return _z_bytes_reader_read(reader, b, 1) == 1 ? _Z_RES_OK : _Z_ERR_DID_NOT_READ; +} + +int8_t _z_bytes_reader_read_zint(_z_bytes_reader_t *reader, _z_zint_t *zint) { + return _z_zsize_decode_with_reader(zint, __read_single_byte, reader); +} + +int8_t _z_bytes_reader_read_slices(_z_bytes_reader_t *reader, size_t len, _z_bytes_t *out) { + *out = _z_bytes_null(); + int8_t res = _Z_RES_OK; + + for (size_t i = reader->slice_idx; i < _z_bytes_num_slices(reader->bytes) && len > 0; ++i) { + _z_arc_slice_t *s = _z_bytes_get_slice(reader->bytes, i); + size_t s_len = _z_arc_slice_len(s); + + size_t remaining = s_len - reader->in_slice_idx; + size_t len_to_copy = remaining > len ? len : remaining; + _z_arc_slice_t ss = _z_arc_slice_get_subslice(s, reader->in_slice_idx, len_to_copy); + reader->in_slice_idx += len_to_copy; + reader->byte_idx += len_to_copy; + if (reader->in_slice_idx == s_len) { + reader->slice_idx++; + reader->in_slice_idx = 0; + } + + if (ss.slice.in == NULL) { + res = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + + res = _z_bytes_append_slice(out, &ss); + if (res != _Z_RES_OK) { + _z_arc_slice_drop(&ss); + break; + } + len -= len_to_copy; + } + + if (len > 0 && res == _Z_RES_OK) res = _Z_ERR_DID_NOT_READ; + if (res != _Z_RES_OK) _z_bytes_drop(out); + + return res; +} + +_z_bytes_iterator_t _z_bytes_get_iterator(const _z_bytes_t *bytes) { + return (_z_bytes_iterator_t){._reader = _z_bytes_get_reader(bytes)}; +} + +int8_t _z_bytes_iterator_next(_z_bytes_iterator_t *iter, _z_bytes_t *b) { + *b = _z_bytes_null(); + _z_zint_t len; + if (_z_bytes_reader_read_zint(&iter->_reader, &len) != _Z_RES_OK) { + return _Z_ERR_DID_NOT_READ; + } + return _z_bytes_reader_read_slices(&iter->_reader, len, b); +} + +_z_bytes_writer_t _z_bytes_get_writer(_z_bytes_t *bytes, size_t cache_size) { + return (_z_bytes_writer_t){.cache = NULL, .cache_size = cache_size, .bytes = bytes}; +} + +int8_t _z_bytes_writer_ensure_cache(_z_bytes_writer_t *writer) { + // first we check if cache stayed untouched since previous write operation + if (writer->cache != NULL) { + _z_arc_slice_t *arc_s = _z_bytes_get_slice(writer->bytes, _z_bytes_num_slices(writer->bytes) - 1); + if (_Z_RC_IN_VAL(&arc_s->slice).start + arc_s->len == writer->cache) { + size_t remaining_in_cache = _Z_RC_IN_VAL(&arc_s->slice).len - arc_s->len; + if (remaining_in_cache > 0) return _Z_RES_OK; + } + } + // otherwise we allocate a new cache + assert(writer->cache_size > 0); + _z_slice_t s = _z_slice_make(writer->cache_size); + if (s.start == NULL) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + _z_arc_slice_t cache = _z_arc_slice_wrap(s, 0, 0); + if (_Z_RC_IS_NULL(&cache.slice)) { + _z_slice_clear(&s); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_append_slice(writer->bytes, &cache), _z_arc_slice_drop(&cache)); + writer->cache = (uint8_t *)_Z_RC_IN_VAL(&cache.slice).start; + return _Z_RES_OK; +} + +int8_t _z_bytes_writer_write(_z_bytes_writer_t *writer, const uint8_t *src, size_t len) { + if (writer->cache_size == 0) { // no cache - append data as a single slice + _z_slice_t s = _z_slice_wrap_copy(src, len); + if (s.len != len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + _z_arc_slice_t arc_s = _z_arc_slice_wrap(s, 0, len); + if _Z_RC_IS_NULL (&arc_s.slice) { + _z_slice_clear(&s); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + return _z_bytes_append_slice(writer->bytes, &arc_s); + } + + while (len > 0) { + _Z_RETURN_IF_ERR(_z_bytes_writer_ensure_cache(writer)); + _z_arc_slice_t *arc_s = _z_bytes_get_slice(writer->bytes, _z_bytes_num_slices(writer->bytes) - 1); + size_t remaining_in_cache = _Z_RC_IN_VAL(&arc_s->slice).len - arc_s->len; + size_t to_copy = remaining_in_cache < len ? remaining_in_cache : len; + memcpy(writer->cache, src, to_copy); + len -= to_copy; + arc_s->len += to_copy; + src += to_copy; + writer->cache += to_copy; + } + return _Z_RES_OK; +} + +_z_bytes_iterator_writer_t _z_bytes_get_iterator_writer(_z_bytes_t *bytes) { + return (_z_bytes_iterator_writer_t){.writer = _z_bytes_get_writer(bytes, 0)}; +} +int8_t _z_bytes_iterator_writer_write(_z_bytes_iterator_writer_t *writer, _z_bytes_t *src) { + uint8_t l_buf[16]; + size_t l_len = _z_zsize_encode_buf(l_buf, _z_bytes_len(src)); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_writer_write(&writer->writer, l_buf, l_len), _z_bytes_drop(src)); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_append_bytes(writer->writer.bytes, src), _z_bytes_drop(src)); + + return _Z_RES_OK; +} diff --git a/src/collections/slice.c b/src/collections/slice.c index 41ad0bf03..1a059a8cb 100644 --- a/src/collections/slice.c +++ b/src/collections/slice.c @@ -27,13 +27,16 @@ _z_slice_t _z_slice_empty(void) { return (_z_slice_t){.start = NULL, .len = 0, . int8_t _z_slice_init(_z_slice_t *bs, size_t capacity) { int8_t ret = _Z_RES_OK; - bs->start = (uint8_t *)z_malloc(capacity); + bs->start = capacity == 0 ? NULL : (uint8_t *)z_malloc(capacity); if (bs->start != NULL) { bs->len = capacity; bs->_is_alloc = true; } else { bs->len = 0; bs->_is_alloc = false; + } + + if (bs->len != capacity) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; } @@ -54,6 +57,11 @@ _z_slice_t _z_slice_wrap(const uint8_t *p, size_t len) { return bs; } +_z_slice_t _z_slice_wrap_copy(const uint8_t *p, size_t len) { + _z_slice_t bs = _z_slice_wrap(p, len); + return _z_slice_duplicate(&bs); +} + void _z_slice_reset(_z_slice_t *bs) { bs->start = NULL; bs->len = 0; @@ -78,12 +86,13 @@ void _z_slice_free(_z_slice_t **bs) { } } -void _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src) { +int8_t _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src) { int8_t ret = _z_slice_init(dst, src->len); // FIXME: it should check if dst is already initialized. Otherwise it will leak if (ret == _Z_RES_OK) { (void)memcpy((uint8_t *)dst->start, src->start, src->len); } + return ret; } void _z_slice_move(_z_slice_t *dst, _z_slice_t *src) { @@ -110,150 +119,3 @@ _z_slice_t _z_slice_steal(_z_slice_t *b) { _Bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right) { return left->len == right->len && memcmp(left->start, right->start, left->len) == 0; } - -/*-------- Bytes --------*/ -_Bool _z_bytes_check(_z_bytes_t bytes) { return _z_slice_check(bytes._slice); } - -_z_bytes_t _z_bytes_null(void) { - return (_z_bytes_t){ - ._slice = _z_slice_empty(), - }; -} - -_z_bytes_t _z_bytes_make(size_t capacity) { - return (_z_bytes_t){ - ._slice = _z_slice_make(capacity), - }; -} - -void _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src) { - // Init only if needed - if (!_z_slice_check(dst->_slice)) { - if (_z_slice_init(&dst->_slice, src->_slice.len) != _Z_RES_OK) { - return; - } - } - (void)memcpy((uint8_t *)dst->_slice.start, src->_slice.start, src->_slice.len); -} - -_z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src) { - _z_bytes_t dst = _z_bytes_null(); - _z_bytes_copy(&dst, src); - return dst; -} - -void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src) { _z_slice_move(&dst->_slice, &src->_slice); } - -void _z_bytes_clear(_z_bytes_t *bytes) { _z_slice_clear(&bytes->_slice); } - -void _z_bytes_free(_z_bytes_t **bs) { - _z_bytes_t *ptr = *bs; - - if (ptr != NULL) { - _z_bytes_clear(ptr); - - z_free(ptr); - *bs = NULL; - } -} - -uint8_t _z_bytes_to_uint8(const _z_bytes_t *bs) { - uint8_t val = 0; - memcpy(&val, bs->_slice.start, sizeof(val)); - return val; -} - -uint16_t _z_bytes_to_uint16(const _z_bytes_t *bs) { return _z_host_le_load16(bs->_slice.start); } - -uint32_t _z_bytes_to_uint32(const _z_bytes_t *bs) { return _z_host_le_load32(bs->_slice.start); } - -uint64_t _z_bytes_to_uint64(const _z_bytes_t *bs) { return _z_host_le_load64(bs->_slice.start); } - -float _z_bytes_to_float(const _z_bytes_t *bs) { - float val = 0; - memcpy(&val, bs->_slice.start, sizeof(val)); - return val; -} - -double _z_bytes_to_double(const _z_bytes_t *bs) { - double val = 0; - memcpy(&val, bs->_slice.start, sizeof(val)); - return val; -} - -_z_slice_t _z_bytes_to_slice(const _z_bytes_t *bytes) { - // Allocate slice - _z_slice_t ret = _z_slice_make(bytes->_slice.len); - if (!_z_slice_check(ret)) { - return ret; - } - // Recopy data - memcpy((uint8_t *)ret.start, bytes->_slice.start, bytes->_slice.len); - return ret; -} - -_z_bytes_t _z_bytes_from_uint8(uint8_t val) { - _z_bytes_t ret = _z_bytes_null(); - // Init bytes array - if (_z_slice_init(&ret._slice, sizeof(val)) != _Z_RES_OK) { - return ret; - } - // Encode int - memcpy((uint8_t *)ret._slice.start, &val, sizeof(val)); - return ret; -} - -_z_bytes_t _z_bytes_from_uint16(uint16_t val) { - _z_bytes_t ret = _z_bytes_null(); - // Init bytes array - if (_z_slice_init(&ret._slice, sizeof(val)) != _Z_RES_OK) { - return ret; - } - // Encode int - _z_host_le_store16(val, (uint8_t *)ret._slice.start); - return ret; -} - -_z_bytes_t _z_bytes_from_uint32(uint32_t val) { - _z_bytes_t ret = _z_bytes_null(); - // Init bytes array - if (_z_slice_init(&ret._slice, sizeof(val)) != _Z_RES_OK) { - return ret; - } - // Encode int - _z_host_le_store32(val, (uint8_t *)ret._slice.start); - return ret; -} - -_z_bytes_t _z_bytes_from_uint64(uint64_t val) { - _z_bytes_t ret = _z_bytes_null(); - // Init bytes array - if (_z_slice_init(&ret._slice, sizeof(val)) != _Z_RES_OK) { - return ret; - } - // Encode int - _z_host_le_store64(val, (uint8_t *)ret._slice.start); - return ret; -} - -_z_bytes_t _z_bytes_from_float(float val) { - _z_bytes_t ret = _z_bytes_null(); - // Init bytes array - if (_z_slice_init(&ret._slice, sizeof(val)) != _Z_RES_OK) { - return ret; - } - // Encode float - memcpy((uint8_t *)ret._slice.start, &val, sizeof(val)); - return ret; -} - -_z_bytes_t _z_bytes_from_double(double val) { - _z_bytes_t ret = _z_bytes_null(); - // Init bytes array - if (_z_slice_init(&ret._slice, sizeof(val)) != _Z_RES_OK) { - return ret; - } - // Encode double - memcpy((uint8_t *)ret._slice.start, &val, sizeof(val)); - return ret; -} diff --git a/src/collections/string.c b/src/collections/string.c index fc7e5f868..3d2ff0069 100644 --- a/src/collections/string.c +++ b/src/collections/string.c @@ -113,18 +113,26 @@ _z_string_t _z_string_convert_bytes(const _z_slice_t *bs) { } _z_string_t _z_string_from_bytes(const _z_slice_t *bs) { + _z_string_t s = _z_string_preallocate(bs->len); + if (s.val == NULL) { + return s; + } + // Recopy data + memcpy(s.val, bs->start, bs->len); + return s; +} + +_z_string_t _z_string_preallocate(size_t len) { _z_string_t s = _z_string_null(); // Allocate string - s.len = bs->len + (size_t)1; // bytes data + null terminator - char *str_val = (char *)z_malloc(s.len * sizeof(char)); + s.len = len; + char *str_val = (char *)z_malloc((s.len + (size_t)1) * sizeof(char)); // bytes data + null terminator if (str_val == NULL) { + s.len = 0; return s; } - // Recopy data s.val = str_val; - memcpy(s.val, bs->start, bs->len); - // Set null terminator - s.val[bs->len] = '\0'; + s.val[len] = '\0'; return s; } diff --git a/src/collections/vec.c b/src/collections/vec.c index 8da49dd72..9acd13f85 100644 --- a/src/collections/vec.c +++ b/src/collections/vec.c @@ -53,7 +53,10 @@ void _z_vec_clear(_z_vec_t *v, z_element_free_f free_f) { for (size_t i = 0; i < v->_len; i++) { free_f(&v->_val[i]); } + _z_vec_release(v); +} +void _z_vec_release(_z_vec_t *v) { z_free(v->_val); v->_val = NULL; @@ -124,3 +127,134 @@ void _z_vec_remove(_z_vec_t *v, size_t pos, z_element_free_f free_f) { v->_val[v->_len] = NULL; v->_len = v->_len - 1; } + +/*-------- svec --------*/ +_z_svec_t _z_svec_make(size_t capacity, size_t element_size) { + _z_svec_t v = {._capacity = 0, ._len = 0, ._val = NULL}; + if (capacity != 0) { + v._val = z_malloc(element_size * capacity); + } + if (v._val != NULL) { + v._capacity = capacity; + } + return v; +} + +void __z_svec_copy_inner(void *dst, const void *src, z_element_copy_f copy, size_t num_elements, size_t element_size) { + if (copy == NULL) { + memcpy(dst, src, num_elements * element_size); + } else { + size_t offset = 0; + for (size_t i = 0; i < num_elements; i++) { + copy((uint8_t *)dst + offset, (uint8_t *)src + offset); + offset += element_size; + } + } +} + +void __z_svec_move_inner(void *dst, void *src, z_element_move_f move, size_t num_elements, size_t element_size) { + if (move == NULL) { + memcpy(dst, src, num_elements * element_size); + } else { + size_t offset = 0; + for (size_t i = 0; i < num_elements; i++) { + move((uint8_t *)dst + offset, (uint8_t *)src + offset); + offset += element_size; + } + } +} + +void _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size) { + dst->_capacity = 0; + dst->_len = 0; + dst->_val = z_malloc(element_size * src->_capacity); + if (dst->_val != NULL) { + dst->_capacity = src->_capacity; + dst->_len = src->_len; + __z_svec_copy_inner(dst->_val, src->_val, copy, src->_len, element_size); + } +} + +void _z_svec_reset(_z_svec_t *v, z_element_clear_f clear, size_t element_size) { + if (clear != NULL) { + size_t offset = 0; + for (size_t i = 0; i < v->_len; i++) { + clear((uint8_t *)v->_val + offset); + offset += element_size; + } + } + v->_len = 0; +} + +void _z_svec_clear(_z_svec_t *v, z_element_clear_f clear_f, size_t element_size) { + _z_svec_reset(v, clear_f, element_size); + _z_svec_release(v); +} + +void _z_svec_release(_z_svec_t *v) { + z_free(v->_val); + v->_val = NULL; + + v->_capacity = 0; + v->_len = 0; +} + +void _z_svec_free(_z_svec_t **v, z_element_clear_f clear, size_t element_size) { + _z_svec_t *ptr = (_z_svec_t *)*v; + + if (ptr != NULL) { + _z_svec_clear(ptr, clear, element_size); + + z_free(ptr); + *v = NULL; + } +} + +size_t _z_svec_len(const _z_svec_t *v) { return v->_len; } + +_Bool _z_svec_is_empty(const _z_svec_t *v) { return v->_len == 0; } + +bool _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f move, size_t element_size) { + if (v->_len == v->_capacity) { + // Allocate a new vector + size_t _capacity = v->_capacity == 0 ? 1 : (v->_capacity << 1); + void *_val = (void *)z_malloc(_capacity * element_size); + if (_val != NULL) { + __z_svec_move_inner(_val, v->_val, move, v->_len, element_size); + // Free the old data + z_free(v->_val); + + // Update the current vector + v->_val = _val; + v->_capacity = _capacity; + memcpy((uint8_t *)v->_val + v->_len * element_size, e, element_size); + v->_len++; + } else { + return false; + } + } else { + memcpy((uint8_t *)v->_val + v->_len * element_size, e, element_size); + v->_len++; + } + return true; +} + +void *_z_svec_get(const _z_svec_t *v, size_t i, size_t element_size) { + assert(i < v->_len); + return (uint8_t *)v->_val + i * element_size; +} + +void _z_svec_set(_z_svec_t *v, size_t i, void *e, z_element_clear_f clear, size_t element_size) { + assert(i < v->_len); + clear((uint8_t *)v->_val + i * element_size); + memcpy((uint8_t *)v->_val + i * element_size, e, element_size); +} + +void _z_svec_remove(_z_svec_t *v, size_t pos, z_element_clear_f clear, z_element_move_f move, size_t element_size) { + assert(pos < v->_len); + clear((uint8_t *)v->_val + pos * element_size); + __z_svec_move_inner((uint8_t *)v->_val + pos * element_size, (uint8_t *)v->_val + (pos + 1) * element_size, move, + (v->_len - pos - 1) * element_size, element_size); + + v->_len--; +} diff --git a/src/net/memory.c b/src/net/memory.c index 1d60c338f..2a5096845 100644 --- a/src/net/memory.c +++ b/src/net/memory.c @@ -35,7 +35,7 @@ void _z_hello_free(_z_hello_t **hello) { void _z_value_clear(_z_value_t *value) { _z_encoding_clear(&value->encoding); - _z_bytes_clear(&value->payload); + _z_bytes_drop(&value->payload); } void _z_value_free(_z_value_t **value) { diff --git a/src/net/primitives.c b/src/net/primitives.c index f50cbd611..4385c7799 100644 --- a/src/net/primitives.c +++ b/src/net/primitives.c @@ -130,9 +130,9 @@ int8_t _z_undeclare_publisher(_z_publisher_t *pub) { } /*------------------ Write ------------------*/ -int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, const size_t len, - const _z_encoding_t encoding, const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, - z_priority_t priority, const _z_bytes_t attachment) { +int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, const _z_encoding_t encoding, + const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, z_priority_t priority, + const _z_bytes_t attachment) { int8_t ret = _Z_RES_OK; _z_network_message_t msg; switch (kind) { @@ -148,7 +148,7 @@ int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *pay ._body._body._put = { ._commons = {._timestamp = _z_timestamp_null(), ._source_info = _z_source_info_null()}, - ._payload = _z_slice_wrap(payload, len), + ._payload = payload, ._encoding = encoding, ._attachment = attachment, }, @@ -353,7 +353,7 @@ int8_t _z_send_reply(const _z_query_t *query, _z_keyexpr_t keyexpr, const _z_val z_msg._body._response._tag = _Z_RESPONSE_BODY_REPLY; z_msg._body._response._body._reply._consolidation = Z_CONSOLIDATION_MODE_DEFAULT; z_msg._body._response._body._reply._body._is_put = true; - z_msg._body._response._body._reply._body._body._put._payload = payload.payload._slice; + z_msg._body._response._body._reply._body._body._put._payload = payload.payload; z_msg._body._response._body._reply._body._body._put._encoding = payload.encoding; z_msg._body._response._body._reply._body._body._put._commons._timestamp = _z_timestamp_null(); z_msg._body._response._body._reply._body._body._put._commons._source_info = _z_source_info_null(); diff --git a/src/net/query.c b/src/net/query.c index 798dbd2a1..fb79133a7 100644 --- a/src/net/query.c +++ b/src/net/query.c @@ -38,12 +38,12 @@ void _z_query_clear(_z_query_t *q) { z_free(q->_parameters); _z_keyexpr_clear(&q->_key); _z_value_clear(&q->_value); - _z_bytes_clear(&q->attachment); + _z_bytes_drop(&q->attachment); } #if Z_FEATURE_QUERYABLE == 1 _z_query_t _z_query_create(const _z_value_t *value, const _z_keyexpr_t *key, const _z_slice_t *parameters, - _z_session_t *zn, uint32_t request_id, const _z_bytes_t att) { + _z_session_t *zn, uint32_t request_id, const _z_bytes_t attachment) { _z_query_t q = _z_query_null(); q._request_id = request_id; q._zn = zn; // Ideally would have been an rc @@ -51,7 +51,7 @@ _z_query_t _z_query_create(const _z_value_t *value, const _z_keyexpr_t *key, con memcpy(q._parameters, parameters->start, parameters->len); q._parameters[parameters->len] = 0; q._anyke = (strstr(q._parameters, Z_SELECTOR_QUERY_MATCH) == NULL) ? false : true; - q.attachment._slice = _z_slice_steal((_z_slice_t *)&att._slice); + _z_bytes_copy(&q.attachment, &attachment); _z_keyexpr_copy(&q._key, key); _z_value_copy(&q._value, value); diff --git a/src/net/reply.c b/src/net/reply.c index 2dff090e2..43de427ba 100644 --- a/src/net/reply.c +++ b/src/net/reply.c @@ -84,9 +84,9 @@ void _z_pending_reply_clear(_z_pending_reply_t *pr) { _z_timestamp_clear(&pr->_tstamp); } -_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, z_reply_tag_t tag, _z_id_t id, const _z_slice_t *payload, +_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, z_reply_tag_t tag, _z_id_t id, const _z_bytes_t payload, const _z_timestamp_t *timestamp, _z_encoding_t encoding, z_sample_kind_t kind, - const _z_bytes_t att) { + const _z_bytes_t attachment) { _z_reply_t reply = _z_reply_null(); reply._tag = tag; if (tag == Z_REPLY_TAG_DATA) { @@ -95,10 +95,10 @@ _z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, z_reply_tag_t tag, _z_id_t id, _z_sample_t sample = _z_sample_null(); sample.keyexpr = keyexpr; // FIXME: call z_keyexpr_move or copy sample.encoding = encoding; // FIXME: call z_encoding_move or copy - _z_slice_copy(&sample.payload._slice, payload); + _z_bytes_copy(&sample.payload, &payload); sample.kind = kind; sample.timestamp = _z_timestamp_duplicate(timestamp); - sample.attachment._slice = _z_slice_steal((_z_slice_t *)&att._slice); + _z_bytes_copy(&sample.attachment, &attachment); // Create sample rc from value reply.data.sample = _z_sample_rc_new_from_val(sample); @@ -106,9 +106,9 @@ _z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, z_reply_tag_t tag, _z_id_t id, return reply; } #else -_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, z_reply_tag_t tag, _z_id_t id, const _z_slice_t *payload, +_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, z_reply_tag_t tag, _z_id_t id, const _z_bytes_t payload, const _z_timestamp_t *timestamp, _z_encoding_t encoding, z_sample_kind_t kind, - const _z_bytes_t att) { + const _z_bytes_t attachment) { _ZP_UNUSED(keyexpr); _ZP_UNUSED(tag); _ZP_UNUSED(id); @@ -116,7 +116,7 @@ _z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, z_reply_tag_t tag, _z_id_t id, _ZP_UNUSED(timestamp); _ZP_UNUSED(encoding); _ZP_UNUSED(kind); - _ZP_UNUSED(att); + _ZP_UNUSED(attachment); return _z_reply_null(); } #endif diff --git a/src/net/sample.c b/src/net/sample.c index 9db7355e3..14196a668 100644 --- a/src/net/sample.c +++ b/src/net/sample.c @@ -30,7 +30,7 @@ _z_sample_t _z_sample_null(void) { } _Bool _z_sample_check(const _z_sample_t *sample) { - return _z_keyexpr_check(sample->keyexpr) && _z_bytes_check(sample->payload); + return _z_keyexpr_check(sample->keyexpr) && _z_bytes_check(&sample->payload); } void _z_sample_move(_z_sample_t *dst, _z_sample_t *src) { @@ -47,10 +47,10 @@ void _z_sample_move(_z_sample_t *dst, _z_sample_t *src) { void _z_sample_clear(_z_sample_t *sample) { _z_keyexpr_clear(&sample->keyexpr); - _z_bytes_clear(&sample->payload); + _z_bytes_drop(&sample->payload); _z_encoding_clear(&sample->encoding); _z_timestamp_clear(&sample->timestamp); - _z_bytes_clear(&sample->attachment); + _z_bytes_drop(&sample->attachment); } void _z_sample_free(_z_sample_t **sample) { @@ -64,11 +64,11 @@ void _z_sample_free(_z_sample_t **sample) { void _z_sample_copy(_z_sample_t *dst, const _z_sample_t *src) { dst->keyexpr = _z_keyexpr_duplicate(src->keyexpr); - dst->payload = _z_bytes_duplicate(&src->payload); + _z_bytes_copy(&dst->payload, &src->payload); dst->timestamp = _z_timestamp_duplicate(&src->timestamp); _z_encoding_copy(&dst->encoding, &src->encoding); dst->kind = src->kind; - dst->attachment = _z_bytes_duplicate(&src->attachment); + _z_bytes_copy(&dst->attachment, &src->attachment); } _z_sample_t _z_sample_duplicate(const _z_sample_t *src) { @@ -78,30 +78,30 @@ _z_sample_t _z_sample_duplicate(const _z_sample_t *src) { } #if Z_FEATURE_SUBSCRIPTION == 1 -_z_sample_t _z_sample_create(const _z_keyexpr_t *key, const _z_slice_t *payload, const _z_timestamp_t timestamp, +_z_sample_t _z_sample_create(const _z_keyexpr_t *key, const _z_bytes_t payload, const _z_timestamp_t timestamp, const _z_encoding_t encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t att) { + const _z_bytes_t attachment) { _z_sample_t s = _z_sample_null(); _z_keyexpr_copy(&s.keyexpr, key); - _z_slice_copy(&s.payload._slice, payload); + _z_bytes_copy(&s.payload, &payload); _z_encoding_copy(&s.encoding, &encoding); s.kind = kind; s.timestamp = timestamp; s.qos = qos; - s.attachment._slice = _z_slice_steal((_z_slice_t *)&att._slice); + _z_bytes_copy(&s.attachment, &attachment); return s; } #else -_z_sample_t _z_sample_create(const _z_keyexpr_t *key, const _z_slice_t *payload, const _z_timestamp_t timestamp, +_z_sample_t _z_sample_create(const _z_keyexpr_t *key, const _z_bytes_t payload, const _z_timestamp_t timestamp, const _z_encoding_t encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t att) { + const _z_bytes_t attachment) { _ZP_UNUSED(key); _ZP_UNUSED(payload); _ZP_UNUSED(timestamp); _ZP_UNUSED(encoding); _ZP_UNUSED(kind); _ZP_UNUSED(qos); - _ZP_UNUSED(att); + _ZP_UNUSED(attachment); return _z_sample_null(); } #endif diff --git a/src/protocol/codec.c b/src/protocol/codec.c index d0d19faa0..ab4211713 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -129,18 +129,30 @@ uint8_t _z_zint_len(uint64_t v) { } } -int8_t _z_zint64_encode(_z_wbuf_t *wbf, uint64_t v) { +uint8_t _z_zint64_encode_buf(uint8_t *buf, uint64_t v) { uint64_t lv = v; uint8_t len = 0; + size_t start = 0; while ((lv & VLE_LEN1_MASK) != 0) { uint8_t c = (lv & 0x7f) | 0x80; - _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, c)) + buf[start++] = c; len++; lv = lv >> (uint64_t)7; } if (len != VLE_LEN) { uint8_t c = (lv & 0xff); - _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, c)) + buf[start++] = c; + } + + return (uint8_t)start; +} + +int8_t _z_zint64_encode(_z_wbuf_t *wbf, uint64_t v) { + uint8_t buf[VLE_LEN]; + size_t len = _z_zint64_encode_buf(buf, v); + + for (size_t i = 0; i < len; i++) { + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, buf[i])); } return _Z_RES_OK; } @@ -149,16 +161,16 @@ int8_t _z_zint16_encode(_z_wbuf_t *wbf, uint16_t v) { return _z_zint64_encode(wb int8_t _z_zint32_encode(_z_wbuf_t *wbf, uint32_t v) { return _z_zint64_encode(wbf, (uint64_t)v); } int8_t _z_zsize_encode(_z_wbuf_t *wbf, _z_zint_t v) { return _z_zint64_encode(wbf, (uint64_t)v); } -int8_t _z_zint64_decode(uint64_t *zint, _z_zbuf_t *zbf) { +int8_t _z_zint64_decode_with_reader(uint64_t *zint, __z_single_byte_reader_t reader, void *context) { *zint = 0; uint8_t b = 0; - _Z_RETURN_IF_ERR(_z_uint8_decode(&b, zbf)); + _Z_RETURN_IF_ERR(reader(&b, context)); uint8_t i = 0; while (((b & 0x80) != 0) && (i != 7 * (VLE_LEN - 1))) { *zint = *zint | ((uint64_t)(b & 0x7f)) << i; - _Z_RETURN_IF_ERR(_z_uint8_decode(&b, zbf)); + _Z_RETURN_IF_ERR(reader(&b, context)); i = i + (uint8_t)7; } *zint = *zint | ((uint64_t)b << i); @@ -166,6 +178,23 @@ int8_t _z_zint64_decode(uint64_t *zint, _z_zbuf_t *zbf) { return _Z_RES_OK; } +int8_t _z_zsize_decode_with_reader(_z_zint_t *zint, __z_single_byte_reader_t reader, void *context) { + uint64_t i = 0; + int8_t res = _z_zint64_decode_with_reader(&i, reader, context); + if (res != _Z_RES_OK || i > SIZE_MAX) { + res = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } else { + *zint = (_z_zint_t)i; + } + return res; +} + +int8_t _z_uint8_decode_reader(uint8_t *zint, void *context) { return _z_uint8_decode(zint, (_z_zbuf_t *)context); } + +int8_t _z_zint64_decode(uint64_t *zint, _z_zbuf_t *zbf) { + return _z_zint64_decode_with_reader(zint, _z_uint8_decode_reader, (void *)zbf); +} + int8_t _z_zint16_decode(uint16_t *zint, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; uint64_t buf; @@ -191,30 +220,24 @@ int8_t _z_zint32_decode(uint32_t *zint, _z_zbuf_t *zbf) { } int8_t _z_zsize_decode(_z_zint_t *zint, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - uint64_t buf; - _Z_RETURN_IF_ERR(_z_zint64_decode(&buf, zbf)); - if (buf <= SIZE_MAX) { - *zint = (_z_zint_t)buf; - } else { - ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; - } - return ret; + return _z_zsize_decode_with_reader(zint, _z_uint8_decode_reader, (void *)zbf); } /*------------------ uint8_array ------------------*/ -int8_t _z_slice_val_encode(_z_wbuf_t *wbf, const _z_slice_t *bs) { +int8_t _z_buf_encode(_z_wbuf_t *wbf, const uint8_t *buf, size_t len) { int8_t ret = _Z_RES_OK; - if ((wbf->_expansion_step != 0) && (bs->len > Z_TSID_LENGTH)) { - ret |= _z_wbuf_wrap_bytes(wbf, bs->start, 0, bs->len); + if ((wbf->_expansion_step != 0) && (len > Z_TSID_LENGTH)) { + ret |= _z_wbuf_wrap_bytes(wbf, buf, 0, len); } else { - ret |= _z_wbuf_write_bytes(wbf, bs->start, 0, bs->len); + ret |= _z_wbuf_write_bytes(wbf, buf, 0, len); } return ret; } +int8_t _z_slice_val_encode(_z_wbuf_t *wbf, const _z_slice_t *bs) { return _z_buf_encode(wbf, bs->start, bs->len); } + int8_t _z_slice_encode(_z_wbuf_t *wbf, const _z_slice_t *bs) { int8_t ret = _Z_RES_OK; @@ -246,21 +269,38 @@ int8_t _z_slice_val_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf) { } int8_t _z_slice_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - - ret |= _z_zsize_decode(&bs->len, zbf); - ret |= _z_slice_val_decode_na(bs, zbf); - - return ret; + _Z_RETURN_IF_ERR(_z_zsize_decode(&bs->len, zbf)); + return _z_slice_val_decode_na(bs, zbf); } int8_t _z_slice_val_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice_val_decode_na(bs, zbf); } int8_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice_decode_na(bs, zbf); } -int8_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { return _z_slice_decode_na(&bs->_slice, zbf); } +int8_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { + _z_slice_t s; + _Z_RETURN_IF_ERR(_z_slice_decode(&s, zbf)); + if (s._is_alloc) { + return _z_bytes_from_slice(bs, s); + } else { + return _z_bytes_from_buf(bs, s.start, s.len); + } +} -int8_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs) { return _z_slice_encode(wbf, &bs->_slice); } +int8_t _z_bytes_encode_val(_z_wbuf_t *wbf, const _z_bytes_t *bs) { + int8_t ret = _Z_RES_OK; + for (size_t i = 0; i < _z_bytes_num_slices(bs); ++i) { + const _z_arc_slice_t *arc_s = _z_bytes_get_slice(bs, i); + _Z_RETURN_IF_ERR(_z_buf_encode(wbf, _z_arc_slice_data(arc_s), _z_arc_slice_len(arc_s))) + } + + return ret; +} + +int8_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs) { + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, _z_bytes_len(bs))) + return _z_bytes_encode_val(wbf, bs); +} /*------------------ string with null terminator ------------------*/ int8_t _z_str_encode(_z_wbuf_t *wbf, const char *s) { @@ -363,3 +403,16 @@ int8_t _z_encoding_decode(_z_encoding_t *en, _z_zbuf_t *zbf) { } return _Z_RES_OK; } + +int8_t _z_value_encode(_z_wbuf_t *wbf, const _z_value_t *value) { + size_t total_len = _z_encoding_len(&value->encoding) + _z_bytes_len(&value->payload); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, total_len)); + _Z_RETURN_IF_ERR(_z_encoding_encode(wbf, &value->encoding)); + return _z_bytes_encode_val(wbf, &value->payload); +} + +int8_t _z_value_decode(_z_value_t *value, _z_zbuf_t *zbf) { + _Z_RETURN_IF_ERR(_z_encoding_decode(&value->encoding, zbf)); + _Z_RETURN_IF_ERR(_z_bytes_from_buf(&value->payload, (uint8_t *)_z_zbuf_start(zbf), _z_zbuf_len(zbf))); + return _Z_RES_OK; +} diff --git a/src/protocol/codec/message.c b/src/protocol/codec/message.c index 2b75503a8..f6cbadfa7 100644 --- a/src/protocol/codec/message.c +++ b/src/protocol/codec/message.c @@ -254,7 +254,7 @@ int8_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb) { pshb->_body._put._commons._source_info._source_sn != 0 || pshb->_body._put._commons._source_info._entity_id != 0; - _Bool has_attachment = pshb->_is_put && _z_bytes_check(pshb->_body._put._attachment); + _Bool has_attachment = pshb->_is_put && _z_bytes_check(&pshb->_body._put._attachment); _Bool has_timestamp = _z_timestamp_check(&pshb->_body._put._commons._timestamp); _Bool has_encoding = false; if (has_source_info || has_attachment) { @@ -288,10 +288,10 @@ int8_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb) { } if (has_attachment) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x03)); - _Z_RETURN_IF_ERR(_z_slice_encode(wbf, &pshb->_body._put._attachment._slice)); + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &pshb->_body._put._attachment)); } if (pshb->_is_put) { - _Z_RETURN_IF_ERR(_z_slice_encode(wbf, &pshb->_body._put._payload)); + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &pshb->_body._put._payload)); } return 0; @@ -306,9 +306,13 @@ int8_t _z_push_body_decode_extensions(_z_msg_ext_t *extension, void *ctx) { break; } case _Z_MSG_EXT_ENC_ZBUF | 0x03: { // Attachment - pshb->_body._put._attachment._slice = extension->_body._zbuf._val._is_alloc - ? _z_slice_steal(&extension->_body._zbuf._val) - : _z_slice_duplicate(&extension->_body._zbuf._val); + _z_slice_t s; + if (extension->_body._zbuf._val._is_alloc) { + s = _z_slice_steal(&extension->_body._zbuf._val); + } else { + _Z_RETURN_IF_ERR(_z_slice_copy(&s, &extension->_body._zbuf._val)); + } + ret = _z_bytes_from_slice(&pshb->_body._put._attachment, s); break; } default: @@ -336,7 +340,7 @@ int8_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t header) _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_push_body_decode_extensions, pshb)); } if (ret == _Z_RES_OK) { - _Z_RETURN_IF_ERR(_z_slice_decode(&pshb->_body._put._payload, zbf)); + _Z_RETURN_IF_ERR(_z_bytes_decode(&pshb->_body._put._payload, zbf)); } break; } @@ -414,10 +418,7 @@ int8_t _z_query_encode(_z_wbuf_t *wbf, const _z_msg_query_t *msg) { extheader |= _Z_FLAG_Z_Z; } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR( - _z_zsize_encode(wbf, _z_encoding_len(&msg->_ext_value.encoding) + msg->_ext_value.payload._slice.len)); - _Z_RETURN_IF_ERR(_z_encoding_encode(wbf, &msg->_ext_value.encoding)); - _Z_RETURN_IF_ERR(_z_slice_val_encode(wbf, &msg->_ext_value.payload._slice)); + _Z_RETURN_IF_ERR(_z_value_encode(wbf, &msg->_ext_value)); } if (required_exts.info) { uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x01; @@ -429,7 +430,7 @@ int8_t _z_query_encode(_z_wbuf_t *wbf, const _z_msg_query_t *msg) { } if (required_exts.attachment) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x05)); - _Z_RETURN_IF_ERR(_z_slice_encode(wbf, &msg->_ext_attachment._slice)); + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &msg->_ext_attachment)); } return ret; } @@ -445,15 +446,17 @@ int8_t _z_query_decode_extensions(_z_msg_ext_t *extension, void *ctx) { } case _Z_MSG_EXT_ENC_ZBUF | 0x03: { // Payload _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); - ret = _z_encoding_decode(&msg->_ext_value.encoding, &zbf); - _z_slice_t bytes = _z_slice_wrap((uint8_t *)_z_zbuf_start(&zbf), _z_zbuf_len(&zbf)); - _z_slice_copy(&msg->_ext_value.payload._slice, &bytes); + ret = _z_value_decode(&msg->_ext_value, &zbf); break; } case _Z_MSG_EXT_ENC_ZBUF | 0x05: { // Attachment - msg->_ext_attachment._slice = extension->_body._zbuf._val._is_alloc - ? _z_slice_steal(&extension->_body._zbuf._val) - : _z_slice_duplicate(&extension->_body._zbuf._val); + _z_slice_t s; + if (extension->_body._zbuf._val._is_alloc) { + s = _z_slice_steal(&extension->_body._zbuf._val); + } else { + _Z_RETURN_IF_ERR(_z_slice_copy(&s, &extension->_body._zbuf._val)); + } + ret = _z_bytes_from_slice(&msg->_ext_attachment, s); break; } default: @@ -550,7 +553,7 @@ int8_t _z_err_encode(_z_wbuf_t *wbf, const _z_msg_err_t *err) { _Z_RETURN_IF_ERR(_z_source_info_encode_ext(wbf, &err->_ext_source_info)); } // Encode payload - _Z_RETURN_IF_ERR(_z_slice_encode(wbf, &err->_payload)); + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &err->_payload)); return ret; } int8_t _z_err_decode_extension(_z_msg_ext_t *extension, void *ctx) { @@ -578,7 +581,7 @@ int8_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header) { if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_err_decode_extension, err)); } - _Z_RETURN_IF_ERR(_z_slice_decode(&err->_payload, zbf)); + _Z_RETURN_IF_ERR(_z_bytes_decode(&err->_payload, zbf)); return _Z_RES_OK; } diff --git a/src/protocol/definitions/message.c b/src/protocol/definitions/message.c index 1f448562c..e9e5fe0af 100644 --- a/src/protocol/definitions/message.c +++ b/src/protocol/definitions/message.c @@ -24,15 +24,15 @@ void _z_msg_reply_clear(_z_msg_reply_t *msg) { _z_push_body_clear(&msg->_body); void _z_msg_put_clear(_z_msg_put_t *msg) { _z_encoding_clear(&msg->_encoding); - _z_slice_clear(&msg->_payload); + _z_bytes_drop(&msg->_payload); _z_timestamp_clear(&msg->_commons._timestamp); } _z_msg_query_reqexts_t _z_msg_query_required_extensions(const _z_msg_query_t *msg) { return (_z_msg_query_reqexts_t){ - .body = msg->_ext_value.payload._slice.start != NULL || _z_encoding_check(&msg->_ext_value.encoding), + .body = _z_bytes_check(&msg->_ext_value.payload) || _z_encoding_check(&msg->_ext_value.encoding), .info = _z_id_check(msg->_ext_info._id) || msg->_ext_info._entity_id != 0 || msg->_ext_info._source_sn != 0, - .attachment = _z_bytes_check(msg->_ext_attachment), + .attachment = _z_bytes_check(&msg->_ext_attachment), }; } @@ -42,5 +42,5 @@ void _z_msg_query_clear(_z_msg_query_t *msg) { } void _z_msg_err_clear(_z_msg_err_t *err) { _z_encoding_clear(&err->encoding); - _z_slice_clear(&err->_payload); + _z_bytes_drop(&err->_payload); } diff --git a/src/session/push.c b/src/session/push.c index 4c2645f41..b8a1cab9a 100644 --- a/src/session/push.c +++ b/src/session/push.c @@ -26,7 +26,7 @@ int8_t _z_trigger_push(_z_session_t *zn, _z_n_msg_push_t *push) { // TODO check body to know where to dispatch #if Z_FEATURE_SUBSCRIPTION == 1 - _z_slice_t payload = push->_body._is_put ? push->_body._body._put._payload : _z_slice_empty(); + _z_bytes_t payload = push->_body._is_put ? push->_body._body._put._payload : _z_bytes_null(); _z_encoding_t encoding = push->_body._is_put ? push->_body._body._put._encoding : _z_encoding_null(); size_t kind = push->_body._is_put ? Z_SAMPLE_KIND_PUT : Z_SAMPLE_KIND_DELETE; ret = _z_trigger_subscriptions(zn, push->_key, payload, encoding, kind, push->_timestamp, push->_qos, diff --git a/src/session/query.c b/src/session/query.c index e8dabd71c..c31f10f2f 100644 --- a/src/session/query.c +++ b/src/session/query.c @@ -114,7 +114,7 @@ int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, cons } // Build the reply - _z_reply_t reply = _z_reply_create(expanded_ke, Z_REPLY_TAG_DATA, zn->_local_zid, &msg->_payload, + _z_reply_t reply = _z_reply_create(expanded_ke, Z_REPLY_TAG_DATA, zn->_local_zid, msg->_payload, &msg->_commons._timestamp, msg->_encoding, Z_SAMPLE_KIND_PUT, msg->_attachment); // Verify if this is a newer reply, free the old one in case it is diff --git a/src/session/queryable.c b/src/session/queryable.c index a09afd6ab..53d9747ca 100644 --- a/src/session/queryable.c +++ b/src/session/queryable.c @@ -133,7 +133,7 @@ _z_session_queryable_rc_t *_z_register_session_queryable(_z_session_t *zn, _z_se } int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *msgq, const _z_keyexpr_t q_key, uint32_t qid, - const _z_bytes_t att) { + const _z_bytes_t attachment) { int8_t ret = _Z_RES_OK; _zp_session_lock_mutex(zn); @@ -146,7 +146,7 @@ int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *msgq, const // Build the z_query _z_query_rc_t query = _z_query_rc_new(); - query.in->val = _z_query_create(&msgq->_ext_value, &key, &msgq->_parameters, zn, qid, att); + query.in->val = _z_query_create(&msgq->_ext_value, &key, &msgq->_parameters, zn, qid, attachment); // Parse session_queryable list _z_session_queryable_rc_list_t *xs = qles; while (xs != NULL) { diff --git a/src/session/rx.c b/src/session/rx.c index 2f040a4fa..aaa95eead 100644 --- a/src/session/rx.c +++ b/src/session/rx.c @@ -111,7 +111,7 @@ int8_t _z_handle_network_message(_z_session_t *zn, _z_zenoh_message_t *msg, uint case _Z_REQUEST_DEL: { #if Z_FEATURE_SUBSCRIPTION == 1 _z_msg_del_t del = req._body._del; - ret = _z_trigger_subscriptions(zn, req._key, _z_slice_empty(), _z_encoding_null(), + ret = _z_trigger_subscriptions(zn, req._key, _z_bytes_null(), _z_encoding_null(), Z_SAMPLE_KIND_DELETE, del._commons._timestamp, req._ext_qos, _z_bytes_null()); #endif @@ -133,7 +133,7 @@ int8_t _z_handle_network_message(_z_session_t *zn, _z_zenoh_message_t *msg, uint case _Z_RESPONSE_BODY_ERR: { // @TODO: expose zenoh errors to the user _z_msg_err_t error = response._body._err; - _z_slice_t payload = error._payload; + _z_slice_t payload = _z_bytes_try_get_contiguous(&error._payload); _ZP_UNUSED(payload); // Unused when logs are deactivated _Z_ERROR("Received Err for query %zu: message=%.*s", response._request_id, (int)payload.len, payload.start); diff --git a/src/session/subscription.c b/src/session/subscription.c index ec0980feb..b146cdaa4 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -138,17 +138,17 @@ _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_loca return ret; } -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, - _z_zint_t payload_len, const _z_n_qos_t qos, const _z_bytes_t att) { +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, + const _z_n_qos_t qos, const _z_bytes_t attachment) { _z_encoding_t encoding = _z_encoding_null(); - int8_t ret = _z_trigger_subscriptions(zn, keyexpr, _z_slice_wrap(payload, payload_len), encoding, Z_SAMPLE_KIND_PUT, - _z_timestamp_null(), qos, att); + int8_t ret = _z_trigger_subscriptions(zn, keyexpr, payload, encoding, Z_SAMPLE_KIND_PUT, _z_timestamp_null(), qos, + attachment); (void)ret; } -int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_slice_t payload, +int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, const _z_encoding_t encoding, const _z_zint_t kind, const _z_timestamp_t timestamp, - const _z_n_qos_t qos, const _z_bytes_t att) { + const _z_n_qos_t qos, const _z_bytes_t attachment) { int8_t ret = _Z_RES_OK; _zp_session_lock_mutex(zn); @@ -163,7 +163,7 @@ int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, co // Build the sample _z_sample_rc_t sample = _z_sample_rc_new(); - sample.in->val = _z_sample_create(&key, &payload, timestamp, encoding, kind, qos, att); + sample.in->val = _z_sample_create(&key, payload, timestamp, encoding, kind, qos, attachment); // Parse subscription list _z_subscription_rc_list_t *xs = subs; _Z_DEBUG("Triggering %ju subs", (uintmax_t)_z_subscription_rc_list_len(xs)); @@ -208,14 +208,13 @@ void _z_flush_subscriptions(_z_session_t *zn) { } #else // Z_FEATURE_SUBSCRIPTION == 0 -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, - _z_zint_t payload_len, _z_n_qos_t qos, const _z_bytes_t att) { +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, + _z_n_qos_t qos, const _z_bytes_t attachment) { _ZP_UNUSED(zn); _ZP_UNUSED(keyexpr); _ZP_UNUSED(payload); - _ZP_UNUSED(payload_len); _ZP_UNUSED(qos); - _ZP_UNUSED(att); + _ZP_UNUSED(attachment); } #endif // Z_FEATURE_SUBSCRIPTION == 1 diff --git a/tests/z_api_bytes_test.c b/tests/z_api_bytes_test.c new file mode 100644 index 000000000..ca08dfd85 --- /dev/null +++ b/tests/z_api_bytes_test.c @@ -0,0 +1,214 @@ +// +// Copyright (c) 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 +// 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 "zenoh-pico/api/primitives.h" +#include "zenoh-pico/api/types.h" + +#undef NDEBUG +#include + +void test_reader_seek(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + z_owned_bytes_t payload; + z_bytes_serialize_from_slice(&payload, data, 10); + + z_bytes_reader_t reader = z_bytes_get_reader(z_bytes_loan(&payload)); + assert(z_bytes_reader_tell(&reader) == 0); + + assert(0 == z_bytes_reader_seek(&reader, 5, SEEK_CUR)); + assert(z_bytes_reader_tell(&reader) == 5); + + assert(0 == z_bytes_reader_seek(&reader, 7, SEEK_SET)); + assert(z_bytes_reader_tell(&reader) == 7); + + assert(0 == z_bytes_reader_seek(&reader, -1, SEEK_END)); + assert(z_bytes_reader_tell(&reader) == 9); + + assert(z_bytes_reader_seek(&reader, 20, SEEK_SET) < 0); + + assert(0 == z_bytes_reader_seek(&reader, 5, SEEK_SET)); + assert(z_bytes_reader_tell(&reader) == 5); + + assert(z_bytes_reader_seek(&reader, 10, SEEK_CUR) < 0); + assert(z_bytes_reader_seek(&reader, 10, SEEK_END) < 0); + assert(z_bytes_reader_seek(&reader, -20, SEEK_END) < 0); + + z_bytes_drop(z_bytes_move(&payload)); +} + +void test_reader_read(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t data_out[10] = {0}; + + z_owned_bytes_t payload; + z_bytes_serialize_from_slice(&payload, data, 10); + z_bytes_reader_t reader = z_bytes_get_reader(z_bytes_loan(&payload)); + + assert(5 == z_bytes_reader_read(&reader, data_out, 5)); + + z_bytes_reader_seek(&reader, 2, SEEK_CUR); + assert(2 == z_bytes_reader_read(&reader, data_out + 7, 2)); + + z_bytes_reader_seek(&reader, 5, SEEK_SET); + assert(2 == z_bytes_reader_read(&reader, data_out + 5, 2)); + + z_bytes_reader_seek(&reader, -1, SEEK_END); + assert(1 == z_bytes_reader_read(&reader, data_out + 9, 10)); + + assert(0 == z_bytes_reader_read(&reader, data_out, 10)); + + assert(!memcmp(data, data_out, 10)); + + z_bytes_drop(z_bytes_move(&payload)); +} + +void test_writer(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t data_out[10] = {0}; + + z_owned_bytes_t payload; + z_bytes_empty(&payload); + + z_owned_bytes_writer_t writer; + z_bytes_get_writer(z_bytes_loan_mut(&payload), &writer); + + assert(z_bytes_writer_write(z_bytes_writer_loan_mut(&writer), data, 3) == 0); + assert(z_bytes_writer_write(z_bytes_writer_loan_mut(&writer), data + 3, 5) == 0); + assert(z_bytes_writer_write(z_bytes_writer_loan_mut(&writer), data + 8, 2) == 0); + + z_bytes_writer_drop(z_bytes_writer_move(&writer)); + + z_bytes_reader_t reader = z_bytes_get_reader(z_bytes_loan(&payload)); + + assert(10 == z_bytes_reader_read(&reader, data_out, 10)); + assert(0 == memcmp(data, data_out, 10)); + + z_bytes_drop(z_bytes_move(&payload)); +} + +void test_slice(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + z_owned_bytes_t payload; + z_bytes_serialize_from_slice(&payload, data, 10); + + z_owned_slice_t out; + data[5] = 0; + z_bytes_deserialize_into_slice(z_bytes_loan(&payload), &out); + + assert(!memcmp(data, z_slice_data(z_slice_loan(&out)), 10)); + + 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_bytes_loan(&payload2), &out2); + data[5] = 0; + assert(!memcmp(data, z_slice_data(z_slice_loan(&out2)), 10)); + + z_bytes_drop(z_bytes_move(&payload)); + z_bytes_drop(z_bytes_move(&payload2)); + z_slice_drop(z_slice_move(&out)); + z_slice_drop(z_slice_move(&out2)); +} + +#define TEST_ARITHMETIC(TYPE, EXT, VAL) \ + { \ + TYPE in = VAL, out; \ + z_owned_bytes_t payload; \ + z_bytes_serialize_from_##EXT(&payload, in); \ + z_bytes_deserialize_into_##EXT(z_bytes_loan(&payload), &out); \ + assert(in == out); \ + z_bytes_drop(z_bytes_move(&payload)); \ + } + +void test_arithmetic(void) { + TEST_ARITHMETIC(uint8_t, uint8, 5); + TEST_ARITHMETIC(uint16_t, uint16, 1000); + TEST_ARITHMETIC(uint32_t, uint32, 51000000); + TEST_ARITHMETIC(uint64_t, uint64, 1000000000005); + + TEST_ARITHMETIC(int8_t, int8, 5); + TEST_ARITHMETIC(int16_t, int16, -1000); + TEST_ARITHMETIC(int32_t, int32, 51000000); + TEST_ARITHMETIC(int64_t, int64, -1000000000005); + + TEST_ARITHMETIC(float, float, 10.1f); + TEST_ARITHMETIC(double, double, -105.001); +} + +bool iter_body(z_owned_bytes_t* b, void* context) { + uint8_t* val = (uint8_t*)context; + if (*val >= 10) { + return false; + } else { + z_bytes_serialize_from_uint8(b, *val); + } + *val = *val + 1; + return true; +} + +void test_iter(void) { + uint8_t data_out[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + z_owned_bytes_t payload; + uint8_t context = 0; + z_bytes_serialize_from_iter(&payload, iter_body, (void*)(&context)); + + z_bytes_iterator_t it = z_bytes_get_iterator(z_bytes_loan(&payload)); + + size_t i = 0; + z_owned_bytes_t out; + while (z_bytes_iterator_next(&it, &out)) { + uint8_t res; + z_bytes_deserialize_into_uint8(z_bytes_loan(&out), &res); + assert(res == data_out[i]); + i++; + z_bytes_drop(z_bytes_move(&out)); + } + assert(i == 10); + z_bytes_drop(z_bytes_move(&payload)); +} + +void test_pair(void) { + 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_bytes_move(&payload1), z_bytes_move(&payload2)); + + z_bytes_deserialize_into_pair(z_bytes_loan(&payload), &payload1_out, &payload2_out); + + int16_t i; + double d; + z_bytes_deserialize_into_int16(z_bytes_loan(&payload1_out), &i); + z_bytes_deserialize_into_double(z_bytes_loan(&payload2_out), &d); + + assert(i == -500); + assert(d == 123.45); +} + +int main(void) { + test_reader_seek(); + test_reader_read(); + test_writer(); + test_slice(); + test_arithmetic(); + test_iter(); + test_pair(); +} diff --git a/tests/z_bytes_test.c b/tests/z_bytes_test.c new file mode 100644 index 000000000..11a095114 --- /dev/null +++ b/tests/z_bytes_test.c @@ -0,0 +1,224 @@ +// +// Copyright (c) 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 +// 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 "zenoh-pico/collections/bytes.h" + +#undef NDEBUG +#include + +void test_null_bytes(void) { + _z_bytes_t b = _z_bytes_null(); + assert(_z_bytes_len(&b) == 0); + assert(_z_bytes_is_empty(&b)); + assert(!_z_bytes_check(&b)); + assert(_z_bytes_num_slices(&b) == 0); + _z_bytes_drop(&b); // no crush +} + +void test_slice(void) { + uint8_t data[5] = {1, 2, 3, 4, 5}; + uint8_t data_out[5] = {0}; + _z_slice_t s = _z_slice_wrap_copy(data, 5); + _z_bytes_t b; + _z_bytes_from_slice(&b, s); + + assert(_z_bytes_len(&b) == 5); + assert(!_z_bytes_is_empty(&b)); + assert(_z_bytes_check(&b)); + assert(_z_bytes_num_slices(&b) == 1); + assert(_z_slice_eq(&_z_bytes_get_slice(&b, 0)->slice.in->val, &s)); + + assert(_z_bytes_to_buf(&b, data_out, 5) == 5); + assert(memcmp(data, data_out, 5) == 0); + + _z_bytes_drop(&b); +} + +void test_append(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + uint8_t data_in[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint8_t data_out[10] = {0}; + _z_arc_slice_t s1 = _z_arc_slice_wrap(_z_slice_wrap_copy(data1, 5), 0, 5); + _z_arc_slice_t s2 = _z_arc_slice_wrap(_z_slice_wrap_copy(data2, 5), 2, 3); + _z_arc_slice_t s3 = _z_arc_slice_wrap(_z_slice_wrap_copy(data3, 3), 1, 2); + + _z_bytes_t b = _z_bytes_null(); + + _z_bytes_append_slice(&b, &s1); + _z_bytes_append_slice(&b, &s2); + _z_bytes_append_slice(&b, &s3); + + assert(_z_bytes_len(&b) == 10); + assert(!_z_bytes_is_empty(&b)); + assert(_z_bytes_check(&b)); + assert(_z_bytes_num_slices(&b) == 3); + assert(_z_slice_eq(&_z_bytes_get_slice(&b, 0)->slice.in->val, &s1.slice.in->val)); + assert(_z_slice_eq(&_z_bytes_get_slice(&b, 1)->slice.in->val, &s2.slice.in->val)); + assert(_z_slice_eq(&_z_bytes_get_slice(&b, 2)->slice.in->val, &s3.slice.in->val)); + + assert(_z_bytes_to_buf(&b, data_out, 15) == 10); + assert(memcmp(data_in, data_out, 10) == 0); + + _z_bytes_drop(&b); +} + +void test_reader_read(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + uint8_t data_in[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint8_t data_out[10] = {0}; + _z_arc_slice_t s1 = _z_arc_slice_wrap(_z_slice_wrap_copy(data1, 5), 0, 5); + _z_arc_slice_t s2 = _z_arc_slice_wrap(_z_slice_wrap_copy(data2, 5), 2, 3); + _z_arc_slice_t s3 = _z_arc_slice_wrap(_z_slice_wrap_copy(data3, 3), 1, 2); + + _z_bytes_t b = _z_bytes_null(); + + _z_bytes_append_slice(&b, &s1); + _z_bytes_append_slice(&b, &s2); + _z_bytes_append_slice(&b, &s3); + + _z_bytes_reader_t reader = _z_bytes_get_reader(&b); + + uint8_t out; + assert(_z_bytes_reader_tell(&reader) == 0); + _z_bytes_reader_read(&reader, &out, 1); + assert(_z_bytes_reader_tell(&reader) == 1); + assert(out == 1); + + _z_bytes_reader_read(&reader, data_out, 3); + assert(_z_bytes_reader_tell(&reader) == 4); + assert(memcmp(data_out, data_in + 1, 3) == 0); + + _z_bytes_reader_read(&reader, data_out, 6); + assert(_z_bytes_reader_tell(&reader) == 10); + assert(memcmp(data_out, data_in + 4, 6) == 0); + + _z_bytes_drop(&b); +} + +void test_reader_seek(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + _z_arc_slice_t s1 = _z_arc_slice_wrap(_z_slice_wrap_copy(data1, 5), 0, 5); + _z_arc_slice_t s2 = _z_arc_slice_wrap(_z_slice_wrap_copy(data2, 5), 2, 3); + _z_arc_slice_t s3 = _z_arc_slice_wrap(_z_slice_wrap_copy(data3, 3), 1, 2); + + _z_bytes_t b = _z_bytes_null(); + + _z_bytes_append_slice(&b, &s1); + _z_bytes_append_slice(&b, &s2); + _z_bytes_append_slice(&b, &s3); + + _z_bytes_reader_t reader = _z_bytes_get_reader(&b); + + assert(_z_bytes_reader_tell(&reader) == 0); + assert(_z_bytes_reader_seek(&reader, 3, SEEK_CUR) == 0); + assert(_z_bytes_reader_tell(&reader) == 3); + assert(_z_bytes_reader_seek(&reader, 5, SEEK_CUR) == 0); + assert(_z_bytes_reader_tell(&reader) == 8); + assert(_z_bytes_reader_seek(&reader, 10, SEEK_CUR) != 0); + + assert(_z_bytes_reader_seek(&reader, 0, SEEK_SET) == 0); + assert(_z_bytes_reader_tell(&reader) == 0); + + assert(_z_bytes_reader_seek(&reader, 3, SEEK_SET) == 0); + assert(_z_bytes_reader_tell(&reader) == 3); + assert(_z_bytes_reader_seek(&reader, 8, SEEK_SET) == 0); + assert(_z_bytes_reader_tell(&reader) == 8); + assert(_z_bytes_reader_seek(&reader, 20, SEEK_SET) != 0); + assert(_z_bytes_reader_seek(&reader, -20, SEEK_SET) != 0); + + assert(_z_bytes_reader_seek(&reader, 0, SEEK_END) == 0); + assert(_z_bytes_reader_tell(&reader) == 10); + assert(_z_bytes_reader_seek(&reader, -3, SEEK_END) == 0); + assert(_z_bytes_reader_tell(&reader) == 7); + assert(_z_bytes_reader_seek(&reader, -8, SEEK_END) == 0); + assert(_z_bytes_reader_tell(&reader) == 2); + assert(_z_bytes_reader_seek(&reader, -10, SEEK_END) == 0); + assert(_z_bytes_reader_tell(&reader) == 0); + assert(_z_bytes_reader_seek(&reader, -20, SEEK_END) != 0); + assert(_z_bytes_reader_seek(&reader, 5, SEEK_END) != 0); + + _z_bytes_drop(&b); +} + +void test_writer_no_cache(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + + _z_bytes_t b = _z_bytes_null(); + _z_bytes_writer_t writer = _z_bytes_get_writer(&b, 0); + + _z_bytes_writer_write(&writer, data1, 5); + assert(_z_bytes_len(&b) == 5); + assert(_z_bytes_num_slices(&b) == 1); + _z_bytes_writer_write(&writer, data2, 5); + assert(_z_bytes_len(&b) == 10); + assert(_z_bytes_num_slices(&b) == 2); + _z_bytes_writer_write(&writer, data3, 3); + assert(_z_bytes_len(&b) == 13); + assert(_z_bytes_num_slices(&b) == 3); + + assert(memcmp(data1, _z_arc_slice_data(_z_bytes_get_slice(&b, 0)), 5) == 0); + assert(memcmp(data2, _z_arc_slice_data(_z_bytes_get_slice(&b, 1)), 5) == 0); + assert(memcmp(data3, _z_arc_slice_data(_z_bytes_get_slice(&b, 2)), 3) == 0); + _z_bytes_drop(&b); +} + +void test_writer_with_cache(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + + uint8_t data1_out[7] = {1, 2, 3, 4, 5, 1, 2}; + uint8_t data2_out[6] = {6, 7, 8, 3, 9, 10}; + _z_bytes_t b = _z_bytes_null(); + _z_bytes_writer_t writer = _z_bytes_get_writer(&b, 7); + + _z_bytes_writer_write(&writer, data1, 5); + assert(_z_bytes_len(&b) == 5); + assert(_z_bytes_num_slices(&b) == 1); + _z_bytes_writer_write(&writer, data2, 5); + assert(_z_bytes_len(&b) == 10); + assert(_z_bytes_num_slices(&b) == 2); + _z_bytes_writer_write(&writer, data3, 3); + assert(_z_bytes_len(&b) == 13); + assert(_z_bytes_num_slices(&b) == 2); + + assert(_z_arc_slice_len(_z_bytes_get_slice(&b, 0)) == 7); + assert(_z_arc_slice_len(_z_bytes_get_slice(&b, 1)) == 6); + assert(memcmp(data1_out, _z_arc_slice_data(_z_bytes_get_slice(&b, 0)), 7) == 0); + assert(memcmp(data2_out, _z_arc_slice_data(_z_bytes_get_slice(&b, 1)), 6) == 0); + _z_bytes_drop(&b); +} + +int main(void) { + test_null_bytes(); + test_slice(); + test_append(); + test_reader_read(); + test_reader_seek(); + test_writer_no_cache(); + test_writer_with_cache(); + return 0; +} diff --git a/tests/z_channels_test.c b/tests/z_channels_test.c index ef123ad0d..aff99a581 100644 --- a/tests/z_channels_test.c +++ b/tests/z_channels_test.c @@ -23,16 +23,18 @@ #undef NDEBUG #include -#define SEND(closure, v) \ - do { \ - _z_sample_t s = {.keyexpr = _z_rname("key"), \ - .payload = {._slice = {.start = (const uint8_t *)v, .len = strlen(v)}}, \ - .timestamp = _z_timestamp_null(), \ - .encoding = _z_encoding_null(), \ - .kind = 0, \ - .qos = {0}}; \ - z_loaned_sample_t sample = _z_sample_rc_new_from_val(s); \ - z_call(closure, &sample); \ +#define SEND(closure, v) \ + do { \ + _z_bytes_t payload; \ + _z_bytes_from_slice(&payload, (_z_slice_t){.start = (const uint8_t *)v, .len = strlen(v)}); \ + _z_sample_t s = {.keyexpr = _z_rname("key"), \ + .payload = payload, \ + .timestamp = _z_timestamp_null(), \ + .encoding = _z_encoding_null(), \ + .kind = 0, \ + .qos = {0}}; \ + z_loaned_sample_t sample = _z_sample_rc_new_from_val(s); \ + z_call(closure, &sample); \ } while (0); #define _RECV(handler, method, buf) \ diff --git a/tests/z_client_test.c b/tests/z_client_test.c index 206573196..fea41db83 100644 --- a/tests/z_client_test.c +++ b/tests/z_client_test.c @@ -83,7 +83,7 @@ void reply_handler(const z_loaned_reply_t *reply, void *arg) { z_keyexpr_to_string(z_sample_keyexpr(sample), &k_str); z_owned_string_t value; z_bytes_deserialize_into_string(z_sample_payload(sample), &value); - assert(z_string_len(z_loan(value)) == strlen(res) + 1); + assert(z_string_len(z_loan(value)) == strlen(res)); assert(strncmp(res, z_string_data(z_loan(value)), strlen(res)) == 0); assert(_z_str_eq(z_loan(k_str)->val, res) == true); diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index e39ee5a11..fef9c7998 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -170,16 +170,6 @@ _z_wbuf_t gen_wbuf(size_t len) { return _z_wbuf_make(len, is_expandable); } -_z_slice_t gen_payload(size_t len) { - _z_slice_t pld; - pld._is_alloc = true; - pld.len = len; - pld.start = (uint8_t *)z_malloc(len); - z_random_fill((uint8_t *)pld.start, pld.len); - - return pld; -} - _z_slice_t gen_slice(size_t len) { _z_slice_t arr; arr._is_alloc = true; @@ -195,10 +185,19 @@ _z_slice_t gen_slice(size_t len) { return arr; } +_z_bytes_t gen_payload(size_t len) { + _z_slice_t pld = gen_slice(len); + _z_bytes_t b; + _z_bytes_from_slice(&b, pld); + + return b; +} + _z_bytes_t gen_bytes(size_t len) { - return (_z_bytes_t){ - ._slice = gen_slice(len), - }; + _z_slice_t s = gen_slice(len); + _z_bytes_t b; + _z_bytes_from_slice(&b, s); + return b; } _z_id_t gen_zid(void) { @@ -518,7 +517,26 @@ void assert_eq_string(const _z_string_t *left, const _z_string_t *right) { } void assert_eq_bytes(const _z_bytes_t *left, const _z_bytes_t *right) { - assert_eq_slice(&left->_slice, &right->_slice); + size_t len_left = _z_bytes_len(left); + size_t len_right = _z_bytes_len(right); + printf("Array -> "); + printf("Length (%zu:%zu), ", len_left, len_right); + + assert(len_left == len_right); + printf("Content ("); + _z_bytes_reader_t reader_left = _z_bytes_get_reader(left); + _z_bytes_reader_t reader_right = _z_bytes_get_reader(right); + for (size_t i = 0; i < len_left; i++) { + uint8_t l = 0, r = 0; + _z_bytes_reader_read(&reader_left, &l, 1); + _z_bytes_reader_read(&reader_right, &r, 1); + + printf("%02x:%02x", l, r); + if (i < len_left - 1) printf(" "); + + assert(l == r); + } + printf(")"); } void payload_field(void) { @@ -526,26 +544,26 @@ void payload_field(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize - _z_slice_t e_pld = gen_payload(64); + _z_bytes_t e_pld = gen_payload(64); // Encode - int8_t res = _z_slice_encode(&wbf, &e_pld); + int8_t res = _z_bytes_encode(&wbf, &e_pld); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_slice_t d_pld; - res = _z_slice_decode(&d_pld, &zbf); + _z_bytes_t d_pld; + res = _z_bytes_decode(&d_pld, &zbf); assert(res == _Z_RES_OK); printf(" "); - assert_eq_slice(&e_pld, &d_pld); + assert_eq_bytes(&e_pld, &d_pld); printf("\n"); // Free - _z_slice_clear(&e_pld); - _z_slice_clear(&d_pld); + _z_bytes_drop(&e_pld); + _z_bytes_drop(&d_pld); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } @@ -1162,7 +1180,7 @@ _z_push_body_t gen_push_body(void) { return (_z_push_body_t){._is_put = true, ._body._put = { ._commons = commons, - ._payload = gen_slice(64), + ._payload = gen_bytes(64), ._encoding = gen_encoding(), }}; } else { @@ -1173,7 +1191,7 @@ _z_push_body_t gen_push_body(void) { void assert_eq_push_body(const _z_push_body_t *left, const _z_push_body_t *right) { assert(left->_is_put == right->_is_put); if (left->_is_put) { - assert_eq_slice(&left->_body._put._payload, &right->_body._put._payload); + assert_eq_bytes(&left->_body._put._payload, &right->_body._put._payload); assert_eq_encoding(&left->_body._put._encoding, &right->_body._put._encoding); assert_eq_timestamp(&left->_body._put._commons._timestamp, &right->_body._put._commons._timestamp); assert_eq_source_info(&left->_body._put._commons._source_info, &right->_body._put._commons._source_info); @@ -1256,7 +1274,7 @@ _z_msg_err_t gen_err(void) { void assert_eq_err(const _z_msg_err_t *left, const _z_msg_err_t *right) { assert_eq_encoding(&left->encoding, &right->encoding); assert_eq_source_info(&left->_ext_source_info, &right->_ext_source_info); - assert_eq_slice(&left->_payload, &right->_payload); + assert_eq_bytes(&left->_payload, &right->_payload); } void err_message(void) { diff --git a/zenohpico.pc b/zenohpico.pc index 08c617f59..c4b0e4a08 100644 --- a/zenohpico.pc +++ b/zenohpico.pc @@ -3,6 +3,6 @@ prefix=/usr/local Name: zenohpico Description: URL: -Version: 1.0.20240625dev +Version: 0.11.20240627dev Cflags: -I${prefix}/include Libs: -L${prefix}/lib -lzenohpico