Skip to content

Migrate CPP SDK from FieldValue to Protobuf #577

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 46 commits into from
Aug 18, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e5c1837
FieldValue port
schmidt-sebastian Jul 27, 2021
baed896
Feedback
schmidt-sebastian Jul 28, 2021
0ed529e
Lint
schmidt-sebastian Jul 28, 2021
273171b
Update source to master
schmidt-sebastian Jul 28, 2021
ab8b574
Fix compile
schmidt-sebastian Jul 28, 2021
a19d7cc
Add nanopb
schmidt-sebastian Jul 28, 2021
2206809
Use header
schmidt-sebastian Jul 28, 2021
147d5a8
Fix build
schmidt-sebastian Jul 29, 2021
f139608
Merge branch 'main' into mrschmidt/fieldvalue
schmidt-sebastian Jul 29, 2021
0b200d3
Updated Android and iOS dependencies for 8.4.0 release
schmidt-sebastian Aug 10, 2021
a511c1b
Merge
schmidt-sebastian Aug 10, 2021
30a4590
Merge branch 'main' into mrschmidt/fieldvalue
schmidt-sebastian Aug 10, 2021
4c572f7
Add header back
schmidt-sebastian Aug 11, 2021
fd4e5c2
Merge branch 'main' into mrschmidt/fieldvalue
schmidt-sebastian Aug 11, 2021
fb68ec7
Update CMakeLists.txt
schmidt-sebastian Aug 11, 2021
e12fb04
Fix test
schmidt-sebastian Aug 12, 2021
97c2a9c
Merge branch 'mrschmidt/fieldvalue' of github.com:firebase/firebase-c…
schmidt-sebastian Aug 12, 2021
b55a85f
Fix server timestamp
schmidt-sebastian Aug 12, 2021
2214b24
Add the nanopb header path to the internal testapp xcode project
a-maurice Aug 12, 2021
f24e3f7
More ServerTimestamp fixes
schmidt-sebastian Aug 12, 2021
36b4088
Merge branch 'mrschmidt/fieldvalue' of github.com:firebase/firebase-c…
schmidt-sebastian Aug 12, 2021
90918ca
Fix logic
schmidt-sebastian Aug 12, 2021
2c73631
Use valid values
schmidt-sebastian Aug 12, 2021
b898ab2
Missing break
schmidt-sebastian Aug 13, 2021
bb85fae
Merge branch 'main' into mrschmidt/fieldvalue
schmidt-sebastian Aug 13, 2021
322622a
Enable debug logging
schmidt-sebastian Aug 13, 2021
1e0c794
Only run one test
schmidt-sebastian Aug 13, 2021
e57cd53
Merge branch 'mrschmidt/fieldvalue' of github.com:firebase/firebase-c…
schmidt-sebastian Aug 13, 2021
6ac8e12
More tests
schmidt-sebastian Aug 13, 2021
929a343
Only run Firestore
schmidt-sebastian Aug 13, 2021
59b2f99
Don't crash
schmidt-sebastian Aug 13, 2021
91898df
More logging
schmidt-sebastian Aug 13, 2021
a655e31
More logging
schmidt-sebastian Aug 16, 2021
ee65f4e
Fix build
schmidt-sebastian Aug 16, 2021
38b6729
Merge branch 'main' into mrschmidt/fieldvalue
schmidt-sebastian Aug 16, 2021
10e6769
Display more test results
schmidt-sebastian Aug 16, 2021
89cb07b
Merge branch 'mrschmidt/fieldvalue' of github.com:firebase/firebase-c…
schmidt-sebastian Aug 16, 2021
cedfa82
Temporarily comment out the tests that fail on tvOS.
var-const Aug 17, 2021
d60bf24
Merge branch 'mrschmidt/fieldvalue' of https://github.com/firebase/fi…
var-const Aug 17, 2021
60b0dc1
Comment out `query_snapshot_test.cc` for good measure.
var-const Aug 17, 2021
cd23164
Merge branch 'mrschmidt/fieldvalue' of https://github.com/firebase/fi…
var-const Aug 17, 2021
55e61ed
Make sure the CMake build uses the same Nanopb definitions as the iOS
var-const Aug 18, 2021
268b1e9
Restore the commented out tests.
var-const Aug 18, 2021
e024ee1
Revert debugging changes
schmidt-sebastian Aug 18, 2021
7899926
Merge branch 'mrschmidt/fieldvalue' of github.com:firebase/firebase-c…
schmidt-sebastian Aug 18, 2021
2495ac3
Revert
schmidt-sebastian Aug 18, 2021
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
2 changes: 1 addition & 1 deletion cmake/external/firestore.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ if(TARGET firestore)
return()
endif()

