Skip to content

Commit

Permalink
add z_attachment_is_empty and z_bytes_map_is_empty functions
Browse files Browse the repository at this point in the history
  • Loading branch information
DenisBiryukov91 committed Mar 11, 2024
1 parent 98b5ed4 commit 8c35add
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 12 deletions.
2 changes: 2 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Bytes map
.. 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 @@ -159,6 +160,7 @@ 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
8 changes: 8 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 Down Expand Up @@ -1113,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 Down
51 changes: 39 additions & 12 deletions src/attachment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,38 +115,58 @@ pub extern "C" fn z_attachment_get(this: z_attachment_t, key: z_bytes_t) -> z_by
}
}

/// 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 {
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) => {
let mut count: usize = 0;
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 usize);
*context += 1;
0
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 as *mut _ as *mut c_void,
&mut count_context as *mut _ as *mut c_void,
);
count
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 @@ -201,6 +221,13 @@ pub extern "C" fn z_bytes_map_len(this: &mut z_owned_bytes_map_t) -> usize {
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
5 changes: 5 additions & 0 deletions tests/z_api_attachment_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void writting_through_map_by_alias_read_by_get() {

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 @@ -67,6 +68,7 @@ void writting_through_map_by_copy_read_by_iter() {
// 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 @@ -89,6 +91,7 @@ void writting_no_map_read_by_get() {

// 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 @@ -103,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

0 comments on commit 8c35add

Please sign in to comment.