Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
11 changes: 7 additions & 4 deletions Firestore/core/src/bundle/bundle_serializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ void DecodeCollectionSource(JsonReader& reader,
const json& from_json,
ResourcePath& parent,
std::string& group) {
if (!from_json.is_array()) {
reader.Fail("'from' clause is not an array as expected.");
return;
}
const auto& from = from_json.get_ref<const std::vector<json>&>();
if (from.size() != 1) {
reader.Fail(
Expand Down Expand Up @@ -274,10 +278,9 @@ int32_t DecodeLimit(JsonReader& reader, const json& query) {
// "limit" can be encoded as integer or "{"value": integer}".
if (limit_object.is_number_integer()) {
return limit_object.get<int32_t>();
} else if (limit_object.is_object()) {
if (limit_object.at("value").is_number_integer()) {
return limit_object.at("value").get<int32_t>();
}
} else if (limit_object.is_object() && limit_object.contains("value") &&
limit_object.at("value").is_number_integer()) {
return limit_object.at("value").get<int32_t>();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

low

Using contains followed by multiple at calls results in redundant lookups in the JSON object. We can optimize this by using find to perform a single lookup.

Suggested change
} else if (limit_object.is_object() && limit_object.contains("value") &&
limit_object.at("value").is_number_integer()) {
return limit_object.at("value").get<int32_t>();
}
} else if (limit_object.is_object()) {
auto it = limit_object.find("value");
if (it != limit_object.end() && it->is_number_integer()) {
return it->get<int32_t>();
}
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call, switched to a single find lookup so the value key is only resolved once. Pushed.

reader.Fail("'limit' is not encoded as a valid integer");
return limit;
Expand Down
18 changes: 18 additions & 0 deletions Firestore/core/test/unit/bundle/bundle_serializer_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,24 @@ TEST_F(BundleSerializerTest, DecodeQueriesFromOtherProjectsFails) {
}
}

TEST_F(BundleSerializerTest, DecodeFromClauseWithWrongTypeFails) {
std::string json_string = NamedQueryJsonString(testutil::Query("colls"));
json parsed = Parse(json_string);
parsed["bundledQuery"]["structuredQuery"]["from"] = "colls";
JsonReader reader;
bundle_serializer.DecodeNamedQuery(reader, parsed);
EXPECT_NOT_OK(reader.status());
}

TEST_F(BundleSerializerTest, DecodeLimitObjectWithoutValueFails) {
std::string json_string = NamedQueryJsonString(testutil::Query("colls"));
json parsed = Parse(json_string);
parsed["bundledQuery"]["structuredQuery"]["limit"] = json::object();
JsonReader reader;
bundle_serializer.DecodeNamedQuery(reader, parsed);
EXPECT_NOT_OK(reader.status());
}

TEST_F(BundleSerializerTest, DecodesCollectionGroupQuery) {
core::Query original = testutil::CollectionGroupQuery("bundles/docs/colls");
VerifyNamedQueryRoundtrip(original);
Expand Down
Loading