aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar zxu <zxu@google.com>2018-03-14 08:57:31 -0400
committerGravatar GitHub <noreply@github.com>2018-03-14 08:57:31 -0400
commit9e815620e9f7f43b42e03db4e5118d7ad03ddee7 (patch)
tree86f362bad99281325fca7ee3ae116b6a0f36d511
parentd4d73ea53ecdf1e8ade3d00921419645dd5d66f7 (diff)
grand PR to port the remaining paths (FieldPath and ResourcePath). (#865)
* naively remove FSTPath import and source/test files. * port FieldPath, part I * port FieldPath, part II * port ResourcePath, part I * port ResourcePath, part II * the grand commit to fix build errors * use testutil:: helper instead of those from FSTHelpers * fix test and lint * use c_str in errmsg directly * fix * fix * make code clean * fix integration test I missed * fix to avoid naming collision in preprocessor * address changes * address changes * address changes * fix: fieldMask are actually shared with different context. * address changes * address changes
-rw-r--r--Firestore/Example/Firestore.xcodeproj/project.pbxproj4
-rw-r--r--Firestore/Example/Tests/API/FIRCollectionReferenceTests.mm6
-rw-r--r--Firestore/Example/Tests/API/FIRDocumentReferenceTests.mm6
-rw-r--r--Firestore/Example/Tests/API/FIRFieldPathTests.mm11
-rw-r--r--Firestore/Example/Tests/API/FIRQuerySnapshotTests.mm2
-rw-r--r--Firestore/Example/Tests/API/FIRQueryTests.mm9
-rw-r--r--Firestore/Example/Tests/API/FSTAPIHelpers.h4
-rw-r--r--Firestore/Example/Tests/API/FSTAPIHelpers.mm34
-rw-r--r--Firestore/Example/Tests/Core/FSTEventManagerTests.mm10
-rw-r--r--Firestore/Example/Tests/Core/FSTQueryListenerTests.mm24
-rw-r--r--Firestore/Example/Tests/Core/FSTQueryTests.mm256
-rw-r--r--Firestore/Example/Tests/Core/FSTViewSnapshotTest.mm3
-rw-r--r--Firestore/Example/Tests/Core/FSTViewTests.mm1
-rw-r--r--Firestore/Example/Tests/Integration/API/FIRValidationTests.mm2
-rw-r--r--Firestore/Example/Tests/Integration/FSTDatastoreTests.mm1
-rw-r--r--Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm13
-rw-r--r--Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm7
-rw-r--r--Firestore/Example/Tests/Local/FSTLocalStoreTests.mm37
-rw-r--r--Firestore/Example/Tests/Local/FSTMutationQueueTests.mm10
-rw-r--r--Firestore/Example/Tests/Local/FSTQueryCacheTests.mm22
-rw-r--r--Firestore/Example/Tests/Local/FSTRemoteDocumentCacheTests.mm2
-rw-r--r--Firestore/Example/Tests/Model/FSTDocumentSetTests.mm2
-rw-r--r--Firestore/Example/Tests/Model/FSTDocumentTests.mm9
-rw-r--r--Firestore/Example/Tests/Model/FSTFieldValueTests.mm43
-rw-r--r--Firestore/Example/Tests/Model/FSTMutationTests.mm21
-rw-r--r--Firestore/Example/Tests/Model/FSTPathTests.mm224
-rw-r--r--Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm33
-rw-r--r--Firestore/Example/Tests/SpecTests/FSTSpecTests.mm16
-rw-r--r--Firestore/Example/Tests/Util/FSTHelpers.h62
-rw-r--r--Firestore/Example/Tests/Util/FSTHelpers.mm71
-rw-r--r--Firestore/Source/API/FIRCollectionReference+Internal.h7
-rw-r--r--Firestore/Source/API/FIRCollectionReference.mm20
-rw-r--r--Firestore/Source/API/FIRDocumentReference+Internal.h6
-rw-r--r--Firestore/Source/API/FIRDocumentReference.mm22
-rw-r--r--Firestore/Source/API/FIRDocumentSnapshot.mm12
-rw-r--r--Firestore/Source/API/FIRFieldPath+Internal.h8
-rw-r--r--Firestore/Source/API/FIRFieldPath.mm40
-rw-r--r--Firestore/Source/API/FIRFirestore.mm11
-rw-r--r--Firestore/Source/API/FIRQuery.mm49
-rw-r--r--Firestore/Source/API/FSTUserDataConverter.mm160
-rw-r--r--Firestore/Source/Core/FSTFirestoreClient.mm2
-rw-r--r--Firestore/Source/Core/FSTQuery.mm28
-rw-r--r--Firestore/Source/Core/FSTSyncEngine.mm1
-rw-r--r--Firestore/Source/Local/FSTLevelDB.mm3
-rw-r--r--Firestore/Source/Local/FSTLevelDBKey.h21
-rw-r--r--Firestore/Source/Local/FSTLevelDBKey.mm26
-rw-r--r--Firestore/Source/Local/FSTLevelDBMutationQueue.mm17
-rw-r--r--Firestore/Source/Local/FSTLevelDBQueryCache.mm4
-rw-r--r--Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm4
-rw-r--r--Firestore/Source/Local/FSTLocalDocumentsView.mm13
-rw-r--r--Firestore/Source/Local/FSTMemoryMutationQueue.mm1
-rw-r--r--Firestore/Source/Local/FSTMemoryRemoteDocumentCache.mm1
-rw-r--r--Firestore/Source/Model/FSTDocument.h5
-rw-r--r--Firestore/Source/Model/FSTDocument.mm9
-rw-r--r--Firestore/Source/Model/FSTFieldValue.h9
-rw-r--r--Firestore/Source/Model/FSTFieldValue.mm31
-rw-r--r--Firestore/Source/Model/FSTMutation.h14
-rw-r--r--Firestore/Source/Model/FSTMutation.mm45
-rw-r--r--Firestore/Source/Model/FSTPath.h167
-rw-r--r--Firestore/Source/Model/FSTPath.mm399
-rw-r--r--Firestore/Source/Remote/FSTDatastore.mm12
-rw-r--r--Firestore/Source/Remote/FSTRemoteStore.mm4
-rw-r--r--Firestore/Source/Remote/FSTSerializerBeta.mm175
-rw-r--r--Firestore/core/src/firebase/firestore/model/field_path.h10
-rw-r--r--Firestore/core/src/firebase/firestore/model/resource_path.h5
-rw-r--r--Firestore/core/src/firebase/firestore/util/string_apple.h8
66 files changed, 787 insertions, 1507 deletions
diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj
index 92b4b7b..3b1c328 100644
--- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj
+++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj
@@ -98,7 +98,6 @@
5492E0B12021552D00B64F25 /* FSTRemoteDocumentCacheTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E09C2021552D00B64F25 /* FSTRemoteDocumentCacheTests.mm */; };
5492E0B92021555100B64F25 /* FSTDocumentKeyTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0B22021555000B64F25 /* FSTDocumentKeyTests.mm */; };
5492E0BA2021555100B64F25 /* FSTDocumentSetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0B32021555100B64F25 /* FSTDocumentSetTests.mm */; };
- 5492E0BC2021555100B64F25 /* FSTPathTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0B52021555100B64F25 /* FSTPathTests.mm */; };
5492E0BD2021555100B64F25 /* FSTDocumentTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0B62021555100B64F25 /* FSTDocumentTests.mm */; };
5492E0BE2021555100B64F25 /* FSTMutationTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0B72021555100B64F25 /* FSTMutationTests.mm */; };
5492E0BF2021555100B64F25 /* FSTFieldValueTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0B82021555100B64F25 /* FSTFieldValueTests.mm */; };
@@ -313,7 +312,6 @@
5492E09C2021552D00B64F25 /* FSTRemoteDocumentCacheTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTRemoteDocumentCacheTests.mm; sourceTree = "<group>"; };
5492E0B22021555000B64F25 /* FSTDocumentKeyTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTDocumentKeyTests.mm; sourceTree = "<group>"; };
5492E0B32021555100B64F25 /* FSTDocumentSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTDocumentSetTests.mm; sourceTree = "<group>"; };
- 5492E0B52021555100B64F25 /* FSTPathTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTPathTests.mm; sourceTree = "<group>"; };
5492E0B62021555100B64F25 /* FSTDocumentTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTDocumentTests.mm; sourceTree = "<group>"; };
5492E0B72021555100B64F25 /* FSTMutationTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTMutationTests.mm; sourceTree = "<group>"; };
5492E0B82021555100B64F25 /* FSTFieldValueTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTFieldValueTests.mm; sourceTree = "<group>"; };
@@ -758,7 +756,6 @@
5492E0B62021555100B64F25 /* FSTDocumentTests.mm */,
5492E0B82021555100B64F25 /* FSTFieldValueTests.mm */,
5492E0B72021555100B64F25 /* FSTMutationTests.mm */,
- 5492E0B52021555100B64F25 /* FSTPathTests.mm */,
);
path = Model;
sourceTree = "<group>";
@@ -1466,7 +1463,6 @@
B686F2B22025000D0028D6BE /* resource_path_test.cc in Sources */,
5492E0CA2021557E00B64F25 /* FSTWatchChangeTests.mm in Sources */,
5492E063202154B900B64F25 /* FSTViewSnapshotTest.mm in Sources */,
- 5492E0BC2021555100B64F25 /* FSTPathTests.mm in Sources */,
5492E0B02021552D00B64F25 /* FSTWriteGroupTests.mm in Sources */,
5492E058202154AB00B64F25 /* FSTAPIHelpers.mm in Sources */,
AB380CFB2019388600D97691 /* target_id_generator_test.cc in Sources */,
diff --git a/Firestore/Example/Tests/API/FIRCollectionReferenceTests.mm b/Firestore/Example/Tests/API/FIRCollectionReferenceTests.mm
index 547078f..cb99d24 100644
--- a/Firestore/Example/Tests/API/FIRCollectionReferenceTests.mm
+++ b/Firestore/Example/Tests/API/FIRCollectionReferenceTests.mm
@@ -28,9 +28,9 @@ NS_ASSUME_NONNULL_BEGIN
@implementation FIRCollectionReferenceTests
- (void)testEquals {
- FIRCollectionReference *referenceFoo = FSTTestCollectionRef(@"foo");
- FIRCollectionReference *referenceFooDup = FSTTestCollectionRef(@"foo");
- FIRCollectionReference *referenceBar = FSTTestCollectionRef(@"bar");
+ FIRCollectionReference *referenceFoo = FSTTestCollectionRef("foo");
+ FIRCollectionReference *referenceFooDup = FSTTestCollectionRef("foo");
+ FIRCollectionReference *referenceBar = FSTTestCollectionRef("bar");
XCTAssertEqualObjects(referenceFoo, referenceFooDup);
XCTAssertNotEqualObjects(referenceFoo, referenceBar);
diff --git a/Firestore/Example/Tests/API/FIRDocumentReferenceTests.mm b/Firestore/Example/Tests/API/FIRDocumentReferenceTests.mm
index cc2b431..4124cd0 100644
--- a/Firestore/Example/Tests/API/FIRDocumentReferenceTests.mm
+++ b/Firestore/Example/Tests/API/FIRDocumentReferenceTests.mm
@@ -28,9 +28,9 @@ NS_ASSUME_NONNULL_BEGIN
@implementation FIRDocumentReferenceTests
- (void)testEquals {
- FIRDocumentReference *referenceFoo = FSTTestDocRef(@"rooms/foo");
- FIRDocumentReference *referenceFooDup = FSTTestDocRef(@"rooms/foo");
- FIRDocumentReference *referenceBar = FSTTestDocRef(@"rooms/bar");
+ FIRDocumentReference *referenceFoo = FSTTestDocRef("rooms/foo");
+ FIRDocumentReference *referenceFooDup = FSTTestDocRef("rooms/foo");
+ FIRDocumentReference *referenceBar = FSTTestDocRef("rooms/bar");
XCTAssertEqualObjects(referenceFoo, referenceFooDup);
XCTAssertNotEqualObjects(referenceFoo, referenceBar);
diff --git a/Firestore/Example/Tests/API/FIRFieldPathTests.mm b/Firestore/Example/Tests/API/FIRFieldPathTests.mm
index 679ea89..50d37c1 100644
--- a/Firestore/Example/Tests/API/FIRFieldPathTests.mm
+++ b/Firestore/Example/Tests/API/FIRFieldPathTests.mm
@@ -19,10 +19,13 @@
#import <XCTest/XCTest.h>
#import "Firestore/Source/API/FIRFieldPath+Internal.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
+#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+
+namespace testutil = firebase::firestore::testutil;
+
NS_ASSUME_NONNULL_BEGIN
@interface FIRFieldPathTests : XCTestCase
@@ -31,9 +34,9 @@ NS_ASSUME_NONNULL_BEGIN
@implementation FIRFieldPathTests
- (void)testEquals {
- FIRFieldPath *foo = [[FIRFieldPath alloc] initPrivate:FSTTestFieldPath(@"foo.ooo.oooo")];
- FIRFieldPath *fooDup = [[FIRFieldPath alloc] initPrivate:FSTTestFieldPath(@"foo.ooo.oooo")];
- FIRFieldPath *bar = [[FIRFieldPath alloc] initPrivate:FSTTestFieldPath(@"baa.aaa.aaar")];
+ FIRFieldPath *foo = [[FIRFieldPath alloc] initPrivate:testutil::Field("foo.ooo.oooo")];
+ FIRFieldPath *fooDup = [[FIRFieldPath alloc] initPrivate:testutil::Field("foo.ooo.oooo")];
+ FIRFieldPath *bar = [[FIRFieldPath alloc] initPrivate:testutil::Field("baa.aaa.aaar")];
XCTAssertEqualObjects(foo, fooDup);
XCTAssertNotEqualObjects(foo, bar);
diff --git a/Firestore/Example/Tests/API/FIRQuerySnapshotTests.mm b/Firestore/Example/Tests/API/FIRQuerySnapshotTests.mm
index 067425a..bb8110b 100644
--- a/Firestore/Example/Tests/API/FIRQuerySnapshotTests.mm
+++ b/Firestore/Example/Tests/API/FIRQuerySnapshotTests.mm
@@ -18,8 +18,6 @@
#import <XCTest/XCTest.h>
-#import "Firestore/Source/Model/FSTPath.h"
-
#import "Firestore/Example/Tests/API/FSTAPIHelpers.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Example/Tests/API/FIRQueryTests.mm b/Firestore/Example/Tests/API/FIRQueryTests.mm
index 83f90be..c02c92c 100644
--- a/Firestore/Example/Tests/API/FIRQueryTests.mm
+++ b/Firestore/Example/Tests/API/FIRQueryTests.mm
@@ -20,7 +20,6 @@
#import "Firestore/Source/API/FIRQuery+Internal.h"
#import "Firestore/Source/Core/FSTQuery.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Example/Tests/API/FSTAPIHelpers.h"
@@ -33,9 +32,9 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testEquals {
FIRFirestore *firestore = FSTTestFirestore();
- FIRQuery *queryFoo = [FIRQuery referenceWithQuery:FSTTestQuery(@"foo") firestore:firestore];
- FIRQuery *queryFooDup = [FIRQuery referenceWithQuery:FSTTestQuery(@"foo") firestore:firestore];
- FIRQuery *queryBar = [FIRQuery referenceWithQuery:FSTTestQuery(@"bar") firestore:firestore];
+ FIRQuery *queryFoo = [FIRQuery referenceWithQuery:FSTTestQuery("foo") firestore:firestore];
+ FIRQuery *queryFooDup = [FIRQuery referenceWithQuery:FSTTestQuery("foo") firestore:firestore];
+ FIRQuery *queryBar = [FIRQuery referenceWithQuery:FSTTestQuery("bar") firestore:firestore];
XCTAssertEqualObjects(queryFoo, queryFooDup);
XCTAssertNotEqualObjects(queryFoo, queryBar);
XCTAssertEqualObjects([queryFoo queryWhereField:@"f" isEqualTo:@1],
@@ -53,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testFilteringWithPredicate {
FIRFirestore *firestore = FSTTestFirestore();
- FIRQuery *query = [FIRQuery referenceWithQuery:FSTTestQuery(@"foo") firestore:firestore];
+ FIRQuery *query = [FIRQuery referenceWithQuery:FSTTestQuery("foo") firestore:firestore];
FIRQuery *query1 = [query queryWhereField:@"f" isLessThanOrEqualTo:@1];
FIRQuery *query2 = [query queryFilteredUsingPredicate:[NSPredicate predicateWithFormat:@"f<=1"]];
FIRQuery *query3 =
diff --git a/Firestore/Example/Tests/API/FSTAPIHelpers.h b/Firestore/Example/Tests/API/FSTAPIHelpers.h
index 0729af0..4edd7d5 100644
--- a/Firestore/Example/Tests/API/FSTAPIHelpers.h
+++ b/Firestore/Example/Tests/API/FSTAPIHelpers.h
@@ -41,10 +41,10 @@ FIRDocumentSnapshot *FSTTestDocSnapshot(NSString *path,
BOOL fromCache);
/** A convenience method for creating a collection reference from a path string. */
-FIRCollectionReference *FSTTestCollectionRef(NSString *path);
+FIRCollectionReference *FSTTestCollectionRef(const absl::string_view path);
/** A convenience method for creating a document reference from a path string. */
-FIRDocumentReference *FSTTestDocRef(NSString *path);
+FIRDocumentReference *FSTTestDocRef(const absl::string_view path);
/**
* A convenience method for creating a particular query snapshot for tests.
diff --git a/Firestore/Example/Tests/API/FSTAPIHelpers.mm b/Firestore/Example/Tests/API/FSTAPIHelpers.mm
index d091842..c180dc4 100644
--- a/Firestore/Example/Tests/API/FSTAPIHelpers.mm
+++ b/Firestore/Example/Tests/API/FSTAPIHelpers.mm
@@ -31,7 +31,12 @@
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTDocumentSet.h"
-#import "Firestore/Source/Model/FSTPath.h"
+
+#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+
+namespace testutil = firebase::firestore::testutil;
+namespace util = firebase::firestore::util;
NS_ASSUME_NONNULL_BEGIN
@@ -65,12 +70,14 @@ FIRDocumentSnapshot *FSTTestDocSnapshot(NSString *path,
fromCache:fromCache];
}
-FIRCollectionReference *FSTTestCollectionRef(NSString *path) {
- return [FIRCollectionReference referenceWithPath:FSTTestPath(path) firestore:FSTTestFirestore()];
+FIRCollectionReference *FSTTestCollectionRef(const absl::string_view path) {
+ return [FIRCollectionReference referenceWithPath:testutil::Resource(path)
+ firestore:FSTTestFirestore()];
}
-FIRDocumentReference *FSTTestDocRef(NSString *path) {
- return [FIRDocumentReference referenceWithPath:FSTTestPath(path) firestore:FSTTestFirestore()];
+FIRDocumentReference *FSTTestDocRef(const absl::string_view path) {
+ return [FIRDocumentReference referenceWithPath:testutil::Resource(path)
+ firestore:FSTTestFirestore()];
}
/** A convenience method for creating a query snapshots for tests. */
@@ -99,15 +106,16 @@ FIRQuerySnapshot *FSTTestQuerySnapshot(
changeWithDocument:docToAdd
type:FSTDocumentViewChangeTypeAdded]];
}
- FSTViewSnapshot *viewSnapshot = [[FSTViewSnapshot alloc] initWithQuery:FSTTestQuery(path)
- documents:newDocuments
- oldDocuments:oldDocuments
- documentChanges:documentChanges
- fromCache:fromCache
- hasPendingWrites:hasPendingWrites
- syncStateChanged:YES];
+ FSTViewSnapshot *viewSnapshot =
+ [[FSTViewSnapshot alloc] initWithQuery:FSTTestQuery(util::MakeStringView(path))
+ documents:newDocuments
+ oldDocuments:oldDocuments
+ documentChanges:documentChanges
+ fromCache:fromCache
+ hasPendingWrites:hasPendingWrites
+ syncStateChanged:YES];
return [FIRQuerySnapshot snapshotWithFirestore:FSTTestFirestore()
- originalQuery:FSTTestQuery(path)
+ originalQuery:FSTTestQuery(util::MakeStringView(path))
snapshot:viewSnapshot
metadata:metadata];
}
diff --git a/Firestore/Example/Tests/Core/FSTEventManagerTests.mm b/Firestore/Example/Tests/Core/FSTEventManagerTests.mm
index f5f7b5b..952d01f 100644
--- a/Firestore/Example/Tests/Core/FSTEventManagerTests.mm
+++ b/Firestore/Example/Tests/Core/FSTEventManagerTests.mm
@@ -52,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testHandlesManyListenersPerQuery {
- FSTQuery *query = FSTTestQuery(@"foo/bar");
+ FSTQuery *query = FSTTestQuery("foo/bar");
FSTQueryListener *listener1 = [self noopListenerForQuery:query];
FSTQueryListener *listener2 = [self noopListenerForQuery:query];
@@ -73,7 +73,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testHandlesUnlistenOnUnknownListenerGracefully {
- FSTQuery *query = FSTTestQuery(@"foo/bar");
+ FSTQuery *query = FSTTestQuery("foo/bar");
FSTQueryListener *listener = [self noopListenerForQuery:query];
FSTSyncEngine *syncEngineMock = OCMStrictClassMock([FSTSyncEngine class]);
@@ -95,8 +95,8 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testNotifiesListenersInTheRightOrder {
- FSTQuery *query1 = FSTTestQuery(@"foo/bar");
- FSTQuery *query2 = FSTTestQuery(@"bar/baz");
+ FSTQuery *query1 = FSTTestQuery("foo/bar");
+ FSTQuery *query2 = FSTTestQuery("bar/baz");
NSMutableArray *eventOrder = [NSMutableArray array];
FSTQueryListener *listener1 = [self makeMockListenerForQuery:query1
@@ -135,7 +135,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testWillForwardOnlineStateChanges {
- FSTQuery *query = FSTTestQuery(@"foo/bar");
+ FSTQuery *query = FSTTestQuery("foo/bar");
FSTQueryListener *fakeListener = OCMClassMock([FSTQueryListener class]);
NSMutableArray *events = [NSMutableArray array];
OCMStub([fakeListener query]).andReturn(query);
diff --git a/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm b/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm
index 1b26360..55c4219 100644
--- a/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm
+++ b/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm
@@ -45,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN
NSMutableArray<FSTViewSnapshot *> *accum = [NSMutableArray array];
NSMutableArray<FSTViewSnapshot *> *otherAccum = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTDocument *doc1 = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, NO);
FSTDocument *doc2 = FSTTestDoc(@"rooms/Hades", 2, @{@"name" : @"Hades"}, NO);
FSTDocument *doc2prime =
@@ -88,7 +88,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testRaisesErrorEvent {
NSMutableArray<NSError *> *accum = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms/Eros");
+ FSTQuery *query = FSTTestQuery("rooms/Eros");
FSTQueryListener *listener = [self listenToQuery:query
handler:^(FSTViewSnapshot *snapshot, NSError *error) {
@@ -104,7 +104,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testRaisesEventForEmptyCollectionAfterSync {
NSMutableArray<FSTViewSnapshot *> *accum = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTQueryListener *listener = [self listenToQuery:query accumulatingSnapshots:accum];
@@ -126,7 +126,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testMutingAsyncListenerPreventsAllSubsequentEvents {
NSMutableArray<FSTViewSnapshot *> *accum = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms/Eros");
+ FSTQuery *query = FSTTestQuery("rooms/Eros");
FSTDocument *doc1 = FSTTestDoc(@"rooms/Eros", 3, @{@"name" : @"Eros"}, NO);
FSTDocument *doc2 = FSTTestDoc(@"rooms/Eros", 4, @{@"name" : @"Eros2"}, NO);
@@ -166,7 +166,7 @@ NS_ASSUME_NONNULL_BEGIN
NSMutableArray<FSTViewSnapshot *> *filteredAccum = [NSMutableArray array];
NSMutableArray<FSTViewSnapshot *> *fullAccum = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTDocument *doc1 = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, NO);
FSTDocument *doc2 = FSTTestDoc(@"rooms/Hades", 2, @{@"name" : @"Hades"}, NO);
@@ -204,7 +204,7 @@ NS_ASSUME_NONNULL_BEGIN
NSMutableArray<FSTViewSnapshot *> *filteredAccum = [NSMutableArray array];
NSMutableArray<FSTViewSnapshot *> *fullAccum = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTDocument *doc1 = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, YES);
FSTDocument *doc2 = FSTTestDoc(@"rooms/Hades", 2, @{@"name" : @"Hades"}, NO);
FSTDocument *doc1Prime = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, NO);
@@ -253,7 +253,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testRaisesQueryMetadataEventsOnlyWhenHasPendingWritesOnTheQueryChanges {
NSMutableArray<FSTViewSnapshot *> *fullAccum = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTDocument *doc1 = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, YES);
FSTDocument *doc2 = FSTTestDoc(@"rooms/Hades", 2, @{@"name" : @"Hades"}, YES);
FSTDocument *doc1Prime = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, NO);
@@ -290,7 +290,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testMetadataOnlyDocumentChangesAreFilteredOutWhenIncludeDocumentMetadataChangesIsFalse {
NSMutableArray<FSTViewSnapshot *> *filteredAccum = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTDocument *doc1 = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, YES);
FSTDocument *doc2 = FSTTestDoc(@"rooms/Hades", 2, @{@"name" : @"Hades"}, NO);
FSTDocument *doc1Prime = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, NO);
@@ -322,7 +322,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testWillWaitForSyncIfOnline {
NSMutableArray<FSTViewSnapshot *> *events = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTDocument *doc1 = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, NO);
FSTDocument *doc2 = FSTTestDoc(@"rooms/Hades", 2, @{@"name" : @"Hades"}, NO);
FSTQueryListener *listener =
@@ -365,7 +365,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testWillRaiseInitialEventWhenGoingOffline {
NSMutableArray<FSTViewSnapshot *> *events = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTDocument *doc1 = FSTTestDoc(@"rooms/Eros", 1, @{@"name" : @"Eros"}, NO);
FSTDocument *doc2 = FSTTestDoc(@"rooms/Hades", 2, @{@"name" : @"Hades"}, NO);
FSTQueryListener *listener =
@@ -411,7 +411,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testWillRaiseInitialEventWhenGoingOfflineAndThereAreNoDocs {
NSMutableArray<FSTViewSnapshot *> *events = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTQueryListener *listener = [self listenToQuery:query
options:[FSTListenOptions defaultOptions]
accumulatingSnapshots:events];
@@ -437,7 +437,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testWillRaiseInitialEventWhenStartingOfflineAndThereAreNoDocs {
NSMutableArray<FSTViewSnapshot *> *events = [NSMutableArray array];
- FSTQuery *query = FSTTestQuery(@"rooms");
+ FSTQuery *query = FSTTestQuery("rooms");
FSTQueryListener *listener = [self listenToQuery:query
options:[FSTListenOptions defaultOptions]
accumulatingSnapshots:events];
diff --git a/Firestore/Example/Tests/Core/FSTQueryTests.mm b/Firestore/Example/Tests/Core/FSTQueryTests.mm
index 5f6d279..8b5b524 100644
--- a/Firestore/Example/Tests/Core/FSTQueryTests.mm
+++ b/Firestore/Example/Tests/Core/FSTQueryTests.mm
@@ -21,7 +21,6 @@
#import "Firestore/Source/API/FIRFirestore+Internal.h"
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
@@ -30,6 +29,7 @@
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+#include "absl/strings/string_view.h"
namespace testutil = firebase::firestore::testutil;
namespace util = firebase::firestore::util;
@@ -41,16 +41,14 @@ NS_ASSUME_NONNULL_BEGIN
/** Convenience methods for building test queries. */
@interface FSTQuery (Tests)
-- (FSTQuery *)queryByAddingSortBy:(NSString *)key ascending:(BOOL)ascending;
+- (FSTQuery *)queryByAddingSortBy:(const absl::string_view)key ascending:(BOOL)ascending;
@end
@implementation FSTQuery (Tests)
-- (FSTQuery *)queryByAddingSortBy:(NSString *)key ascending:(BOOL)ascending {
- return [self
- queryByAddingSortOrder:[FSTSortOrder
- sortOrderWithFieldPath:testutil::Field(util::MakeStringView(key))
- ascending:ascending]];
+- (FSTQuery *)queryByAddingSortBy:(const absl::string_view)key ascending:(BOOL)ascending {
+ return [self queryByAddingSortOrder:[FSTSortOrder sortOrderWithFieldPath:testutil::Field(key)
+ ascending:ascending]];
}
@end
@@ -61,9 +59,8 @@ NS_ASSUME_NONNULL_BEGIN
@implementation FSTQueryTests
- (void)testConstructor {
- FSTResourcePath *path =
- [FSTResourcePath pathWithSegments:@[ @"rooms", @"Firestore", @"messages", @"0001" ]];
- FSTQuery *query = [FSTQuery queryWithPath:[path toCPPResourcePath]];
+ const ResourcePath path{"rooms", "Firestore", "messages", "0001"};
+ FSTQuery *query = [FSTQuery queryWithPath:path];
XCTAssertNotNil(query);
XCTAssertEqual(query.sortOrders.count, 1);
@@ -74,7 +71,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testOrderBy {
- FSTQuery *query = FSTTestQuery(@"rooms/Firestore/messages");
+ FSTQuery *query = FSTTestQuery("rooms/Firestore/messages");
query =
[query queryByAddingSortOrder:[FSTSortOrder sortOrderWithFieldPath:testutil::Field("length")
ascending:NO]];
@@ -96,7 +93,7 @@ NS_ASSUME_NONNULL_BEGIN
FSTDocument *doc3 = FSTTestDoc(@"rooms/other/messages/1", 0, @{@"text" : @"msg3"}, NO);
// document query
- FSTQuery *query = FSTTestQuery(@"rooms/eros/messages/1");
+ FSTQuery *query = FSTTestQuery("rooms/eros/messages/1");
XCTAssertTrue([query matchesDocument:doc1]);
XCTAssertFalse([query matchesDocument:doc2]);
XCTAssertFalse([query matchesDocument:doc3]);
@@ -109,7 +106,7 @@ NS_ASSUME_NONNULL_BEGIN
FSTDocument *doc3 = FSTTestDoc(@"rooms/other/messages/1", 0, @{@"text" : @"msg3"}, NO);
// shallow ancestor query
- FSTQuery *query = FSTTestQuery(@"rooms/eros/messages");
+ FSTQuery *query = FSTTestQuery("rooms/eros/messages");
XCTAssertTrue([query matchesDocument:doc1]);
XCTAssertFalse([query matchesDocument:doc1Meta]);
XCTAssertTrue([query matchesDocument:doc2]);
@@ -120,17 +117,17 @@ NS_ASSUME_NONNULL_BEGIN
FSTDocument *doc1 = FSTTestDoc(@"rooms/eros/messages/1", 0, @{@"text" : @"msg1"}, NO);
FSTDocument *doc2 = FSTTestDoc(@"rooms/eros/messages/2", 0, @{}, NO);
- FSTQuery *query = [FSTTestQuery(@"rooms/eros/messages")
- queryByAddingFilter:FSTTestFilter(@"text", @"==", @"msg1")];
+ FSTQuery *query = [FSTTestQuery("rooms/eros/messages")
+ queryByAddingFilter:FSTTestFilter("text", @"==", @"msg1")];
XCTAssertTrue([query matchesDocument:doc1]);
XCTAssertFalse([query matchesDocument:doc2]);
}
- (void)testMatchesPrimitiveValuesForFilters {
FSTQuery *query1 =
- [FSTTestQuery(@"collection") queryByAddingFilter:FSTTestFilter(@"sort", @">=", @(2))];
+ [FSTTestQuery("collection") queryByAddingFilter:FSTTestFilter("sort", @">=", @(2))];
FSTQuery *query2 =
- [FSTTestQuery(@"collection") queryByAddingFilter:FSTTestFilter(@"sort", @"<=", @(2))];
+ [FSTTestQuery("collection") queryByAddingFilter:FSTTestFilter("sort", @"<=", @(2))];
FSTDocument *doc1 = FSTTestDoc(@"collection/1", 0, @{ @"sort" : @1 }, NO);
FSTDocument *doc2 = FSTTestDoc(@"collection/2", 0, @{ @"sort" : @2 }, NO);
@@ -155,8 +152,8 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testNullFilter {
- FSTQuery *query = [FSTTestQuery(@"collection")
- queryByAddingFilter:FSTTestFilter(@"sort", @"==", [NSNull null])];
+ FSTQuery *query =
+ [FSTTestQuery("collection") queryByAddingFilter:FSTTestFilter("sort", @"==", [NSNull null])];
FSTDocument *doc1 = FSTTestDoc(@"collection/1", 0, @{@"sort" : [NSNull null]}, NO);
FSTDocument *doc2 = FSTTestDoc(@"collection/2", 0, @{ @"sort" : @2 }, NO);
FSTDocument *doc3 = FSTTestDoc(@"collection/2", 0, @{ @"sort" : @3.1 }, NO);
@@ -172,7 +169,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testNanFilter {
FSTQuery *query =
- [FSTTestQuery(@"collection") queryByAddingFilter:FSTTestFilter(@"sort", @"==", @(NAN))];
+ [FSTTestQuery("collection") queryByAddingFilter:FSTTestFilter("sort", @"==", @(NAN))];
FSTDocument *doc1 = FSTTestDoc(@"collection/1", 0, @{ @"sort" : @(NAN) }, NO);
FSTDocument *doc2 = FSTTestDoc(@"collection/2", 0, @{ @"sort" : @2 }, NO);
FSTDocument *doc3 = FSTTestDoc(@"collection/2", 0, @{ @"sort" : @3.1 }, NO);
@@ -188,9 +185,9 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testDoesNotMatchComplexObjectsForFilters {
FSTQuery *query1 =
- [FSTTestQuery(@"collection") queryByAddingFilter:FSTTestFilter(@"sort", @"<=", @(2))];
+ [FSTTestQuery("collection") queryByAddingFilter:FSTTestFilter("sort", @"<=", @(2))];
FSTQuery *query2 =
- [FSTTestQuery(@"collection") queryByAddingFilter:FSTTestFilter(@"sort", @">=", @(2))];
+ [FSTTestQuery("collection") queryByAddingFilter:FSTTestFilter("sort", @">=", @(2))];
FSTDocument *doc1 = FSTTestDoc(@"collection/1", 0, @{ @"sort" : @2 }, NO);
FSTDocument *doc2 = FSTTestDoc(@"collection/2", 0, @{ @"sort" : @[] }, NO);
@@ -218,7 +215,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testDoesntRemoveComplexObjectsWithOrderBy {
- FSTQuery *query1 = [FSTTestQuery(@"collection")
+ FSTQuery *query1 = [FSTTestQuery("collection")
queryByAddingSortOrder:[FSTSortOrder sortOrderWithFieldPath:testutil::Field("sort")
ascending:YES]];
@@ -238,16 +235,16 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testFiltersBasedOnArrayValue {
- FSTQuery *baseQuery = FSTTestQuery(@"collection");
+ FSTQuery *baseQuery = FSTTestQuery("collection");
FSTDocument *doc1 = FSTTestDoc(@"collection/doc", 0, @{ @"tags" : @[ @"foo", @1, @YES ] }, NO);
NSArray<id<FSTFilter>> *matchingFilters =
- @[ FSTTestFilter(@"tags", @"==", @[ @"foo", @1, @YES ]) ];
+ @[ FSTTestFilter("tags", @"==", @[ @"foo", @1, @YES ]) ];
NSArray<id<FSTFilter>> *nonMatchingFilters = @[
- FSTTestFilter(@"tags", @"==", @"foo"),
- FSTTestFilter(@"tags", @"==", @[ @"foo", @1 ]),
- FSTTestFilter(@"tags", @"==", @[ @"foo", @YES, @1 ]),
+ FSTTestFilter("tags", @"==", @"foo"),
+ FSTTestFilter("tags", @"==", @[ @"foo", @1 ]),
+ FSTTestFilter("tags", @"==", @[ @"foo", @YES, @1 ]),
];
for (id<FSTFilter> filter in matchingFilters) {
@@ -260,27 +257,27 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testFiltersBasedOnObjectValue {
- FSTQuery *baseQuery = FSTTestQuery(@"collection");
+ FSTQuery *baseQuery = FSTTestQuery("collection");
FSTDocument *doc1 =
FSTTestDoc(@"collection/doc", 0,
@{ @"tags" : @{@"foo" : @"foo", @"a" : @0, @"b" : @YES, @"c" : @(NAN)} }, NO);
NSArray<id<FSTFilter>> *matchingFilters = @[
- FSTTestFilter(@"tags", @"==",
+ FSTTestFilter("tags", @"==",
@{ @"foo" : @"foo",
@"a" : @0,
@"b" : @YES,
@"c" : @(NAN) }),
- FSTTestFilter(@"tags", @"==",
+ FSTTestFilter("tags", @"==",
@{ @"b" : @YES,
@"a" : @0,
@"foo" : @"foo",
@"c" : @(NAN) }),
- FSTTestFilter(@"tags.foo", @"==", @"foo")
+ FSTTestFilter("tags.foo", @"==", @"foo")
];
NSArray<id<FSTFilter>> *nonMatchingFilters = @[
- FSTTestFilter(@"tags", @"==", @"foo"), FSTTestFilter(@"tags", @"==", @{
+ FSTTestFilter("tags", @"==", @"foo"), FSTTestFilter("tags", @"==", @{
@"foo" : @"foo",
@"a" : @0,
@"b" : @YES,
@@ -312,7 +309,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testSortsDocumentsInTheCorrectOrder {
- FSTQuery *query = FSTTestQuery(@"collection");
+ FSTQuery *query = FSTTestQuery("collection");
query = [query queryByAddingSortOrder:[FSTSortOrder sortOrderWithFieldPath:testutil::Field("sort")
ascending:YES]];
@@ -340,7 +337,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testSortsDocumentsUsingMultipleFields {
- FSTQuery *query = FSTTestQuery(@"collection");
+ FSTQuery *query = FSTTestQuery("collection");
query =
[query queryByAddingSortOrder:[FSTSortOrder sortOrderWithFieldPath:testutil::Field("sort1")
ascending:YES]];
@@ -367,7 +364,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testSortsDocumentsWithDescendingToo {
- FSTQuery *query = FSTTestQuery(@"collection");
+ FSTQuery *query = FSTTestQuery("collection");
query =
[query queryByAddingSortOrder:[FSTSortOrder sortOrderWithFieldPath:testutil::Field("sort1")
ascending:NO]];
@@ -394,40 +391,40 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEquality {
- FSTQuery *q11 = FSTTestQuery(@"foo");
- q11 = [q11 queryByAddingFilter:FSTTestFilter(@"i1", @"<", @(2))];
- q11 = [q11 queryByAddingFilter:FSTTestFilter(@"i2", @"==", @(3))];
- FSTQuery *q12 = FSTTestQuery(@"foo");
- q12 = [q12 queryByAddingFilter:FSTTestFilter(@"i2", @"==", @(3))];
- q12 = [q12 queryByAddingFilter:FSTTestFilter(@"i1", @"<", @(2))];
-
- FSTQuery *q21 = FSTTestQuery(@"foo");
- FSTQuery *q22 = FSTTestQuery(@"foo");
-
- FSTQuery *q31 = FSTTestQuery(@"foo/bar");
- FSTQuery *q32 = FSTTestQuery(@"foo/bar");
-
- FSTQuery *q41 = FSTTestQuery(@"foo");
- q41 = [q41 queryByAddingSortBy:@"foo" ascending:YES];
- q41 = [q41 queryByAddingSortBy:@"bar" ascending:YES];
- FSTQuery *q42 = FSTTestQuery(@"foo");
- q42 = [q42 queryByAddingSortBy:@"foo" ascending:YES];
- q42 = [q42 queryByAddingSortBy:@"bar" ascending:YES];
- FSTQuery *q43Diff = FSTTestQuery(@"foo");
- q43Diff = [q43Diff queryByAddingSortBy:@"bar" ascending:YES];
- q43Diff = [q43Diff queryByAddingSortBy:@"foo" ascending:YES];
-
- FSTQuery *q51 = FSTTestQuery(@"foo");
- q51 = [q51 queryByAddingSortBy:@"foo" ascending:YES];
- q51 = [q51 queryByAddingFilter:FSTTestFilter(@"foo", @">", @(2))];
- FSTQuery *q52 = FSTTestQuery(@"foo");
- q52 = [q52 queryByAddingFilter:FSTTestFilter(@"foo", @">", @(2))];
- q52 = [q52 queryByAddingSortBy:@"foo" ascending:YES];
- FSTQuery *q53Diff = FSTTestQuery(@"foo");
- q53Diff = [q53Diff queryByAddingFilter:FSTTestFilter(@"bar", @">", @(2))];
- q53Diff = [q53Diff queryByAddingSortBy:@"bar" ascending:YES];
-
- FSTQuery *q61 = FSTTestQuery(@"foo");
+ FSTQuery *q11 = FSTTestQuery("foo");
+ q11 = [q11 queryByAddingFilter:FSTTestFilter("i1", @"<", @(2))];
+ q11 = [q11 queryByAddingFilter:FSTTestFilter("i2", @"==", @(3))];
+ FSTQuery *q12 = FSTTestQuery("foo");
+ q12 = [q12 queryByAddingFilter:FSTTestFilter("i2", @"==", @(3))];
+ q12 = [q12 queryByAddingFilter:FSTTestFilter("i1", @"<", @(2))];
+
+ FSTQuery *q21 = FSTTestQuery("foo");
+ FSTQuery *q22 = FSTTestQuery("foo");
+
+ FSTQuery *q31 = FSTTestQuery("foo/bar");
+ FSTQuery *q32 = FSTTestQuery("foo/bar");
+
+ FSTQuery *q41 = FSTTestQuery("foo");
+ q41 = [q41 queryByAddingSortBy:"foo" ascending:YES];
+ q41 = [q41 queryByAddingSortBy:"bar" ascending:YES];
+ FSTQuery *q42 = FSTTestQuery("foo");
+ q42 = [q42 queryByAddingSortBy:"foo" ascending:YES];
+ q42 = [q42 queryByAddingSortBy:"bar" ascending:YES];
+ FSTQuery *q43Diff = FSTTestQuery("foo");
+ q43Diff = [q43Diff queryByAddingSortBy:"bar" ascending:YES];
+ q43Diff = [q43Diff queryByAddingSortBy:"foo" ascending:YES];
+
+ FSTQuery *q51 = FSTTestQuery("foo");
+ q51 = [q51 queryByAddingSortBy:"foo" ascending:YES];
+ q51 = [q51 queryByAddingFilter:FSTTestFilter("foo", @">", @(2))];
+ FSTQuery *q52 = FSTTestQuery("foo");
+ q52 = [q52 queryByAddingFilter:FSTTestFilter("foo", @">", @(2))];
+ q52 = [q52 queryByAddingSortBy:"foo" ascending:YES];
+ FSTQuery *q53Diff = FSTTestQuery("foo");
+ q53Diff = [q53Diff queryByAddingFilter:FSTTestFilter("bar", @">", @(2))];
+ q53Diff = [q53Diff queryByAddingSortBy:"bar" ascending:YES];
+
+ FSTQuery *q61 = FSTTestQuery("foo");
q61 = [q61 queryBySettingLimit:10];
// XCTAssertEqualObjects(q11, q12); // TODO(klimt): not canonical yet
@@ -459,40 +456,40 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testUniqueIds {
- FSTQuery *q11 = FSTTestQuery(@"foo");
- q11 = [q11 queryByAddingFilter:FSTTestFilter(@"i1", @"<", @(2))];
- q11 = [q11 queryByAddingFilter:FSTTestFilter(@"i2", @"==", @(3))];
- FSTQuery *q12 = FSTTestQuery(@"foo");
- q12 = [q12 queryByAddingFilter:FSTTestFilter(@"i2", @"==", @(3))];
- q12 = [q12 queryByAddingFilter:FSTTestFilter(@"i1", @"<", @(2))];
-
- FSTQuery *q21 = FSTTestQuery(@"foo");
- FSTQuery *q22 = FSTTestQuery(@"foo");
-
- FSTQuery *q31 = FSTTestQuery(@"foo/bar");
- FSTQuery *q32 = FSTTestQuery(@"foo/bar");
-
- FSTQuery *q41 = FSTTestQuery(@"foo");
- q41 = [q41 queryByAddingSortBy:@"foo" ascending:YES];
- q41 = [q41 queryByAddingSortBy:@"bar" ascending:YES];
- FSTQuery *q42 = FSTTestQuery(@"foo");
- q42 = [q42 queryByAddingSortBy:@"foo" ascending:YES];
- q42 = [q42 queryByAddingSortBy:@"bar" ascending:YES];
- FSTQuery *q43Diff = FSTTestQuery(@"foo");
- q43Diff = [q43Diff queryByAddingSortBy:@"bar" ascending:YES];
- q43Diff = [q43Diff queryByAddingSortBy:@"foo" ascending:YES];
-
- FSTQuery *q51 = FSTTestQuery(@"foo");
- q51 = [q51 queryByAddingSortBy:@"foo" ascending:YES];
- q51 = [q51 queryByAddingFilter:FSTTestFilter(@"foo", @">", @(2))];
- FSTQuery *q52 = FSTTestQuery(@"foo");
- q52 = [q52 queryByAddingFilter:FSTTestFilter(@"foo", @">", @(2))];
- q52 = [q52 queryByAddingSortBy:@"foo" ascending:YES];
- FSTQuery *q53Diff = FSTTestQuery(@"foo");
- q53Diff = [q53Diff queryByAddingFilter:FSTTestFilter(@"bar", @">", @(2))];
- q53Diff = [q53Diff queryByAddingSortBy:@"bar" ascending:YES];
-
- FSTQuery *q61 = FSTTestQuery(@"foo");
+ FSTQuery *q11 = FSTTestQuery("foo");
+ q11 = [q11 queryByAddingFilter:FSTTestFilter("i1", @"<", @(2))];
+ q11 = [q11 queryByAddingFilter:FSTTestFilter("i2", @"==", @(3))];
+ FSTQuery *q12 = FSTTestQuery("foo");
+ q12 = [q12 queryByAddingFilter:FSTTestFilter("i2", @"==", @(3))];
+ q12 = [q12 queryByAddingFilter:FSTTestFilter("i1", @"<", @(2))];
+
+ FSTQuery *q21 = FSTTestQuery("foo");
+ FSTQuery *q22 = FSTTestQuery("foo");
+
+ FSTQuery *q31 = FSTTestQuery("foo/bar");
+ FSTQuery *q32 = FSTTestQuery("foo/bar");
+
+ FSTQuery *q41 = FSTTestQuery("foo");
+ q41 = [q41 queryByAddingSortBy:"foo" ascending:YES];
+ q41 = [q41 queryByAddingSortBy:"bar" ascending:YES];
+ FSTQuery *q42 = FSTTestQuery("foo");
+ q42 = [q42 queryByAddingSortBy:"foo" ascending:YES];
+ q42 = [q42 queryByAddingSortBy:"bar" ascending:YES];
+ FSTQuery *q43Diff = FSTTestQuery("foo");
+ q43Diff = [q43Diff queryByAddingSortBy:"bar" ascending:YES];
+ q43Diff = [q43Diff queryByAddingSortBy:"foo" ascending:YES];
+
+ FSTQuery *q51 = FSTTestQuery("foo");
+ q51 = [q51 queryByAddingSortBy:"foo" ascending:YES];
+ q51 = [q51 queryByAddingFilter:FSTTestFilter("foo", @">", @(2))];
+ FSTQuery *q52 = FSTTestQuery("foo");
+ q52 = [q52 queryByAddingFilter:FSTTestFilter("foo", @">", @(2))];
+ q52 = [q52 queryByAddingSortBy:"foo" ascending:YES];
+ FSTQuery *q53Diff = FSTTestQuery("foo");
+ q53Diff = [q53Diff queryByAddingFilter:FSTTestFilter("bar", @">", @(2))];
+ q53Diff = [q53Diff queryByAddingSortBy:"bar" ascending:YES];
+
+ FSTQuery *q61 = FSTTestQuery("foo");
q61 = [q61 queryBySettingLimit:10];
// XCTAssertEqual(q11.hash, q12.hash); // TODO(klimt): not canonical yet
@@ -524,52 +521,55 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testImplicitOrderBy {
- FSTQuery *baseQuery = FSTTestQuery(@"foo");
+ FSTQuery *baseQuery = FSTTestQuery("foo");
// Default is ascending
- XCTAssertEqualObjects(baseQuery.sortOrders, @[ FSTTestOrderBy(kDocumentKeyPath, @"asc") ]);
+ XCTAssertEqualObjects(baseQuery.sortOrders,
+ @[ FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"asc") ]);
// Explicit key ordering is respected
XCTAssertEqualObjects(
- [baseQuery queryByAddingSortOrder:FSTTestOrderBy(kDocumentKeyPath, @"asc")].sortOrders,
- @[ FSTTestOrderBy(kDocumentKeyPath, @"asc") ]);
+ [baseQuery queryByAddingSortOrder:FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"asc")]
+ .sortOrders,
+ @[ FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"asc") ]);
XCTAssertEqualObjects(
- [baseQuery queryByAddingSortOrder:FSTTestOrderBy(kDocumentKeyPath, @"desc")].sortOrders,
- @[ FSTTestOrderBy(kDocumentKeyPath, @"desc") ]);
+ [baseQuery queryByAddingSortOrder:FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"desc")]
+ .sortOrders,
+ @[ FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"desc") ]);
XCTAssertEqualObjects(
- [[baseQuery queryByAddingSortOrder:FSTTestOrderBy(@"foo", @"asc")]
- queryByAddingSortOrder:FSTTestOrderBy(kDocumentKeyPath, @"asc")]
+ [[baseQuery queryByAddingSortOrder:FSTTestOrderBy("foo", @"asc")]
+ queryByAddingSortOrder:FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"asc")]
.sortOrders,
- (@[ FSTTestOrderBy(@"foo", @"asc"), FSTTestOrderBy(kDocumentKeyPath, @"asc") ]));
+ (@[ FSTTestOrderBy("foo", @"asc"), FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"asc") ]));
XCTAssertEqualObjects(
- [[baseQuery queryByAddingSortOrder:FSTTestOrderBy(@"foo", @"asc")]
- queryByAddingSortOrder:FSTTestOrderBy(kDocumentKeyPath, @"desc")]
+ [[baseQuery queryByAddingSortOrder:FSTTestOrderBy("foo", @"asc")]
+ queryByAddingSortOrder:FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"desc")]
.sortOrders,
- (@[ FSTTestOrderBy(@"foo", @"asc"), FSTTestOrderBy(kDocumentKeyPath, @"desc") ]));
+ (@[ FSTTestOrderBy("foo", @"asc"), FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"desc") ]));
// Inequality filters add order bys
XCTAssertEqualObjects(
- [baseQuery queryByAddingFilter:FSTTestFilter(@"foo", @"<", @5)].sortOrders,
- (@[ FSTTestOrderBy(@"foo", @"asc"), FSTTestOrderBy(kDocumentKeyPath, @"asc") ]));
+ [baseQuery queryByAddingFilter:FSTTestFilter("foo", @"<", @5)].sortOrders,
+ (@[ FSTTestOrderBy("foo", @"asc"), FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"asc") ]));
// Descending order by applies to implicit key ordering
XCTAssertEqualObjects(
- [baseQuery queryByAddingSortOrder:FSTTestOrderBy(@"foo", @"desc")].sortOrders,
- (@[ FSTTestOrderBy(@"foo", @"desc"), FSTTestOrderBy(kDocumentKeyPath, @"desc") ]));
- XCTAssertEqualObjects([[baseQuery queryByAddingSortOrder:FSTTestOrderBy(@"foo", @"asc")]
- queryByAddingSortOrder:FSTTestOrderBy(@"bar", @"desc")]
+ [baseQuery queryByAddingSortOrder:FSTTestOrderBy("foo", @"desc")].sortOrders,
+ (@[ FSTTestOrderBy("foo", @"desc"), FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"desc") ]));
+ XCTAssertEqualObjects([[baseQuery queryByAddingSortOrder:FSTTestOrderBy("foo", @"asc")]
+ queryByAddingSortOrder:FSTTestOrderBy("bar", @"desc")]
.sortOrders,
(@[
- FSTTestOrderBy(@"foo", @"asc"), FSTTestOrderBy(@"bar", @"desc"),
- FSTTestOrderBy(kDocumentKeyPath, @"desc")
+ FSTTestOrderBy("foo", @"asc"), FSTTestOrderBy("bar", @"desc"),
+ FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"desc")
]));
- XCTAssertEqualObjects([[baseQuery queryByAddingSortOrder:FSTTestOrderBy(@"foo", @"desc")]
- queryByAddingSortOrder:FSTTestOrderBy(@"bar", @"asc")]
+ XCTAssertEqualObjects([[baseQuery queryByAddingSortOrder:FSTTestOrderBy("foo", @"desc")]
+ queryByAddingSortOrder:FSTTestOrderBy("bar", @"asc")]
.sortOrders,
(@[
- FSTTestOrderBy(@"foo", @"desc"), FSTTestOrderBy(@"bar", @"asc"),
- FSTTestOrderBy(kDocumentKeyPath, @"asc")
+ FSTTestOrderBy("foo", @"desc"), FSTTestOrderBy("bar", @"asc"),
+ FSTTestOrderBy(FieldPath::kDocumentKeyPath, @"asc")
]));
}
diff --git a/Firestore/Example/Tests/Core/FSTViewSnapshotTest.mm b/Firestore/Example/Tests/Core/FSTViewSnapshotTest.mm
index fe3e42d..c503684 100644
--- a/Firestore/Example/Tests/Core/FSTViewSnapshotTest.mm
+++ b/Firestore/Example/Tests/Core/FSTViewSnapshotTest.mm
@@ -21,7 +21,6 @@
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentSet.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
@@ -107,7 +106,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testViewSnapshotConstructor {
- FSTQuery *query = FSTTestQuery(@"a");
+ FSTQuery *query = FSTTestQuery("a");
FSTDocumentSet *documents = [FSTDocumentSet documentSetWithComparator:FSTDocumentComparatorByKey];
FSTDocumentSet *oldDocuments = documents;
documents = [documents documentSetByAddingDocument:FSTTestDoc(@"c/a", 1, @{}, NO)];
diff --git a/Firestore/Example/Tests/Core/FSTViewTests.mm b/Firestore/Example/Tests/Core/FSTViewTests.mm
index 7df8195..1e3ec1a 100644
--- a/Firestore/Example/Tests/Core/FSTViewTests.mm
+++ b/Firestore/Example/Tests/Core/FSTViewTests.mm
@@ -25,7 +25,6 @@
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTDocumentSet.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTRemoteEvent.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
diff --git a/Firestore/Example/Tests/Integration/API/FIRValidationTests.mm b/Firestore/Example/Tests/Integration/API/FIRValidationTests.mm
index 49e572a..0ad30fd 100644
--- a/Firestore/Example/Tests/Integration/API/FIRValidationTests.mm
+++ b/Firestore/Example/Tests/Integration/API/FIRValidationTests.mm
@@ -132,7 +132,7 @@
}
- (void)testPathsWithEmptySegmentsFail {
- // We're only testing using collectionWithPath since the validation happens in FSTPath which is
+ // We're only testing using collectionWithPath since the validation happens in BasePath which is
// shared by all methods that accept paths.
// leading / trailing slashes are okay.
diff --git a/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm b/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm
index 77581d4..9ce3d30 100644
--- a/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm
+++ b/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm
@@ -31,7 +31,6 @@
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTDatastore.h"
#import "Firestore/Source/Remote/FSTRemoteEvent.h"
#import "Firestore/Source/Remote/FSTRemoteStore.h"
diff --git a/Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm
index 998d23d..f23b7c5 100644
--- a/Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm
@@ -18,10 +18,14 @@
#import <XCTest/XCTest.h>
-#import "Firestore/Source/Model/FSTPath.h"
-
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
+#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+
+namespace util = firebase::firestore::util;
+namespace testutil = firebase::firestore::testutil;
+
NS_ASSUME_NONNULL_BEGIN
@interface FSTLevelDBKeyTests : XCTestCase
@@ -37,7 +41,8 @@ static std::string RemoteDocKey(NSString *pathString) {
}
static std::string RemoteDocKeyPrefix(NSString *pathString) {
- return [FSTLevelDBRemoteDocumentKey keyPrefixWithResourcePath:FSTTestPath(pathString)];
+ return [FSTLevelDBRemoteDocumentKey
+ keyPrefixWithResourcePath:testutil::Resource(util::MakeStringView(pathString))];
}
static std::string DocMutationKey(NSString *userID, NSString *key, FSTBatchID batchID) {
@@ -199,7 +204,7 @@ static std::string DocTargetKey(NSString *key, FSTTargetID targetID) {
@"[document_mutation: userID=user1 incomplete key]");
auto key = [FSTLevelDBDocumentMutationKey keyPrefixWithUserID:@"user1"
- resourcePath:FSTTestPath(@"foo/bar")];
+ resourcePath:testutil::Resource("foo/bar")];
FSTAssertExpectedKeyDescription(key,
@"[document_mutation: userID=user1 key=foo/bar incomplete key]");
diff --git a/Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm b/Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm
index 1793b23..87242fa 100644
--- a/Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm
@@ -36,14 +36,15 @@
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTSerializerBeta.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+namespace testutil = firebase::firestore::testutil;
using firebase::firestore::model::DatabaseId;
NS_ASSUME_NONNULL_BEGIN
@@ -77,7 +78,7 @@ NS_ASSUME_NONNULL_BEGIN
FSTMutation *set = FSTTestSetMutation(@"foo/bar", @{ @"a" : @"b", @"num" : @1 });
FSTMutation *patch = [[FSTPatchMutation alloc]
initWithKey:FSTTestDocKey(@"bar/baz")
- fieldMask:[[FSTFieldMask alloc] initWithFields:@[ FSTTestFieldPath(@"a") ]]
+ fieldMask:[[FSTFieldMask alloc] initWithFields:{testutil::Field("a")}]
value:FSTTestObjectValue(
@{ @"a" : @"b",
@"num" : @1 })
@@ -156,7 +157,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesQueryData {
- FSTQuery *query = FSTTestQuery(@"room");
+ FSTQuery *query = FSTTestQuery("room");
FSTTargetID targetID = 42;
FSTSnapshotVersion *version = FSTTestVersion(1039);
NSData *resumeToken = FSTTestResumeTokenFromSnapshotVersion(1039);
diff --git a/Firestore/Example/Tests/Local/FSTLocalStoreTests.mm b/Firestore/Example/Tests/Local/FSTLocalStoreTests.mm
index 393f77b..5a386b6 100644
--- a/Firestore/Example/Tests/Local/FSTLocalStoreTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLocalStoreTests.mm
@@ -30,7 +30,6 @@
#import "Firestore/Source/Model/FSTDocumentSet.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTRemoteEvent.h"
#import "Firestore/Source/Remote/FSTWatchChange.h"
#import "Firestore/Source/Util/FSTClasses.h"
@@ -263,7 +262,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
if ([self isTestBaseClass]) return;
// Start a query that requires acks to be held.
- FSTQuery *query = FSTTestQuery(@"foo");
+ FSTQuery *query = FSTTestQuery("foo");
[self allocateQuery:query];
[self writeMutation:FSTTestSetMutation(@"foo/bar", @{@"foo" : @"bar"})];
@@ -342,7 +341,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
- (void)testHandlesPatchWithoutPriorDocument {
if ([self isTestBaseClass]) return;
- [self writeMutation:FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)];
+ [self writeMutation:FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})];
FSTAssertRemoved(@[ @"foo/bar" ]);
FSTAssertNotContains(@"foo/bar");
@@ -354,7 +353,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
- (void)testHandlesPatchMutationThenDocumentThenAck {
if ([self isTestBaseClass]) return;
- [self writeMutation:FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)];
+ [self writeMutation:FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})];
FSTAssertRemoved(@[ @"foo/bar" ]);
FSTAssertNotContains(@"foo/bar");
@@ -371,7 +370,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
- (void)testHandlesPatchMutationThenAckThenDocument {
if ([self isTestBaseClass]) return;
- [self writeMutation:FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)];
+ [self writeMutation:FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})];
FSTAssertRemoved(@[ @"foo/bar" ]);
FSTAssertNotContains(@"foo/bar");
@@ -456,7 +455,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
FSTAssertChanged(@[ FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"old"}, YES) ]);
FSTAssertContains(FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"old"}, YES));
- [self writeMutation:FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)];
+ [self writeMutation:FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})];
FSTAssertChanged(@[ FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"bar"}, YES) ]);
FSTAssertContains(FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"bar"}, YES));
@@ -479,7 +478,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
[self writeMutations:@[
FSTTestSetMutation(@"foo/bar", @{@"foo" : @"old"}),
- FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)
+ FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})
]];
FSTAssertChanged(@[ FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"bar"}, YES) ]);
@@ -493,7 +492,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
[self acknowledgeMutationWithVersion:1];
FSTAssertContains(FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"old"}, NO));
- [self writeMutation:FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)];
+ [self writeMutation:FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})];
FSTAssertContains(FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"bar"}, YES));
[self rejectMutation];
@@ -507,7 +506,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
[self writeMutations:@[
FSTTestSetMutation(@"foo/bar", @{@"foo" : @"old"}),
FSTTestSetMutation(@"bar/baz", @{@"bar" : @"baz"}),
- FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)
+ FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})
]];
FSTAssertChanged((@[
@@ -525,7 +524,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
FSTAssertRemoved(@[ @"foo/bar" ]);
FSTAssertContains(FSTTestDeletedDoc(@"foo/bar", 0));
- [self writeMutation:FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)];
+ [self writeMutation:FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})];
FSTAssertRemoved(@[ @"foo/bar" ]);
FSTAssertContains(FSTTestDeletedDoc(@"foo/bar", 0));
@@ -556,7 +555,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
- (void)testCollectsGarbageAfterChangeBatch {
if ([self isTestBaseClass]) return;
- FSTQuery *query = FSTTestQuery(@"foo");
+ FSTQuery *query = FSTTestQuery("foo");
[self allocateQuery:query];
FSTAssertTargetID(2);
@@ -577,7 +576,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
[self applyRemoteEvent:FSTTestUpdateRemoteEvent(FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"old"}, NO),
@[ @1 ], @[])];
- [self writeMutation:FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)];
+ [self writeMutation:FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})];
[self writeMutation:FSTTestSetMutation(@"foo/bah", @{@"foo" : @"bah"})];
[self writeMutation:FSTTestDeleteMutation(@"foo/baz")];
[self collectGarbage];
@@ -609,7 +608,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
[self applyRemoteEvent:FSTTestUpdateRemoteEvent(FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"old"}, NO),
@[ @1 ], @[])];
- [self writeMutation:FSTTestPatchMutation(@"foo/bar", @{@"foo" : @"bar"}, nil)];
+ [self writeMutation:FSTTestPatchMutation("foo/bar", @{@"foo" : @"bar"}, {})];
[self writeMutation:FSTTestSetMutation(@"foo/bah", @{@"foo" : @"bah"})];
[self writeMutation:FSTTestDeleteMutation(@"foo/baz")];
[self collectGarbage];
@@ -639,7 +638,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
- (void)testPinsDocumentsInTheLocalView {
if ([self isTestBaseClass]) return;
- FSTQuery *query = FSTTestQuery(@"foo");
+ FSTQuery *query = FSTTestQuery("foo");
[self allocateQuery:query];
FSTAssertTargetID(2);
@@ -687,7 +686,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
FSTTestSetMutation(@"foo/baz", @{@"foo" : @"baz"}),
FSTTestSetMutation(@"foo/bar/Foo/Bar", @{@"Foo" : @"Bar"})
]];
- FSTQuery *query = FSTTestQuery(@"foo/bar");
+ FSTQuery *query = FSTTestQuery("foo/bar");
FSTDocumentDictionary *docs = [self.localStore executeQuery:query];
XCTAssertEqualObjects([docs values], @[ FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"bar"}, YES) ]);
}
@@ -702,7 +701,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
FSTTestSetMutation(@"foo/bar/Foo/Bar", @{@"Foo" : @"Bar"}),
FSTTestSetMutation(@"fooo/blah", @{@"fooo" : @"blah"})
]];
- FSTQuery *query = FSTTestQuery(@"foo");
+ FSTQuery *query = FSTTestQuery("foo");
FSTDocumentDictionary *docs = [self.localStore executeQuery:query];
XCTAssertEqualObjects([docs values], (@[
FSTTestDoc(@"foo/bar", 0, @{@"foo" : @"bar"}, YES),
@@ -713,7 +712,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
- (void)testCanExecuteMixedCollectionQueries {
if ([self isTestBaseClass]) return;
- FSTQuery *query = FSTTestQuery(@"foo");
+ FSTQuery *query = FSTTestQuery("foo");
[self allocateQuery:query];
FSTAssertTargetID(2);
@@ -738,7 +737,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
// This test only works in the absence of the FSTEagerGarbageCollector.
[self restartWithNoopGarbageCollector];
- FSTQuery *query = FSTTestQuery(@"foo/bar");
+ FSTQuery *query = FSTTestQuery("foo/bar");
FSTQueryData *queryData = [self.localStore allocateQuery:query];
FSTBoxedTargetID *targetID = @(queryData.targetID);
NSData *resumeToken = FSTTestResumeTokenFromSnapshotVersion(1000);
@@ -772,7 +771,7 @@ FSTDocumentVersionDictionary *FSTVersionDictionary(FSTMutation *mutation,
if ([self isTestBaseClass]) return;
[self restartWithNoopGarbageCollector];
- FSTQuery *query = FSTTestQuery(@"foo");
+ FSTQuery *query = FSTTestQuery("foo");
[self allocateQuery:query];
FSTAssertTargetID(2);
diff --git a/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm b/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm
index f5294d5..57572ec 100644
--- a/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm
+++ b/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm
@@ -259,8 +259,8 @@ NS_ASSUME_NONNULL_BEGIN
@{ @"a" : @1 }),
FSTTestSetMutation(@"foo/bar",
@{ @"a" : @1 }),
- FSTTestPatchMutation(@"foo/bar",
- @{ @"b" : @1 }, nil),
+ FSTTestPatchMutation("foo/bar",
+ @{ @"b" : @1 }, {}),
FSTTestSetMutation(@"foo/bar/suffix/key",
@{ @"a" : @1 }),
FSTTestSetMutation(@"foo/baz",
@@ -296,8 +296,8 @@ NS_ASSUME_NONNULL_BEGIN
@{ @"a" : @1 }),
FSTTestSetMutation(@"foo/bar",
@{ @"a" : @1 }),
- FSTTestPatchMutation(@"foo/bar",
- @{ @"b" : @1 }, nil),
+ FSTTestPatchMutation("foo/bar",
+ @{ @"b" : @1 }, {}),
FSTTestSetMutation(@"foo/bar/suffix/key",
@{ @"a" : @1 }),
FSTTestSetMutation(@"foo/baz",
@@ -319,7 +319,7 @@ NS_ASSUME_NONNULL_BEGIN
[self.persistence commitGroup:group];
NSArray<FSTMutationBatch *> *expected = @[ batches[1], batches[2], batches[4] ];
- FSTQuery *query = FSTTestQuery(@"foo");
+ FSTQuery *query = FSTTestQuery("foo");
NSArray<FSTMutationBatch *> *matches =
[self.mutationQueue allMutationBatchesAffectingQuery:query];
diff --git a/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm b/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm
index 5cdfd66..0618e9c 100644
--- a/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm
+++ b/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm
@@ -39,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)setUp {
[super setUp];
- _queryRooms = FSTTestQuery(@"rooms");
+ _queryRooms = FSTTestQuery("rooms");
_previousSequenceNumber = 1000;
_previousTargetID = 500;
_previousSnapshotVersion = 100;
@@ -76,8 +76,8 @@ NS_ASSUME_NONNULL_BEGIN
// Type information is currently lost in our canonicalID implementations so this currently an
// easy way to force colliding canonicalIDs
- FSTQuery *q1 = [FSTTestQuery(@"a") queryByAddingFilter:FSTTestFilter(@"foo", @"==", @(1))];
- FSTQuery *q2 = [FSTTestQuery(@"a") queryByAddingFilter:FSTTestFilter(@"foo", @"==", @"1")];
+ FSTQuery *q1 = [FSTTestQuery("a") queryByAddingFilter:FSTTestFilter("foo", @"==", @(1))];
+ FSTQuery *q2 = [FSTTestQuery("a") queryByAddingFilter:FSTTestFilter("foo", @"==", @"1")];
XCTAssertEqualObjects(q1.canonicalID, q2.canonicalID);
FSTQueryData *data1 = [self queryDataWithQuery:q1];
@@ -215,14 +215,14 @@ NS_ASSUME_NONNULL_BEGIN
[garbageCollector addGarbageSource:self.queryCache];
FSTAssertEqualSets([garbageCollector collectGarbage], @[]);
- FSTQueryData *rooms = [self queryDataWithQuery:FSTTestQuery(@"rooms")];
+ FSTQueryData *rooms = [self queryDataWithQuery:FSTTestQuery("rooms")];
FSTDocumentKey *room1 = FSTTestDocKey(@"rooms/bar");
FSTDocumentKey *room2 = FSTTestDocKey(@"rooms/foo");
[self addQueryData:rooms];
[self addMatchingKey:room1 forTargetID:rooms.targetID];
[self addMatchingKey:room2 forTargetID:rooms.targetID];
- FSTQueryData *halls = [self queryDataWithQuery:FSTTestQuery(@"halls")];
+ FSTQueryData *halls = [self queryDataWithQuery:FSTTestQuery("halls")];
FSTDocumentKey *hall1 = FSTTestDocKey(@"halls/bar");
FSTDocumentKey *hall2 = FSTTestDocKey(@"halls/foo");
[self addQueryData:halls];
@@ -263,12 +263,12 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testHighestListenSequenceNumber {
if ([self isTestBaseClass]) return;
- FSTQueryData *query1 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery(@"rooms")
+ FSTQueryData *query1 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("rooms")
targetID:1
listenSequenceNumber:10
purpose:FSTQueryPurposeListen];
[self addQueryData:query1];
- FSTQueryData *query2 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery(@"halls")
+ FSTQueryData *query2 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("halls")
targetID:2
listenSequenceNumber:20
purpose:FSTQueryPurposeListen];
@@ -280,7 +280,7 @@ NS_ASSUME_NONNULL_BEGIN
XCTAssertEqual([self.queryCache highestListenSequenceNumber], 20);
// A query with an empty result set still counts.
- FSTQueryData *query3 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery(@"garages")
+ FSTQueryData *query3 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("garages")
targetID:42
listenSequenceNumber:100
purpose:FSTQueryPurposeListen];
@@ -305,7 +305,7 @@ NS_ASSUME_NONNULL_BEGIN
XCTAssertEqual([self.queryCache highestTargetID], 0);
- FSTQueryData *query1 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery(@"rooms")
+ FSTQueryData *query1 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("rooms")
targetID:1
listenSequenceNumber:10
purpose:FSTQueryPurposeListen];
@@ -315,7 +315,7 @@ NS_ASSUME_NONNULL_BEGIN
[self addMatchingKey:key1 forTargetID:1];
[self addMatchingKey:key2 forTargetID:1];
- FSTQueryData *query2 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery(@"halls")
+ FSTQueryData *query2 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("halls")
targetID:2
listenSequenceNumber:20
purpose:FSTQueryPurposeListen];
@@ -329,7 +329,7 @@ NS_ASSUME_NONNULL_BEGIN
XCTAssertEqual([self.queryCache highestTargetID], 2);
// A query with an empty result set still counts.
- FSTQueryData *query3 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery(@"garages")
+ FSTQueryData *query3 = [[FSTQueryData alloc] initWithQuery:FSTTestQuery("garages")
targetID:42
listenSequenceNumber:100
purpose:FSTQueryPurposeListen];
diff --git a/Firestore/Example/Tests/Local/FSTRemoteDocumentCacheTests.mm b/Firestore/Example/Tests/Local/FSTRemoteDocumentCacheTests.mm
index d240604..d056488 100644
--- a/Firestore/Example/Tests/Local/FSTRemoteDocumentCacheTests.mm
+++ b/Firestore/Example/Tests/Local/FSTRemoteDocumentCacheTests.mm
@@ -112,7 +112,7 @@ static const int kVersion = 42;
[self setTestDocumentAtPath:@"b/2"];
[self setTestDocumentAtPath:@"c/1"];
- FSTQuery *query = FSTTestQuery(@"b");
+ FSTQuery *query = FSTTestQuery("b");
FSTDocumentDictionary *results = [self.remoteDocumentCache documentsMatchingQuery:query];
NSArray *expected =
@[ FSTTestDoc(@"b/1", kVersion, _kDocData, NO), FSTTestDoc(@"b/2", kVersion, _kDocData, NO) ];
diff --git a/Firestore/Example/Tests/Model/FSTDocumentSetTests.mm b/Firestore/Example/Tests/Model/FSTDocumentSetTests.mm
index fbaa5d6..d70c44d 100644
--- a/Firestore/Example/Tests/Model/FSTDocumentSetTests.mm
+++ b/Firestore/Example/Tests/Model/FSTDocumentSetTests.mm
@@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)setUp {
[super setUp];
- _comp = FSTTestDocComparator(@"sort");
+ _comp = FSTTestDocComparator("sort");
_doc1 = FSTTestDoc(@"docs/1", 0, @{ @"sort" : @2 }, NO);
_doc2 = FSTTestDoc(@"docs/2", 0, @{ @"sort" : @3 }, NO);
_doc3 = FSTTestDoc(@"docs/3", 0, @{ @"sort" : @1 }, NO);
diff --git a/Firestore/Example/Tests/Model/FSTDocumentTests.mm b/Firestore/Example/Tests/Model/FSTDocumentTests.mm
index 59f526d..0527852 100644
--- a/Firestore/Example/Tests/Model/FSTDocumentTests.mm
+++ b/Firestore/Example/Tests/Model/FSTDocumentTests.mm
@@ -21,10 +21,13 @@
#import "Firestore/Source/Core/FSTSnapshotVersion.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
+#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+
+namespace testutil = firebase::firestore::testutil;
+
NS_ASSUME_NONNULL_BEGIN
@interface FSTDocumentTests : XCTestCase
@@ -55,9 +58,9 @@ NS_ASSUME_NONNULL_BEGIN
FSTDocument *doc =
[FSTDocument documentWithData:data key:key version:version hasLocalMutations:NO];
- XCTAssertEqualObjects([doc fieldForPath:FSTTestFieldPath(@"desc")],
+ XCTAssertEqualObjects([doc fieldForPath:testutil::Field("desc")],
[FSTStringValue stringValue:@"Discuss all the project related stuff"]);
- XCTAssertEqualObjects([doc fieldForPath:FSTTestFieldPath(@"owner.title")],
+ XCTAssertEqualObjects([doc fieldForPath:testutil::Field("owner.title")],
[FSTStringValue stringValue:@"scallywag"]);
}
diff --git a/Firestore/Example/Tests/Model/FSTFieldValueTests.mm b/Firestore/Example/Tests/Model/FSTFieldValueTests.mm
index 03dfa66..1a207f4 100644
--- a/Firestore/Example/Tests/Model/FSTFieldValueTests.mm
+++ b/Firestore/Example/Tests/Model/FSTFieldValueTests.mm
@@ -23,14 +23,15 @@
#import "Firestore/Source/API/FIRFirestore+Internal.h"
#import "Firestore/Source/API/FSTUserDataConverter.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Example/Tests/API/FSTAPIHelpers.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+namespace testutil = firebase::firestore::testutil;
namespace util = firebase::firestore::util;
using firebase::firestore::model::DatabaseId;
@@ -301,20 +302,20 @@ union DoubleBits {
FSTObjectValue *obj = FSTTestObjectValue(@{ @"foo" : @{@"a" : @YES, @"b" : @"string"} });
FSTAssertIsKindOfClass(obj, FSTObjectValue);
- FSTAssertIsKindOfClass([obj valueForPath:FSTTestFieldPath(@"foo")], FSTObjectValue);
- XCTAssertEqualObjects([obj valueForPath:FSTTestFieldPath(@"foo.a")], [FSTBooleanValue trueValue]);
- XCTAssertEqualObjects([obj valueForPath:FSTTestFieldPath(@"foo.b")],
+ FSTAssertIsKindOfClass([obj valueForPath:testutil::Field("foo")], FSTObjectValue);
+ XCTAssertEqualObjects([obj valueForPath:testutil::Field("foo.a")], [FSTBooleanValue trueValue]);
+ XCTAssertEqualObjects([obj valueForPath:testutil::Field("foo.b")],
[FSTStringValue stringValue:@"string"]);
- XCTAssertNil([obj valueForPath:FSTTestFieldPath(@"foo.a.b")]);
- XCTAssertNil([obj valueForPath:FSTTestFieldPath(@"bar")]);
- XCTAssertNil([obj valueForPath:FSTTestFieldPath(@"bar.a")]);
+ XCTAssertNil([obj valueForPath:testutil::Field("foo.a.b")]);
+ XCTAssertNil([obj valueForPath:testutil::Field("bar")]);
+ XCTAssertNil([obj valueForPath:testutil::Field("bar.a")]);
}
- (void)testOverwritesExistingFields {
FSTObjectValue *old = FSTTestObjectValue(@{@"a" : @"old"});
FSTObjectValue *mod =
- [old objectBySettingValue:FSTTestFieldValue(@"mod") forPath:FSTTestFieldPath(@"a")];
+ [old objectBySettingValue:FSTTestFieldValue(@"mod") forPath:testutil::Field("a")];
// Should return a new object, leaving the old one unmodified.
XCTAssertNotEqual(old, mod);
@@ -325,13 +326,13 @@ union DoubleBits {
- (void)testAddsNewFields {
FSTObjectValue *empty = [FSTObjectValue objectValue];
FSTObjectValue *mod =
- [empty objectBySettingValue:FSTTestFieldValue(@"mod") forPath:FSTTestFieldPath(@"a")];
+ [empty objectBySettingValue:FSTTestFieldValue(@"mod") forPath:testutil::Field("a")];
XCTAssertNotEqual(empty, mod);
XCTAssertEqualObjects(empty, FSTTestFieldValue(@{}));
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{@"a" : @"mod"}));
FSTObjectValue *old = mod;
- mod = [old objectBySettingValue:FSTTestFieldValue(@1) forPath:FSTTestFieldPath(@"b")];
+ mod = [old objectBySettingValue:FSTTestFieldValue(@1) forPath:testutil::Field("b")];
XCTAssertNotEqual(old, mod);
XCTAssertEqualObjects(old, FSTTestFieldValue(@{@"a" : @"mod"}));
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"a" : @"mod", @"b" : @1 }));
@@ -340,7 +341,7 @@ union DoubleBits {
- (void)testImplicitlyCreatesObjects {
FSTObjectValue *old = FSTTestObjectValue(@{@"a" : @"old"});
FSTObjectValue *mod =
- [old objectBySettingValue:FSTTestFieldValue(@"mod") forPath:FSTTestFieldPath(@"b.c.d")];
+ [old objectBySettingValue:FSTTestFieldValue(@"mod") forPath:testutil::Field("b.c.d")];
XCTAssertNotEqual(old, mod);
XCTAssertEqualObjects(old, FSTTestFieldValue(@{@"a" : @"old"}));
XCTAssertEqualObjects(mod, FSTTestFieldValue(
@@ -351,7 +352,7 @@ union DoubleBits {
- (void)testCanOverwritePrimitivesWithObjects {
FSTObjectValue *old = FSTTestObjectValue(@{ @"a" : @{@"b" : @"old"} });
FSTObjectValue *mod =
- [old objectBySettingValue:FSTTestFieldValue(@{@"b" : @"mod"}) forPath:FSTTestFieldPath(@"a")];
+ [old objectBySettingValue:FSTTestFieldValue(@{@"b" : @"mod"}) forPath:testutil::Field("a")];
XCTAssertNotEqual(old, mod);
XCTAssertEqualObjects(old, FSTTestFieldValue(@{ @"a" : @{@"b" : @"old"} }));
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"a" : @{@"b" : @"mod"} }));
@@ -360,7 +361,7 @@ union DoubleBits {
- (void)testAddsToNestedObjects {
FSTObjectValue *old = FSTTestObjectValue(@{ @"a" : @{@"b" : @"old"} });
FSTObjectValue *mod =
- [old objectBySettingValue:FSTTestFieldValue(@"mod") forPath:FSTTestFieldPath(@"a.c")];
+ [old objectBySettingValue:FSTTestFieldValue(@"mod") forPath:testutil::Field("a.c")];
XCTAssertNotEqual(old, mod);
XCTAssertEqualObjects(old, FSTTestFieldValue(@{ @"a" : @{@"b" : @"old"} }));
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"a" : @{@"b" : @"old", @"c" : @"mod"} }));
@@ -368,12 +369,12 @@ union DoubleBits {
- (void)testDeletesKeys {
FSTObjectValue *old = FSTTestObjectValue(@{ @"a" : @1, @"b" : @2 });
- FSTObjectValue *mod = [old objectByDeletingPath:FSTTestFieldPath(@"a")];
+ FSTObjectValue *mod = [old objectByDeletingPath:testutil::Field("a")];
XCTAssertNotEqual(old, mod);
XCTAssertEqualObjects(old, FSTTestFieldValue(@{ @"a" : @1, @"b" : @2 }));
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"b" : @2 }));
- FSTObjectValue *empty = [mod objectByDeletingPath:FSTTestFieldPath(@"b")];
+ FSTObjectValue *empty = [mod objectByDeletingPath:testutil::Field("b")];
XCTAssertNotEqual(mod, empty);
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"b" : @2 }));
XCTAssertEqualObjects(empty, FSTTestFieldValue(@{}));
@@ -381,15 +382,15 @@ union DoubleBits {
- (void)testDeletesHandleMissingKeys {
FSTObjectValue *old = FSTTestObjectValue(@{ @"a" : @{@"b" : @1, @"c" : @2} });
- FSTObjectValue *mod = [old objectByDeletingPath:FSTTestFieldPath(@"b")];
+ FSTObjectValue *mod = [old objectByDeletingPath:testutil::Field("b")];
XCTAssertEqualObjects(old, mod);
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"a" : @{@"b" : @1, @"c" : @2} }));
- mod = [old objectByDeletingPath:FSTTestFieldPath(@"a.d")];
+ mod = [old objectByDeletingPath:testutil::Field("a.d")];
XCTAssertEqualObjects(old, mod);
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"a" : @{@"b" : @1, @"c" : @2} }));
- mod = [old objectByDeletingPath:FSTTestFieldPath(@"a.b.c")];
+ mod = [old objectByDeletingPath:testutil::Field("a.b.c")];
XCTAssertEqualObjects(old, mod);
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"a" : @{@"b" : @1, @"c" : @2} }));
}
@@ -397,19 +398,19 @@ union DoubleBits {
- (void)testDeletesNestedKeys {
FSTObjectValue *old = FSTTestObjectValue(
@{ @"a" : @{@"b" : @1, @"c" : @{@"d" : @2, @"e" : @3}} });
- FSTObjectValue *mod = [old objectByDeletingPath:FSTTestFieldPath(@"a.c.d")];
+ FSTObjectValue *mod = [old objectByDeletingPath:testutil::Field("a.c.d")];
XCTAssertNotEqual(old, mod);
XCTAssertEqualObjects(old, FSTTestFieldValue(
@{ @"a" : @{@"b" : @1, @"c" : @{@"d" : @2, @"e" : @3}} }));
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"a" : @{@"b" : @1, @"c" : @{@"e" : @3}} }));
old = mod;
- mod = [old objectByDeletingPath:FSTTestFieldPath(@"a.c")];
+ mod = [old objectByDeletingPath:testutil::Field("a.c")];
XCTAssertEqualObjects(old, FSTTestFieldValue(@{ @"a" : @{@"b" : @1, @"c" : @{@"e" : @3}} }));
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{ @"a" : @{@"b" : @1} }));
old = mod;
- mod = [old objectByDeletingPath:FSTTestFieldPath(@"a")];
+ mod = [old objectByDeletingPath:testutil::Field("a")];
XCTAssertEqualObjects(old, FSTTestFieldValue(@{ @"a" : @{@"b" : @1} }));
XCTAssertEqualObjects(mod, FSTTestFieldValue(@{}));
}
diff --git a/Firestore/Example/Tests/Model/FSTMutationTests.mm b/Firestore/Example/Tests/Model/FSTMutationTests.mm
index 1c1375c..5b056fb 100644
--- a/Firestore/Example/Tests/Model/FSTMutationTests.mm
+++ b/Firestore/Example/Tests/Model/FSTMutationTests.mm
@@ -22,10 +22,13 @@
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
+#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+
+namespace testutil = firebase::firestore::testutil;
+
@interface FSTMutationTests : XCTestCase
@end
@@ -52,8 +55,7 @@
NSDictionary *docData = @{ @"foo" : @{@"bar" : @"bar-value"}, @"baz" : @"baz-value" };
FSTDocument *baseDoc = FSTTestDoc(@"collection/key", 0, docData, NO);
- FSTMutation *patch =
- FSTTestPatchMutation(@"collection/key", @{@"foo.bar" : @"new-bar-value"}, nil);
+ FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo.bar" : @"new-bar-value"}, {});
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
@@ -66,7 +68,7 @@
FSTDocument *baseDoc = FSTTestDoc(@"collection/key", 0, docData, NO);
FSTDocumentKey *key = FSTTestDocKey(@"collection/key");
- FSTFieldMask *mask = [[FSTFieldMask alloc] initWithFields:@[ FSTTestFieldPath(@"foo.bar") ]];
+ FSTFieldMask *mask = [[FSTFieldMask alloc] initWithFields:{testutil::Field("foo.bar")}];
FSTMutation *patch = [[FSTPatchMutation alloc] initWithKey:key
fieldMask:mask
value:[FSTObjectValue objectValue]
@@ -82,8 +84,7 @@
NSDictionary *docData = @{@"foo" : @"foo-value", @"baz" : @"baz-value"};
FSTDocument *baseDoc = FSTTestDoc(@"collection/key", 0, docData, NO);
- FSTMutation *patch =
- FSTTestPatchMutation(@"collection/key", @{@"foo.bar" : @"new-bar-value"}, nil);
+ FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo.bar" : @"new-bar-value"}, {});
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
@@ -93,7 +94,7 @@
- (void)testPatchingDeletedDocumentsDoesNothing {
FSTMaybeDocument *baseDoc = FSTTestDeletedDoc(@"collection/key", 0);
- FSTMutation *patch = FSTTestPatchMutation(@"collection/key", @{@"foo" : @"bar"}, nil);
+ FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo" : @"bar"}, {});
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
XCTAssertEqualObjects(patchedDoc, baseDoc);
@@ -115,7 +116,7 @@
[expectedData objectBySettingValue:[FSTServerTimestampValue
serverTimestampValueWithLocalWriteTime:_timestamp
previousValue:nil]
- forPath:FSTTestFieldPath(@"foo.bar")];
+ forPath:testutil::Field("foo.bar")];
FSTDocument *expectedDoc = [FSTDocument documentWithData:expectedData
key:FSTTestDocKey(@"collection/key")
@@ -176,7 +177,7 @@
NSDictionary *docData = @{@"foo" : @"bar"};
FSTDocument *baseDoc = FSTTestDoc(@"collection/key", 0, docData, NO);
- FSTMutation *patch = FSTTestPatchMutation(@"collection/key", @{@"foo" : @"new-bar"}, nil);
+ FSTMutation *patch = FSTTestPatchMutation("collection/key", @{@"foo" : @"new-bar"}, {});
FSTMutationResult *mutationResult =
[[FSTMutationResult alloc] initWithVersion:FSTTestVersion(4) transformResults:nil];
FSTMaybeDocument *patchedDoc = [patch applyTo:baseDoc
@@ -210,7 +211,7 @@
FSTDeletedDocument *deletedV3 = FSTTestDeletedDoc(@"collection/key", 3);
FSTMutation *setMutation = FSTTestSetMutation(@"collection/key", @{});
- FSTMutation *patchMutation = FSTTestPatchMutation(@"collection/key", @{}, nil);
+ FSTMutation *patchMutation = FSTTestPatchMutation("collection/key", {}, {});
FSTMutation *deleteMutation = FSTTestDeleteMutation(@"collection/key");
ASSERT_VERSION_TRANSITION(setMutation, docV3, docV3);
diff --git a/Firestore/Example/Tests/Model/FSTPathTests.mm b/Firestore/Example/Tests/Model/FSTPathTests.mm
deleted file mode 100644
index 388c5c3..0000000
--- a/Firestore/Example/Tests/Model/FSTPathTests.mm
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright 2017 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "Firestore/Example/Tests/Util/FSTHelpers.h"
-#import "Firestore/Source/Model/FSTPath.h"
-
-#import <XCTest/XCTest.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface FSTFieldPathTests : XCTestCase
-@end
-
-@implementation FSTFieldPathTests
-
-- (void)testConstructor {
- FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
- XCTAssertEqual(3, path.length);
-}
-
-- (void)testIndexing {
- FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
- XCTAssertEqualObjects(@"rooms", path.firstSegment);
- XCTAssertEqualObjects(@"rooms", [path segmentAtIndex:0]);
- XCTAssertEqualObjects(@"rooms", path[0]);
-
- XCTAssertEqualObjects(@"Eros", [path segmentAtIndex:1]);
- XCTAssertEqualObjects(@"Eros", path[1]);
-
- XCTAssertEqualObjects(@"messages", [path segmentAtIndex:2]);
- XCTAssertEqualObjects(@"messages", path[2]);
- XCTAssertEqualObjects(@"messages", path.lastSegment);
-}
-
-- (void)testPathByRemovingFirstSegment {
- FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
- FSTFieldPath *same = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
- FSTFieldPath *second = [FSTFieldPath pathWithSegments:@[ @"Eros", @"messages" ]];
- FSTFieldPath *third = [FSTFieldPath pathWithSegments:@[ @"messages" ]];
- FSTFieldPath *empty = [FSTFieldPath pathWithSegments:@[]];
-
- XCTAssertEqualObjects(second, path.pathByRemovingFirstSegment);
- XCTAssertEqualObjects(third, path.pathByRemovingFirstSegment.pathByRemovingFirstSegment);
- XCTAssertEqualObjects(
- empty, path.pathByRemovingFirstSegment.pathByRemovingFirstSegment.pathByRemovingFirstSegment);
- // unmodified original
- XCTAssertEqualObjects(same, path);
-}
-
-- (void)testPathByRemovingLastSegment {
- FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
- FSTFieldPath *same = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
- FSTFieldPath *second = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros" ]];
- FSTFieldPath *third = [FSTFieldPath pathWithSegments:@[ @"rooms" ]];
- FSTFieldPath *empty = [FSTFieldPath pathWithSegments:@[]];
-
- XCTAssertEqualObjects(second, path.pathByRemovingLastSegment);
- XCTAssertEqualObjects(third, path.pathByRemovingLastSegment.pathByRemovingLastSegment);
- XCTAssertEqualObjects(
- empty, path.pathByRemovingLastSegment.pathByRemovingLastSegment.pathByRemovingLastSegment);
- // unmodified original
- XCTAssertEqualObjects(same, path);
-}
-
-- (void)testPathByAppendingSegment {
- FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms" ]];
- FSTFieldPath *rooms = [FSTFieldPath pathWithSegments:@[ @"rooms" ]];
- FSTFieldPath *roomsEros = [FSTFieldPath pathWithSegments:@[ @"rooms", @"eros" ]];
- FSTFieldPath *roomsEros1 = [FSTFieldPath pathWithSegments:@[ @"rooms", @"eros", @"1" ]];
-
- XCTAssertEqualObjects(roomsEros, [path pathByAppendingSegment:@"eros"]);
- XCTAssertEqualObjects(roomsEros1,
- [[path pathByAppendingSegment:@"eros"] pathByAppendingSegment:@"1"]);
- // unmodified original
- XCTAssertEqualObjects(rooms, path);
-
- FSTFieldPath *sub = [FSTTestFieldPath(@"rooms.eros.1") pathByRemovingFirstSegment];
- FSTFieldPath *appended = [sub pathByAppendingSegment:@"2"];
- XCTAssertEqualObjects(appended, FSTTestFieldPath(@"eros.1.2"));
-}
-
-- (void)testPathComparison {
- FSTFieldPath *path1 = [FSTFieldPath pathWithSegments:@[ @"a", @"b", @"c" ]];
- FSTFieldPath *path2 = [FSTFieldPath pathWithSegments:@[ @"a", @"b", @"c" ]];
- FSTFieldPath *path3 = [FSTFieldPath pathWithSegments:@[ @"x", @"y", @"z" ]];
- XCTAssertTrue([path1 isEqual:path2]);
- XCTAssertFalse([path1 isEqual:path3]);
-
- FSTFieldPath *empty = [FSTFieldPath pathWithSegments:@[]];
- FSTFieldPath *a = [FSTFieldPath pathWithSegments:@[ @"a" ]];
- FSTFieldPath *b = [FSTFieldPath pathWithSegments:@[ @"b" ]];
- FSTFieldPath *ab = [FSTFieldPath pathWithSegments:@[ @"a", @"b" ]];
-
- XCTAssertEqual(NSOrderedAscending, [empty compare:a]);
- XCTAssertEqual(NSOrderedAscending, [a compare:b]);
- XCTAssertEqual(NSOrderedAscending, [a compare:ab]);
-
- XCTAssertEqual(NSOrderedDescending, [a compare:empty]);
- XCTAssertEqual(NSOrderedDescending, [b compare:a]);
- XCTAssertEqual(NSOrderedDescending, [ab compare:a]);
-}
-
-- (void)testIsPrefixOfPath {
- FSTFieldPath *empty = [FSTFieldPath pathWithSegments:@[]];
- FSTFieldPath *a = [FSTFieldPath pathWithSegments:@[ @"a" ]];
- FSTFieldPath *ab = [FSTFieldPath pathWithSegments:@[ @"a", @"b" ]];
- FSTFieldPath *abc = [FSTFieldPath pathWithSegments:@[ @"a", @"b", @"c" ]];
- FSTFieldPath *b = [FSTFieldPath pathWithSegments:@[ @"b" ]];
- FSTFieldPath *ba = [FSTFieldPath pathWithSegments:@[ @"b", @"a" ]];
-
- XCTAssertTrue([empty isPrefixOfPath:a]);
- XCTAssertTrue([empty isPrefixOfPath:ab]);
- XCTAssertTrue([empty isPrefixOfPath:abc]);
- XCTAssertTrue([empty isPrefixOfPath:empty]);
- XCTAssertTrue([empty isPrefixOfPath:b]);
- XCTAssertTrue([empty isPrefixOfPath:ba]);
-
- XCTAssertTrue([a isPrefixOfPath:a]);
- XCTAssertTrue([a isPrefixOfPath:ab]);
- XCTAssertTrue([a isPrefixOfPath:abc]);
- XCTAssertFalse([a isPrefixOfPath:empty]);
- XCTAssertFalse([a isPrefixOfPath:b]);
- XCTAssertFalse([a isPrefixOfPath:ba]);
-
- XCTAssertFalse([ab isPrefixOfPath:a]);
- XCTAssertTrue([ab isPrefixOfPath:ab]);
- XCTAssertTrue([ab isPrefixOfPath:abc]);
- XCTAssertFalse([ab isPrefixOfPath:empty]);
- XCTAssertFalse([ab isPrefixOfPath:b]);
- XCTAssertFalse([ab isPrefixOfPath:ba]);
-
- XCTAssertFalse([abc isPrefixOfPath:a]);
- XCTAssertFalse([abc isPrefixOfPath:ab]);
- XCTAssertTrue([abc isPrefixOfPath:abc]);
- XCTAssertFalse([abc isPrefixOfPath:empty]);
- XCTAssertFalse([abc isPrefixOfPath:b]);
- XCTAssertFalse([abc isPrefixOfPath:ba]);
-}
-
-- (void)testInvalidPaths {
- XCTAssertThrows(FSTTestFieldPath(@""));
- XCTAssertThrows(FSTTestFieldPath(@"."));
- XCTAssertThrows(FSTTestFieldPath(@".foo"));
- XCTAssertThrows(FSTTestFieldPath(@"foo."));
- XCTAssertThrows(FSTTestFieldPath(@"foo..bar"));
-}
-
-#define ASSERT_ROUND_TRIP(str, segments) \
- do { \
- FSTFieldPath *path = [FSTFieldPath pathWithServerFormat:str]; \
- XCTAssertEqual([path length], segments); \
- NSString *canonical = [path canonicalString]; \
- XCTAssertEqualObjects(canonical, str); \
- } while (0);
-
-- (void)testCanonicalString {
- ASSERT_ROUND_TRIP(@"foo", 1);
- ASSERT_ROUND_TRIP(@"foo.bar", 2);
- ASSERT_ROUND_TRIP(@"foo.bar.baz", 3);
- ASSERT_ROUND_TRIP(@"`.foo\\\\`", 1);
- ASSERT_ROUND_TRIP(@"`.foo\\\\`.`.foo`", 2);
- ASSERT_ROUND_TRIP(@"foo.`\\``.bar", 3);
-
- FSTFieldPath *path = [FSTFieldPath pathWithServerFormat:@"foo\\.bar"];
- XCTAssertEqualObjects([path canonicalString], @"`foo.bar`");
- XCTAssertEqual(path.length, 1);
-}
-
-#undef ASSERT_ROUND_TRIP
-
-- (void)testCanonicalStringOfSubstring {
- FSTFieldPath *path = [FSTFieldPath pathWithServerFormat:@"foo.bar.baz"];
- XCTAssertEqualObjects([path canonicalString], @"foo.bar.baz");
-
- FSTFieldPath *pathTail = [path pathByRemovingFirstSegment];
- XCTAssertEqualObjects([pathTail canonicalString], @"bar.baz");
-
- FSTFieldPath *pathHead = [path pathByRemovingLastSegment];
- XCTAssertEqualObjects([pathHead canonicalString], @"foo.bar");
-
- XCTAssertEqualObjects([[pathTail pathByRemovingLastSegment] canonicalString], @"bar");
- XCTAssertEqualObjects([[pathHead pathByRemovingFirstSegment] canonicalString], @"bar");
-}
-
-- (void)testRoundTrip {
- FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
- XCTAssertEqualObjects(path, [FSTFieldPath fieldPathWithCPPFieldPath:[path toCPPFieldPath]]);
-
- const firebase::firestore::model::FieldPath cppPath{"rooms", "Eros", "messages"};
- XCTAssertEqual(cppPath, [[FSTFieldPath fieldPathWithCPPFieldPath:cppPath] toCPPFieldPath]);
-}
-
-@end
-
-@interface FSTResourcePathTests : XCTestCase
-@end
-
-@implementation FSTResourcePathTests
-
-- (void)testRoundTrip {
- FSTResourcePath *path = [FSTResourcePath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
- XCTAssertEqualObjects(path,
- [FSTResourcePath resourcePathWithCPPResourcePath:[path toCPPResourcePath]]);
-
- const firebase::firestore::model::ResourcePath cppPath{"rooms", "Eros", "messages"};
- XCTAssertEqual(cppPath,
- [[FSTResourcePath resourcePathWithCPPResourcePath:cppPath] toCPPResourcePath]);
-}
-
-@end
-NS_ASSUME_NONNULL_END
diff --git a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
index 5cd816f..4c3682f 100644
--- a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
+++ b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
@@ -40,7 +40,6 @@
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTWatchChange.h"
#import "Firestore/Example/Tests/API/FSTAPIHelpers.h"
@@ -338,11 +337,11 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testEncodesPatchMutation {
FSTPatchMutation *mutation =
- FSTTestPatchMutation(@"docs/1",
+ FSTTestPatchMutation("docs/1",
@{ @"a" : @"b",
@"num" : @1,
@"some.de\\\\ep.th\\ing'" : @2 },
- nil);
+ {});
GCFSWrite *proto = [GCFSWrite message];
proto.update = [self.serializer encodedDocumentWithFields:mutation.value key:mutation.key];
proto.updateMask = [self.serializer encodedFieldMask:mutation.fieldMask];
@@ -406,7 +405,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesListenRequestLabels {
- FSTQuery *query = FSTTestQuery(@"collection/key");
+ FSTQuery *query = FSTTestQuery("collection/key");
FSTQueryData *queryData = [[FSTQueryData alloc] initWithQuery:query
targetID:2
listenSequenceNumber:3
@@ -432,7 +431,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesRelationFilter {
- FSTRelationFilter *input = FSTTestFilter(@"item.part.top", @"==", @"food");
+ FSTRelationFilter *input = FSTTestFilter("item.part.top", @"==", @"food");
GCFSStructuredQuery_Filter *actual = [self.serializer encodedRelationFilter:input];
GCFSStructuredQuery_Filter *expected = [GCFSStructuredQuery_Filter message];
@@ -446,7 +445,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - encodedQuery
- (void)testEncodesFirstLevelKeyQueries {
- FSTQuery *q = FSTTestQuery(@"docs/1");
+ FSTQuery *q = FSTTestQuery("docs/1");
FSTQueryData *model = [self queryDataForQuery:q];
GCFSTarget *expected = [GCFSTarget message];
@@ -457,7 +456,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesFirstLevelAncestorQueries {
- FSTQuery *q = FSTTestQuery(@"messages");
+ FSTQuery *q = FSTTestQuery("messages");
FSTQueryData *model = [self queryDataForQuery:q];
GCFSTarget *expected = [GCFSTarget message];
@@ -473,7 +472,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesNestedAncestorQueries {
- FSTQuery *q = FSTTestQuery(@"rooms/1/messages/10/attachments");
+ FSTQuery *q = FSTTestQuery("rooms/1/messages/10/attachments");
FSTQueryData *model = [self queryDataForQuery:q];
GCFSTarget *expected = [GCFSTarget message];
@@ -489,7 +488,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesSingleFiltersAtFirstLevelCollections {
- FSTQuery *q = [FSTTestQuery(@"docs") queryByAddingFilter:FSTTestFilter(@"prop", @"<", @(42))];
+ FSTQuery *q = [FSTTestQuery("docs") queryByAddingFilter:FSTTestFilter("prop", @"<", @(42))];
FSTQueryData *model = [self queryDataForQuery:q];
GCFSTarget *expected = [GCFSTarget message];
@@ -512,9 +511,9 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesMultipleFiltersOnDeeperCollections {
- FSTQuery *q = [[FSTTestQuery(@"rooms/1/messages/10/attachments")
- queryByAddingFilter:FSTTestFilter(@"prop", @">=", @(42))]
- queryByAddingFilter:FSTTestFilter(@"author", @"==", @"dimond")];
+ FSTQuery *q = [[FSTTestQuery("rooms/1/messages/10/attachments")
+ queryByAddingFilter:FSTTestFilter("prop", @">=", @(42))]
+ queryByAddingFilter:FSTTestFilter("author", @"==", @"dimond")];
FSTQueryData *model = [self queryDataForQuery:q];
GCFSTarget *expected = [GCFSTarget message];
@@ -562,7 +561,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)unaryFilterTestWithValue:(id)value
expectedUnaryOperator:(GCFSStructuredQuery_UnaryFilter_Operator)op {
- FSTQuery *q = [FSTTestQuery(@"docs") queryByAddingFilter:FSTTestFilter(@"prop", @"==", value)];
+ FSTQuery *q = [FSTTestQuery("docs") queryByAddingFilter:FSTTestFilter("prop", @"==", value)];
FSTQueryData *model = [self queryDataForQuery:q];
GCFSTarget *expected = [GCFSTarget message];
@@ -582,7 +581,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesSortOrders {
- FSTQuery *q = [FSTTestQuery(@"docs")
+ FSTQuery *q = [FSTTestQuery("docs")
queryByAddingSortOrder:[FSTSortOrder sortOrderWithFieldPath:testutil::Field("prop")
ascending:YES]];
FSTQueryData *model = [self queryDataForQuery:q];
@@ -602,7 +601,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesSortOrdersDescending {
- FSTQuery *q = [FSTTestQuery(@"rooms/1/messages/10/attachments")
+ FSTQuery *q = [FSTTestQuery("rooms/1/messages/10/attachments")
queryByAddingSortOrder:[FSTSortOrder sortOrderWithFieldPath:testutil::Field("prop")
ascending:NO]];
FSTQueryData *model = [self queryDataForQuery:q];
@@ -622,7 +621,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesLimits {
- FSTQuery *q = [FSTTestQuery(@"docs") queryBySettingLimit:26];
+ FSTQuery *q = [FSTTestQuery("docs") queryBySettingLimit:26];
FSTQueryData *model = [self queryDataForQuery:q];
GCFSTarget *expected = [GCFSTarget message];
@@ -639,7 +638,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesResumeTokens {
- FSTQuery *q = FSTTestQuery(@"docs");
+ FSTQuery *q = FSTTestQuery("docs");
FSTQueryData *model = [[FSTQueryData alloc] initWithQuery:q
targetID:1
listenSequenceNumber:0
diff --git a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm
index b00ea07..0f57b81 100644
--- a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm
+++ b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm
@@ -16,6 +16,8 @@
#import "Firestore/Example/Tests/SpecTests/FSTSpecTests.h"
+#include <utility>
+
#import <FirebaseFirestore/FIRFirestoreErrors.h>
#import <GRPCClient/GRPCCall.h>
@@ -30,7 +32,6 @@
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Source/Model/FSTMutation.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTExistenceFilter.h"
#import "Firestore/Source/Remote/FSTWatchChange.h"
#import "Firestore/Source/Util/FSTAssert.h"
@@ -108,11 +109,11 @@ static NSString *const kNoIOSTag = @"no-ios";
- (nullable FSTQuery *)parseQuery:(id)querySpec {
if ([querySpec isKindOfClass:[NSString class]]) {
- return FSTTestQuery(querySpec);
+ return FSTTestQuery(util::MakeStringView((NSString *)querySpec));
} else if ([querySpec isKindOfClass:[NSDictionary class]]) {
NSDictionary *queryDict = (NSDictionary *)querySpec;
NSString *path = queryDict[@"path"];
- __block FSTQuery *query = FSTTestQuery(path);
+ __block FSTQuery *query = FSTTestQuery(util::MakeStringView(path));
if (queryDict[@"limit"]) {
NSNumber *limit = queryDict[@"limit"];
query = [query queryBySettingLimit:limit.integerValue];
@@ -121,14 +122,16 @@ static NSString *const kNoIOSTag = @"no-ios";
NSArray *filters = queryDict[@"filters"];
[filters enumerateObjectsUsingBlock:^(NSArray *_Nonnull filter, NSUInteger idx,
BOOL *_Nonnull stop) {
- query = [query queryByAddingFilter:FSTTestFilter(filter[0], filter[1], filter[2])];
+ query = [query queryByAddingFilter:FSTTestFilter(util::MakeStringView(filter[0]), filter[1],
+ filter[2])];
}];
}
if (queryDict[@"orderBys"]) {
NSArray *orderBys = queryDict[@"orderBys"];
[orderBys enumerateObjectsUsingBlock:^(NSArray *_Nonnull orderBy, NSUInteger idx,
BOOL *_Nonnull stop) {
- query = [query queryByAddingSortOrder:FSTTestOrderBy(orderBy[0], orderBy[1])];
+ query = [query
+ queryByAddingSortOrder:FSTTestOrderBy(util::MakeStringView(orderBy[0]), orderBy[1])];
}];
}
return query;
@@ -174,7 +177,8 @@ static NSString *const kNoIOSTag = @"no-ios";
}
- (void)doPatch:(NSArray *)patchSpec {
- [self.driver writeUserMutation:FSTTestPatchMutation(patchSpec[0], patchSpec[1], nil)];
+ [self.driver
+ writeUserMutation:FSTTestPatchMutation(util::MakeStringView(patchSpec[0]), patchSpec[1], {})];
}
- (void)doDelete:(NSString *)key {
diff --git a/Firestore/Example/Tests/Util/FSTHelpers.h b/Firestore/Example/Tests/Util/FSTHelpers.h
index cc9f2ec..d86201b 100644
--- a/Firestore/Example/Tests/Util/FSTHelpers.h
+++ b/Firestore/Example/Tests/Util/FSTHelpers.h
@@ -16,10 +16,16 @@
#import <Foundation/Foundation.h>
+#include <map>
+#include <vector>
+
#import "Firestore/Source/Core/FSTTypes.h"
#import "Firestore/Source/Model/FSTDocumentDictionary.h"
#import "Firestore/Source/Model/FSTDocumentKeySet.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/field_value.h"
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
#include "absl/strings/string_view.h"
@class FIRGeoPoint;
@@ -28,13 +34,11 @@
@class FSTDocument;
@class FSTDocumentKeyReference;
@class FSTDocumentSet;
-@class FSTFieldPath;
@class FSTFieldValue;
@class FSTLocalViewChanges;
@class FSTPatchMutation;
@class FSTQuery;
@class FSTRemoteEvent;
-@class FSTResourcePath;
@class FSTSetMutation;
@class FSTSnapshotVersion;
@class FSTSortOrder;
@@ -121,18 +125,30 @@ extern "C" {
} \
} while (0)
+static NSString *kExceptionPrefix = @"FIRESTORE INTERNAL ASSERTION FAILED: ";
+
+// Remove possible exception-prefix.
+inline NSString *FSTRemoveExceptionPrefix(NSString *exception) {
+ if ([exception hasPrefix:kExceptionPrefix]) {
+ return [exception substringFromIndex:kExceptionPrefix.length];
+ } else {
+ return exception;
+ }
+}
+
// Helper for validating API exceptions.
-#define FSTAssertThrows(expression, exceptionReason, ...) \
- ({ \
- BOOL __didThrow = NO; \
- @try { \
- (void)(expression); \
- } @catch (NSException * exception) { \
- __didThrow = YES; \
- XCTAssertEqualObjects(exception.reason, exceptionReason); \
- } \
- XCTAssertTrue(__didThrow, ##__VA_ARGS__); \
- })
+#define FSTAssertThrows(expression, exceptionReason, ...) \
+ do { \
+ BOOL didThrow = NO; \
+ @try { \
+ (void)(expression); \
+ } @catch (NSException * exception) { \
+ didThrow = YES; \
+ XCTAssertEqualObjects(FSTRemoveExceptionPrefix(exception.reason), \
+ FSTRemoveExceptionPrefix(exceptionReason)); \
+ } \
+ XCTAssertTrue(didThrow, ##__VA_ARGS__); \
+ } while (0)
/** Creates a new FIRTimestamp from components. Note that year, month, and day are all one-based. */
FIRTimestamp *FSTTestTimestamp(int year, int month, int day, int hour, int minute, int second);
@@ -157,8 +173,6 @@ FIRGeoPoint *FSTTestGeoPoint(double latitude, double longitude);
NSDateComponents *FSTTestDateComponents(
int year, int month, int day, int hour, int minute, int second);
-FSTFieldPath *FSTTestFieldPath(NSString *field);
-
/** Wraps a plain value into an FSTFieldValue instance. */
FSTFieldValue *FSTTestFieldValue(id _Nullable value);
@@ -186,9 +200,6 @@ FSTDocument *FSTTestDoc(NSString *path,
/** A convenience method for creating deleted docs for tests. */
FSTDeletedDocument *FSTTestDeletedDoc(NSString *path, FSTTestSnapshotVersion version);
-/** A convenience method for creating resource paths from a path string. */
-FSTResourcePath *FSTTestPath(NSString *path);
-
/**
* A convenience method for creating a document reference from a path string.
*/
@@ -197,22 +208,22 @@ FSTDocumentKeyReference *FSTTestRef(const absl::string_view projectID,
NSString *path);
/** A convenience method for creating a query for the given path (without any other filters). */
-FSTQuery *FSTTestQuery(NSString *path);
+FSTQuery *FSTTestQuery(const absl::string_view path);
/**
* A convenience method to create a FSTFilter using a string representation for both field
* and operator (<, <=, ==, >=, >).
*/
-id<FSTFilter> FSTTestFilter(NSString *field, NSString *op, id value);
+id<FSTFilter> FSTTestFilter(const absl::string_view field, NSString *op, id value);
/** A convenience method for creating sort orders. */
-FSTSortOrder *FSTTestOrderBy(NSString *field, NSString *direction);
+FSTSortOrder *FSTTestOrderBy(const absl::string_view field, NSString *direction);
/**
* Creates an NSComparator that will compare FSTDocuments by the given fieldPath string then by
* key.
*/
-NSComparator FSTTestDocComparator(NSString *fieldPath);
+NSComparator FSTTestDocComparator(const absl::string_view fieldPath);
/**
* Creates a FSTDocumentSet based on the given comparator, initially containing the given
@@ -229,9 +240,10 @@ FSTViewSnapshot *_Nullable FSTTestApplyChanges(FSTView *view,
FSTSetMutation *FSTTestSetMutation(NSString *path, NSDictionary<NSString *, id> *values);
/** Creates a patch mutation for the document key at the given path. */
-FSTPatchMutation *FSTTestPatchMutation(NSString *path,
- NSDictionary<NSString *, id> *values,
- NSArray<FSTFieldPath *> *_Nullable updateMask);
+FSTPatchMutation *FSTTestPatchMutation(
+ const absl::string_view path,
+ NSDictionary<NSString *, id> *values,
+ const std::vector<firebase::firestore::model::FieldPath> &updateMask);
FSTTransformMutation *FSTTestTransformMutation(NSString *path,
NSArray<NSString *> *serverTimestampFields);
diff --git a/Firestore/Example/Tests/Util/FSTHelpers.mm b/Firestore/Example/Tests/Util/FSTHelpers.mm
index 00464bc..be02002 100644
--- a/Firestore/Example/Tests/Util/FSTHelpers.mm
+++ b/Firestore/Example/Tests/Util/FSTHelpers.mm
@@ -18,6 +18,8 @@
#include <inttypes.h>
#include <list>
+#include <map>
+#include <vector>
#import <FirebaseFirestore/FIRFieldPath.h>
#import <FirebaseFirestore/FIRGeoPoint.h>
@@ -36,18 +38,22 @@
#import "Firestore/Source/Model/FSTDocumentSet.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Source/Model/FSTMutation.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTRemoteEvent.h"
#import "Firestore/Source/Remote/FSTWatchChange.h"
#import "Firestore/Source/Util/FSTAssert.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
+#include "Firestore/core/src/firebase/firestore/model/field_value.h"
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
namespace util = firebase::firestore::util;
namespace testutil = firebase::firestore::testutil;
using firebase::firestore::model::DatabaseId;
+using firebase::firestore::model::FieldPath;
+using firebase::firestore::model::FieldValue;
+using firebase::firestore::model::ResourcePath;
NS_ASSUME_NONNULL_BEGIN
@@ -103,10 +109,6 @@ NSDateComponents *FSTTestDateComponents(
return comps;
}
-FSTFieldPath *FSTTestFieldPath(NSString *field) {
- return [FIRFieldPath pathWithDotSeparatedString:field].internalValue;
-}
-
FSTFieldValue *FSTTestFieldValue(id _Nullable value) {
// This owns the DatabaseIds since we do not have FirestoreClient instance to own them.
static DatabaseId database_id{"project", DatabaseId::kDefault};
@@ -162,18 +164,6 @@ FSTDeletedDocument *FSTTestDeletedDoc(NSString *path, FSTTestSnapshotVersion ver
return [FSTDeletedDocument documentWithKey:key version:FSTTestVersion(version)];
}
-static NSArray<NSString *> *FSTTestSplitPath(NSString *path) {
- if ([path isEqualToString:@""]) {
- return @[];
- } else {
- return [path componentsSeparatedByString:@"/"];
- }
-}
-
-FSTResourcePath *FSTTestPath(NSString *path) {
- return [FSTResourcePath pathWithSegments:FSTTestSplitPath(path)];
-}
-
FSTDocumentKeyReference *FSTTestRef(const absl::string_view projectID,
const absl::string_view database,
NSString *path) {
@@ -184,12 +174,12 @@ FSTDocumentKeyReference *FSTTestRef(const absl::string_view projectID,
databaseID:&database_ids.back()];
}
-FSTQuery *FSTTestQuery(NSString *path) {
- return [FSTQuery queryWithPath:[FSTTestPath(path) toCPPResourcePath]];
+FSTQuery *FSTTestQuery(const absl::string_view path) {
+ return [FSTQuery queryWithPath:testutil::Resource(path)];
}
-id<FSTFilter> FSTTestFilter(NSString *field, NSString *opString, id value) {
- FSTFieldPath *path = FSTTestFieldPath(field);
+id<FSTFilter> FSTTestFilter(const absl::string_view field, NSString *opString, id value) {
+ const FieldPath path = testutil::Field(field);
FSTRelationFilterOperator op;
if ([opString isEqualToString:@"<"]) {
op = FSTRelationFilterOperatorLessThan;
@@ -208,17 +198,17 @@ id<FSTFilter> FSTTestFilter(NSString *field, NSString *opString, id value) {
FSTFieldValue *data = FSTTestFieldValue(value);
if ([data isEqual:[FSTDoubleValue nanValue]]) {
FSTCAssert(op == FSTRelationFilterOperatorEqual, @"Must use == with NAN.");
- return [[FSTNanFilter alloc] initWithField:[path toCPPFieldPath]];
+ return [[FSTNanFilter alloc] initWithField:path];
} else if ([data isEqual:[FSTNullValue nullValue]]) {
FSTCAssert(op == FSTRelationFilterOperatorEqual, @"Must use == with Null.");
- return [[FSTNullFilter alloc] initWithField:[path toCPPFieldPath]];
+ return [[FSTNullFilter alloc] initWithField:path];
} else {
- return [FSTRelationFilter filterWithField:[path toCPPFieldPath] filterOperator:op value:data];
+ return [FSTRelationFilter filterWithField:path filterOperator:op value:data];
}
}
-FSTSortOrder *FSTTestOrderBy(NSString *field, NSString *direction) {
- FSTFieldPath *path = FSTTestFieldPath(field);
+FSTSortOrder *FSTTestOrderBy(const absl::string_view field, NSString *direction) {
+ const FieldPath path = testutil::Field(field);
BOOL ascending;
if ([direction isEqualToString:@"asc"]) {
ascending = YES;
@@ -227,14 +217,13 @@ FSTSortOrder *FSTTestOrderBy(NSString *field, NSString *direction) {
} else {
FSTCFail(@"Unsupported direction: %@", direction);
}
- return [FSTSortOrder sortOrderWithFieldPath:[path toCPPFieldPath] ascending:ascending];
+ return [FSTSortOrder sortOrderWithFieldPath:path ascending:ascending];
}
-NSComparator FSTTestDocComparator(NSString *fieldPath) {
- FSTQuery *query = [FSTTestQuery(@"docs")
- queryByAddingSortOrder:[FSTSortOrder
- sortOrderWithFieldPath:[FSTTestFieldPath(fieldPath) toCPPFieldPath]
- ascending:YES]];
+NSComparator FSTTestDocComparator(const absl::string_view fieldPath) {
+ FSTQuery *query = [FSTTestQuery("docs")
+ queryByAddingSortOrder:[FSTSortOrder sortOrderWithFieldPath:testutil::Field(fieldPath)
+ ascending:YES]];
return [query comparator];
}
@@ -252,23 +241,23 @@ FSTSetMutation *FSTTestSetMutation(NSString *path, NSDictionary<NSString *, id>
precondition:[FSTPrecondition none]];
}
-FSTPatchMutation *FSTTestPatchMutation(NSString *path,
+FSTPatchMutation *FSTTestPatchMutation(const absl::string_view path,
NSDictionary<NSString *, id> *values,
- NSArray<FSTFieldPath *> *_Nullable updateMask) {
- BOOL merge = updateMask != nil;
+ const std::vector<FieldPath> &updateMask) {
+ BOOL merge = !updateMask.empty();
__block FSTObjectValue *objectValue = [FSTObjectValue objectValue];
- NSMutableArray<FSTFieldPath *> *fieldMaskPaths = [NSMutableArray array];
+ __block std::vector<FieldPath> fieldMaskPaths{};
[values enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
- FSTFieldPath *path = FSTTestFieldPath(key);
- [fieldMaskPaths addObject:path];
+ const FieldPath path = testutil::Field(util::MakeStringView(key));
+ fieldMaskPaths.push_back(path);
if (![value isEqual:kDeleteSentinel]) {
FSTFieldValue *parsedValue = FSTTestFieldValue(value);
objectValue = [objectValue objectBySettingValue:parsedValue forPath:path];
}
}];
- FSTDocumentKey *key = [FSTDocumentKey keyWithPath:testutil::Resource([path UTF8String])];
+ FSTDocumentKey *key = [FSTDocumentKey keyWithPath:testutil::Resource(path)];
FSTFieldMask *mask = [[FSTFieldMask alloc] initWithFields:merge ? updateMask : fieldMaskPaths];
return [[FSTPatchMutation alloc] initWithKey:key
fieldMask:mask
@@ -279,10 +268,10 @@ FSTPatchMutation *FSTTestPatchMutation(NSString *path,
// For now this only creates TransformMutations with server timestamps.
FSTTransformMutation *FSTTestTransformMutation(NSString *path,
NSArray<NSString *> *serverTimestampFields) {
- FSTDocumentKey *key = [FSTDocumentKey keyWithPath:testutil::Resource([path UTF8String])];
+ FSTDocumentKey *key = [FSTDocumentKey keyWithPath:testutil::Resource(util::MakeStringView(path))];
NSMutableArray<FSTFieldTransform *> *fieldTransforms = [NSMutableArray array];
for (NSString *field in serverTimestampFields) {
- FSTFieldPath *fieldPath = FSTTestFieldPath(field);
+ const FieldPath fieldPath = testutil::Field(util::MakeStringView(field));
id<FSTTransformOperation> transformOp = [FSTServerTimestampTransform serverTimestampTransform];
FSTFieldTransform *transform =
[[FSTFieldTransform alloc] initWithPath:fieldPath transform:transformOp];
diff --git a/Firestore/Source/API/FIRCollectionReference+Internal.h b/Firestore/Source/API/FIRCollectionReference+Internal.h
index 1d00cbb..9d36ede 100644
--- a/Firestore/Source/API/FIRCollectionReference+Internal.h
+++ b/Firestore/Source/API/FIRCollectionReference+Internal.h
@@ -16,13 +16,14 @@
#import "FIRCollectionReference.h"
-NS_ASSUME_NONNULL_BEGIN
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
-@class FSTResourcePath;
+NS_ASSUME_NONNULL_BEGIN
/** Internal FIRCollectionReference API we don't want exposed in our public header files. */
@interface FIRCollectionReference (Internal)
-+ (instancetype)referenceWithPath:(FSTResourcePath *)path firestore:(FIRFirestore *)firestore;
++ (instancetype)referenceWithPath:(const firebase::firestore::model::ResourcePath &)path
+ firestore:(FIRFirestore *)firestore;
@end
NS_ASSUME_NONNULL_END
diff --git a/Firestore/Source/API/FIRCollectionReference.mm b/Firestore/Source/API/FIRCollectionReference.mm
index 9560d13..dfd06c9 100644
--- a/Firestore/Source/API/FIRCollectionReference.mm
+++ b/Firestore/Source/API/FIRCollectionReference.mm
@@ -24,7 +24,6 @@
#import "Firestore/Source/API/FIRQuery_Init.h"
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTUsageValidation.h"
@@ -38,7 +37,7 @@ using firebase::firestore::util::CreateAutoId;
NS_ASSUME_NONNULL_BEGIN
@interface FIRCollectionReference ()
-- (instancetype)initWithPath:(FSTResourcePath *)path
+- (instancetype)initWithPath:(const ResourcePath &)path
firestore:(FIRFirestore *)firestore NS_DESIGNATED_INITIALIZER;
// Mark the super class designated initializer unavailable.
@@ -48,22 +47,21 @@ NS_ASSUME_NONNULL_BEGIN
@end
@implementation FIRCollectionReference (Internal)
-+ (instancetype)referenceWithPath:(FSTResourcePath *)path firestore:(FIRFirestore *)firestore {
++ (instancetype)referenceWithPath:(const ResourcePath &)path firestore:(FIRFirestore *)firestore {
return [[FIRCollectionReference alloc] initWithPath:path firestore:firestore];
}
@end
@implementation FIRCollectionReference
-- (instancetype)initWithPath:(FSTResourcePath *)path firestore:(FIRFirestore *)firestore {
- if (path.length % 2 != 1) {
+- (instancetype)initWithPath:(const ResourcePath &)path firestore:(FIRFirestore *)firestore {
+ if (path.size() % 2 != 1) {
FSTThrowInvalidArgument(
@"Invalid collection reference. Collection references must have an odd "
- "number of segments, but %@ has %d",
- path.canonicalString, path.length);
+ "number of segments, but %s has %zu",
+ path.CanonicalString().c_str(), path.size());
}
- self =
- [super initWithQuery:[FSTQuery queryWithPath:[path toCPPResourcePath]] firestore:firestore];
+ self = [super initWithQuery:[FSTQuery queryWithPath:path] firestore:firestore];
return self;
}
@@ -116,9 +114,7 @@ NS_ASSUME_NONNULL_BEGIN
}
const ResourcePath subPath = ResourcePath::FromString(util::MakeStringView(documentPath));
const ResourcePath path = self.query.path.Append(subPath);
- return
- [FIRDocumentReference referenceWithPath:[FSTResourcePath resourcePathWithCPPResourcePath:path]
- firestore:self.firestore];
+ return [FIRDocumentReference referenceWithPath:path firestore:self.firestore];
}
- (FIRDocumentReference *)addDocumentWithData:(NSDictionary<NSString *, id> *)data {
diff --git a/Firestore/Source/API/FIRDocumentReference+Internal.h b/Firestore/Source/API/FIRDocumentReference+Internal.h
index 5e12ddc..706e8db 100644
--- a/Firestore/Source/API/FIRDocumentReference+Internal.h
+++ b/Firestore/Source/API/FIRDocumentReference+Internal.h
@@ -16,15 +16,17 @@
#import "FIRDocumentReference.h"
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
+
NS_ASSUME_NONNULL_BEGIN
@class FSTDocumentKey;
-@class FSTResourcePath;
/** Internal FIRDocumentReference API we don't want exposed in our public header files. */
@interface FIRDocumentReference (Internal)
-+ (instancetype)referenceWithPath:(FSTResourcePath *)path firestore:(FIRFirestore *)firestore;
++ (instancetype)referenceWithPath:(const firebase::firestore::model::ResourcePath &)path
+ firestore:(FIRFirestore *)firestore;
+ (instancetype)referenceWithKey:(FSTDocumentKey *)key firestore:(FIRFirestore *)firestore;
@property(nonatomic, strong, readonly) FSTDocumentKey *key;
diff --git a/Firestore/Source/API/FIRDocumentReference.mm b/Firestore/Source/API/FIRDocumentReference.mm
index cc14af5..5968fb2 100644
--- a/Firestore/Source/API/FIRDocumentReference.mm
+++ b/Firestore/Source/API/FIRDocumentReference.mm
@@ -34,7 +34,6 @@
#import "Firestore/Source/Model/FSTDocumentSet.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Source/Model/FSTMutation.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTAsyncQueryListener.h"
#import "Firestore/Source/Util/FSTUsageValidation.h"
@@ -91,16 +90,15 @@ NS_ASSUME_NONNULL_BEGIN
@implementation FIRDocumentReference (Internal)
-+ (instancetype)referenceWithPath:(FSTResourcePath *)path firestore:(FIRFirestore *)firestore {
- if (path.length % 2 != 0) {
++ (instancetype)referenceWithPath:(const ResourcePath &)path firestore:(FIRFirestore *)firestore {
+ if (path.size() % 2 != 0) {
FSTThrowInvalidArgument(
@"Invalid document reference. Document references must have an even "
- "number of segments, but %@ has %d",
- path.canonicalString, path.length);
+ "number of segments, but %s has %zu",
+ path.CanonicalString().c_str(), path.size());
}
return
- [FIRDocumentReference referenceWithKey:[FSTDocumentKey keyWithPath:[path toCPPResourcePath]]
- firestore:firestore];
+ [FIRDocumentReference referenceWithKey:[FSTDocumentKey keyWithPath:path] firestore:firestore];
}
+ (instancetype)referenceWithKey:(FSTDocumentKey *)key firestore:(FIRFirestore *)firestore {
@@ -147,9 +145,8 @@ NS_ASSUME_NONNULL_BEGIN
}
- (FIRCollectionReference *)parent {
- return [FIRCollectionReference
- referenceWithPath:[FSTResourcePath resourcePathWithCPPResourcePath:self.key.path.PopLast()]
- firestore:self.firestore];
+ return
+ [FIRCollectionReference referenceWithPath:self.key.path.PopLast() firestore:self.firestore];
}
- (NSString *)path {
@@ -160,9 +157,8 @@ NS_ASSUME_NONNULL_BEGIN
if (!collectionPath) {
FSTThrowInvalidArgument(@"Collection path cannot be nil.");
}
- FSTResourcePath *subPath = [FSTResourcePath pathWithString:collectionPath];
- FSTResourcePath *path = [FSTResourcePath
- resourcePathWithCPPResourcePath:self.key.path.Append([subPath toCPPResourcePath])];
+ const ResourcePath subPath = ResourcePath::FromString(util::MakeStringView(collectionPath));
+ const ResourcePath path = self.key.path.Append(subPath);
return [FIRCollectionReference referenceWithPath:path firestore:self.firestore];
}
diff --git a/Firestore/Source/API/FIRDocumentSnapshot.mm b/Firestore/Source/API/FIRDocumentSnapshot.mm
index 8e731da..4d82986 100644
--- a/Firestore/Source/API/FIRDocumentSnapshot.mm
+++ b/Firestore/Source/API/FIRDocumentSnapshot.mm
@@ -24,7 +24,6 @@
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTUsageValidation.h"
@@ -184,12 +183,11 @@ NS_ASSUME_NONNULL_BEGIN
// TODO(b/32073923): Log this as a proper warning.
NSLog(
@"WARNING: Document %@ contains a document reference within a different database "
- "(%@/%@) which is not supported. It will be treated as a reference within the "
- "current database (%@/%@) instead.",
- self.reference.path, util::WrapNSStringNoCopy(refDatabase->project_id()),
- util::WrapNSStringNoCopy(refDatabase->database_id()),
- util::WrapNSStringNoCopy(database->project_id()),
- util::WrapNSStringNoCopy(database->database_id()));
+ "(%s/%s) which is not supported. It will be treated as a reference within the "
+ "current database (%s/%s) instead.",
+ self.reference.path, refDatabase->project_id().c_str(),
+ refDatabase->database_id().c_str(), database->project_id().c_str(),
+ database->database_id().c_str());
}
return [FIRDocumentReference referenceWithKey:[ref valueWithOptions:options]
firestore:self.firestore];
diff --git a/Firestore/Source/API/FIRFieldPath+Internal.h b/Firestore/Source/API/FIRFieldPath+Internal.h
index 227cdad..6fb6add 100644
--- a/Firestore/Source/API/FIRFieldPath+Internal.h
+++ b/Firestore/Source/API/FIRFieldPath+Internal.h
@@ -16,16 +16,16 @@
#import "FIRFieldPath.h"
-@class FSTFieldPath;
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
NS_ASSUME_NONNULL_BEGIN
@interface FIRFieldPath ()
-- (instancetype)initPrivate:(FSTFieldPath *)path NS_DESIGNATED_INITIALIZER;
-
/** Internal field path representation */
-@property(nonatomic, strong, readonly) FSTFieldPath *internalValue;
+- (const firebase::firestore::model::FieldPath &)internalValue;
+
+- (instancetype)initPrivate:(firebase::firestore::model::FieldPath)path NS_DESIGNATED_INITIALIZER;
@end
diff --git a/Firestore/Source/API/FIRFieldPath.mm b/Firestore/Source/API/FIRFieldPath.mm
index f4e532f..c651160 100644
--- a/Firestore/Source/API/FIRFieldPath.mm
+++ b/Firestore/Source/API/FIRFieldPath.mm
@@ -16,11 +16,28 @@
#import "Firestore/Source/API/FIRFieldPath+Internal.h"
-#import "Firestore/Source/Model/FSTPath.h"
+#include <functional>
+#include <string>
+#include <utility>
+#include <vector>
+
#import "Firestore/Source/Util/FSTUsageValidation.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+
+namespace util = firebase::firestore::util;
+using firebase::firestore::model::FieldPath;
+
NS_ASSUME_NONNULL_BEGIN
+@interface FIRFieldPath () {
+ /** Internal field path representation */
+ firebase::firestore::model::FieldPath _internalValue;
+}
+
+@end
+
@implementation FIRFieldPath
- (instancetype)initWithFields:(NSArray<NSString *> *)fieldNames {
@@ -28,22 +45,25 @@ NS_ASSUME_NONNULL_BEGIN
FSTThrowInvalidArgument(@"Invalid field path. Provided names must not be empty.");
}
+ std::vector<std::string> field_names{};
+ field_names.reserve(fieldNames.count);
for (int i = 0; i < fieldNames.count; ++i) {
if (fieldNames[i].length == 0) {
FSTThrowInvalidArgument(@"Invalid field name at index %d. Field names must not be empty.", i);
}
+ field_names.emplace_back(util::MakeString(fieldNames[i]));
}
- return [self initPrivate:[FSTFieldPath pathWithSegments:fieldNames]];
+ return [self initPrivate:FieldPath(std::move(field_names))];
}
+ (instancetype)documentID {
- return [[FIRFieldPath alloc] initPrivate:FSTFieldPath.keyFieldPath];
+ return [[FIRFieldPath alloc] initPrivate:FieldPath::KeyFieldPath()];
}
-- (instancetype)initPrivate:(FSTFieldPath *)fieldPath {
+- (instancetype)initPrivate:(FieldPath)fieldPath {
if (self = [super init]) {
- _internalValue = fieldPath;
+ _internalValue = std::move(fieldPath);
}
return self;
}
@@ -77,7 +97,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (id)copyWithZone:(NSZone *__nullable)zone {
- return [[[self class] alloc] initPrivate:self.internalValue];
+ return [[[self class] alloc] initPrivate:_internalValue];
}
- (BOOL)isEqual:(nullable id)object {
@@ -89,11 +109,15 @@ NS_ASSUME_NONNULL_BEGIN
return NO;
}
- return [self.internalValue isEqual:((FIRFieldPath *)object).internalValue];
+ return _internalValue == ((FIRFieldPath *)object)->_internalValue;
}
- (NSUInteger)hash {
- return [self.internalValue hash];
+ return _internalValue.Hash();
+}
+
+- (const firebase::firestore::model::FieldPath &)internalValue {
+ return _internalValue;
}
@end
diff --git a/Firestore/Source/API/FIRFirestore.mm b/Firestore/Source/API/FIRFirestore.mm
index eff0605..f3769ed 100644
--- a/Firestore/Source/API/FIRFirestore.mm
+++ b/Firestore/Source/API/FIRFirestore.mm
@@ -34,7 +34,6 @@
#import "Firestore/Source/Core/FSTFirestoreClient.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTDispatchQueue.h"
#import "Firestore/Source/Util/FSTLogger.h"
@@ -44,6 +43,7 @@
#include "Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h"
#include "Firestore/core/src/firebase/firestore/core/database_info.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
#include "absl/memory/memory.h"
@@ -52,6 +52,7 @@ using firebase::firestore::auth::CredentialsProvider;
using firebase::firestore::auth::FirebaseCredentialsProvider;
using firebase::firestore::core::DatabaseInfo;
using firebase::firestore::model::DatabaseId;
+using firebase::firestore::model::ResourcePath;
NS_ASSUME_NONNULL_BEGIN
@@ -141,9 +142,9 @@ extern "C" NSString *const FIRFirestoreErrorDomain = @"FIRFirestoreErrorDomain";
}
if (!database) {
FSTThrowInvalidArgument(
- @"database identifier may not be nil. Use '%@' if you want the default "
+ @"database identifier may not be nil. Use '%s' if you want the default "
"database",
- util::WrapNSStringNoCopy(DatabaseId::kDefault));
+ DatabaseId::kDefault);
}
// Note: If the key format changes, please change the code that detects FIRApps being deleted
@@ -261,7 +262,7 @@ extern "C" NSString *const FIRFirestoreErrorDomain = @"FIRFirestoreErrorDomain";
FSTThrowInvalidArgument(@"Collection path cannot be nil.");
}
[self ensureClientConfigured];
- FSTResourcePath *path = [FSTResourcePath pathWithString:collectionPath];
+ const ResourcePath path = ResourcePath::FromString(util::MakeStringView(collectionPath));
return [FIRCollectionReference referenceWithPath:path firestore:self];
}
@@ -270,7 +271,7 @@ extern "C" NSString *const FIRFirestoreErrorDomain = @"FIRFirestoreErrorDomain";
FSTThrowInvalidArgument(@"Document path cannot be nil.");
}
[self ensureClientConfigured];
- FSTResourcePath *path = [FSTResourcePath pathWithString:documentPath];
+ const ResourcePath path = ResourcePath::FromString(util::MakeStringView(documentPath));
return [FIRDocumentReference referenceWithPath:path firestore:self];
}
diff --git a/Firestore/Source/API/FIRQuery.mm b/Firestore/Source/API/FIRQuery.mm
index c277561..07dac39 100644
--- a/Firestore/Source/API/FIRQuery.mm
+++ b/Firestore/Source/API/FIRQuery.mm
@@ -33,7 +33,6 @@
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTAsyncQueryListener.h"
#import "Firestore/Source/Util/FSTUsageValidation.h"
@@ -379,8 +378,7 @@ addSnapshotListenerInternalWithOptions:(FSTListenOptions *)internalOptions
@"Invalid query. You must not specify an ending point before specifying the order by.");
}
FSTSortOrder *sortOrder =
- [FSTSortOrder sortOrderWithFieldPath:[fieldPath.internalValue toCPPFieldPath]
- ascending:!descending];
+ [FSTSortOrder sortOrderWithFieldPath:fieldPath.internalValue ascending:!descending];
return [FIRQuery referenceWithQuery:[self.query queryByAddingSortOrder:sortOrder]
firestore:self.firestore];
}
@@ -453,10 +451,10 @@ addSnapshotListenerInternalWithOptions:(FSTListenOptions *)internalOptions
}
- (FIRQuery *)queryWithFilterOperator:(FSTRelationFilterOperator)filterOperator
- path:(FSTFieldPath *)fieldPath
+ path:(const FieldPath &)fieldPath
value:(id)value {
FSTFieldValue *fieldValue;
- if ([fieldPath isKeyFieldPath]) {
+ if (fieldPath.IsKeyFieldPath()) {
if ([value isKindOfClass:[NSString class]]) {
NSString *documentKey = (NSString *)value;
if ([documentKey containsString:@"/"]) {
@@ -492,15 +490,15 @@ addSnapshotListenerInternalWithOptions:(FSTListenOptions *)internalOptions
@"Invalid Query. You can only perform equality comparisons on nil / "
"NSNull.");
}
- filter = [[FSTNullFilter alloc] initWithField:[fieldPath toCPPFieldPath]];
+ filter = [[FSTNullFilter alloc] initWithField:fieldPath];
} else if ([fieldValue isEqual:[FSTDoubleValue nanValue]]) {
if (filterOperator != FSTRelationFilterOperatorEqual) {
FSTThrowInvalidUsage(@"InvalidQueryException",
@"Invalid Query. You can only perform equality comparisons on NaN.");
}
- filter = [[FSTNanFilter alloc] initWithField:[fieldPath toCPPFieldPath]];
+ filter = [[FSTNanFilter alloc] initWithField:fieldPath];
} else {
- filter = [FSTRelationFilter filterWithField:[fieldPath toCPPFieldPath]
+ filter = [FSTRelationFilter filterWithField:fieldPath
filterOperator:filterOperator
value:fieldValue];
[self validateNewRelationFilter:filter];
@@ -517,40 +515,38 @@ addSnapshotListenerInternalWithOptions:(FSTListenOptions *)internalOptions
@"InvalidQueryException",
@"Invalid Query. All where filters with an inequality "
"(lessThan, lessThanOrEqual, greaterThan, or greaterThanOrEqual) must be on the same "
- "field. But you have inequality filters on '%@' and '%@'",
- util::WrapNSStringNoCopy(existingField->CanonicalString()),
- util::WrapNSStringNoCopy(filter.field.CanonicalString()));
+ "field. But you have inequality filters on '%s' and '%s'",
+ existingField->CanonicalString().c_str(), filter.field.CanonicalString().c_str());
}
const FieldPath *firstOrderByField = [self.query firstSortOrderField];
if (firstOrderByField) {
- [self validateOrderByField:[FSTFieldPath fieldPathWithCPPFieldPath:*firstOrderByField]
- matchesInequalityField:[FSTFieldPath fieldPathWithCPPFieldPath:filter.field]];
+ [self validateOrderByField:*firstOrderByField matchesInequalityField:filter.field];
}
}
}
-- (void)validateNewOrderByPath:(FSTFieldPath *)fieldPath {
+- (void)validateNewOrderByPath:(const FieldPath &)fieldPath {
if (![self.query firstSortOrderField]) {
// This is the first order by. It must match any inequality.
const FieldPath *inequalityField = [self.query inequalityFilterField];
if (inequalityField) {
- [self validateOrderByField:fieldPath
- matchesInequalityField:[FSTFieldPath fieldPathWithCPPFieldPath:*inequalityField]];
+ [self validateOrderByField:fieldPath matchesInequalityField:*inequalityField];
}
}
}
-- (void)validateOrderByField:(FSTFieldPath *)orderByField
- matchesInequalityField:(FSTFieldPath *)inequalityField {
- if (!([orderByField isEqual:inequalityField])) {
+- (void)validateOrderByField:(const FieldPath &)orderByField
+ matchesInequalityField:(const FieldPath &)inequalityField {
+ if (orderByField != inequalityField) {
FSTThrowInvalidUsage(
@"InvalidQueryException",
@"Invalid query. You have a where filter with an "
- "inequality (lessThan, lessThanOrEqual, greaterThan, or greaterThanOrEqual) on field '%@' "
- "and so you must also use '%@' as your first queryOrderedBy field, but your first "
- "queryOrderedBy is currently on field '%@' instead.",
- inequalityField, inequalityField, orderByField);
+ "inequality (lessThan, lessThanOrEqual, greaterThan, or greaterThanOrEqual) on field '%s' "
+ "and so you must also use '%s' as your first queryOrderedBy field, but your first "
+ "queryOrderedBy is currently on field '%s' instead.",
+ inequalityField.CanonicalString().c_str(), inequalityField.CanonicalString().c_str(),
+ orderByField.CanonicalString().c_str());
}
}
@@ -581,16 +577,15 @@ addSnapshotListenerInternalWithOptions:(FSTListenOptions *)internalOptions
[components addObject:[FSTReferenceValue referenceValue:document.key
databaseID:self.firestore.databaseID]];
} else {
- FSTFieldValue *value =
- [document fieldForPath:[FSTFieldPath fieldPathWithCPPFieldPath:sortOrder.field]];
+ FSTFieldValue *value = [document fieldForPath:sortOrder.field];
if (value != nil) {
[components addObject:value];
} else {
FSTThrowInvalidUsage(@"InvalidQueryException",
@"Invalid query. You are trying to start or end a query using a "
- "document for which the field '%@' (used as the order by) "
+ "document for which the field '%s' (used as the order by) "
"does not exist.",
- util::WrapNSStringNoCopy(sortOrder.field.CanonicalString()));
+ sortOrder.field.CanonicalString().c_str());
}
}
}
diff --git a/Firestore/Source/API/FSTUserDataConverter.mm b/Firestore/Source/API/FSTUserDataConverter.mm
index 5f89b8e..e418996 100644
--- a/Firestore/Source/API/FSTUserDataConverter.mm
+++ b/Firestore/Source/API/FSTUserDataConverter.mm
@@ -16,6 +16,10 @@
#import "Firestore/Source/API/FSTUserDataConverter.h"
+#include <memory>
+#include <utility>
+#include <vector>
+
#import "FIRTimestamp.h"
#import "FIRGeoPoint.h"
@@ -27,15 +31,17 @@
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Source/Model/FSTMutation.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTUsageValidation.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+#include "absl/memory/memory.h"
namespace util = firebase::firestore::util;
using firebase::firestore::model::DatabaseId;
+using firebase::firestore::model::FieldPath;
NS_ASSUME_NONNULL_BEGIN
@@ -126,9 +132,6 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
* A "context" object passed around while parsing user data.
*/
@interface FSTParseContext : NSObject
-/** The current path being parsed. */
-// TODO(b/34871131): path should never be nil, but we don't support array paths right now.
-@property(nonatomic, strong, readonly, nullable) FSTFieldPath *path;
/** Whether or not this context corresponds to an element of an array. */
@property(nonatomic, assign, readonly, getter=isArrayElement) BOOL arrayElement;
@@ -139,7 +142,6 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
*/
@property(nonatomic, assign) FSTUserDataSource dataSource;
@property(nonatomic, strong, readonly) NSMutableArray<FSTFieldTransform *> *fieldTransforms;
-@property(nonatomic, strong, readonly) NSMutableArray<FSTFieldPath *> *fieldMask;
- (instancetype)init NS_UNAVAILABLE;
/**
@@ -150,71 +152,94 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
* the context represents the root of the data being parsed), or a nonempty path (indicating the
* context represents a nested location within the data).
*
- * TODO(b/34871131): We don't support array paths right now, so path can be nil to indicate
+ * TODO(b/34871131): We don't support array paths right now, so path can be nullptr to indicate
* the context represents any location within an array (in which case certain features will not work
* and errors will be somewhat compromised).
*/
- (instancetype)initWithSource:(FSTUserDataSource)dataSource
- path:(nullable FSTFieldPath *)path
+ path:(std::unique_ptr<FieldPath>)path
arrayElement:(BOOL)arrayElement
fieldTransforms:(NSMutableArray<FSTFieldTransform *> *)fieldTransforms
- fieldMask:(NSMutableArray<FSTFieldPath *> *)fieldMask
+ fieldMask:(std::shared_ptr<std::vector<FieldPath>>)fieldMask
NS_DESIGNATED_INITIALIZER;
// Helpers to get a FSTParseContext for a child field.
- (instancetype)contextForField:(NSString *)fieldName;
-- (instancetype)contextForFieldPath:(FSTFieldPath *)fieldPath;
+- (instancetype)contextForFieldPath:(const FieldPath &)fieldPath;
- (instancetype)contextForArrayIndex:(NSUInteger)index;
/** Returns true for the non-query parse contexts (Set, MergeSet and Update) */
- (BOOL)isWrite;
+
+- (const FieldPath *)path;
+
+- (const std::vector<FieldPath> *)fieldMask;
+
+- (void)appendToFieldMaskWithFieldPath:(FieldPath)fieldPath;
+
@end
-@implementation FSTParseContext
+@implementation FSTParseContext {
+ /** The current path being parsed. */
+ // TODO(b/34871131): path should never be nullptr, but we don't support array paths right now.
+ std::unique_ptr<FieldPath> _path;
+ // _fieldMask is shared across all active context objects to accumulate the result. For example,
+ // the result of calling any of contextForField, contextForFieldPath and contextForArrayIndex
+ // shares the ownership of _fieldMask.
+ std::shared_ptr<std::vector<FieldPath>> _fieldMask;
+}
-+ (instancetype)contextWithSource:(FSTUserDataSource)dataSource path:(nullable FSTFieldPath *)path {
- FSTParseContext *context = [[FSTParseContext alloc] initWithSource:dataSource
- path:path
- arrayElement:NO
- fieldTransforms:[NSMutableArray array]
- fieldMask:[NSMutableArray array]];
++ (instancetype)contextWithSource:(FSTUserDataSource)dataSource
+ path:(std::unique_ptr<FieldPath>)path {
+ FSTParseContext *context =
+ [[FSTParseContext alloc] initWithSource:dataSource
+ path:std::move(path)
+ arrayElement:NO
+ fieldTransforms:[NSMutableArray array]
+ fieldMask:std::make_shared<std::vector<FieldPath>>()];
[context validatePath];
return context;
}
- (instancetype)initWithSource:(FSTUserDataSource)dataSource
- path:(nullable FSTFieldPath *)path
+ path:(std::unique_ptr<FieldPath>)path
arrayElement:(BOOL)arrayElement
fieldTransforms:(NSMutableArray<FSTFieldTransform *> *)fieldTransforms
- fieldMask:(NSMutableArray<FSTFieldPath *> *)fieldMask {
+ fieldMask:(std::shared_ptr<std::vector<FieldPath>>)fieldMask {
if (self = [super init]) {
_dataSource = dataSource;
- _path = path;
+ _path = std::move(path);
_arrayElement = arrayElement;
_fieldTransforms = fieldTransforms;
- _fieldMask = fieldMask;
+ _fieldMask = std::move(fieldMask);
}
return self;
}
- (instancetype)contextForField:(NSString *)fieldName {
- FSTParseContext *context =
- [[FSTParseContext alloc] initWithSource:self.dataSource
- path:[self.path pathByAppendingSegment:fieldName]
- arrayElement:NO
- fieldTransforms:self.fieldTransforms
- fieldMask:self.fieldMask];
+ std::unique_ptr<FieldPath> path{};
+ if (_path) {
+ path = absl::make_unique<FieldPath>(_path->Append(util::MakeString(fieldName)));
+ }
+ FSTParseContext *context = [[FSTParseContext alloc] initWithSource:self.dataSource
+ path:std::move(path)
+ arrayElement:NO
+ fieldTransforms:self.fieldTransforms
+ fieldMask:_fieldMask];
[context validatePathSegment:fieldName];
return context;
}
-- (instancetype)contextForFieldPath:(FSTFieldPath *)fieldPath {
- FSTParseContext *context =
- [[FSTParseContext alloc] initWithSource:self.dataSource
- path:[self.path pathByAppendingPath:fieldPath]
- arrayElement:NO
- fieldTransforms:self.fieldTransforms
- fieldMask:self.fieldMask];
+- (instancetype)contextForFieldPath:(const FieldPath &)fieldPath {
+ std::unique_ptr<FieldPath> path{};
+ if (_path) {
+ path = absl::make_unique<FieldPath>(_path->Append(fieldPath));
+ }
+ FSTParseContext *context = [[FSTParseContext alloc] initWithSource:self.dataSource
+ path:std::move(path)
+ arrayElement:NO
+ fieldTransforms:self.fieldTransforms
+ fieldMask:_fieldMask];
[context validatePath];
return context;
}
@@ -225,7 +250,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
path:nil
arrayElement:YES
fieldTransforms:self.fieldTransforms
- fieldMask:self.fieldMask];
+ fieldMask:_fieldMask];
}
/**
@@ -233,10 +258,10 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
*/
- (NSString *)fieldDescription {
// TODO(b/34871131): Remove nil check once we have proper paths for fields within arrays.
- if (!self.path || self.path.empty) {
+ if (!_path || _path->empty()) {
return @"";
} else {
- return [NSString stringWithFormat:@" (found in field %@)", self.path];
+ return [NSString stringWithFormat:@" (found in field %s)", _path->CanonicalString().c_str()];
}
}
@@ -255,11 +280,11 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
- (void)validatePath {
// TODO(b/34871131): Remove nil check once we have proper paths for fields within arrays.
- if (self.path == nil) {
+ if (_path == nullptr) {
return;
}
- for (int i = 0; i < self.path.length; i++) {
- [self validatePathSegment:[self.path segmentAtIndex:i]];
+ for (const auto &segment : *_path) {
+ [self validatePathSegment:util::WrapNSStringNoCopy(segment)];
}
}
@@ -271,6 +296,18 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
}
}
+- (const FieldPath *)path {
+ return _path.get();
+}
+
+- (const std::vector<FieldPath> *)fieldMask {
+ return _fieldMask.get();
+}
+
+- (void)appendToFieldMaskWithFieldPath:(FieldPath)fieldPath {
+ _fieldMask->push_back(std::move(fieldPath));
+}
+
@end
#pragma mark - FSTDocumentKeyReference
@@ -316,13 +353,14 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
}
FSTParseContext *context =
- [FSTParseContext contextWithSource:FSTUserDataSourceMergeSet path:[FSTFieldPath emptyPath]];
+ [FSTParseContext contextWithSource:FSTUserDataSourceMergeSet
+ path:absl::make_unique<FieldPath>(FieldPath::EmptyPath())];
FSTObjectValue *updateData = (FSTObjectValue *)[self parseData:input context:context];
- return
- [[FSTParsedSetData alloc] initWithData:updateData
- fieldMask:[[FSTFieldMask alloc] initWithFields:context.fieldMask]
- fieldTransforms:context.fieldTransforms];
+ return [[FSTParsedSetData alloc]
+ initWithData:updateData
+ fieldMask:[[FSTFieldMask alloc] initWithFields:*context.fieldMask]
+ fieldTransforms:context.fieldTransforms];
}
- (FSTParsedSetData *)parsedSetData:(id)input {
@@ -333,7 +371,8 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
}
FSTParseContext *context =
- [FSTParseContext contextWithSource:FSTUserDataSourceSet path:[FSTFieldPath emptyPath]];
+ [FSTParseContext contextWithSource:FSTUserDataSourceSet
+ path:absl::make_unique<FieldPath>(FieldPath::EmptyPath())];
FSTObjectValue *updateData = (FSTObjectValue *)[self parseData:input context:context];
return [[FSTParsedSetData alloc] initWithData:updateData
@@ -350,13 +389,14 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
NSDictionary *dict = input;
- NSMutableArray<FSTFieldPath *> *fieldMaskPaths = [NSMutableArray array];
+ __block std::vector<FieldPath> fieldMaskPaths{};
__block FSTObjectValue *updateData = [FSTObjectValue objectValue];
FSTParseContext *context =
- [FSTParseContext contextWithSource:FSTUserDataSourceUpdate path:[FSTFieldPath emptyPath]];
+ [FSTParseContext contextWithSource:FSTUserDataSourceUpdate
+ path:absl::make_unique<FieldPath>(FieldPath::EmptyPath())];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
- FSTFieldPath *path;
+ FieldPath path{};
if ([key isKindOfClass:[NSString class]]) {
path = [FIRFieldPath pathWithDotSeparatedString:key].internalValue;
@@ -370,12 +410,12 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
value = self.preConverter(value);
if ([value isKindOfClass:[FSTDeleteFieldValue class]]) {
// Add it to the field mask, but don't add anything to updateData.
- [fieldMaskPaths addObject:path];
+ fieldMaskPaths.push_back(path);
} else {
FSTFieldValue *_Nullable parsedValue =
[self parseData:value context:[context contextForFieldPath:path]];
if (parsedValue) {
- [fieldMaskPaths addObject:path];
+ fieldMaskPaths.push_back(path);
updateData = [updateData objectBySettingValue:parsedValue forPath:path];
}
}
@@ -389,7 +429,8 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
- (FSTFieldValue *)parsedQueryValue:(id)input {
FSTParseContext *context =
- [FSTParseContext contextWithSource:FSTUserDataSourceQueryValue path:[FSTFieldPath emptyPath]];
+ [FSTParseContext contextWithSource:FSTUserDataSourceQueryValue
+ path:absl::make_unique<FieldPath>(FieldPath::EmptyPath())];
FSTFieldValue *_Nullable parsed = [self parseData:input context:context];
FSTAssert(parsed, @"Parsed data should not be nil.");
FSTAssert(context.fieldTransforms.count == 0, @"Field transforms should have been disallowed.");
@@ -427,7 +468,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
// If context.path is nil we are already inside an array and we don't support field mask paths
// more granular than the top-level array.
if (context.path) {
- [context.fieldMask addObject:context.path];
+ [context appendToFieldMaskWithFieldPath:*context.path];
}
return [[FSTArrayValue alloc] initWithValueNoCopy:result];
@@ -448,7 +489,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
// If context.path is null, we are inside an array and we should have already added the root of
// the array to the field mask.
if (context.path) {
- [context.fieldMask addObject:context.path];
+ [context appendToFieldMaskWithFieldPath:*context.path];
}
return [self parseScalarValue:input context:context];
}
@@ -557,11 +598,10 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
if (*reference.databaseID != *self.databaseID) {
const DatabaseId *other = reference.databaseID;
FSTThrowInvalidArgument(
- @"Document Reference is for database %@/%@ but should be for database %@/%@%@",
- util::WrapNSStringNoCopy(other->project_id()),
- util::WrapNSStringNoCopy(other->database_id()),
- util::WrapNSStringNoCopy(self.databaseID->project_id()),
- util::WrapNSStringNoCopy(self.databaseID->database_id()), [context fieldDescription]);
+ @"Document Reference is for database %s/%s but should be for database %s/%s%@",
+ other->project_id().c_str(), other->database_id().c_str(),
+ self.databaseID->project_id().c_str(), self.databaseID->database_id().c_str(),
+ [context fieldDescription]);
}
return [FSTReferenceValue referenceValue:reference.key databaseID:self.databaseID];
@@ -570,7 +610,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
if (context.dataSource == FSTUserDataSourceMergeSet) {
return nil;
} else if (context.dataSource == FSTUserDataSourceUpdate) {
- FSTAssert(context.path.length > 0,
+ FSTAssert(context.path->size() > 0,
@"FieldValue.delete() at the top level should have already been handled.");
FSTThrowInvalidArgument(
@"FieldValue.delete() can only appear at the top level of your "
@@ -594,7 +634,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
}
[context.fieldTransforms
addObject:[[FSTFieldTransform alloc]
- initWithPath:context.path
+ initWithPath:*context.path
transform:[FSTServerTimestampTransform serverTimestampTransform]]];
// Return nil so this value is omitted from the parsed result.
diff --git a/Firestore/Source/Core/FSTFirestoreClient.mm b/Firestore/Source/Core/FSTFirestoreClient.mm
index 288cbe2..9f0779a 100644
--- a/Firestore/Source/Core/FSTFirestoreClient.mm
+++ b/Firestore/Source/Core/FSTFirestoreClient.mm
@@ -205,7 +205,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)userDidChange:(const User &)user {
[self.workerDispatchQueue verifyIsCurrentQueue];
- FSTLog(@"User Changed: %@", util::WrapNSStringNoCopy(user.uid()));
+ FSTLog(@"User Changed: %s", user.uid().c_str());
[self.syncEngine userDidChange:user];
}
diff --git a/Firestore/Source/Core/FSTQuery.mm b/Firestore/Source/Core/FSTQuery.mm
index c10b94d..43b6356 100644
--- a/Firestore/Source/Core/FSTQuery.mm
+++ b/Firestore/Source/Core/FSTQuery.mm
@@ -23,7 +23,6 @@
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#include "Firestore/core/src/firebase/firestore/model/field_path.h"
@@ -153,8 +152,7 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
NSComparisonResult comparison = FSTDocumentKeyComparator(document.key, refValue.value);
return [self matchesComparison:comparison];
} else {
- return [self
- matchesValue:[document fieldForPath:[FSTFieldPath fieldPathWithCPPFieldPath:self.field]]];
+ return [self matchesValue:[document fieldForPath:self.field]];
}
}
@@ -220,8 +218,7 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
}
- (BOOL)matchesDocument:(FSTDocument *)document {
- FSTFieldValue *fieldValue =
- [document fieldForPath:[FSTFieldPath fieldPathWithCPPFieldPath:self.field]];
+ FSTFieldValue *fieldValue = [document fieldForPath:self.field];
return fieldValue != nil && [fieldValue isEqual:[FSTNullValue nullValue]];
}
@@ -267,8 +264,7 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
}
- (BOOL)matchesDocument:(FSTDocument *)document {
- FSTFieldValue *fieldValue =
- [document fieldForPath:[FSTFieldPath fieldPathWithCPPFieldPath:self.field]];
+ FSTFieldValue *fieldValue = [document fieldForPath:self.field];
return fieldValue != nil && [fieldValue isEqual:[FSTDoubleValue nanValue]];
}
@@ -338,10 +334,8 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
if (_field == FieldPath::KeyFieldPath()) {
result = FSTDocumentKeyComparator(document1.key, document2.key);
} else {
- FSTFieldValue *value1 =
- [document1 fieldForPath:[FSTFieldPath fieldPathWithCPPFieldPath:self.field]];
- FSTFieldValue *value2 =
- [document2 fieldForPath:[FSTFieldPath fieldPathWithCPPFieldPath:self.field]];
+ FSTFieldValue *value1 = [document1 fieldForPath:self.field];
+ FSTFieldValue *value2 = [document2 fieldForPath:self.field];
FSTAssert(value1 != nil && value2 != nil,
@"Trying to compare documents on fields that don't exist.");
result = [value1 compare:value2];
@@ -434,8 +428,7 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
FSTReferenceValue *refValue = (FSTReferenceValue *)fieldValue;
comparison = [refValue.value compare:document.key];
} else {
- FSTFieldValue *docValue =
- [document fieldForPath:[FSTFieldPath fieldPathWithCPPFieldPath:sortOrderComponent.field]];
+ FSTFieldValue *docValue = [document fieldForPath:sortOrderComponent.field];
FSTAssert(docValue != nil, @"Field should exist since document matched the orderBy already.");
comparison = [fieldValue compare:docValue];
}
@@ -590,9 +583,9 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
}
} else {
FSTAssert(!inequalityField || *inequalityField == *firstSortOrderField,
- @"First orderBy %@ should match inequality field %@.",
- util::WrapNSStringNoCopy(firstSortOrderField->CanonicalString()),
- util::WrapNSStringNoCopy(inequalityField->CanonicalString()));
+ @"First orderBy %s should match inequality field %s.",
+ firstSortOrderField->CanonicalString().c_str(),
+ inequalityField->CanonicalString().c_str());
__block BOOL foundKeyOrder = NO;
@@ -791,8 +784,7 @@ NSString *FSTStringFromQueryRelationOperator(FSTRelationFilterOperator filterOpe
for (FSTSortOrder *orderBy in self.explicitSortOrders) {
const FieldPath &fieldPath = orderBy.field;
// order by key always matches
- if (fieldPath != FieldPath::KeyFieldPath() &&
- [document fieldForPath:[FSTFieldPath fieldPathWithCPPFieldPath:fieldPath]] == nil) {
+ if (fieldPath != FieldPath::KeyFieldPath() && [document fieldForPath:fieldPath] == nil) {
return NO;
}
}
diff --git a/Firestore/Source/Core/FSTSyncEngine.mm b/Firestore/Source/Core/FSTSyncEngine.mm
index a857f5a..61fac7d 100644
--- a/Firestore/Source/Core/FSTSyncEngine.mm
+++ b/Firestore/Source/Core/FSTSyncEngine.mm
@@ -36,7 +36,6 @@
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTDocumentSet.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTRemoteEvent.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTDispatchQueue.h"
diff --git a/Firestore/Source/Local/FSTLevelDB.mm b/Firestore/Source/Local/FSTLevelDB.mm
index 9d3c35e..ac29304 100644
--- a/Firestore/Source/Local/FSTLevelDB.mm
+++ b/Firestore/Source/Local/FSTLevelDB.mm
@@ -113,8 +113,7 @@ using leveldb::WriteOptions;
NSString *segment = util::WrapNSStringNoCopy(databaseInfo.database_id().project_id());
if (!databaseInfo.database_id().IsDefaultDatabase()) {
segment = [NSString
- stringWithFormat:@"%@.%@", segment,
- util::WrapNSStringNoCopy(databaseInfo.database_id().database_id())];
+ stringWithFormat:@"%@.%s", segment, databaseInfo.database_id().database_id().c_str()];
}
directory = [directory stringByAppendingPathComponent:segment];
diff --git a/Firestore/Source/Local/FSTLevelDBKey.h b/Firestore/Source/Local/FSTLevelDBKey.h
index f3f4bcf..c7a64ee 100644
--- a/Firestore/Source/Local/FSTLevelDBKey.h
+++ b/Firestore/Source/Local/FSTLevelDBKey.h
@@ -19,8 +19,9 @@
#import "Firestore/Source/Core/FSTTypes.h"
#import "Firestore/Source/Local/StringView.h"
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
+
@class FSTDocumentKey;
-@class FSTResourcePath;
NS_ASSUME_NONNULL_BEGIN
@@ -34,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
// document_mutations:
// - tableName: string = "document_mutation"
// - userID: string
-// - path: FSTResourcePath
+// - path: ResourcePath
// - batchID: FSTBatchID
//
// mutation_queues:
@@ -56,16 +57,16 @@ NS_ASSUME_NONNULL_BEGIN
// target_documents:
// - tableName: string = "target_document"
// - targetID: FSTTargetID
-// - path: FSTResourcePath
+// - path: ResourcePath
//
// document_targets:
// - tableName: string = "document_target"
-// - path: FSTResourcePath
+// - path: ResourcePath
// - targetID: FSTTargetID
//
// remote_documents:
// - tableName: string = "remote_document"
-// - path: FSTResourcePath
+// - path: ResourcePath
/** Helpers for any LevelDB key. */
@interface FSTLevelDBKey : NSObject
@@ -128,12 +129,12 @@ NS_ASSUME_NONNULL_BEGIN
/**
* Creates a key prefix that points just before the first key for the userID and resource path.
*
- * Note that this uses an FSTResourcePath rather than an FSTDocumentKey in order to allow prefix
+ * Note that this uses a ResourcePath rather than an FSTDocumentKey in order to allow prefix
* scans over a collection. However a naive scan over those results isn't useful since it would
* match both immediate children of the collection and any subcollections.
*/
+ (std::string)keyPrefixWithUserID:(Firestore::StringView)userID
- resourcePath:(FSTResourcePath *)resourcePath;
+ resourcePath:(const firebase::firestore::model::ResourcePath &)resourcePath;
/** Creates a complete key that points to a specific userID, document key, and batchID. */
+ (std::string)keyWithUserID:(Firestore::StringView)userID
@@ -291,7 +292,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (std::string)keyPrefix;
/** Creates a key that points to the first document-target association for document. */
-+ (std::string)keyPrefixWithResourcePath:(FSTResourcePath *)resourcePath;
++ (std::string)keyPrefixWithResourcePath:
+ (const firebase::firestore::model::ResourcePath &)resourcePath;
/** Creates a key that points to a specific document-target entry. */
+ (std::string)keyWithDocumentKey:(FSTDocumentKey *)documentKey targetID:(FSTTargetID)targetID;
@@ -328,7 +330,8 @@ NS_ASSUME_NONNULL_BEGIN
* a document key prefix will match the document itself and any documents that exist in its
* subcollections.
*/
-+ (std::string)keyPrefixWithResourcePath:(FSTResourcePath *)resourcePath;
++ (std::string)keyPrefixWithResourcePath:
+ (const firebase::firestore::model::ResourcePath &)resourcePath;
/**
* Decodes the contents of a remote document key into properties on this instance. This can only
diff --git a/Firestore/Source/Local/FSTLevelDBKey.mm b/Firestore/Source/Local/FSTLevelDBKey.mm
index bd7b44a..e23f5b7 100644
--- a/Firestore/Source/Local/FSTLevelDBKey.mm
+++ b/Firestore/Source/Local/FSTLevelDBKey.mm
@@ -21,16 +21,19 @@
#include <vector>
#import "Firestore/Source/Model/FSTDocumentKey.h"
-#import "Firestore/Source/Model/FSTPath.h"
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
#include "Firestore/core/src/firebase/firestore/util/ordered_code.h"
+#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+
+namespace util = firebase::firestore::util;
namespace util = firebase::firestore::util;
using firebase::firestore::model::ResourcePath;
NS_ASSUME_NONNULL_BEGIN
+using firebase::firestore::model::ResourcePath;
using firebase::firestore::util::OrderedCode;
using Firestore::StringView;
using leveldb::Slice;
@@ -255,10 +258,10 @@ BOOL ReadLabeledStringMatching(Slice *contents,
* For each segment in the given resource path writes an FSTComponentLabelPathSegment component
* label and a string containing the path segment.
*/
-void WriteResourcePath(std::string *dest, FSTResourcePath *path) {
- for (int i = 0; i < path.length; i++) {
+void WriteResourcePath(std::string *dest, const ResourcePath &path) {
+ for (const auto &segment : path) {
WriteComponentLabel(dest, FSTComponentLabelPathSegment);
- OrderedCode::WriteString(dest, StringView([path segmentAtIndex:i]));
+ OrderedCode::WriteString(dest, segment);
}
}
@@ -522,7 +525,8 @@ NSString *InvalidKey(const Slice &key) {
return result;
}
-+ (std::string)keyPrefixWithUserID:(StringView)userID resourcePath:(FSTResourcePath *)resourcePath {
++ (std::string)keyPrefixWithUserID:(StringView)userID
+ resourcePath:(const ResourcePath &)resourcePath {
std::string result;
WriteTableName(&result, kDocumentMutationsTable);
WriteUserID(&result, userID);
@@ -536,7 +540,7 @@ NSString *InvalidKey(const Slice &key) {
std::string result;
WriteTableName(&result, kDocumentMutationsTable);
WriteUserID(&result, userID);
- WriteResourcePath(&result, [FSTResourcePath resourcePathWithCPPResourcePath:documentKey.path]);
+ WriteResourcePath(&result, documentKey.path);
WriteBatchID(&result, batchID);
WriteTerminator(&result);
return result;
@@ -690,7 +694,7 @@ NSString *InvalidKey(const Slice &key) {
std::string result;
WriteTableName(&result, kTargetDocumentsTable);
WriteTargetID(&result, targetID);
- WriteResourcePath(&result, [FSTResourcePath resourcePathWithCPPResourcePath:documentKey.path]);
+ WriteResourcePath(&result, documentKey.path);
WriteTerminator(&result);
return result;
}
@@ -714,7 +718,7 @@ NSString *InvalidKey(const Slice &key) {
return result;
}
-+ (std::string)keyPrefixWithResourcePath:(FSTResourcePath *)resourcePath {
++ (std::string)keyPrefixWithResourcePath:(const ResourcePath &)resourcePath {
std::string result;
WriteTableName(&result, kDocumentTargetsTable);
WriteResourcePath(&result, resourcePath);
@@ -724,7 +728,7 @@ NSString *InvalidKey(const Slice &key) {
+ (std::string)keyWithDocumentKey:(FSTDocumentKey *)documentKey targetID:(FSTTargetID)targetID {
std::string result;
WriteTableName(&result, kDocumentTargetsTable);
- WriteResourcePath(&result, [FSTResourcePath resourcePathWithCPPResourcePath:documentKey.path]);
+ WriteResourcePath(&result, documentKey.path);
WriteTargetID(&result, targetID);
WriteTerminator(&result);
return result;
@@ -749,7 +753,7 @@ NSString *InvalidKey(const Slice &key) {
return result;
}
-+ (std::string)keyPrefixWithResourcePath:(FSTResourcePath *)path {
++ (std::string)keyPrefixWithResourcePath:(const ResourcePath &)path {
std::string result;
WriteTableName(&result, kRemoteDocumentsTable);
WriteResourcePath(&result, path);
@@ -759,7 +763,7 @@ NSString *InvalidKey(const Slice &key) {
+ (std::string)keyWithDocumentKey:(FSTDocumentKey *)key {
std::string result;
WriteTableName(&result, kRemoteDocumentsTable);
- WriteResourcePath(&result, [FSTResourcePath resourcePathWithCPPResourcePath:key.path]);
+ WriteResourcePath(&result, key.path);
WriteTerminator(&result);
return result;
}
diff --git a/Firestore/Source/Local/FSTLevelDBMutationQueue.mm b/Firestore/Source/Local/FSTLevelDBMutationQueue.mm
index d7b5eca..ac93ab1 100644
--- a/Firestore/Source/Local/FSTLevelDBMutationQueue.mm
+++ b/Firestore/Source/Local/FSTLevelDBMutationQueue.mm
@@ -30,10 +30,10 @@
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#include "Firestore/core/src/firebase/firestore/auth/user.h"
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
#include "Firestore/core/src/firebase/firestore/util/string_util.h"
@@ -42,6 +42,7 @@ NS_ASSUME_NONNULL_BEGIN
namespace util = firebase::firestore::util;
using Firestore::StringView;
using firebase::firestore::auth::User;
+using firebase::firestore::model::ResourcePath;
using leveldb::DB;
using leveldb::Iterator;
using leveldb::ReadOptions;
@@ -380,9 +381,8 @@ static ReadOptions StandardReadOptions() {
NSString *userID = self.userID;
// Scan the document-mutation index starting with a prefix starting with the given documentKey.
- std::string indexPrefix = [FSTLevelDBDocumentMutationKey
- keyPrefixWithUserID:self.userID
- resourcePath:[FSTResourcePath resourcePathWithCPPResourcePath:documentKey.path]];
+ std::string indexPrefix =
+ [FSTLevelDBDocumentMutationKey keyPrefixWithUserID:self.userID resourcePath:documentKey.path];
std::unique_ptr<Iterator> indexIterator(_db->NewIterator(StandardReadOptions()));
indexIterator->Seek(indexPrefix);
@@ -432,8 +432,8 @@ static ReadOptions StandardReadOptions() {
FSTAssert(![query isDocumentQuery], @"Document queries shouldn't go down this path");
NSString *userID = self.userID;
- FSTResourcePath *queryPath = [FSTResourcePath resourcePathWithCPPResourcePath:query.path];
- int immediateChildrenPathLength = queryPath.length + 1;
+ const ResourcePath &queryPath = query.path;
+ size_t immediateChildrenPathLength = queryPath.size() + 1;
// TODO(mcg): Actually implement a single-collection query
//
@@ -620,9 +620,8 @@ static ReadOptions StandardReadOptions() {
#pragma mark - FSTGarbageSource implementation
- (BOOL)containsKey:(FSTDocumentKey *)documentKey {
- std::string indexPrefix = [FSTLevelDBDocumentMutationKey
- keyPrefixWithUserID:self.userID
- resourcePath:[FSTResourcePath resourcePathWithCPPResourcePath:documentKey.path]];
+ std::string indexPrefix =
+ [FSTLevelDBDocumentMutationKey keyPrefixWithUserID:self.userID resourcePath:documentKey.path];
std::unique_ptr<Iterator> indexIterator(_db->NewIterator(StandardReadOptions()));
indexIterator->Seek(indexPrefix);
diff --git a/Firestore/Source/Local/FSTLevelDBQueryCache.mm b/Firestore/Source/Local/FSTLevelDBQueryCache.mm
index dcbcee1..fe1bf19 100644
--- a/Firestore/Source/Local/FSTLevelDBQueryCache.mm
+++ b/Firestore/Source/Local/FSTLevelDBQueryCache.mm
@@ -27,7 +27,6 @@
#import "Firestore/Source/Local/FSTQueryData.h"
#import "Firestore/Source/Local/FSTWriteGroup.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
NS_ASSUME_NONNULL_BEGIN
@@ -340,8 +339,7 @@ using leveldb::WriteOptions;
#pragma mark - FSTGarbageSource implementation
- (BOOL)containsKey:(FSTDocumentKey *)key {
- std::string indexPrefix = [FSTLevelDBDocumentTargetKey
- keyPrefixWithResourcePath:[FSTResourcePath resourcePathWithCPPResourcePath:key.path]];
+ std::string indexPrefix = [FSTLevelDBDocumentTargetKey keyPrefixWithResourcePath:key.path];
std::unique_ptr<Iterator> indexIterator(_db->NewIterator([FSTLevelDB standardReadOptions]));
indexIterator->Seek(indexPrefix);
diff --git a/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm b/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm
index 423912f..c86318d 100644
--- a/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm
+++ b/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm
@@ -29,7 +29,6 @@
#import "Firestore/Source/Model/FSTDocumentDictionary.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTDocumentSet.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
NS_ASSUME_NONNULL_BEGIN
@@ -104,8 +103,7 @@ static ReadOptions StandardReadOptions() {
// Documents are ordered by key, so we can use a prefix scan to narrow down
// the documents we need to match the query against.
- std::string startKey = [FSTLevelDBRemoteDocumentKey
- keyPrefixWithResourcePath:[FSTResourcePath resourcePathWithCPPResourcePath:query.path]];
+ std::string startKey = [FSTLevelDBRemoteDocumentKey keyPrefixWithResourcePath:query.path];
std::unique_ptr<Iterator> it(_db->NewIterator(StandardReadOptions()));
it->Seek(startKey);
diff --git a/Firestore/Source/Local/FSTLocalDocumentsView.mm b/Firestore/Source/Local/FSTLocalDocumentsView.mm
index 0059e28..c059146 100644
--- a/Firestore/Source/Local/FSTLocalDocumentsView.mm
+++ b/Firestore/Source/Local/FSTLocalDocumentsView.mm
@@ -25,9 +25,12 @@
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
+
+using firebase::firestore::model::ResourcePath;
+
NS_ASSUME_NONNULL_BEGIN
@interface FSTLocalDocumentsView ()
@@ -76,18 +79,16 @@ NS_ASSUME_NONNULL_BEGIN
- (FSTDocumentDictionary *)documentsMatchingQuery:(FSTQuery *)query {
if ([FSTDocumentKey isDocumentKey:query.path]) {
- return [self documentsMatchingDocumentQuery:[FSTResourcePath
- resourcePathWithCPPResourcePath:query.path]];
+ return [self documentsMatchingDocumentQuery:query.path];
} else {
return [self documentsMatchingCollectionQuery:query];
}
}
-- (FSTDocumentDictionary *)documentsMatchingDocumentQuery:(FSTResourcePath *)docPath {
+- (FSTDocumentDictionary *)documentsMatchingDocumentQuery:(const ResourcePath &)docPath {
FSTDocumentDictionary *result = [FSTDocumentDictionary documentDictionary];
// Just do a simple document lookup.
- FSTMaybeDocument *doc =
- [self documentForKey:[FSTDocumentKey keyWithPath:[docPath toCPPResourcePath]]];
+ FSTMaybeDocument *doc = [self documentForKey:[FSTDocumentKey keyWithPath:docPath]];
if ([doc isKindOfClass:[FSTDocument class]]) {
result = [result dictionaryBySettingObject:(FSTDocument *)doc forKey:doc.key];
}
diff --git a/Firestore/Source/Local/FSTMemoryMutationQueue.mm b/Firestore/Source/Local/FSTMemoryMutationQueue.mm
index 7e5cc02..8375efd 100644
--- a/Firestore/Source/Local/FSTMemoryMutationQueue.mm
+++ b/Firestore/Source/Local/FSTMemoryMutationQueue.mm
@@ -21,7 +21,6 @@
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
diff --git a/Firestore/Source/Local/FSTMemoryRemoteDocumentCache.mm b/Firestore/Source/Local/FSTMemoryRemoteDocumentCache.mm
index b0d6807..fed608c 100644
--- a/Firestore/Source/Local/FSTMemoryRemoteDocumentCache.mm
+++ b/Firestore/Source/Local/FSTMemoryRemoteDocumentCache.mm
@@ -20,7 +20,6 @@
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentDictionary.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
-#import "Firestore/Source/Model/FSTPath.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Source/Model/FSTDocument.h b/Firestore/Source/Model/FSTDocument.h
index 100f553..36237fd 100644
--- a/Firestore/Source/Model/FSTDocument.h
+++ b/Firestore/Source/Model/FSTDocument.h
@@ -16,8 +16,9 @@
#import <Foundation/Foundation.h>
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+
@class FSTDocumentKey;
-@class FSTFieldPath;
@class FSTFieldValue;
@class FSTObjectValue;
@class FSTSnapshotVersion;
@@ -41,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN
version:(FSTSnapshotVersion *)version
hasLocalMutations:(BOOL)mutations;
-- (nullable FSTFieldValue *)fieldForPath:(FSTFieldPath *)path;
+- (nullable FSTFieldValue *)fieldForPath:(const firebase::firestore::model::FieldPath &)path;
@property(nonatomic, strong, readonly) FSTObjectValue *data;
@property(nonatomic, readonly, getter=hasLocalMutations) BOOL localMutations;
diff --git a/Firestore/Source/Model/FSTDocument.mm b/Firestore/Source/Model/FSTDocument.mm
index 58d3629..ca66da1 100644
--- a/Firestore/Source/Model/FSTDocument.mm
+++ b/Firestore/Source/Model/FSTDocument.mm
@@ -19,9 +19,14 @@
#import "Firestore/Source/Core/FSTSnapshotVersion.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+
+namespace util = firebase::firestore::util;
+using firebase::firestore::model::FieldPath;
+
NS_ASSUME_NONNULL_BEGIN
@interface FSTMaybeDocument ()
@@ -99,7 +104,7 @@ NS_ASSUME_NONNULL_BEGIN
self.localMutations ? @"YES" : @"NO", self.data];
}
-- (nullable FSTFieldValue *)fieldForPath:(FSTFieldPath *)path {
+- (nullable FSTFieldValue *)fieldForPath:(const FieldPath &)path {
return [_data valueForPath:path];
}
diff --git a/Firestore/Source/Model/FSTFieldValue.h b/Firestore/Source/Model/FSTFieldValue.h
index be8ba45..7d72138 100644
--- a/Firestore/Source/Model/FSTFieldValue.h
+++ b/Firestore/Source/Model/FSTFieldValue.h
@@ -19,9 +19,9 @@
#import "Firestore/third_party/Immutable/FSTImmutableSortedDictionary.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
@class FSTDocumentKey;
-@class FSTFieldPath;
@class FIRTimestamp;
@class FSTFieldValueOptions;
@class FIRGeoPoint;
@@ -243,19 +243,20 @@ typedef NS_ENUM(NSInteger, FSTServerTimestampBehavior) {
- (FSTImmutableSortedDictionary<NSString *, FSTFieldValue *> *)internalValue;
/** Returns the value at the given path if it exists. Returns nil otherwise. */
-- (nullable FSTFieldValue *)valueForPath:(FSTFieldPath *)fieldPath;
+- (nullable FSTFieldValue *)valueForPath:(const firebase::firestore::model::FieldPath &)fieldPath;
/**
* Returns a new object where the field at the named path has its value set to the given value.
* This object remains unmodified.
*/
-- (FSTObjectValue *)objectBySettingValue:(FSTFieldValue *)value forPath:(FSTFieldPath *)fieldPath;
+- (FSTObjectValue *)objectBySettingValue:(FSTFieldValue *)value
+ forPath:(const firebase::firestore::model::FieldPath &)fieldPath;
/**
* Returns a new object where the field at the named path has been removed. If any segment of the
* path does not exist within this object's structure, no change is performed.
*/
-- (FSTObjectValue *)objectByDeletingPath:(FSTFieldPath *)fieldPath;
+- (FSTObjectValue *)objectByDeletingPath:(const firebase::firestore::model::FieldPath &)fieldPath;
@end
/**
diff --git a/Firestore/Source/Model/FSTFieldValue.mm b/Firestore/Source/Model/FSTFieldValue.mm
index 5ef64e1..2f013c3 100644
--- a/Firestore/Source/Model/FSTFieldValue.mm
+++ b/Firestore/Source/Model/FSTFieldValue.mm
@@ -24,15 +24,16 @@
#import "Firestore/Source/API/FIRGeoPoint+Internal.h"
#import "Firestore/Source/API/FIRSnapshotOptions+Internal.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTClasses.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
namespace util = firebase::firestore::util;
using firebase::firestore::model::DatabaseId;
+using firebase::firestore::model::FieldPath;
using firebase::firestore::util::Comparator;
using firebase::firestore::util::CompareMixedNumber;
using firebase::firestore::util::DoubleBitwiseEquals;
@@ -808,25 +809,26 @@ static const NSComparator StringComparator = ^NSComparisonResult(NSString *left,
}
}
-- (nullable FSTFieldValue *)valueForPath:(FSTFieldPath *)fieldPath {
+- (nullable FSTFieldValue *)valueForPath:(const FieldPath &)fieldPath {
FSTFieldValue *value = self;
- for (int i = 0, max = fieldPath.length; value && i < max; i++) {
+ for (size_t i = 0, max = fieldPath.size(); value && i < max; i++) {
if (![value isMemberOfClass:[FSTObjectValue class]]) {
return nil;
}
- NSString *fieldName = fieldPath[i];
+ NSString *fieldName = util::WrapNSStringNoCopy(fieldPath[i]);
value = ((FSTObjectValue *)value).internalValue[fieldName];
}
return value;
}
-- (FSTObjectValue *)objectBySettingValue:(FSTFieldValue *)value forPath:(FSTFieldPath *)fieldPath {
- FSTAssert([fieldPath length] > 0, @"Cannot set value with an empty path");
+- (FSTObjectValue *)objectBySettingValue:(FSTFieldValue *)value
+ forPath:(const FieldPath &)fieldPath {
+ FSTAssert(fieldPath.size() > 0, @"Cannot set value with an empty path");
- NSString *childName = [fieldPath firstSegment];
- if ([fieldPath length] == 1) {
+ NSString *childName = util::WrapNSString(fieldPath.first_segment());
+ if (fieldPath.size() == 1) {
// Recursive base case:
return [self objectBySettingValue:value forField:childName];
} else {
@@ -841,23 +843,22 @@ static const NSComparator StringComparator = ^NSComparisonResult(NSString *left,
// there.
childObject = [FSTObjectValue objectValue];
}
- FSTFieldValue *newChild =
- [childObject objectBySettingValue:value forPath:[fieldPath pathByRemovingFirstSegment]];
+ FSTFieldValue *newChild = [childObject objectBySettingValue:value forPath:fieldPath.PopFirst()];
return [self objectBySettingValue:newChild forField:childName];
}
}
-- (FSTObjectValue *)objectByDeletingPath:(FSTFieldPath *)fieldPath {
- FSTAssert([fieldPath length] > 0, @"Cannot delete an empty path");
- NSString *childName = [fieldPath firstSegment];
- if ([fieldPath length] == 1) {
+- (FSTObjectValue *)objectByDeletingPath:(const FieldPath &)fieldPath {
+ FSTAssert(fieldPath.size() > 0, @"Cannot delete an empty path");
+ NSString *childName = util::WrapNSString(fieldPath.first_segment());
+ if (fieldPath.size() == 1) {
return [[FSTObjectValue alloc]
initWithImmutableDictionary:[_internalValue dictionaryByRemovingObjectForKey:childName]];
} else {
FSTFieldValue *child = _internalValue[childName];
if ([child isKindOfClass:[FSTObjectValue class]]) {
FSTObjectValue *newChild =
- [((FSTObjectValue *)child) objectByDeletingPath:[fieldPath pathByRemovingFirstSegment]];
+ [((FSTObjectValue *)child) objectByDeletingPath:fieldPath.PopFirst()];
return [self objectBySettingValue:newChild forField:childName];
} else {
// If the child is not found or is a primitive type, make no modifications
diff --git a/Firestore/Source/Model/FSTMutation.h b/Firestore/Source/Model/FSTMutation.h
index 72f6a25..2d29dc9 100644
--- a/Firestore/Source/Model/FSTMutation.h
+++ b/Firestore/Source/Model/FSTMutation.h
@@ -16,9 +16,12 @@
#import <Foundation/Foundation.h>
+#include <vector>
+
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+
@class FSTDocument;
@class FSTDocumentKey;
-@class FSTFieldPath;
@class FSTFieldValue;
@class FSTMaybeDocument;
@class FSTObjectValue;
@@ -46,9 +49,10 @@ NS_ASSUME_NONNULL_BEGIN
* Initializes the field mask with the given field paths. Caller is expected to either copy or
* or release the array of fields.
*/
-- (instancetype)initWithFields:(NSArray<FSTFieldPath *> *)fields NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithFields:(std::vector<firebase::firestore::model::FieldPath>)fields
+ NS_DESIGNATED_INITIALIZER;
-@property(nonatomic, strong, readonly) NSArray<FSTFieldPath *> *fields;
+- (const std::vector<firebase::firestore::model::FieldPath> &)fields;
@end
#pragma mark - FSTFieldTransform
@@ -65,9 +69,9 @@ NS_ASSUME_NONNULL_BEGIN
/** A field path and the FSTTransformOperation to perform upon it. */
@interface FSTFieldTransform : NSObject
- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithPath:(FSTFieldPath *)path
+- (instancetype)initWithPath:(firebase::firestore::model::FieldPath)path
transform:(id<FSTTransformOperation>)transform NS_DESIGNATED_INITIALIZER;
-@property(nonatomic, strong, readonly) FSTFieldPath *path;
+- (const firebase::firestore::model::FieldPath &)path;
@property(nonatomic, strong, readonly) id<FSTTransformOperation> transform;
@end
diff --git a/Firestore/Source/Model/FSTMutation.mm b/Firestore/Source/Model/FSTMutation.mm
index e702644..a61ee84 100644
--- a/Firestore/Source/Model/FSTMutation.mm
+++ b/Firestore/Source/Model/FSTMutation.mm
@@ -22,19 +22,24 @@
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTClasses.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+
+using firebase::firestore::model::FieldPath;
+
NS_ASSUME_NONNULL_BEGIN
#pragma mark - FSTFieldMask
-@implementation FSTFieldMask
+@implementation FSTFieldMask {
+ std::vector<FieldPath> _fields;
+}
-- (instancetype)initWithFields:(NSArray<FSTFieldPath *> *)fields {
+- (instancetype)initWithFields:(std::vector<FieldPath>)fields {
if (self = [super init]) {
- _fields = fields;
+ _fields = std::move(fields);
}
return self;
}
@@ -48,11 +53,19 @@ NS_ASSUME_NONNULL_BEGIN
}
FSTFieldMask *otherMask = (FSTFieldMask *)other;
- return [self.fields isEqual:otherMask.fields];
+ return _fields == otherMask->_fields;
}
- (NSUInteger)hash {
- return self.fields.hash;
+ NSUInteger hashResult = 0;
+ for (const FieldPath &field : _fields) {
+ hashResult = hashResult * 31u + field.Hash();
+ }
+ return hashResult;
+}
+
+- (const std::vector<FieldPath> &)fields {
+ return _fields;
}
@end
@@ -85,12 +98,14 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - FSTFieldTransform
-@implementation FSTFieldTransform
+@implementation FSTFieldTransform {
+ FieldPath _path;
+}
-- (instancetype)initWithPath:(FSTFieldPath *)path transform:(id<FSTTransformOperation>)transform {
+- (instancetype)initWithPath:(FieldPath)path transform:(id<FSTTransformOperation>)transform {
self = [super init];
if (self) {
- _path = path;
+ _path = std::move(path);
_transform = transform;
}
return self;
@@ -100,16 +115,20 @@ NS_ASSUME_NONNULL_BEGIN
if (other == self) return YES;
if (![[other class] isEqual:[self class]]) return NO;
FSTFieldTransform *otherFieldTransform = other;
- return [self.path isEqual:otherFieldTransform.path] &&
+ return self.path == otherFieldTransform.path &&
[self.transform isEqual:otherFieldTransform.transform];
}
- (NSUInteger)hash {
- NSUInteger hash = [self.path hash];
+ NSUInteger hash = self.path.Hash();
hash = hash * 31 + [self.transform hash];
return hash;
}
+- (const firebase::firestore::model::FieldPath &)path {
+ return _path;
+}
+
@end
#pragma mark - FSTPrecondition
@@ -405,7 +424,7 @@ NS_ASSUME_NONNULL_BEGIN
- (FSTObjectValue *)patchObjectValue:(FSTObjectValue *)objectValue {
FSTObjectValue *result = objectValue;
- for (FSTFieldPath *fieldPath in self.fieldMask.fields) {
+ for (const FieldPath &fieldPath : self.fieldMask.fields) {
FSTFieldValue *newValue = [self.value valueForPath:fieldPath];
if (newValue) {
result = [result objectBySettingValue:newValue forPath:fieldPath];
@@ -529,7 +548,7 @@ NS_ASSUME_NONNULL_BEGIN
for (NSUInteger i = 0; i < self.fieldTransforms.count; i++) {
FSTFieldTransform *fieldTransform = self.fieldTransforms[i];
id<FSTTransformOperation> transform = fieldTransform.transform;
- FSTFieldPath *fieldPath = fieldTransform.path;
+ FieldPath fieldPath = fieldTransform.path;
if ([transform isKindOfClass:[FSTServerTimestampTransform class]]) {
objectValue = [objectValue objectBySettingValue:transformResults[i] forPath:fieldPath];
} else {
diff --git a/Firestore/Source/Model/FSTPath.h b/Firestore/Source/Model/FSTPath.h
deleted file mode 100644
index f127156..0000000
--- a/Firestore/Source/Model/FSTPath.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright 2017 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import <Foundation/Foundation.h>
-
-#include "Firestore/core/src/firebase/firestore/model/field_path.h"
-#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- * FSTPath represents a path sequence in the Firestore database. It is composed of an ordered
- * sequence of string segments.
- *
- * ## Subclassing Notes
- *
- * FSTPath itself is an abstract class that must be specialized by subclasses. Subclasses should
- * implement constructors for common string-based representations of the path and also override
- * -canonicalString which converts back to the canonical string-based representation of the path.
- */
-@interface FSTPath <SelfType> : NSObject
-
-/** Returns the path segment of the given index. */
-- (NSString *)segmentAtIndex:(int)index;
-- (id)objectAtIndexedSubscript:(int)index;
-
-- (BOOL)isEqual:(id)path;
-- (NSComparisonResult)compare:(SelfType)other;
-
-/**
- * Returns a new path whose segments are the current path's plus one more.
- *
- * @param segment The new segment to concatenate to the path.
- * @return A new path with this path's segment plus the new one.
- */
-- (instancetype)pathByAppendingSegment:(NSString *)segment;
-
-/**
- * Returns a new path whose segments are the current path's plus another's.
- *
- * @param path The new path whose segments should be concatenated to the path.
- * @return A new path with this path's segment plus the new ones.
- */
-- (instancetype)pathByAppendingPath:(SelfType)path;
-
-/** Returns a new path whose segments are the same as this one's minus the first one. */
-- (instancetype)pathByRemovingFirstSegment;
-
-/** Returns a new path whose segments are the same as this one's minus the first `count`. */
-- (instancetype)pathByRemovingFirstSegments:(int)count;
-
-/** Returns a new path whose segments are the same as this one's minus the last one. */
-- (instancetype)pathByRemovingLastSegment;
-
-/** Convenience method for getting the first segment of this path. */
-- (NSString *)firstSegment;
-
-/** Convenience method for getting the last segment of this path. */
-- (NSString *)lastSegment;
-
-/** Returns true if this path is a prefix of the given path. */
-- (BOOL)isPrefixOfPath:(SelfType)other;
-
-/** Returns a standardized string representation of this path. */
-- (NSString *)canonicalString;
-
-/** The number of segments in the path. */
-@property(nonatomic, readonly) int length;
-
-/** True if the path is empty. */
-@property(nonatomic, readonly, getter=isEmpty) BOOL empty;
-
-@end
-
-/** A dot-separated path for navigating sub-objects within a document. */
-@class FSTFieldPath;
-
-@interface FSTFieldPath : FSTPath <FSTFieldPath *>
-
-/**
- * Creates and returns a new path with the given segments. The array of segments is not copied, so
- * one should not mutate the array once it is passed in here.
- *
- * @param segments The underlying array of segments for the path.
- * @return A new instance of FSTPath.
- */
-+ (instancetype)pathWithSegments:(NSArray<NSString *> *)segments;
-
-/**
- * Creates and returns a new path from the server formatted field-path string, where path segments
- * are separated by a dot "." and optionally encoded using backticks.
- *
- * @param fieldPath A dot-separated string representing the path.
- */
-+ (instancetype)pathWithServerFormat:(NSString *)fieldPath;
-
-/** Returns a field path that represents a document key. */
-+ (instancetype)keyFieldPath;
-
-/** Returns a field path that represents an empty path. */
-+ (instancetype)emptyPath;
-
-/** Returns YES if this is the `FSTFieldPath.keyFieldPath` field path. */
-- (BOOL)isKeyFieldPath;
-
-/** Creates and returns a new path from C++ FieldPath.
- *
- * @param fieldPath A C++ FieldPath.
- */
-+ (instancetype)fieldPathWithCPPFieldPath:(const firebase::firestore::model::FieldPath &)fieldPath;
-
-/**
- * Creates and returns a new C++ FieldPath.
- */
-- (firebase::firestore::model::FieldPath)toCPPFieldPath;
-
-@end
-
-/** A slash-separated path for navigating resources (documents and collections) within Firestore. */
-@class FSTResourcePath;
-
-@interface FSTResourcePath : FSTPath <FSTResourcePath *>
-
-/**
- * Creates and returns a new path with the given segments. The array of segments is not copied, so
- * one should not mutate the array once it is passed in here.
- *
- * @param segments The underlying array of segments for the path.
- * @return A new instance of FSTPath.
- */
-+ (instancetype)pathWithSegments:(NSArray<NSString *> *)segments;
-
-/**
- * Creates and returns a new path from the given resource-path string, where the path segments are
- * separated by a slash "/".
- *
- * @param resourcePath A slash-separated string representing the path.
- */
-+ (instancetype)pathWithString:(NSString *)resourcePath;
-
-/** Creates and returns a new path from C++ ResourcePath.
- *
- * @param resourcePath A C++ ResourcePath.
- */
-+ (instancetype)resourcePathWithCPPResourcePath:
- (const firebase::firestore::model::ResourcePath &)resourcePath;
-
-/**
- * Creates and returns a new C++ ResourcePath.
- */
-- (firebase::firestore::model::ResourcePath)toCPPResourcePath;
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Firestore/Source/Model/FSTPath.mm b/Firestore/Source/Model/FSTPath.mm
deleted file mode 100644
index b91e428..0000000
--- a/Firestore/Source/Model/FSTPath.mm
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright 2017 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#import "Firestore/Source/Model/FSTPath.h"
-
-#include <string>
-
-#import "Firestore/Source/Model/FSTDocumentKey.h"
-#import "Firestore/Source/Util/FSTAssert.h"
-#import "Firestore/Source/Util/FSTClasses.h"
-#import "Firestore/Source/Util/FSTUsageValidation.h"
-
-#include "Firestore/core/src/firebase/firestore/model/field_path.h"
-#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
-#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
-
-namespace util = firebase::firestore::util;
-using firebase::firestore::model::FieldPath;
-using firebase::firestore::model::ResourcePath;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface FSTPath ()
-/** An underlying array of which a subset of elements are the segments of the path. */
-@property(strong, nonatomic) NSArray<NSString *> *segments;
-/** The index into the segments array of the first segment in this path. */
-@property int offset;
-@end
-
-@implementation FSTPath
-
-/**
- * Designated initializer.
- *
- * @param segments The underlying array of segments for the path.
- * @param offset The starting index in the underlying array for the subarray to use.
- * @param length The length of the subarray to use.
- */
-- (instancetype)initWithSegments:(NSArray<NSString *> *)segments
- offset:(int)offset
- length:(int)length {
- FSTAssert(offset <= segments.count, @"offset %d out of range %d", offset, (int)segments.count);
- FSTAssert(length <= segments.count - offset, @"offset %d out of range %d", offset,
- (int)segments.count - offset);
-
- if (self = [super init]) {
- _segments = segments;
- _offset = offset;
- _length = length;
- }
- return self;
-}
-
-- (BOOL)isEqual:(id)object {
- if (self == object) {
- return YES;
- }
- if (![object isKindOfClass:[FSTPath class]]) {
- return NO;
- }
- FSTPath *path = object;
- return [self compare:path] == NSOrderedSame;
-}
-
-- (NSUInteger)hash {
- NSUInteger hash = 0;
- for (int i = 0; i < self.length; ++i) {
- hash += [self segmentAtIndex:i].hash;
- }
- return hash;
-}
-
-- (NSString *)description {
- return [self canonicalString];
-}
-
-- (id)objectAtIndexedSubscript:(int)index {
- return [self segmentAtIndex:index];
-}
-
-- (NSString *)segmentAtIndex:(int)index {
- FSTAssert(index < self.length, @"index %d out of range", index);
- return self.segments[self.offset + index];
-}
-
-- (NSString *)firstSegment {
- FSTAssert(!self.isEmpty, @"Cannot call firstSegment on empty path");
- return [self segmentAtIndex:0];
-}
-
-- (NSString *)lastSegment {
- FSTAssert(!self.isEmpty, @"Cannot call lastSegment on empty path");
- return [self segmentAtIndex:self.length - 1];
-}
-
-- (NSComparisonResult)compare:(FSTPath *)other {
- int length = MIN(self.length, other.length);
- for (int i = 0; i < length; ++i) {
- NSString *left = [self segmentAtIndex:i];
- NSString *right = [other segmentAtIndex:i];
- NSComparisonResult result = [left compare:right];
- if (result != NSOrderedSame) {
- return result;
- }
- }
- if (self.length < other.length) {
- return NSOrderedAscending;
- }
- if (self.length > other.length) {
- return NSOrderedDescending;
- }
- return NSOrderedSame;
-}
-
-- (instancetype)pathWithSegments:(NSArray<NSString *> *)segments
- offset:(int)offset
- length:(int)length {
- return [[[self class] alloc] initWithSegments:segments offset:offset length:length];
-}
-
-- (instancetype)pathByAppendingSegment:(NSString *)segment {
- int newLength = self.length + 1;
- NSMutableArray<NSString *> *segments = [NSMutableArray arrayWithCapacity:newLength];
- for (int i = 0; i < self.length; ++i) {
- [segments addObject:self[i]];
- }
- [segments addObject:segment];
- return [self pathWithSegments:segments offset:0 length:newLength];
-}
-
-- (instancetype)pathByAppendingPath:(FSTPath *)path {
- int newLength = self.length + path.length;
- NSMutableArray<NSString *> *segments = [NSMutableArray arrayWithCapacity:newLength];
- for (int i = 0; i < self.length; ++i) {
- [segments addObject:self[i]];
- }
- for (int i = 0; i < path.length; ++i) {
- [segments addObject:path[i]];
- }
- return [self pathWithSegments:segments offset:0 length:newLength];
-}
-
-- (BOOL)isEmpty {
- return self.length == 0;
-}
-
-- (instancetype)pathByRemovingFirstSegment {
- FSTAssert(!self.isEmpty, @"Cannot call pathByRemovingFirstSegment on empty path");
- return [self pathWithSegments:self.segments offset:self.offset + 1 length:self.length - 1];
-}
-
-- (instancetype)pathByRemovingFirstSegments:(int)count {
- FSTAssert(self.length >= count, @"pathByRemovingFirstSegments:%d on path of length %d", count,
- self.length);
- return
- [self pathWithSegments:self.segments offset:self.offset + count length:self.length - count];
-}
-
-- (instancetype)pathByRemovingLastSegment {
- FSTAssert(!self.isEmpty, @"Cannot call pathByRemovingLastSegment on empty path");
- return [self pathWithSegments:self.segments offset:self.offset length:self.length - 1];
-}
-
-- (BOOL)isPrefixOfPath:(FSTPath *)other {
- if (other.length < self.length) {
- return NO;
- }
- for (int i = 0; i < self.length; ++i) {
- if (![self[i] isEqual:other[i]]) {
- return NO;
- }
- }
- return YES;
-}
-
-/** Returns a standardized string representation of this path. */
-- (NSString *)canonicalString {
- @throw FSTAbstractMethodException(); // NOLINT
-}
-@end
-
-@implementation FSTFieldPath
-+ (instancetype)pathWithSegments:(NSArray<NSString *> *)segments {
- return [[FSTFieldPath alloc] initWithSegments:segments offset:0 length:(int)segments.count];
-}
-
-+ (instancetype)pathWithServerFormat:(NSString *)fieldPath {
- NSMutableArray<NSString *> *segments = [NSMutableArray array];
-
- // TODO(b/37244157): Once we move to v1beta1, we should make this more strict. Right now, it
- // allows non-identifier path components, even if they aren't escaped. Technically, this will
- // mangle paths with backticks in them used in v1alpha1, but that's fine.
-
- const char *source = [fieldPath UTF8String];
- char *segment = (char *)malloc(strlen(source) + 1);
- char *segmentEnd = segment;
-
- // If we're inside '`' backticks, then we should ignore '.' dots.
- BOOL inBackticks = NO;
-
- char c;
- do {
- // Examine current character. This is legit even on zero-length strings because there's always
- // a null terminator.
- c = *source++;
- switch (c) {
- case '\0': // Falls through
- case '.':
- if (!inBackticks) {
- // Segment is complete
- *segmentEnd = '\0';
- if (segment == segmentEnd) {
- FSTThrowInvalidArgument(
- @"Invalid field path (%@). Paths must not be empty, begin with "
- @"'.', end with '.', or contain '..'",
- fieldPath);
- }
-
- [segments addObject:[NSString stringWithUTF8String:segment]];
- segmentEnd = segment;
- } else {
- // copy into the current segment
- *segmentEnd++ = c;
- }
- break;
-
- case '`':
- if (inBackticks) {
- inBackticks = NO;
- } else {
- inBackticks = YES;
- }
- break;
-
- case '\\':
- // advance to escaped character
- c = *source++;
- // TODO(b/37244157): Make this a user-facing exception once we finalize field escaping.
- FSTAssert(c != '\0', @"Trailing escape characters not allowed in %@", fieldPath);
- // Fall through
-
- default:
- // copy into the current segment
- *segmentEnd++ = c;
- break;
- }
- } while (c);
-
- FSTAssert(!inBackticks, @"Unterminated ` in path %@", fieldPath);
-
- free(segment);
- return [FSTFieldPath pathWithSegments:segments];
-}
-
-+ (instancetype)keyFieldPath {
- static FSTFieldPath *keyFieldPath;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- keyFieldPath = [FSTFieldPath pathWithSegments:@[ kDocumentKeyPath ]];
- });
- return keyFieldPath;
-}
-
-+ (instancetype)emptyPath {
- static FSTFieldPath *emptyPath;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- emptyPath = [FSTFieldPath pathWithSegments:@[]];
- });
- return emptyPath;
-}
-
-/** Return YES if the string could be used as a segment in a field path without escaping. */
-+ (BOOL)isValidIdentifier:(NSString *)segment {
- if (segment.length == 0) {
- return NO;
- }
- unichar first = [segment characterAtIndex:0];
- if (first != '_' && (first < 'a' || first > 'z') && (first < 'A' || first > 'Z')) {
- return NO;
- }
- for (int i = 1; i < segment.length; i++) {
- unichar c = [segment characterAtIndex:i];
- if (c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9')) {
- return NO;
- }
- }
- return YES;
-}
-
-- (BOOL)isKeyFieldPath {
- return [self isEqual:FSTFieldPath.keyFieldPath];
-}
-
-- (NSString *)canonicalString {
- NSMutableString *result = [NSMutableString string];
- for (int i = 0; i < self.length; i++) {
- if (i > 0) {
- [result appendString:@"."];
- }
-
- NSString *escaped = [self[i] stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"];
- escaped = [escaped stringByReplacingOccurrencesOfString:@"`" withString:@"\\`"];
- if (![FSTFieldPath isValidIdentifier:escaped]) {
- escaped = [NSString stringWithFormat:@"`%@`", escaped];
- }
-
- [result appendString:escaped];
- }
- return result;
-}
-
-+ (instancetype)fieldPathWithCPPFieldPath:(const FieldPath &)fieldPath {
- NSMutableArray<NSString *> *segments = [NSMutableArray arrayWithCapacity:fieldPath.size()];
- for (int i = 0; i < fieldPath.size(); i++) {
- segments[i] = util::WrapNSString(fieldPath[i]);
- }
- return [FSTFieldPath pathWithSegments:segments];
-}
-
-- (FieldPath)toCPPFieldPath {
- std::vector<std::string> segments(self.length);
- for (int i = 0; i < self.length; i++) {
- segments[i] = [[self segmentAtIndex:i] UTF8String];
- }
- return FieldPath(segments.begin(), segments.end());
-}
-
-@end
-
-@implementation FSTResourcePath
-+ (instancetype)pathWithSegments:(NSArray<NSString *> *)segments {
- return [[FSTResourcePath alloc] initWithSegments:segments offset:0 length:(int)segments.count];
-}
-
-+ (instancetype)pathWithString:(NSString *)resourcePath {
- // NOTE: The client is ignorant of any path segments containing escape sequences (e.g. __id123__)
- // and just passes them through raw (they exist for legacy reasons and should not be used
- // frequently).
-
- if ([resourcePath rangeOfString:@"//"].location != NSNotFound) {
- FSTThrowInvalidArgument(@"Invalid path (%@). Paths must not contain // in them.", resourcePath);
- }
-
- NSMutableArray *segments = [[resourcePath componentsSeparatedByString:@"/"] mutableCopy];
- // We may still have an empty segment at the beginning or end if they had a leading or trailing
- // slash (which we allow).
- [segments removeObject:@""];
-
- return [self pathWithSegments:segments];
-}
-
-- (NSString *)canonicalString {
- // NOTE: The client is ignorant of any path segments containing escape sequences (e.g. __id123__)
- // and just passes them through raw (they exist for legacy reasons and should not be used
- // frequently).
-
- NSMutableString *result = [NSMutableString string];
- for (int i = 0; i < self.length; i++) {
- if (i > 0) {
- [result appendString:@"/"];
- }
- [result appendString:self[i]];
- }
- return result;
-}
-
-+ (instancetype)resourcePathWithCPPResourcePath:(const ResourcePath &)resourcePath {
- NSMutableArray<NSString *> *segments = [NSMutableArray arrayWithCapacity:resourcePath.size()];
- for (int i = 0; i < resourcePath.size(); i++) {
- segments[i] = util::WrapNSString(resourcePath[i]);
- }
- return [FSTResourcePath pathWithSegments:segments];
-}
-
-- (ResourcePath)toCPPResourcePath {
- std::vector<std::string> segments(self.length);
- for (int i = 0; i < self.length; i++) {
- segments[i] = [[self segmentAtIndex:i] UTF8String];
- }
- return ResourcePath(segments.begin(), segments.end());
-}
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Firestore/Source/Remote/FSTDatastore.mm b/Firestore/Source/Remote/FSTDatastore.mm
index 3b536ab..e63017a 100644
--- a/Firestore/Source/Remote/FSTDatastore.mm
+++ b/Firestore/Source/Remote/FSTDatastore.mm
@@ -111,10 +111,9 @@ typedef GRPCProtoCall * (^RPCFactory)(void);
}
- (NSString *)description {
- return [NSString
- stringWithFormat:@"<FSTDatastore: <DatabaseInfo: database_id:%@ host:%@>>",
- util::WrapNSStringNoCopy(self.databaseInfo->database_id().database_id()),
- util::WrapNSStringNoCopy(self.databaseInfo->host())];
+ return [NSString stringWithFormat:@"<FSTDatastore: <DatabaseInfo: database_id:%s host:%s>>",
+ self.databaseInfo->database_id().database_id().c_str(),
+ self.databaseInfo->host().c_str()];
}
/**
@@ -186,9 +185,8 @@ typedef GRPCProtoCall * (^RPCFactory)(void);
/** Returns the string to be used as google-cloud-resource-prefix header value. */
+ (NSString *)googleCloudResourcePrefixForDatabaseID:(const DatabaseId *)databaseID {
- return [NSString stringWithFormat:@"projects/%@/databases/%@",
- util::WrapNSStringNoCopy(databaseID->project_id()),
- util::WrapNSStringNoCopy(databaseID->database_id())];
+ return [NSString stringWithFormat:@"projects/%s/databases/%s", databaseID->project_id().c_str(),
+ databaseID->database_id().c_str()];
}
/**
* Takes a dictionary of (HTTP) response headers and returns the set of whitelisted headers
diff --git a/Firestore/Source/Remote/FSTRemoteStore.mm b/Firestore/Source/Remote/FSTRemoteStore.mm
index 2c8e84a..f484278 100644
--- a/Firestore/Source/Remote/FSTRemoteStore.mm
+++ b/Firestore/Source/Remote/FSTRemoteStore.mm
@@ -27,7 +27,6 @@
#import "Firestore/Source/Model/FSTDocumentKey.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTDatastore.h"
#import "Firestore/Source/Remote/FSTExistenceFilter.h"
#import "Firestore/Source/Remote/FSTOnlineStateTracker.h"
@@ -211,8 +210,7 @@ static const int kMaxPendingWrites = 10;
}
- (void)userDidChange:(const User &)user {
- FSTLog(@"FSTRemoteStore %p changing users: %@", (__bridge void *)self,
- util::WrapNSStringNoCopy(user.uid()));
+ FSTLog(@"FSTRemoteStore %p changing users: %s", (__bridge void *)self, user.uid().c_str());
if ([self isNetworkEnabled]) {
// Tear down and re-create our network streams. This will ensure we get a fresh auth token
// for the new user and re-fill the write pipeline with new mutations from the LocalStore
diff --git a/Firestore/Source/Remote/FSTSerializerBeta.mm b/Firestore/Source/Remote/FSTSerializerBeta.mm
index 00391ec..77d2ec7 100644
--- a/Firestore/Source/Remote/FSTSerializerBeta.mm
+++ b/Firestore/Source/Remote/FSTSerializerBeta.mm
@@ -39,16 +39,19 @@
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Model/FSTMutationBatch.h"
-#import "Firestore/Source/Model/FSTPath.h"
#import "Firestore/Source/Remote/FSTExistenceFilter.h"
#import "Firestore/Source/Remote/FSTWatchChange.h"
#import "Firestore/Source/Util/FSTAssert.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
namespace util = firebase::firestore::util;
using firebase::firestore::model::DatabaseId;
+using firebase::firestore::model::FieldPath;
+using firebase::firestore::model::ResourcePath;
NS_ASSUME_NONNULL_BEGIN
@@ -104,73 +107,67 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - FSTDocumentKey <=> Key proto
- (NSString *)encodedDocumentKey:(FSTDocumentKey *)key {
- return [self
- encodedResourcePathForDatabaseID:self.databaseID
- path:[FSTResourcePath resourcePathWithCPPResourcePath:key.path]];
+ return [self encodedResourcePathForDatabaseID:self.databaseID path:key.path];
}
- (FSTDocumentKey *)decodedDocumentKey:(NSString *)name {
- FSTResourcePath *path = [self decodedResourcePathWithDatabaseID:name];
- FSTAssert([[path segmentAtIndex:1]
- isEqualToString:util::WrapNSStringNoCopy(self.databaseID->project_id())],
+ const ResourcePath path = [self decodedResourcePathWithDatabaseID:name];
+ FSTAssert(path[1] == self.databaseID->project_id(),
@"Tried to deserialize key from different project.");
- FSTAssert([[path segmentAtIndex:3]
- isEqualToString:util::WrapNSStringNoCopy(self.databaseID->database_id())],
+ FSTAssert(path[3] == self.databaseID->database_id(),
@"Tried to deserialize key from different datbase.");
- return [FSTDocumentKey
- keyWithPath:[[self localResourcePathForQualifiedResourcePath:path] toCPPResourcePath]];
+ return [FSTDocumentKey keyWithPath:[self localResourcePathForQualifiedResourcePath:path]];
}
- (NSString *)encodedResourcePathForDatabaseID:(const DatabaseId *)databaseID
- path:(FSTResourcePath *)path {
- return [[[[self encodedResourcePathForDatabaseID:databaseID] pathByAppendingSegment:@"documents"]
- pathByAppendingPath:path] canonicalString];
+ path:(const ResourcePath &)path {
+ return util::WrapNSString([self encodedResourcePathForDatabaseID:databaseID]
+ .Append("documents")
+ .Append(path)
+ .CanonicalString());
}
-- (FSTResourcePath *)decodedResourcePathWithDatabaseID:(NSString *)name {
- FSTResourcePath *path = [FSTResourcePath pathWithString:name];
- FSTAssert([self validQualifiedResourcePath:path], @"Tried to deserialize invalid key %@", path);
+- (ResourcePath)decodedResourcePathWithDatabaseID:(NSString *)name {
+ const ResourcePath path = ResourcePath::FromString(util::MakeStringView(name));
+ FSTAssert([self validQualifiedResourcePath:path], @"Tried to deserialize invalid key %s",
+ path.CanonicalString().c_str());
return path;
}
-- (NSString *)encodedQueryPath:(FSTResourcePath *)path {
- if (path.length == 0) {
+- (NSString *)encodedQueryPath:(const ResourcePath &)path {
+ if (path.size() == 0) {
// If the path is empty, the backend requires we leave off the /documents at the end.
return [self encodedDatabaseID];
}
return [self encodedResourcePathForDatabaseID:self.databaseID path:path];
}
-- (FSTResourcePath *)decodedQueryPath:(NSString *)name {
- FSTResourcePath *resource = [self decodedResourcePathWithDatabaseID:name];
- if (resource.length == 4) {
- return [FSTResourcePath pathWithSegments:@[]];
+- (ResourcePath)decodedQueryPath:(NSString *)name {
+ const ResourcePath resource = [self decodedResourcePathWithDatabaseID:name];
+ if (resource.size() == 4) {
+ return ResourcePath{};
} else {
return [self localResourcePathForQualifiedResourcePath:resource];
}
}
-- (FSTResourcePath *)encodedResourcePathForDatabaseID:(const DatabaseId *)databaseID {
- return [FSTResourcePath pathWithSegments:@[
- @"projects", util::WrapNSString(databaseID->project_id()), @"databases",
- util::WrapNSString(databaseID->database_id())
- ]];
+- (ResourcePath)encodedResourcePathForDatabaseID:(const DatabaseId *)databaseID {
+ return ResourcePath{"projects", databaseID->project_id(), "databases", databaseID->database_id()};
}
-- (FSTResourcePath *)localResourcePathForQualifiedResourcePath:(FSTResourcePath *)resourceName {
- FSTAssert(
- resourceName.length > 4 && [[resourceName segmentAtIndex:4] isEqualToString:@"documents"],
- @"Tried to deserialize invalid key %@", resourceName);
- return [resourceName pathByRemovingFirstSegments:5];
+- (ResourcePath)localResourcePathForQualifiedResourcePath:(const ResourcePath &)resourceName {
+ FSTAssert(resourceName.size() > 4 && resourceName[4] == "documents",
+ @"Tried to deserialize invalid key %s", resourceName.CanonicalString().c_str());
+ return resourceName.PopFirst(5);
}
-- (BOOL)validQualifiedResourcePath:(FSTResourcePath *)path {
- return path.length >= 4 && [[path segmentAtIndex:0] isEqualToString:@"projects"] &&
- [[path segmentAtIndex:2] isEqualToString:@"databases"];
+- (BOOL)validQualifiedResourcePath:(const ResourcePath &)path {
+ return path.size() >= 4 && path[0] == "projects" && path[2] == "databases";
}
- (NSString *)encodedDatabaseID {
- return [[self encodedResourcePathForDatabaseID:self.databaseID] canonicalString];
+ return util::WrapNSString(
+ [self encodedResourcePathForDatabaseID:self.databaseID].CanonicalString());
}
#pragma mark - FSTFieldValue <=> Value proto
@@ -310,31 +307,25 @@ NS_ASSUME_NONNULL_BEGIN
- (GCFSValue *)encodedReferenceValueForDatabaseID:(const DatabaseId *)databaseID
key:(FSTDocumentKey *)key {
- FSTAssert(*databaseID == *self.databaseID, @"Database %@:%@ cannot encode reference from %@:%@",
- util::WrapNSStringNoCopy(self.databaseID->project_id()),
- util::WrapNSStringNoCopy(self.databaseID->database_id()),
- util::WrapNSStringNoCopy(databaseID->project_id()),
- util::WrapNSStringNoCopy(databaseID->database_id()));
+ FSTAssert(*databaseID == *self.databaseID, @"Database %s:%s cannot encode reference from %s:%s",
+ self.databaseID->project_id().c_str(), self.databaseID->database_id().c_str(),
+ databaseID->project_id().c_str(), databaseID->database_id().c_str());
GCFSValue *result = [GCFSValue message];
- result.referenceValue = [self
- encodedResourcePathForDatabaseID:databaseID
- path:[FSTResourcePath resourcePathWithCPPResourcePath:key.path]];
+ result.referenceValue = [self encodedResourcePathForDatabaseID:databaseID path:key.path];
return result;
}
- (FSTReferenceValue *)decodedReferenceValue:(NSString *)resourceName {
- FSTResourcePath *path = [self decodedResourcePathWithDatabaseID:resourceName];
- NSString *project = [path segmentAtIndex:1];
- NSString *database = [path segmentAtIndex:3];
- FSTDocumentKey *key = [FSTDocumentKey
- keyWithPath:[[self localResourcePathForQualifiedResourcePath:path] toCPPResourcePath]];
-
- const DatabaseId database_id(util::MakeStringView(project), util::MakeStringView(database));
- FSTAssert(database_id == *self.databaseID, @"Database %@:%@ cannot encode reference from %@:%@",
- util::WrapNSStringNoCopy(self.databaseID->project_id()),
- util::WrapNSStringNoCopy(self.databaseID->database_id()),
- util::WrapNSStringNoCopy(database_id.project_id()),
- util::WrapNSStringNoCopy(database_id.database_id()));
+ const ResourcePath path = [self decodedResourcePathWithDatabaseID:resourceName];
+ const std::string &project = path[1];
+ const std::string &database = path[3];
+ FSTDocumentKey *key =
+ [FSTDocumentKey keyWithPath:[self localResourcePathForQualifiedResourcePath:path]];
+
+ const DatabaseId database_id(project, database);
+ FSTAssert(database_id == *self.databaseID, @"Database %s:%s cannot encode reference from %s:%s",
+ self.databaseID->project_id().c_str(), self.databaseID->database_id().c_str(),
+ database_id.project_id().c_str(), database_id.database_id().c_str());
return [FSTReferenceValue referenceValue:key databaseID:self.databaseID];
}
@@ -389,7 +380,7 @@ NS_ASSUME_NONNULL_BEGIN
__block FSTObjectValue *result = [FSTObjectValue objectValue];
[fields enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, GCFSValue *_Nonnull obj,
BOOL *_Nonnull stop) {
- FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ key ]];
+ FieldPath path{util::MakeString(key)};
FSTFieldValue *value = [self decodedFieldValue:obj];
result = [result objectBySettingValue:value forPath:path];
}];
@@ -550,19 +541,19 @@ NS_ASSUME_NONNULL_BEGIN
- (GCFSDocumentMask *)encodedFieldMask:(FSTFieldMask *)fieldMask {
GCFSDocumentMask *mask = [GCFSDocumentMask message];
- for (FSTFieldPath *field in fieldMask.fields) {
- [mask.fieldPathsArray addObject:field.canonicalString];
+ for (const FieldPath &field : fieldMask.fields) {
+ [mask.fieldPathsArray addObject:util::WrapNSString(field.CanonicalString())];
}
return mask;
}
- (FSTFieldMask *)decodedFieldMask:(GCFSDocumentMask *)fieldMask {
- NSMutableArray<FSTFieldPath *> *fields =
- [NSMutableArray arrayWithCapacity:fieldMask.fieldPathsArray_Count];
+ std::vector<FieldPath> fields{};
+ fields.reserve(fieldMask.fieldPathsArray_Count);
for (NSString *path in fieldMask.fieldPathsArray) {
- [fields addObject:[FSTFieldPath pathWithServerFormat:path]];
+ fields.push_back(FieldPath::FromServerFormat(util::MakeStringView(path)));
}
- return [[FSTFieldMask alloc] initWithFields:fields];
+ return [[FSTFieldMask alloc] initWithFields:std::move(fields)];
}
- (NSMutableArray<GCFSDocumentTransform_FieldTransform *> *)encodedFieldTransforms:
@@ -572,7 +563,7 @@ NS_ASSUME_NONNULL_BEGIN
FSTAssert([fieldTransform.transform isKindOfClass:[FSTServerTimestampTransform class]],
@"Unknown transform: %@", fieldTransform.transform);
GCFSDocumentTransform_FieldTransform *proto = [GCFSDocumentTransform_FieldTransform message];
- proto.fieldPath = fieldTransform.path.canonicalString;
+ proto.fieldPath = util::WrapNSString(fieldTransform.path.CanonicalString());
proto.setToServerValue = GCFSDocumentTransform_FieldTransform_ServerValue_RequestTime;
[protos addObject:proto];
}
@@ -588,7 +579,8 @@ NS_ASSUME_NONNULL_BEGIN
@"Unknown transform setToServerValue: %d", proto.setToServerValue);
[fieldTransforms
addObject:[[FSTFieldTransform alloc]
- initWithPath:[FSTFieldPath pathWithServerFormat:proto.fieldPath]
+ initWithPath:FieldPath::FromServerFormat(
+ util::MakeStringView(proto.fieldPath))
transform:[FSTServerTimestampTransform serverTimestampTransform]]];
}
return fieldTransforms;
@@ -659,8 +651,7 @@ NS_ASSUME_NONNULL_BEGIN
- (GCFSTarget_DocumentsTarget *)encodedDocumentsTarget:(FSTQuery *)query {
GCFSTarget_DocumentsTarget *result = [GCFSTarget_DocumentsTarget message];
NSMutableArray<NSString *> *docs = result.documentsArray;
- [docs addObject:[self encodedQueryPath:[FSTResourcePath
- resourcePathWithCPPResourcePath:query.path]]];
+ [docs addObject:[self encodedQueryPath:query.path]];
return result;
}
@@ -670,21 +661,20 @@ NS_ASSUME_NONNULL_BEGIN
(unsigned long)documents.count);
NSString *name = documents[0];
- return [FSTQuery queryWithPath:[[self decodedQueryPath:name] toCPPResourcePath]];
+ return [FSTQuery queryWithPath:[self decodedQueryPath:name]];
}
- (GCFSTarget_QueryTarget *)encodedQueryTarget:(FSTQuery *)query {
// Dissect the path into parent, collectionId, and optional key filter.
GCFSTarget_QueryTarget *queryTarget = [GCFSTarget_QueryTarget message];
- if (query.path.empty()) {
- queryTarget.parent =
- [self encodedQueryPath:[FSTResourcePath resourcePathWithCPPResourcePath:query.path]];
+ if (query.path.size() == 0) {
+ queryTarget.parent = [self encodedQueryPath:query.path];
} else {
- FSTResourcePath *path = [FSTResourcePath resourcePathWithCPPResourcePath:query.path];
- FSTAssert(path.length % 2 != 0, @"Document queries with filters are not supported.");
- queryTarget.parent = [self encodedQueryPath:[path pathByRemovingLastSegment]];
+ const ResourcePath &path = query.path;
+ FSTAssert(path.size() % 2 != 0, @"Document queries with filters are not supported.");
+ queryTarget.parent = [self encodedQueryPath:path.PopLast()];
GCFSStructuredQuery_CollectionSelector *from = [GCFSStructuredQuery_CollectionSelector message];
- from.collectionId = path.lastSegment;
+ from.collectionId = util::WrapNSString(path.last_segment());
[queryTarget.structuredQuery.fromArray addObject:from];
}
@@ -715,7 +705,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (FSTQuery *)decodedQueryFromQueryTarget:(GCFSTarget_QueryTarget *)target {
- FSTResourcePath *path = [self decodedQueryPath:target.parent];
+ ResourcePath path = [self decodedQueryPath:target.parent];
GCFSStructuredQuery *query = target.structuredQuery;
NSUInteger fromCount = query.fromArray_Count;
@@ -724,7 +714,7 @@ NS_ASSUME_NONNULL_BEGIN
@"StructuredQuery.from with more than one collection is not supported.");
GCFSStructuredQuery_CollectionSelector *from = query.fromArray[0];
- path = [path pathByAppendingSegment:from.collectionId];
+ path = path.Append(util::MakeString(from.collectionId));
}
NSArray<id<FSTFilter>> *filterBy;
@@ -756,7 +746,7 @@ NS_ASSUME_NONNULL_BEGIN
endAt = [self decodedBound:query.endAt];
}
- return [[FSTQuery alloc] initWithPath:[path toCPPResourcePath]
+ return [[FSTQuery alloc] initWithPath:path
filterBy:filterBy
orderBy:orderBy
limit:limit
@@ -825,25 +815,22 @@ NS_ASSUME_NONNULL_BEGIN
- (GCFSStructuredQuery_Filter *)encodedRelationFilter:(FSTRelationFilter *)filter {
GCFSStructuredQuery_Filter *proto = [GCFSStructuredQuery_Filter message];
GCFSStructuredQuery_FieldFilter *fieldFilter = proto.fieldFilter;
- fieldFilter.field = [self encodedFieldPath:[FSTFieldPath fieldPathWithCPPFieldPath:filter.field]];
+ fieldFilter.field = [self encodedFieldPath:filter.field];
fieldFilter.op = [self encodedRelationFilterOperator:filter.filterOperator];
fieldFilter.value = [self encodedFieldValue:filter.value];
return proto;
}
- (FSTRelationFilter *)decodedRelationFilter:(GCFSStructuredQuery_FieldFilter *)proto {
- FSTFieldPath *fieldPath = [FSTFieldPath pathWithServerFormat:proto.field.fieldPath];
+ FieldPath fieldPath = FieldPath::FromServerFormat(util::MakeString(proto.field.fieldPath));
FSTRelationFilterOperator filterOperator = [self decodedRelationFilterOperator:proto.op];
FSTFieldValue *value = [self decodedFieldValue:proto.value];
- return [FSTRelationFilter filterWithField:[fieldPath toCPPFieldPath]
- filterOperator:filterOperator
- value:value];
+ return [FSTRelationFilter filterWithField:fieldPath filterOperator:filterOperator value:value];
}
- (GCFSStructuredQuery_Filter *)encodedUnaryFilter:(id<FSTFilter>)filter {
GCFSStructuredQuery_Filter *proto = [GCFSStructuredQuery_Filter message];
- proto.unaryFilter.field =
- [self encodedFieldPath:[FSTFieldPath fieldPathWithCPPFieldPath:filter.field]];
+ proto.unaryFilter.field = [self encodedFieldPath:filter.field];
if ([filter isKindOfClass:[FSTNanFilter class]]) {
proto.unaryFilter.op = GCFSStructuredQuery_UnaryFilter_Operator_IsNan;
} else if ([filter isKindOfClass:[FSTNullFilter class]]) {
@@ -855,22 +842,22 @@ NS_ASSUME_NONNULL_BEGIN
}
- (id<FSTFilter>)decodedUnaryFilter:(GCFSStructuredQuery_UnaryFilter *)proto {
- FSTFieldPath *field = [FSTFieldPath pathWithServerFormat:proto.field.fieldPath];
+ FieldPath field = FieldPath::FromServerFormat(util::MakeString(proto.field.fieldPath));
switch (proto.op) {
case GCFSStructuredQuery_UnaryFilter_Operator_IsNan:
- return [[FSTNanFilter alloc] initWithField:[field toCPPFieldPath]];
+ return [[FSTNanFilter alloc] initWithField:field];
case GCFSStructuredQuery_UnaryFilter_Operator_IsNull:
- return [[FSTNullFilter alloc] initWithField:[field toCPPFieldPath]];
+ return [[FSTNullFilter alloc] initWithField:field];
default:
FSTFail(@"Unrecognized UnaryFilter.operator %d", proto.op);
}
}
-- (GCFSStructuredQuery_FieldReference *)encodedFieldPath:(FSTFieldPath *)fieldPath {
+- (GCFSStructuredQuery_FieldReference *)encodedFieldPath:(const FieldPath &)fieldPath {
GCFSStructuredQuery_FieldReference *ref = [GCFSStructuredQuery_FieldReference message];
- ref.fieldPath = fieldPath.canonicalString;
+ ref.fieldPath = util::WrapNSString(fieldPath.CanonicalString());
return ref;
}
@@ -930,7 +917,7 @@ NS_ASSUME_NONNULL_BEGIN
- (GCFSStructuredQuery_Order *)encodedSortOrder:(FSTSortOrder *)sortOrder {
GCFSStructuredQuery_Order *proto = [GCFSStructuredQuery_Order message];
- proto.field = [self encodedFieldPath:[FSTFieldPath fieldPathWithCPPFieldPath:sortOrder.field]];
+ proto.field = [self encodedFieldPath:sortOrder.field];
if (sortOrder.ascending) {
proto.direction = GCFSStructuredQuery_Direction_Ascending;
} else {
@@ -940,7 +927,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (FSTSortOrder *)decodedSortOrder:(GCFSStructuredQuery_Order *)proto {
- FSTFieldPath *fieldPath = [FSTFieldPath pathWithServerFormat:proto.field.fieldPath];
+ FieldPath fieldPath = FieldPath::FromServerFormat(util::MakeString(proto.field.fieldPath));
BOOL ascending;
switch (proto.direction) {
case GCFSStructuredQuery_Direction_Ascending:
@@ -952,7 +939,7 @@ NS_ASSUME_NONNULL_BEGIN
default:
FSTFail(@"Unrecognized GCFSStructuredQuery_Direction %d", proto.direction);
}
- return [FSTSortOrder sortOrderWithFieldPath:[fieldPath toCPPFieldPath] ascending:ascending];
+ return [FSTSortOrder sortOrderWithFieldPath:fieldPath ascending:ascending];
}
#pragma mark - Bounds/Cursors
diff --git a/Firestore/core/src/firebase/firestore/model/field_path.h b/Firestore/core/src/firebase/firestore/model/field_path.h
index fdf4918..ce3527d 100644
--- a/Firestore/core/src/firebase/firestore/model/field_path.h
+++ b/Firestore/core/src/firebase/firestore/model/field_path.h
@@ -48,6 +48,8 @@ class FieldPath : public impl::BasePath<FieldPath> {
}
FieldPath(std::initializer_list<std::string> list) : BasePath{list} {
}
+ explicit FieldPath(SegmentsT&& segments) : BasePath{std::move(segments)} {
+ }
/**
* Creates and returns a new path from the server formatted field-path string,
@@ -83,14 +85,6 @@ class FieldPath : public impl::BasePath<FieldPath> {
bool operator>=(const FieldPath& rhs) const {
return BasePath::operator>=(rhs);
}
-
- private:
- explicit FieldPath(SegmentsT&& segments) : BasePath{std::move(segments)} {
- }
-
- // So that methods of base can construct FieldPath using the private
- // constructor.
- friend class BasePath;
};
} // namespace model
diff --git a/Firestore/core/src/firebase/firestore/model/resource_path.h b/Firestore/core/src/firebase/firestore/model/resource_path.h
index 6ff1b68..acdf1e2 100644
--- a/Firestore/core/src/firebase/firestore/model/resource_path.h
+++ b/Firestore/core/src/firebase/firestore/model/resource_path.h
@@ -70,11 +70,6 @@ class ResourcePath : public impl::BasePath<ResourcePath> {
bool operator>=(const ResourcePath& rhs) const {
return BasePath::operator>=(rhs);
}
-
- private:
- // So that methods of base can construct ResourcePath using the private
- // constructor.
- friend class BasePath;
};
} // namespace model
diff --git a/Firestore/core/src/firebase/firestore/util/string_apple.h b/Firestore/core/src/firebase/firestore/util/string_apple.h
index 3f6b814..73388be 100644
--- a/Firestore/core/src/firebase/firestore/util/string_apple.h
+++ b/Firestore/core/src/firebase/firestore/util/string_apple.h
@@ -22,6 +22,8 @@
#import <Foundation/Foundation.h>
+#include <string>
+
#include "absl/strings/string_view.h"
namespace firebase {
@@ -57,6 +59,12 @@ inline absl::string_view MakeStringView(NSString* str) {
[str UTF8String], [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
}
+// Creates a std::string wrapper for the contents of the given NSString.
+inline std::string MakeString(NSString* str) {
+ return std::string([str UTF8String],
+ [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
+}
+
} // namespace util
} // namespace firestore
} // namespace firebase