Skip to content

Commit 886b50f

Browse files
committed
Address feedback
1 parent 699ee91 commit 886b50f

File tree

12 files changed

+382
-290
lines changed

12 files changed

+382
-290
lines changed

Firestore/Example/Tests/Integration/API/FIRIndexingTests.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ - (void)testBadJsonDoesNotCrashClient {
7474
completion:^(NSError* error) {
7575
XCTAssertNotNil(error);
7676
XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
77-
XCTAssertEqual(error.code, FIRFirestoreErrorCodeDataLoss);
77+
XCTAssertEqual(error.code, FIRFirestoreErrorCodeInvalidArgument);
7878
}];
7979
}
8080

@@ -95,7 +95,7 @@ - (void)testBadIndexDoesNotCrashClient {
9595
completion:^(NSError* error) {
9696
XCTAssertNotNil(error);
9797
XCTAssertEqualObjects(error.domain, FIRFirestoreErrorDomain);
98-
XCTAssertEqual(error.code, FIRFirestoreErrorCodeDataLoss);
98+
XCTAssertEqual(error.code, FIRFirestoreErrorCodeInvalidArgument);
9999
}];
100100
}
101101

Firestore/Source/Public/FirebaseFirestore/FIRFirestore.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,20 @@ NS_SWIFT_NAME(Firestore)
7272
*/
7373
@property(strong, nonatomic, readonly) FIRApp *app;
7474

75-
// This method is in preview. API signature and functionality are subject to change.
7675
#pragma mark - Configure FieldIndexes
7776

7877
/**
78+
* This method is in preview. API signature and functionality are subject to change.
79+
*
7980
* Configures indexing for local query execution. Any previous index configuration is overridden.
8081
*
8182
* The index entries themselves are created asynchronously. You can continue to use queries
8283
* that require indexing even if the indices are not yet available. Query execution will
8384
* automatically start using the index once the index entries have been written.
8485
*
85-
* Indexes are only supported with LevelDB persistence. Invoke `set_persistence_enabled(true)`
86-
* before setting an index configuration. If LevelDB is not enabled, any index configuration
87-
* will be rejected.
88-
*
8986
* The method accepts the JSON format exported by the Firebase CLI (`firebase
90-
* firestore:indexes`). If the JSON format is invalid, this method ignores the changes.
87+
* firestore:indexes`). If the JSON format is invalid, the completion block will be
88+
* invoked with a NSError.
9189
*
9290
* @param json The JSON format exported by the Firebase CLI.
9391
* @param completion A block to execute when setting is in a final state. The `error` parameter
@@ -98,6 +96,8 @@ NS_SWIFT_NAME(Firestore)
9896
NS_SWIFT_NAME(setIndexConfiguration(_:completion:));
9997

10098
/**
99+
* This method is in preview. API signature and functionality are subject to change.
100+
*
101101
* Configures indexing for local query execution. Any previous index configuration is overridden.
102102
*
103103
* The index entries themselves are created asynchronously. You can continue to use queries

Firestore/core/src/api/firestore.cc

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#include "Firestore/core/src/util/exception.h"
4141
#include "Firestore/core/src/util/executor.h"
4242
#include "Firestore/core/src/util/hard_assert.h"
43+
#include "Firestore/core/src/util/json_reader.h"
44+
#include "Firestore/core/src/util/log.h"
4345
#include "Firestore/core/src/util/status.h"
4446
#include "Firestore/third_party/nlohmann_json/json.hpp"
4547
#include "absl/memory/memory.h"
@@ -251,32 +253,33 @@ DatabaseInfo Firestore::MakeDatabaseInfo() const {
251253
settings_.ssl_enabled());
252254
}
253255

254-
void Firestore::SetIndexConfiguration(std::string config,
255-
util::StatusCallback callback) {
256+
void Firestore::SetIndexConfiguration(const std::string& config,
257+
const util::StatusCallback& callback) {
256258
EnsureClientConfigured();
257259

258-
bundle::JsonReader reader;
260+
util::JsonReader reader;
259261
if (!settings_.persistence_enabled()) {
260-
callback(Status(Error::kErrorFailedPrecondition,
261-
"Cannot enable indexes when persistence is disabled."));
262+
LOG_DEBUG("Cannot enable indexes when persistence is disabled.");
263+
callback(util::Status::OK());
262264
return;
263265
}
264266

265267
auto json_object =
266268
nlohmann::json::parse(config.begin(), config.end(),
267269
/*callback=*/nullptr, /*allow_exceptions=*/false);
268270
if (json_object.is_discarded()) {
269-
callback(Status(Error::kErrorDataLoss, "Invalid Json format."));
271+
callback(Status(Error::kErrorInvalidArgument, "Invalid Json format."));
270272
return;
271273
}
272274

