Skip to content

ValueUtil changes for FieldValue migration #7991

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

Merged
merged 3 commits into from
May 14, 2021

Conversation

schmidt-sebastian
Copy link
Contributor

@schmidt-sebastian schmidt-sebastian commented Apr 28, 2021

This is part of #7904. It will break the feature branch, but I am planning to send out small reviewable chunks with an end goal of a feature branch that passes CI.

This PR adds a couple of new utilities that are used in the FieldValue port (and changes some signatures). They are all based on Android: https://github.com/firebase/firebase-android-sdk/blob/master/firebase-firestore/src/main/java/com/google/firebase/firestore/model/Values.java

The PR also adds logic to treat zero-length strings/bytes the same as null bytes and strings, as nanopb uses both representations.

@schmidt-sebastian schmidt-sebastian changed the base branch from master to mrschmidt/mutabledocuments April 28, 2021 02:52
@schmidt-sebastian schmidt-sebastian changed the title Mrschmidt/valueutil This PR adds a couple of new classes and methods that are used in the FieldValue port. Apr 28, 2021
@google-cla google-cla bot added the cla: yes label Apr 28, 2021
@google-oss-bot
Copy link

1 Warning
⚠️ Did you forget to add a changelog entry? (Add #no-changelog to the PR description to silence this warning.)

Generated by 🚫 Danger

@schmidt-sebastian schmidt-sebastian changed the title This PR adds a couple of new classes and methods that are used in the FieldValue port. @schmidt-sebastian ValueUtil changes for FieldValue migration Apr 28, 2021
@schmidt-sebastian schmidt-sebastian changed the title @schmidt-sebastian ValueUtil changes for FieldValue migration ValueUtil changes for FieldValue migration Apr 28, 2021
@schmidt-sebastian
Copy link
Contributor Author

@wu-hui Do you have time to take a look at this?

Copy link
Contributor

@wu-hui wu-hui left a comment

Choose a reason for hiding this comment

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

Some minor changes requested, almost LGTM.

// An empty blob is represented by a nullptr
return util::Compare(left.bytes_value != nullptr,
right.bytes_value != nullptr);
// An empty blob is represented by a nullptr (or an empty byte array)
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: this seems to be a behavior change from below? Can you explain why? Not that I am against..

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not meant to be a behavior change but rather a bug fix. When we create an empty bytes array directly with NanoPB, it uses nullptr and does not actually allocate memory. When we receive documents from the backend, these empty byte arrays are represented using a zero-length array, but one with an actual address in memory. We need these two representations to yield the same comparison behavior so our users don't see any behavior change.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good, thanks.


bool IsNaNValue(const google_firestore_v1_Value& value) {
return value.which_value_type == google_firestore_v1_Value_double_value_tag &&
isnan(value.double_value);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be std::isnan from cmath instead.

isnan is also available because cmath also include math.h, but should not be directly used. Just learnt this today from Costa's code review :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Very nice. Hopefully I can use this information in my next code review.

/**
* Generate the canonical ID for the provided field value (as used in Target
* serialization).
*/
std::string CanonicalId(const google_firestore_v1_Value& value);

/**
* Generate the canonical ID for the provided array value (as used in Target
Copy link
Contributor

Choose a reason for hiding this comment

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

"Generates"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

bool Contains(google_firestore_v1_ArrayValue haystack,
google_firestore_v1_Value needle);

/** Returns `nullptr` in its Protobuf representation. */
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe Returns a null Protobuf value? nullptr is pretty specifically a pointer to address 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

/** Returns `nullptr` in its Protobuf representation. */
google_firestore_v1_Value NullValue();

/** Returns `true` if `value` is `nullptr` in its Protobuf representation. */
Copy link
Contributor

Choose a reason for hiding this comment

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

...if given value is a null Protobuf value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

/** Returns `true` if `value` is `NaN` in its Protobuf representation. */
bool IsNaNValue(const google_firestore_v1_Value& value);

google_firestore_v1_Value RefValue(const DatabaseId& database_id,
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@wu-hui wu-hui assigned schmidt-sebastian and unassigned wu-hui May 14, 2021
Copy link
Contributor Author

@schmidt-sebastian schmidt-sebastian left a comment

Choose a reason for hiding this comment

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

Thanks for the review!

// An empty blob is represented by a nullptr
return util::Compare(left.bytes_value != nullptr,
right.bytes_value != nullptr);
// An empty blob is represented by a nullptr (or an empty byte array)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not meant to be a behavior change but rather a bug fix. When we create an empty bytes array directly with NanoPB, it uses nullptr and does not actually allocate memory. When we receive documents from the backend, these empty byte arrays are represented using a zero-length array, but one with an actual address in memory. We need these two representations to yield the same comparison behavior so our users don't see any behavior change.


bool IsNaNValue(const google_firestore_v1_Value& value) {
return value.which_value_type == google_firestore_v1_Value_double_value_tag &&
isnan(value.double_value);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Very nice. Hopefully I can use this information in my next code review.

bool Contains(google_firestore_v1_ArrayValue haystack,
google_firestore_v1_Value needle);

/** Returns `nullptr` in its Protobuf representation. */
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

/** Returns `nullptr` in its Protobuf representation. */
google_firestore_v1_Value NullValue();

/** Returns `true` if `value` is `nullptr` in its Protobuf representation. */
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

/** Returns `true` if `value` is `NaN` in its Protobuf representation. */
bool IsNaNValue(const google_firestore_v1_Value& value);

google_firestore_v1_Value RefValue(const DatabaseId& database_id,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

@wu-hui wu-hui left a comment

Choose a reason for hiding this comment

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

There is one place you missed to update a comment. But LGTM still!

// An empty blob is represented by a nullptr
return util::Compare(left.bytes_value != nullptr,
right.bytes_value != nullptr);
// An empty blob is represented by a nullptr (or an empty byte array)
Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good, thanks.

@wu-hui wu-hui assigned schmidt-sebastian and unassigned wu-hui May 14, 2021
@schmidt-sebastian schmidt-sebastian merged commit e614d95 into mrschmidt/mutabledocuments May 14, 2021
@schmidt-sebastian schmidt-sebastian deleted the mrschmidt/valueutil branch May 14, 2021 22:31
@firebase firebase locked and limited conversation to collaborators Jun 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants