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 len() and is_empty() methods to z_attachment and z_owned_bytes_map_t #280

Merged
merged 2 commits into from
Mar 18, 2024
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
4 changes: 4 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Bytes map
.. autocfunction:: zenoh_commons.h::z_bytes_map_null
.. autocfunction:: zenoh_commons.h::z_bytes_map_drop
.. autocfunction:: zenoh_commons.h::z_bytes_map_get
.. autocfunction:: zenoh_commons.h::z_bytes_map_len
.. autocfunction:: zenoh_commons.h::z_bytes_map_is_empty
.. autocfunction:: zenoh_commons.h::z_bytes_map_insert_by_alias
.. autocfunction:: zenoh_commons.h::z_bytes_map_insert_by_copy
.. autocfunction:: zenoh_commons.h::z_bytes_map_iter
Expand Down Expand Up @@ -157,6 +159,8 @@ Attachment

.. autocfunction:: zenoh_commons.h::z_attachment_null
.. autocfunction:: zenoh_commons.h::z_attachment_get
.. autocfunction:: zenoh_commons.h::z_attachment_len
.. autocfunction:: zenoh_commons.h::z_attachment_is_empty
.. autocfunction:: zenoh_commons.h::z_attachment_check
.. autocfunction:: zenoh_commons.h::z_attachment_iterate

Expand Down
18 changes: 18 additions & 0 deletions include/zenoh_commons.h
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,10 @@ ZENOHC_API bool z_attachment_check(const struct z_attachment_t *this_);
* Returns the value associated with the key.
*/
ZENOHC_API struct z_bytes_t z_attachment_get(struct z_attachment_t this_, struct z_bytes_t key);
/**
* Returns true if `z_attachment_t` contains no key-value pairs, false otherwise.
*/
ZENOHC_API bool z_attachment_is_empty(struct z_attachment_t this_);
/**
* Iterate over `this`'s key-value pairs, breaking if `body` returns a non-zero
* value for a key-value pair, and returning the latest return value.
Expand All @@ -1038,6 +1042,12 @@ ZENOHC_API
int8_t z_attachment_iterate(struct z_attachment_t this_,
z_attachment_iter_body_t body,
void *context);
/**
* Returns number of key-value pairs for `z_attachment_t`.
*
* Does so by iterating over all existing key-value pairs.
*/
ZENOHC_API size_t z_attachment_len(struct z_attachment_t this_);
/**
* Returns the gravestone value for `z_attachment_t`.
*/
Expand Down Expand Up @@ -1107,6 +1117,10 @@ ZENOHC_API
void z_bytes_map_insert_by_copy(const struct z_owned_bytes_map_t *this_,
struct z_bytes_t key,
struct z_bytes_t value);
/**
* Returns true if the map is empty, false otherwise.
*/
ZENOHC_API bool z_bytes_map_is_empty(struct z_owned_bytes_map_t *this_);
/**
* Iterates over the key-value pairs in the map.
*
Expand All @@ -1123,6 +1137,10 @@ ZENOHC_API
int8_t z_bytes_map_iter(const struct z_owned_bytes_map_t *this_,
z_attachment_iter_body_t body,
void *ctx);
/**
* Returns number of key-value pairs in the map.
*/
ZENOHC_API size_t z_bytes_map_len(struct z_owned_bytes_map_t *this_);
/**
* Constructs a new map.
*/
Expand Down
66 changes: 66 additions & 0 deletions src/attachment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,58 @@ pub extern "C" fn z_attachment_get(this: z_attachment_t, key: z_bytes_t) -> z_by
}
}

fn _z_attachment_len(this: z_attachment_t, check_if_non_empty: bool) -> usize {
match this.iteration_driver.as_ref() {
None => 0,
Some(iteration_driver) => {
struct count_context_t {
count: usize,
stop_if_not_empty: bool,
}

extern "C" fn attachment_count_iterator(
_key: z_bytes_t,
_value: z_bytes_t,
context: *mut c_void,
) -> i8 {
unsafe {
let context = &mut *(context as *mut count_context_t);
context.count += 1;
if context.stop_if_not_empty {
1
} else {
0
}
}
}
let mut count_context = count_context_t {
count: 0,
stop_if_not_empty: check_if_non_empty,
};
(iteration_driver)(
this.data,
attachment_count_iterator,
&mut count_context as *mut _ as *mut c_void,
);
count_context.count
}
}
}

/// Returns number of key-value pairs for `z_attachment_t`.
///
/// Does so by iterating over all existing key-value pairs.
#[no_mangle]
pub extern "C" fn z_attachment_len(this: z_attachment_t) -> usize {
_z_attachment_len(this, false)
}

/// Returns true if `z_attachment_t` contains no key-value pairs, false otherwise.
#[no_mangle]
pub extern "C" fn z_attachment_is_empty(this: z_attachment_t) -> bool {
_z_attachment_len(this, true) == 0
}

/// A map of maybe-owned vector of bytes to owned vector of bytes.
///
/// In Zenoh C, this map is backed by Rust's standard HashMap, with a DoS-resistant hasher
Expand Down Expand Up @@ -162,6 +214,20 @@ pub extern "C" fn z_bytes_map_drop(this: &mut z_owned_bytes_map_t) {
this.take();
}

/// Returns number of key-value pairs in the map.
#[no_mangle]
pub extern "C" fn z_bytes_map_len(this: &mut z_owned_bytes_map_t) -> usize {
let this = unsafe { &*this.get() };
this.as_ref().map(|m| m.len()).unwrap_or(0)
}

/// Returns true if the map is empty, false otherwise.
#[no_mangle]
pub extern "C" fn z_bytes_map_is_empty(this: &mut z_owned_bytes_map_t) -> bool {
let this = unsafe { &*this.get() };
this.as_ref().map(|m| m.is_empty()).unwrap_or(true)
}

/// Returns the value associated with `key`, returning a gravestone value if:
/// - `this` or `key` is in gravestone state.
/// - `this` has no value associated to `key`
Expand Down
14 changes: 14 additions & 0 deletions tests/z_api_attachment_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ void writting_through_map_by_alias_read_by_get() {
z_attachment_t attachment = z_bytes_map_as_attachment(&map);

// Elements check

assert(z_bytes_map_len(&map) == 2);
assert(z_attachment_len(attachment) == 2);
assert(!z_attachment_is_empty(attachment));

z_bytes_t a1 = z_attachment_get(attachment, z_bytes_from_str("k1"));
ASSERT_STR_BYTES_EQUAL("v1", a1);

Expand Down Expand Up @@ -61,6 +66,10 @@ void writting_through_map_by_copy_read_by_iter() {
z_attachment_t attachment = z_bytes_map_as_attachment(&map);

// Elements check
assert(z_bytes_map_len(&map) == 2);
assert(z_attachment_len(attachment) == 2);
assert(!z_attachment_is_empty(attachment));

int res = z_attachment_iterate(attachment, _attachment_reader, (void*)42);
assert(res == 24);

Expand All @@ -81,6 +90,9 @@ void writting_no_map_read_by_get() {
z_attachment_t attachment = {.data = NULL, .iteration_driver = &_iteration_driver};

// Elements check
assert(z_attachment_len(attachment) == 2);
assert(!z_attachment_is_empty(attachment));

z_bytes_t a1 = z_attachment_get(attachment, z_bytes_from_str("k1"));
ASSERT_STR_BYTES_EQUAL("v1", a1);

Expand All @@ -94,6 +106,8 @@ void writting_no_map_read_by_get() {

void invalid_attachment_safety() {
z_attachment_t attachment = z_attachment_null();
assert(z_attachment_is_empty(attachment));
assert(z_attachment_len(attachment) == 0);

z_bytes_t a_non = z_attachment_get(attachment, z_bytes_from_str("k_non"));
assert(a_non.start == NULL);
Expand Down
Loading