diff --git a/Firestore/core/src/bundle/bundle_serializer.cc b/Firestore/core/src/bundle/bundle_serializer.cc index e41f7219263..8efb86f5739 100644 --- a/Firestore/core/src/bundle/bundle_serializer.cc +++ b/Firestore/core/src/bundle/bundle_serializer.cc @@ -26,11 +26,12 @@ #include "Firestore/core/src/core/order_by.h" #include "Firestore/core/src/core/query.h" #include "Firestore/core/src/core/target.h" -#include "Firestore/core/src/model/document.h" #include "Firestore/core/src/model/field_path.h" -#include "Firestore/core/src/model/field_value.h" +#include "Firestore/core/src/model/mutable_document.h" #include "Firestore/core/src/model/resource_path.h" +#include "Firestore/core/src/model/value_util.h" #include "Firestore/core/src/nanopb/byte_string.h" +#include "Firestore/core/src/nanopb/nanopb_util.h" #include "Firestore/core/src/timestamp_internal.h" #include "Firestore/core/src/util/statusor.h" #include "Firestore/core/src/util/string_util.h" @@ -55,15 +56,17 @@ using core::OrderByList; using core::Query; using core::Target; using immutable::AppendOnlyList; -using model::Document; using model::DocumentKey; using model::FieldPath; -using model::FieldValue; +using model::MutableDocument; +using model::NaNValue; +using model::NullValue; using model::ObjectValue; using model::ResourcePath; using model::SnapshotVersion; using nanopb::ByteString; using nanopb::Reader; +using nanopb::SetRepeatedField; using nlohmann::json; using util::ReadContext; using util::StatusOr; @@ -221,16 +224,16 @@ Filter DecodeUnaryFilter(JsonReader& reader, const json& filter) { if (op == "IS_NAN") { return FieldFilter::Create(std::move(path), Filter::Operator::Equal, - FieldValue::Nan()); + NaNValue()); } else if (op == "IS_NULL") { return FieldFilter::Create(std::move(path), Filter::Operator::Equal, - FieldValue::Null()); + NullValue()); } else if (op == "IS_NOT_NAN") { return FieldFilter::Create(std::move(path), Filter::Operator::NotEqual, - FieldValue::Nan()); + NaNValue()); } else if (op == "IS_NOT_NULL") { return FieldFilter::Create(std::move(path), Filter::Operator::NotEqual, - FieldValue::Null()); + NullValue()); } reader.Fail("Unexpected unary filter operator: " + op); @@ -294,21 +297,22 @@ LimitType DecodeLimitType(JsonReader& reader, const json& query) { } } -FieldValue DecodeGeoPointValue(JsonReader& reader, const json& geo_json) { - double latitude = reader.OptionalDouble("latitude", geo_json, 0.0); - double longitude = reader.OptionalDouble("longitude", geo_json, 0.0); - - return FieldValue::FromGeoPoint(GeoPoint(latitude, longitude)); +google_type_LatLng DecodeGeoPointValue(JsonReader& reader, + const json& geo_json) { + google_type_LatLng result{}; + result.latitude = reader.OptionalDouble("latitude", geo_json, 0.0); + result.longitude = reader.OptionalDouble("longitude", geo_json, 0.0); + return result; } -FieldValue DecodeBytesValue(JsonReader& reader, - const std::string& bytes_string) { +pb_bytes_array_t* DecodeBytesValue(JsonReader& reader, + const std::string& bytes_string) { std::string decoded; if (!absl::Base64Unescape(bytes_string, &decoded)) { reader.Fail("Failed to decode bytesValue string into binary form"); return {}; } - return FieldValue::FromBlob(ByteString((decoded))); + return nanopb::MakeBytesArray(decoded); } } // namespace @@ -522,13 +526,13 @@ BundledQuery BundleSerializer::DecodeBundledQuery( auto start_at_bound = DecodeBound(reader, structured_query, "startAt"); std::shared_ptr start_at; - if (!start_at_bound.position().empty()) { + if (start_at_bound.position().values_count > 0) { start_at = std::make_shared(std::move(start_at_bound)); } auto end_at_bound = DecodeBound(reader, structured_query, "endAt"); std::shared_ptr end_at; - if (!end_at_bound.position().empty()) { + if (end_at_bound.position().values_count > 0) { end_at = std::make_shared(std::move(end_at_bound)); } @@ -591,7 +595,7 @@ Filter BundleSerializer::DecodeFieldFilter(JsonReader& reader, const auto& op_string = reader.RequiredString("op", filter); auto op = DecodeFieldFilterOperator(reader, op_string); - FieldValue value = + google_firestore_v1_Value value = DecodeValue(reader, reader.RequiredObject("value", filter)); // Return early if !ok(), because `FieldFilter::Create` will abort with @@ -632,63 +636,75 @@ Bound BundleSerializer::DecodeBound(JsonReader& reader, } const json& bound_json = reader.RequiredObject(bound_name, query); + std::vector values = reader.RequiredArray("values", bound_json); bool before = reader.OptionalBool("before", bound_json); - std::vector positions; - - for (const auto& value : reader.RequiredArray("values", bound_json)) { - positions.push_back(DecodeValue(reader, value)); - } - - return Bound(std::move(positions), before); + google_firestore_v1_ArrayValue positions{}; + SetRepeatedField(&positions.values, &positions.values_count, values, + [&](const json& j) { return DecodeValue(reader, j); }); + return Bound(positions, before); } -FieldValue BundleSerializer::DecodeValue(JsonReader& reader, - const json& value) const { +google_firestore_v1_Value BundleSerializer::DecodeValue( + JsonReader& reader, const json& value) const { if (!value.is_object()) { reader.Fail("'value' is not encoded as JSON object"); return {}; } + google_firestore_v1_Value result{}; if (value.contains("nullValue")) { - return FieldValue::Null(); + result.which_value_type = google_firestore_v1_Value_null_value_tag; } else if (value.contains("booleanValue")) { + result.which_value_type = google_firestore_v1_Value_boolean_value_tag; auto val = value.at("booleanValue"); if (!val.is_boolean()) { reader.Fail("'booleanValue' is not encoded as a valid boolean"); return {}; } - return FieldValue::FromBoolean(val.get()); + result.boolean_value = val.get(); } else if (value.contains("integerValue")) { - return FieldValue::FromInteger( - reader.RequiredInt("integerValue", value)); + result.which_value_type = google_firestore_v1_Value_integer_value_tag; + result.integer_value = reader.RequiredInt("integerValue", value); } else if (value.contains("doubleValue")) { - return FieldValue::FromDouble(reader.RequiredDouble("doubleValue", value)); + result.which_value_type = google_firestore_v1_Value_double_value_tag; + result.double_value = reader.RequiredDouble("doubleValue", value); } else if (value.contains("timestampValue")) { auto val = DecodeTimestamp(reader, value.at("timestampValue")); - return FieldValue::FromTimestamp(val); + result.which_value_type = google_firestore_v1_Value_timestamp_value_tag; + result.timestamp_value.seconds = val.seconds(); + result.timestamp_value.nanos = val.nanoseconds(); } else if (value.contains("stringValue")) { - auto val = reader.RequiredString("stringValue", value); - return FieldValue::FromString(std::move(val)); + result.which_value_type = google_firestore_v1_Value_string_value_tag; + result.string_value = + nanopb::MakeBytesArray(reader.RequiredString("stringValue", value)); } else if (value.contains("bytesValue")) { - return DecodeBytesValue(reader, reader.RequiredString("bytesValue", value)); + result.which_value_type = google_firestore_v1_Value_bytes_value_tag; + result.bytes_value = + DecodeBytesValue(reader, reader.RequiredString("bytesValue", value)); } else if (value.contains("referenceValue")) { - return DecodeReferenceValue(reader, - reader.RequiredString("referenceValue", value)); + result.which_value_type = google_firestore_v1_Value_reference_value_tag; + result.reference_value = + nanopb::MakeBytesArray(reader.RequiredString("referenceValue", value)); } else if (value.contains("geoPointValue")) { - return DecodeGeoPointValue(reader, value.at("geoPointValue")); + result.which_value_type = google_firestore_v1_Value_geo_point_value_tag; + result.geo_point_value = + DecodeGeoPointValue(reader, value.at("geoPointValue")); } else if (value.contains("arrayValue")) { - return DecodeArrayValue(reader, value.at("arrayValue")); + result.which_value_type = google_firestore_v1_Value_array_value_tag; + result.array_value = DecodeArrayValue(reader, value.at("arrayValue")); } else if (value.contains("mapValue")) { - return DecodeMapValue(reader, value.at("mapValue")); + result.which_value_type = google_firestore_v1_Value_map_value_tag; + result.map_value = DecodeMapValue(reader, value.at("mapValue")); } else { reader.Fail("Failed to decode value, no type is recognized"); return {}; } + return result; } -FieldValue BundleSerializer::DecodeMapValue(JsonReader& reader, - const json& map_json) const { +google_firestore_v1_MapValue BundleSerializer::DecodeMapValue( + JsonReader& reader, const json& map_json) const { if (!map_json.is_object() || !map_json.contains("fields")) { reader.Fail("mapValue is not a valid map"); return {}; @@ -699,37 +715,25 @@ FieldValue BundleSerializer::DecodeMapValue(JsonReader& reader, return {}; } - immutable::SortedMap field_values; - for (auto it = fields.begin(); it != fields.end(); ++it) { - field_values = - field_values.insert(it.key(), DecodeValue(reader, it.value())); - } - - return FieldValue::FromMap(std::move(field_values)); + google_firestore_v1_MapValue map_value{}; + SetRepeatedField(&map_value.fields, &map_value.fields_count, fields, + [&](const std::pair& entry) { + google_firestore_v1_MapValue_FieldsEntry result{}; + result.key = nanopb::MakeBytesArray(entry.first); + result.value = DecodeValue(reader, entry.second); + return result; + }); + return map_value; } -FieldValue BundleSerializer::DecodeArrayValue(JsonReader& reader, - const json& array_json) const { +google_firestore_v1_ArrayValue BundleSerializer::DecodeArrayValue( + JsonReader& reader, const json& array_json) const { const auto& values = reader.RequiredArray("values", array_json); - std::vector field_values; - for (const json& json_value : values) { - field_values.push_back(DecodeValue(reader, json_value)); - } - if (!reader.ok()) { - return {}; - } - - return FieldValue::FromArray(std::move(field_values)); -} - -FieldValue BundleSerializer::DecodeReferenceValue( - JsonReader& reader, const std::string& ref_string) const { - // Check if ref_string is indeed a valid string passed in. - if (!reader.ok()) { - return {}; - } - return rpc_serializer_.DecodeReference(&reader, ref_string); + google_firestore_v1_ArrayValue array_value{}; + SetRepeatedField(&array_value.values, &array_value.values_count, values, + [&](const json& j) { return DecodeValue(reader, j); }); + return array_value; } BundledDocumentMetadata BundleSerializer::DecodeDocumentMetadata( @@ -778,9 +782,8 @@ BundleDocument BundleSerializer::DecodeDocument(JsonReader& reader, auto map_value = DecodeMapValue(reader, document); - return BundleDocument(Document(ObjectValue::FromMap(map_value.object_value()), - std::move(key), update_time, - model::DocumentState::kSynced)); + return BundleDocument(MutableDocument::FoundDocument( + key, update_time, ObjectValue::FromMapValue(map_value))); } } // namespace bundle