set(version CocoaPods-8.4.0)
set(version master)
ExternalProject_Add(
firestore

Expand Down
2 changes: 1 addition & 1 deletion firestore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ target_link_libraries(firebase_firestore

if(FIRESTORE_USE_EXTERNAL_CMAKE_BUILD)
target_link_libraries(firebase_firestore
PRIVATE
PUBLIC
firestore_core
absl_variant
)
Expand Down
132 changes: 78 additions & 54 deletions firestore/src/main/document_snapshot_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
#include "Firestore/core/src/model/database_id.h"
#include "Firestore/core/src/model/document_key.h"
#include "Firestore/core/src/model/field_path.h"
#include "Firestore/core/src/model/field_value_options.h"
#include "Firestore/core/src/model/server_timestamp_util.h"
#include "Firestore/core/src/nanopb/byte_string.h"
#include "Firestore/core/src/nanopb/message.h"
#include "Firestore/core/src/nanopb/nanopb_util.h"
#include "absl/memory/memory.h"
#include "firestore/src/common/macros.h"
#include "firestore/src/include/firebase/firestore.h"
Expand All @@ -20,7 +22,13 @@ namespace firebase {
namespace firestore {

using ServerTimestampBehavior = DocumentSnapshot::ServerTimestampBehavior;
using Type = model::FieldValue::Type;
using model::DatabaseId;
using model::DocumentKey;
using model::GetLocalWriteTime;
using model::GetPreviousValue;
using model::IsServerTimestamp;
using nanopb::MakeString;
using nanopb::Message;

DocumentSnapshotInternal::DocumentSnapshotInternal(
api::DocumentSnapshot&& snapshot)
Expand Down Expand Up @@ -55,12 +63,11 @@ bool DocumentSnapshotInternal::exists() const { return snapshot_.exists(); }

MapFieldValue DocumentSnapshotInternal::GetData(
ServerTimestampBehavior stb) const {
using Map = model::FieldValue::Map;
absl::optional<google_firestore_v1_Value> data =
snapshot_.GetValue(model::FieldPath::EmptyPath());
if (!data) return MapFieldValue{};

absl::optional<model::ObjectValue> maybe_object = snapshot_.GetData();
const Map& map =
maybe_object ? maybe_object.value().GetInternalValue() : Map{};
FieldValue result = ConvertObject(map, stb);
FieldValue result = ConvertObject(data->map_value, stb);
SIMPLE_HARD_ASSERT(result.type() == FieldValue::Type::kMap,
"Expected snapshot data to parse to a map");
return result.map_value();
Expand All @@ -73,7 +80,8 @@ FieldValue DocumentSnapshotInternal::Get(const FieldPath& field,

FieldValue DocumentSnapshotInternal::GetValue(
const model::FieldPath& path, ServerTimestampBehavior stb) const {
absl::optional<model::FieldValue> maybe_value = snapshot_.GetValue(path);
absl::optional<google_firestore_v1_Value> maybe_value =
snapshot_.GetValue(path);
if (maybe_value) {
return ConvertAnyValue(std::move(maybe_value).value(), stb);
} else {
Expand All @@ -84,95 +92,111 @@ FieldValue DocumentSnapshotInternal::GetValue(
// FieldValue parsing

FieldValue DocumentSnapshotInternal::ConvertAnyValue(
const model::FieldValue& input, ServerTimestampBehavior stb) const {
switch (input.type()) {
case Type::Object:
return ConvertObject(input.object_value(), stb);
case Type::Array:
return ConvertArray(input.array_value(), stb);
const google_firestore_v1_Value& input, ServerTimestampBehavior stb) const {
switch (input.which_value_type) {
case google_firestore_v1_Value_map_value_tag:
return ConvertObject(input.map_value, stb);
case google_firestore_v1_Value_array_value_tag:
return ConvertArray(input.array_value, stb);
default:
return ConvertScalar(input, stb);
}
}

FieldValue DocumentSnapshotInternal::ConvertObject(
const model::FieldValue::Map& object, ServerTimestampBehavior stb) const {
const google_firestore_v1_MapValue& object,
ServerTimestampBehavior stb) const {
MapFieldValue result;
for (const auto& kv : object) {
result[kv.first] = ConvertAnyValue(kv.second, stb);
for (pb_size_t i = 0; i < object.fields_count; ++i) {
std::string key = MakeString(object.fields[i].key);
const google_firestore_v1_Value& value = object.fields[i].value;
result[std::move(key)] = ConvertAnyValue(value, stb);
}

return FieldValue::Map(std::move(result));
}

FieldValue DocumentSnapshotInternal::ConvertArray(
const model::FieldValue::Array& array, ServerTimestampBehavior stb) const {
const google_firestore_v1_ArrayValue& array,
ServerTimestampBehavior stb) const {
std::vector<FieldValue> result;
for (const auto& value : array) {
result.push_back(ConvertAnyValue(value, stb));
for (pb_size_t i = 0; i < array.values_count; ++i) {
result.push_back(ConvertAnyValue(array.values[i], stb));
}

return FieldValue::Array(std::move(result));
}

FieldValue DocumentSnapshotInternal::ConvertScalar(
const model::FieldValue& scalar, ServerTimestampBehavior stb) const {
switch (scalar.type()) {
case Type::Null:
const google_firestore_v1_Value& scalar,
ServerTimestampBehavior stb) const {
switch (scalar.which_value_type) {
case google_firestore_v1_Value_map_value_tag:
if (IsServerTimestamp(scalar)) {
return ConvertServerTimestamp(scalar, stb);
}
return FieldValue::Null();
case Type::Boolean:
return FieldValue::Boolean(scalar.boolean_value());
case Type::Integer:
return FieldValue::Integer(scalar.integer_value());
case Type::Double:
return FieldValue::Double(scalar.double_value());
case Type::String:
return FieldValue::String(scalar.string_value());
case Type::Timestamp:
return FieldValue::Timestamp(scalar.timestamp_value());
case Type::GeoPoint:
return FieldValue::GeoPoint(scalar.geo_point_value());
case Type::Blob:
return FieldValue::Blob(scalar.blob_value().data(),
scalar.blob_value().size());
case Type::Reference:
return ConvertReference(scalar.reference_value());
case Type::ServerTimestamp:
return ConvertServerTimestamp(scalar.server_timestamp_value(), stb);
case google_firestore_v1_Value_boolean_value_tag:
return FieldValue::Boolean(scalar.boolean_value);
case google_firestore_v1_Value_integer_value_tag:
return FieldValue::Integer(scalar.integer_value);
case google_firestore_v1_Value_double_value_tag:
return FieldValue::Double(scalar.double_value);
case google_firestore_v1_Value_string_value_tag:
return FieldValue::String(MakeString(scalar.string_value));
case google_firestore_v1_Value_timestamp_value_tag:
return FieldValue::Timestamp(Timestamp(scalar.timestamp_value.seconds,
scalar.timestamp_value.nanos));
case google_firestore_v1_Value_geo_point_value_tag:
return FieldValue::GeoPoint(GeoPoint(scalar.geo_point_value.latitude,
scalar.geo_point_value.longitude));
case google_firestore_v1_Value_bytes_value_tag:
return scalar.bytes_value ? FieldValue::Blob(scalar.bytes_value->bytes,
scalar.bytes_value->size)
: FieldValue::Blob(nullptr, 0);
case google_firestore_v1_Value_reference_value_tag:
return ConvertReference(scalar);
default: {
// TODO(b/147444199): use string formatting.
// HARD_FAIL("Unexpected kind of FieldValue: '%s'", scalar.type());
auto message = std::string("Unexpected kind of FieldValue: '") +
std::to_string(static_cast<int>(scalar.type())) + "'";
auto message = std::string("Unexpected kind of FieldValue");
SIMPLE_HARD_FAIL(message);
}
}
}

FieldValue DocumentSnapshotInternal::ConvertReference(
const model::FieldValue::Reference& reference) const {
SIMPLE_HARD_ASSERT(
reference.database_id() == firestore_internal()->database_id(),
"Converted reference is from another database");
const google_firestore_v1_Value& reference) const {
std::string ref = MakeString(reference.reference_value);
DatabaseId database_id = DatabaseId::FromName(ref);
DocumentKey key = DocumentKey::FromName(ref);

SIMPLE_HARD_ASSERT(database_id == firestore_internal()->database_id(),
"Converted reference is from another database");

api::DocumentReference api_reference{reference.key(), snapshot_.firestore()};
api::DocumentReference api_reference{std::move(key), snapshot_.firestore()};
return FieldValue::Reference(MakePublic(std::move(api_reference)));
}

FieldValue DocumentSnapshotInternal::ConvertServerTimestamp(
const model::FieldValue::ServerTimestamp& server_timestamp,
const google_firestore_v1_Value& server_timestamp,
ServerTimestampBehavior stb) const {
switch (stb) {
case ServerTimestampBehavior::kNone:
return FieldValue::Null();
case ServerTimestampBehavior::kEstimate: {
return FieldValue::Timestamp(server_timestamp.local_write_time());
google_protobuf_Timestamp timestamp = GetLocalWriteTime(server_timestamp);
return FieldValue::Timestamp(
Timestamp(timestamp.seconds, timestamp.nanos));
}
case ServerTimestampBehavior::kPrevious:
if (server_timestamp.previous_value()) {
return ConvertScalar(server_timestamp.previous_value().value(), stb);
case ServerTimestampBehavior::kPrevious: {
absl::optional<google_firestore_v1_Value> previous_value =
GetPreviousValue(server_timestamp);
if (previous_value) {
return ConvertScalar(*previous_value, stb);
}
return FieldValue::Null();
}
}
FIRESTORE_UNREACHABLE();
}
Expand Down
15 changes: 7 additions & 8 deletions firestore/src/main/document_snapshot_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
#include <string>
#include <vector>

#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
#include "Firestore/core/src/api/document_snapshot.h"
#include "Firestore/core/src/model/field_value.h"
#include "firestore/src/include/firebase/firestore/document_reference.h"
#include "firestore/src/include/firebase/firestore/document_snapshot.h"
#include "firestore/src/include/firebase/firestore/field_value.h"
Expand Down Expand Up @@ -57,18 +57,17 @@ class DocumentSnapshotInternal {

// Note: these are member functions only because access to `api::Firestore`
// is needed to create a `DocumentReferenceInternal`.
FieldValue ConvertAnyValue(const model::FieldValue& input,
FieldValue ConvertAnyValue(const google_firestore_v1_Value& input,
ServerTimestampBehavior stb) const;
FieldValue ConvertObject(const model::FieldValue::Map& object,
FieldValue ConvertObject(const google_firestore_v1_MapValue& object,
ServerTimestampBehavior stb) const;
FieldValue ConvertArray(const model::FieldValue::Array& array,
FieldValue ConvertArray(const google_firestore_v1_ArrayValue& array,
ServerTimestampBehavior stb) const;
FieldValue ConvertReference(
const model::FieldValue::Reference& reference) const;
FieldValue ConvertReference(const google_firestore_v1_Value& reference) const;
FieldValue ConvertServerTimestamp(
const model::FieldValue::ServerTimestamp& server_timestamp,
const google_firestore_v1_Value& server_timestamp,
ServerTimestampBehavior stb) const;
FieldValue ConvertScalar(const model::FieldValue& scalar,
FieldValue ConvertScalar(const google_firestore_v1_Value& scalar,
ServerTimestampBehavior stb) const;

api::DocumentSnapshot snapshot_;
Expand Down
Loading