273275
std::vector<FieldIndex> parsed_indexes;
274-
const auto& json_indexes = reader.RequiredArray("indexes", json_object);
276+
const std::vector<json> default_vector;
277+
const auto& json_indexes =
278+
reader.OptionalArray("indexes", json_object, default_vector);
275279
for (const auto& json_index : json_indexes) {
276280
const std::string& collection_group =
277281
reader.RequiredString("collectionGroup", json_index);
278282
std::vector<Segment> segments;
279-
std::vector<json> default_vector;
280283
const auto& json_fields =
281284
reader.OptionalArray("fields", json_index, default_vector);
282285
for (const auto& json_field : json_fields) {
@@ -297,16 +300,17 @@ void Firestore::SetIndexConfiguration(std::string config,
297300
Segment(std::move(field_path), Segment::Kind::kDescending));
298301
}
299302
}
303+
304+
if (reader.status() != util::Status::OK()) {
305+
callback(reader.status());
306+
return;
307+
}
308+
300309
parsed_indexes.emplace_back(
301310
FieldIndex(FieldIndex::UnknownId(), collection_group,
302311
std::move(segments), FieldIndex::InitialState()));
303312
}
304313

305-
if (reader.status() != util::Status::OK()) {
306-
callback(reader.status());
307-
return;
308-
}
309-
310314
client_->ConfigureFieldIndexes(std::move(parsed_indexes));
311315

312316
callback(util::Status::OK());

