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

feat: Map item iterators #1143

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open

feat: Map item iterators #1143

wants to merge 13 commits into from

Conversation

limbonaut
Copy link
Collaborator

@limbonaut limbonaut commented Feb 6, 2025

This PR introduces map item iterators. Iterator can be used to traverse the map (aka object) key-value pairs. Iterators can also be used to selectively erase items (aka filtering).

Rationale

There is currently no way to get the keys of a map object. We need such a function to build proper representations in upstream SDKs (like sentry-godot). See #1142 for more details.

Supercedes #1142

Copy link

github-actions bot commented Feb 6, 2025

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against dcc5f20

Copy link

codecov bot commented Feb 6, 2025

Codecov Report

Attention: Patch coverage is 0% with 44 lines in your changes missing coverage. Please review.

Project coverage is 82.13%. Comparing base (03143a8) to head (dcc5f20).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1143      +/-   ##
==========================================
- Coverage   82.66%   82.13%   -0.54%     
==========================================
  Files          53       53              
  Lines        7927     7971      +44     
  Branches     1239     1244       +5     
==========================================
- Hits         6553     6547       -6     
- Misses       1263     1312      +49     
- Partials      111      112       +1     

@@ -1,5 +1,9 @@
# Changelog

## Unreleased

- Add map item iterators. ([#1143](https://github.com/getsentry/sentry-native/pull/1143))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that the comments in the header use "map" quite often to talk about interfaces related to the "object" value type, but I would prefer to call this an "object item iterator", given that "object" is the nomenclature that the API uses, especially in the change log.

@@ -244,6 +244,50 @@ SENTRY_API int sentry_value_remove_by_key(sentry_value_t value, const char *k);
SENTRY_API int sentry_value_remove_by_key_n(
sentry_value_t value, const char *k, size_t k_len);

/**
* Map item iterator.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Map item iterator.
* Object item iterator.

/**
* Map item iterator.
*
* It's used to iterate over the key-value pairs of a map.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* It's used to iterate over the key-value pairs of a map.
* It's used to iterate over the key-value pairs of an object.

typedef struct sentry_item_iter_s sentry_item_iter_t;

/**
* Creates a new map item iterator.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Creates a new map item iterator.
* Creates a new object item iterator.

/**
* Creates a new map item iterator.
*
* Returns NULL if the given value is not a map.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Returns NULL if the given value is not a map.
* Returns `NULL` if the given value is not an object.

sentry_value_t
sentry_value_item_iter_get_value(sentry_item_iter_t *item_iter)
{
if (item_iter->index >= *item_iter->len) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

if (item_iter->index >= *item_iter->len) {
return sentry_value_new_null();
}
return item_iter->pairs[item_iter->index].v;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

int
sentry_value_item_iter_valid(sentry_item_iter_t *item_iter)
{
return item_iter->index < *item_iter->len && item_iter->pairs != NULL;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we check pairs here, we should check len too.

if (item_iter->frozen || item_iter->index >= *item_iter->len) {
return 1;
}
obj_pair_t *pair = &item_iter->pairs[item_iter->index];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, do we assume that pairs and len are valid pointers in this case?

If so, why? Because valid() does the check? If so, we must decide whether users must check for validity every time either the iterator or the object changed and erase(), get_key() and get_value() assume valid iterators or add the checks in all of those functions.

Whichever way we choose, we should be consistent regarding the guarantees of calling valid(), the accessors, and mutators (since adding new keys will then also be used if iterators allow object mutation).

This demonstrates how easily checks (and thus guarantees) can become inconsistent quickly when an in-place erasure is introduced. If you introduce the guarantees for each getter and mutator (making valid() solely a function for a loop-invariant), then you can't change that without breaking code. OTOH, adding those guarantees later won't break any code.

}
sentry_free(it);
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we keep the mutating iterator, please also add a loop that adds keys or documents that this is forbidden.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants