Skip to content

Commit

Permalink
Multi-slice bytes support (#439)
Browse files Browse the repository at this point in the history
* wip

* bytes tests and fixes

* merge

* warning fixes

* use new zz_bytes on user side

* rename zz_bytes -> z_bytes

* merge

* fmt

* fixes

* fixes

* fixed svec implementation;
fixed z_client_test checking string length;
minor readability fixes;

* fixe _z_sample_create signature

* fix _z_trigger_local_subscriptions signature

* fix attachment examples

* fixed uninitialized owned_bytes pointer

* added z_bytes_len and z_bytes_is_empty functions; updated docs

* exposed z_bytes_reader_t

* remove _Z_DO_AND_RETURN_IF_ERR since _Z_CLEAN_RETURN_IF_ERR does the same

* serialization fixes

* ensure that decoded z_bytes never contanin non-_is_alloc slice

* added z_bytes_writer implementation

* format

* fixed attachments

* use _ZP_UNUSED instead of (void)(...)

* fixed _z_bytes_reader_read return value;
fixed public z_bytes api;
added public z_bytes_api tests;
  • Loading branch information
DenisBiryukov91 authored Jun 28, 2024
1 parent 27000eb commit 2668357
Show file tree
Hide file tree
Showing 49 changed files with 2,001 additions and 600 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand All @@ -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)
Expand All @@ -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)
Expand Down
22 changes: 22 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
~~~~~~~~~~~
Expand Down Expand Up @@ -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
~~~~~~~~~~~

Expand Down Expand Up @@ -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
~~~~~~~~~~~

Expand Down Expand Up @@ -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
Expand Down
26 changes: 8 additions & 18 deletions examples/unix/c11/z_get_attachment.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,36 +46,26 @@ 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) {
return false;
} 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);
Expand Down Expand Up @@ -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;
Expand Down
18 changes: 3 additions & 15 deletions examples/unix/c11/z_pub_attachment.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,15 @@ 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) {
return false;
} 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;
}
Expand Down Expand Up @@ -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
Expand Down
15 changes: 8 additions & 7 deletions examples/unix/c11/z_queryable_attachment.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,25 +58,26 @@ 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) {
return false;
} 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);
Expand Down Expand Up @@ -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);
Expand Down
9 changes: 5 additions & 4 deletions examples/unix/c11/z_sub_attachment.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
26 changes: 26 additions & 0 deletions include/zenoh-pico/api/olv_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; } \
Expand Down Expand Up @@ -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)

Expand Down
Loading

0 comments on commit 2668357

Please sign in to comment.