Firestore/core/src/api/firestore.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ class Firestore : public std::enable_shared_from_this<Firestore> {
107107
void EnableNetwork(util::StatusCallback callback);
108108
void DisableNetwork(util::StatusCallback callback);
109109

110-
void SetIndexConfiguration(std::string config, util::StatusCallback callback);
110+
void SetIndexConfiguration(const std::string& config,
111+
const util::StatusCallback& callback);
111112

112113
std::shared_ptr<api::LoadBundleTask> LoadBundle(
113114
std::unique_ptr<util::ByteStream> bundle_data);

Firestore/core/src/bundle/bundle_reader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "Firestore/core/src/bundle/bundle_metadata.h"
2525
#include "Firestore/core/src/bundle/bundle_serializer.h"
2626
#include "Firestore/core/src/util/byte_stream.h"
27+
#include "Firestore/core/src/util/json_reader.h"
2728
#include "absl/types/optional.h"
2829

2930
namespace firebase {
@@ -111,7 +112,7 @@ class BundleReader {
111112
std::unique_ptr<BundleElement> DecodeBundleElementFromBuffer();
112113

113114
BundleSerializer serializer_;
114-
JsonReader json_reader_;
115+
util::JsonReader json_reader_;
115116

116117
// Input stream holding bundle data.
117118
std::unique_ptr<util::ByteStream> input_;

Firestore/core/src/bundle/bundle_serializer.cc

Lines changed: 2 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
namespace firebase {
4646
namespace firestore {
4747
namespace bundle {
48-
namespace {
4948

5049
using absl::Time;
5150
using core::Bound;
@@ -73,21 +72,16 @@ using nanopb::Message;
7372
using nanopb::SetRepeatedField;
7473
using nanopb::SharedMessage;
7574
using nlohmann::json;
75+
using util::JsonReader;
7676
using util::NoDestructor;
7777
using util::StatusOr;
7878
using util::StringFormat;
7979
using Operator = FieldFilter::Operator;
8080

8181
namespace {
82+
8283
const NoDestructor<Bound> kDefaultBound{Bound::FromValue(
8384
MakeSharedMessage<google_firestore_v1_ArrayValue>({}), false)};
84-
} // namespace
85-
86-
template <typename T>
87-
const std::vector<T>& EmptyVector() {
88-
static NoDestructor<std::vector<T>> empty;
89-
return *empty;
90-
}
9185

9286
Timestamp DecodeTimestamp(JsonReader& reader, const json& version) {
9387
StatusOr<Timestamp> decoded;
@@ -326,180 +320,6 @@ pb_bytes_array_t* DecodeBytesValue(JsonReader& reader,
326320

327321
} // namespace
328322

329-
// Mark: JsonReader
330-
331-
const std::string& JsonReader::RequiredString(const char* name,
332-
const json& json_object) {
333-
if (json_object.contains(name)) {
334-
const json& child = json_object.at(name);
335-
if (child.is_string()) {
336-
return child.get_ref<const std::string&>();
337-
}
338-
}
339-
340-
Fail("'%s' is missing or is not a string", name);
341-
return util::EmptyString();
342-
}
343-
344-
const std::string& JsonReader::OptionalString(
345-
const char* name,
346-
const json& json_object,
347-
const std::string& default_value) {
348-
if (json_object.contains(name)) {
349-
const json& child = json_object.at(name);
350-
if (child.is_string()) {
351-
return child.get_ref<const std::string&>();
352-
}
353-
}
354-
355-
return default_value;
356-
}
357-
358-
const std::vector<json>& JsonReader::RequiredArray(const char* name,
359-
const json& json_object) {
360-
if (json_object.contains(name)) {
361-
const json& child = json_object.at(name);
362-
if (child.is_array()) {
363-
return child.get_ref<const std::vector<json>&>();
364-
}
365-
}
366-
367-
Fail("'%s' is missing or is not an array", name);
368-
return EmptyVector<json>();
369-
}
370-
371-
const std::vector<json>& JsonReader::OptionalArray(
372-
const char* name,
373-
const json& json_object,
374-
const std::vector<json>& default_value) {
375-
if (!json_object.contains(name)) {
376-
return default_value;
377-
}
378-
379-
const json& child = json_object.at(name);
380-
if (child.is_array()) {
381-
return child.get_ref<const std::vector<json>&>();
382-
} else {
383-
Fail("'%s' is not an array", name);
384-
return EmptyVector<json>();
385-
}
386-
}
387-
388-
bool JsonReader::OptionalBool(const char* name,
389-
const json& json_object,
390-
bool default_value) {
391-
return (json_object.contains(name) && json_object.at(name).is_boolean() &&
392-
json_object.at(name).get<bool>()) ||
393-
default_value;
394-
}
395-
396-
const nlohmann::json& JsonReader::RequiredObject(const char* child_name,
397-
const json& json_object) {
398-
if (!json_object.contains(child_name)) {
399-
Fail("Missing child '%s'", child_name);
400-
return json_object;
401-
}
402-
return json_object.at(child_name);
403-
}
404-
405-
const nlohmann::json& JsonReader::OptionalObject(
406-
const char* child_name,
407-
const json& json_object,
408-
const nlohmann::json& default_value) {
409-
if (json_object.contains(child_name)) {
410-
return json_object.at(child_name);
411-
}
412-
return default_value;
413-
}
414-
415-
double JsonReader::RequiredDouble(const char* name, const json& json_object) {
416-
if (json_object.contains(name)) {
417-
double result = DecodeDouble(json_object.at(name));
418-
if (ok()) {
419-
return result;
420-
}
421-
}
422-
423-
Fail("'%s' is missing or is not a double", name);
424-
return 0.0;
425-
}
426-
427-
double JsonReader::OptionalDouble(const char* name,
428-
const json& json_object,
429-
double default_value) {
430-
if (json_object.contains(name)) {
431-
double result = DecodeDouble(json_object.at(name));
432-
if (ok()) {
433-
return result;
434-
}
435-
}
436-
437-
return default_value;
438-
}
439-
440-
double JsonReader::DecodeDouble(const nlohmann::json& value) {
441-
if (value.is_number()) {
442-
return value.get<double>();
443-
}
444-
445-
double result = 0;
446-
if (value.is_string()) {
447-
const auto& s = value.get_ref<const std::string&>();
448-
auto ok = absl::SimpleAtod(s, &result);
449-
if (!ok) {
450-
Fail("Failed to parse into double: " + s);
451-
}
452-
}
453-
return result;
454-
}
455-
456-
template <typename IntType>
457-
IntType ParseInt(const json& value, JsonReader& reader) {
458-
if (value.is_number_integer()) {
459-
return value.get<IntType>();
460-
}
461-
462-
IntType result = 0;
463-
if (value.is_string()) {
464-
const auto& s = value.get_ref<const std::string&>();
465-
auto ok = absl::SimpleAtoi<IntType>(s, &result);
466-
if (!ok) {
467-
reader.Fail("Failed to parse into integer: " + s);
468-
return 0;
469-
}
470-
471-
return result;
472-
}
473-
474-
reader.Fail("Only integer and string can be parsed into int type");
475-
return 0;
476-
}
477-
478-
template <typename IntType>
479-
IntType JsonReader::RequiredInt(const char* name, const json& json_object) {
480-
if (!json_object.contains(name)) {
481-
Fail("'%s' is missing or is not a double", name);
482-
return 0;
483-
}
484-
485-
const json& value = json_object.at(name);
486-
return ParseInt<IntType>(value, *this);
487-
}
488-
489-
template <typename IntType>
490-
IntType JsonReader::OptionalInt(const char* name,
491-
const json& json_object,
492-
IntType default_value) {
493-
if (!json_object.contains(name)) {
494-
return default_value;
495-
}
496-
497-
const json& value = json_object.at(name);
498-
return ParseInt<IntType>(value, *this);
499-
}
500-
501-
// Mark: BundleSerializer
502-
503323
BundleMetadata BundleSerializer::DecodeBundleMetadata(
504324
JsonReader& reader, const json& metadata) const {
505325
return BundleMetadata(

0 commit comments

Comments
 (0)