diff --git a/docs/api.rst b/docs/api.rst index 1fea537d1..4c2087e1a 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -54,6 +54,7 @@ Data Structures .. autoctype:: types.h::zp_send_join_options_t .. autoctype:: types.h::z_bytes_reader_t .. autoctype:: types.h::z_bytes_iterator_t +.. autoctype:: types.h::z_bytes_slice_iterator_t .. autoctype:: types.h::z_bytes_writer_t @@ -204,6 +205,10 @@ TODO: view type description Represents a string without null-terminator. +.. c:type:: z_view_slice_t + + Represents an array of bytes. + .. c:type:: z_view_keyexpr_t Represents a key expression in Zenoh. @@ -351,6 +356,8 @@ Primitives .. 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_slice_iterator +.. autocfunction:: primitives.h::z_bytes_slice_iterator_next .. autocfunction:: primitives.h::z_bytes_get_reader .. autocfunction:: primitives.h::z_bytes_reader_read .. autocfunction:: primitives.h::z_bytes_reader_read_bounded diff --git a/include/zenoh-pico/api/macros.h b/include/zenoh-pico/api/macros.h index 4dedda8dc..28b30382e 100644 --- a/include/zenoh-pico/api/macros.h +++ b/include/zenoh-pico/api/macros.h @@ -50,6 +50,7 @@ z_owned_sample_t : z_sample_loan, \ z_owned_query_t : z_query_loan, \ z_owned_slice_t : z_slice_loan, \ + z_view_slice_t : z_view_slice_loan, \ z_owned_bytes_t : z_bytes_loan, \ z_owned_encoding_t : z_encoding_loan, \ z_owned_task_t : z_task_loan, \ @@ -83,6 +84,7 @@ z_owned_sample_t : z_sample_loan_mut, \ z_owned_query_t : z_query_loan_mut, \ z_owned_slice_t : z_slice_loan_mut, \ + z_view_slice_t : z_view_slice_loan_mut, \ z_owned_bytes_t : z_bytes_loan_mut, \ z_owned_task_t : z_task_loan_mut, \ z_owned_mutex_t : z_mutex_loan_mut, \ @@ -381,6 +383,7 @@ inline const z_loaned_string_array_t* z_loan(const z_owned_string_array_t& x) { inline const z_loaned_sample_t* z_loan(const z_owned_sample_t& x) { return z_sample_loan(&x); } inline const z_loaned_query_t* z_loan(const z_owned_query_t& x) { return z_query_loan(&x); } inline const z_loaned_slice_t* z_loan(const z_owned_slice_t& x) { return z_slice_loan(&x); } +inline const z_loaned_slice_t* z_loan(const z_view_slice_t& x) { return z_view_slice_loan(&x); } inline const z_loaned_bytes_t* z_loan(const z_owned_bytes_t& x) { return z_bytes_loan(&x); } inline const z_loaned_encoding_t* z_loan(const z_owned_encoding_t& x) { return z_encoding_loan(&x); } inline const z_loaned_task_t* z_loan(const z_owned_task_t& x) { return z_task_loan(&x); } @@ -410,6 +413,7 @@ inline z_loaned_reply_t* z_loan_mut(z_owned_reply_t& x) { return z_reply_loan_mu inline z_loaned_hello_t* z_loan_mut(z_owned_hello_t& x) { return z_hello_loan_mut(&x); } inline z_loaned_string_t* z_loan_mut(z_owned_string_t& x) { return z_string_loan_mut(&x); } inline z_loaned_string_t* z_loan_mut(z_view_string_t& x) { return z_view_string_loan_mut(&x); } +inline z_loaned_slice_t* z_loan_mut(z_view_slice_t& x) { return z_view_slice_loan_mut(&x); } inline z_loaned_string_array_t* z_loan_mut(z_owned_string_array_t& x) { return z_string_array_loan_mut(&x); } inline z_loaned_sample_t* z_loan_mut(z_owned_sample_t& x) { return z_sample_loan_mut(&x); } inline z_loaned_query_t* z_loan_mut(z_owned_query_t& x) { return z_query_loan_mut(&x); } diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index 4d5cbeb3f..d9f48d709 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -961,12 +961,40 @@ z_bytes_iterator_t z_bytes_get_iterator(const z_loaned_bytes_t *bytes); * * Parameters: * iter: An iterator over multi-element serialized data. - * out: An uninitialized :c:type:`z_owned_bytes_t` that will contained next serialized element. + * out: An uninitialized :c:type:`z_owned_bytes_t` that will contain 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 an iterator on raw bytes slices contained in the `z_loaned_bytes_t`. + * + * Zenoh may store data in non-contiguous regions of memory, this iterator + * then allows to access raw data directly without any attempt of deserializing it. + * Please note that no guarantee is provided on the internal memory layout. + * The only provided guarantee is on the bytes order that is preserved. + * + * Parameters: + * bytes: Data to iterate over. + * + * Return: + * The constructed :c:type:`z_bytes_slice_iterator_t`. + */ +z_bytes_slice_iterator_t z_bytes_get_slice_iterator(const z_loaned_bytes_t *bytes); + +/** + * Constructs :c:type:`z_view_slice_t` providing view to the next slice. + * + * + * Parameters: + * iter: An iterator over slices of serialized data. + * out: An uninitialized :c:type:`z_view_slice_t` that will contain next slice. + * Return: + * ``false`` when iterator reaches the end, ``true`` otherwise. + */ +_Bool z_bytes_slice_iterator_next(z_bytes_slice_iterator_t *iter, z_view_slice_t *out); + /** * Returns a reader for the `bytes`. * @@ -1326,6 +1354,7 @@ _Z_OWNED_FUNCTIONS_CLOSURE_DEF(closure_zid) _Z_VIEW_FUNCTIONS_DEF(keyexpr) _Z_VIEW_FUNCTIONS_DEF(string) +_Z_VIEW_FUNCTIONS_DEF(slice) /** * Loans a :c:type:`z_owned_sample_t`. diff --git a/include/zenoh-pico/api/types.h b/include/zenoh-pico/api/types.h index 1db2306c2..0a4f931f6 100644 --- a/include/zenoh-pico/api/types.h +++ b/include/zenoh-pico/api/types.h @@ -64,6 +64,7 @@ typedef _z_timestamp_t z_timestamp_t; * uint8_t *start: A pointer to the bytes array. */ _Z_OWNED_TYPE_VALUE(_z_slice_t, slice) +_Z_VIEW_TYPE(_z_slice_t, slice) /** * Represents a container for slices. @@ -85,6 +86,14 @@ typedef _z_bytes_iterator_t z_bytes_iterator_t; */ typedef _z_bytes_iterator_t z_bytes_reader_t; +/** + * An iterator over slices of serialized data. + */ +typedef struct { + const _z_bytes_t *_bytes; + size_t _slice_idx; +} z_bytes_slice_iterator_t; + /** * Represents a string without null-terminator. * diff --git a/src/api/api.c b/src/api/api.c index 105ff350a..6eae91b57 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -638,6 +638,20 @@ _Bool z_bytes_iterator_next(z_bytes_iterator_t *iter, z_owned_bytes_t *bytes) { return true; } +z_bytes_slice_iterator_t z_bytes_get_slice_iterator(const z_loaned_bytes_t *bytes) { + return (z_bytes_slice_iterator_t){._bytes = bytes, ._slice_idx = 0}; +} + +_Bool z_bytes_slice_iterator_next(z_bytes_slice_iterator_t *iter, z_view_slice_t *out) { + if (iter->_slice_idx >= _z_bytes_num_slices(iter->_bytes)) { + return false; + } + const _z_arc_slice_t *arc_slice = _z_bytes_get_slice(iter->_bytes, iter->_slice_idx); + out->_val = _z_slice_alias_buf(_Z_RC_IN_VAL(&arc_slice->slice)->start + arc_slice->start, arc_slice->len); + iter->_slice_idx++; + return true; +} + z_bytes_writer_t z_bytes_get_writer(z_loaned_bytes_t *bytes) { return _z_bytes_get_iterator_writer(bytes, Z_IOSLICE_SIZE); } @@ -748,6 +762,7 @@ _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_keyexpr_t, keyexpr, _z_keyexpr_check, _z_keyexp _z_keyexpr_clear) _Z_VIEW_FUNCTIONS_IMPL(_z_keyexpr_t, keyexpr, _z_keyexpr_check, _z_keyexpr_null) _Z_VIEW_FUNCTIONS_IMPL(_z_string_t, string, _z_string_check, _z_string_null) +_Z_VIEW_FUNCTIONS_IMPL(_z_slice_t, slice, _z_slice_check, _z_slice_empty) _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_hello_t, hello, _z_hello_check, _z_hello_null, _z_hello_copy, _z_hello_clear) diff --git a/tests/z_api_bytes_test.c b/tests/z_api_bytes_test.c index cbf0c9610..ae1812137 100644 --- a/tests/z_api_bytes_test.c +++ b/tests/z_api_bytes_test.c @@ -299,6 +299,49 @@ void test_pair(void) { assert(d == 123.45); } +_Bool check_slice(const z_loaned_bytes_t *b, const uint8_t *data, size_t len) { + z_bytes_slice_iterator_t it = z_bytes_get_slice_iterator(b); + uint8_t *data_out = (uint8_t *)malloc(len); + z_view_slice_t v; + size_t pos = 0; + while (z_bytes_slice_iterator_next(&it, &v)) { + const uint8_t *slice_data = z_slice_data(z_view_slice_loan(&v)); + size_t slice_len = z_slice_len(z_view_slice_loan(&v)); + memcpy(data_out + pos, slice_data, slice_len); + pos += slice_len; + } + assert(pos == len); + assert(memcmp(data, data_out, len) == 0); + free(data_out); + return true; +} + +void test_slices(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + z_owned_bytes_t payload; + z_bytes_empty(&payload); + + z_bytes_writer_t writer = z_bytes_get_writer(z_bytes_loan_mut(&payload)); + z_bytes_writer_write_all(&writer, data, 10); + + assert(check_slice(z_bytes_loan(&payload), data, 10)); + + z_bytes_drop(z_bytes_move(&payload)); + z_bytes_empty(&payload); + + // possible multiple slices + writer = z_bytes_get_writer(z_bytes_loan_mut(&payload)); + + for (size_t i = 0; i < 10; i++) { + z_owned_bytes_t b; + z_bytes_serialize_from_buf(&b, data + i, 1); + z_bytes_writer_append(&writer, z_bytes_move(&b)); + } + + assert(check_slice(z_bytes_loan(&payload), data, 10)); + z_bytes_drop(z_bytes_move(&payload)); +} + int main(void) { test_reader_seek(); test_reader_read(); @@ -309,4 +352,5 @@ int main(void) { test_append(); test_iter(); test_pair(); + test_slices(); } diff --git a/zenohpico.pc b/zenohpico.pc index 45f37d7e1..8c92f5f98 100644 --- a/zenohpico.pc +++ b/zenohpico.pc @@ -3,6 +3,6 @@ prefix=/usr/local Name: zenohpico Description: URL: -Version: 1.0.20240830dev +Version: 1.0.20240905dev Cflags: -I${prefix}/include Libs: -L${prefix}/lib -lzenohpico