Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add functionality to iterate over z_bytes slices #629

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions include/zenoh-pico/api/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
Expand Down Expand Up @@ -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, \
Expand Down Expand Up @@ -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); }
Expand Down Expand Up @@ -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); }
Expand Down
31 changes: 30 additions & 1 deletion include/zenoh-pico/api/primitives.h
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
*
Expand Down Expand Up @@ -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`.
Expand Down
9 changes: 9 additions & 0 deletions include/zenoh-pico/api/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
*
Expand Down
15 changes: 15 additions & 0 deletions src/api/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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)

Expand Down
44 changes: 44 additions & 0 deletions tests/z_api_bytes_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -309,4 +352,5 @@ int main(void) {
test_append();
test_iter();
test_pair();
test_slices();
}
2 changes: 1 addition & 1 deletion zenohpico.pc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading