aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Carthage.md5
-rw-r--r--Example/Auth/Sample/MainViewController.m11
-rw-r--r--Example/Auth/Tests/FIRAuthTests.m4
-rw-r--r--Example/Auth/Tests/FIRUserTests.m6
-rw-r--r--Example/Core/Tests/FIRAppTest.m40
-rw-r--r--Example/Core/Tests/FIRLoggerTest.m4
-rw-r--r--Example/Core/Tests/FIROptionsTest.m67
-rw-r--r--Example/Core/Tests/FIRTestCase.m1
-rw-r--r--Example/Firebase.xcodeproj/project.pbxproj392
-rw-r--r--Example/Firebase.xcodeproj/xcshareddata/xcschemes/Messaging_Sample_iOS.xcscheme91
-rw-r--r--Example/Messaging/App/iOS/Base.lproj/LaunchScreen.storyboard12
-rw-r--r--Example/Messaging/App/iOS/Base.lproj/Main.storyboard47
-rw-r--r--Example/Messaging/App/iOS/FIRAppDelegate.h23
-rw-r--r--Example/Messaging/App/iOS/FIRAppDelegate.m58
-rw-r--r--Example/Messaging/App/iOS/FIRViewController.h21
-rw-r--r--Example/Messaging/App/iOS/FIRViewController.m33
-rw-r--r--Example/Messaging/App/iOS/main.m22
-rw-r--r--Example/Messaging/Sample/GoogleService-Info.plist (renamed from Example/Messaging/App/GoogleService-Info.plist)0
-rw-r--r--Example/Messaging/Sample/iOS/AppDelegate.swift (renamed from Example/Messaging/App/iOS/AppDelegate.swift)0
-rw-r--r--Example/Messaging/Sample/iOS/Base.lproj/LaunchScreen.storyboard27
-rw-r--r--Example/Messaging/Sample/iOS/Base.lproj/Main.storyboard48
-rw-r--r--Example/Messaging/Sample/iOS/Data+MessagingExtensions.swift (renamed from Example/Messaging/App/iOS/Data+MessagingExtensions.swift)0
-rw-r--r--Example/Messaging/Sample/iOS/Environment.swift (renamed from Example/Messaging/App/iOS/Environment.swift)0
-rw-r--r--Example/Messaging/Sample/iOS/Messaging-Info.plist (renamed from Example/Messaging/App/iOS/Messaging-Info.plist)0
-rw-r--r--Example/Messaging/Sample/iOS/MessagingViewController.swift (renamed from Example/Messaging/App/iOS/MessagingViewController.swift)0
-rw-r--r--Example/Messaging/Sample/iOS/Messaging_Example.entitlements (renamed from Example/Messaging/App/iOS/Messaging_Example.entitlements)0
-rw-r--r--Example/Messaging/Sample/iOS/NotificationsController.swift (renamed from Example/Messaging/App/iOS/NotificationsController.swift)0
-rw-r--r--Example/Messaging/Tests/FIRMessagingServiceTest.m6
-rw-r--r--Example/Podfile6
-rw-r--r--Example/Storage/App/iOS/FIRAppDelegate.m2
-rw-r--r--Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m32
-rw-r--r--Example/Storage/Tests/Unit/FIRStorageMetadataTests.m60
-rw-r--r--Firebase/Auth/Source/Public/FIRAuth.h2
-rw-r--r--Firebase/Core/CHANGELOG.md2
-rw-r--r--Firebase/Core/FIRApp.m24
-rw-r--r--Firebase/Core/FIRConfiguration.m6
-rw-r--r--Firebase/Core/FIROptions.m39
-rw-r--r--Firebase/Core/Public/FIRApp.h13
-rw-r--r--Firebase/Core/Public/FIRConfiguration.h28
-rw-r--r--Firebase/Core/Public/FIROptions.h19
-rw-r--r--Firebase/Core/third_party/FIRAppEnvironmentUtil.m7
-rw-r--r--Firebase/Database/Core/FPersistentConnection.m16
-rw-r--r--Firebase/Database/Core/FRepo.m4
-rw-r--r--Firebase/Messaging/FIRMMessageCode.h2
-rw-r--r--Firebase/Messaging/FIRMessaging.m90
-rw-r--r--Firebase/Messaging/FIRMessagingPubSub.h8
-rw-r--r--Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m19
-rw-r--r--Firebase/Messaging/FIRMessaging_Private.h3
-rw-r--r--Firebase/Messaging/Public/FIRMessaging.h93
-rw-r--r--Firebase/Storage/CHANGELOG.md6
-rw-r--r--Firebase/Storage/FIRStorageErrors.m17
-rw-r--r--Firebase/Storage/FIRStorageGetDownloadURLTask.m117
-rw-r--r--Firebase/Storage/FIRStorageGetMetadataTask.m36
-rw-r--r--Firebase/Storage/FIRStorageMetadata.m48
-rw-r--r--Firebase/Storage/FIRStorageReference.m16
-rw-r--r--Firebase/Storage/FIRStorageUpdateMetadataTask.m36
-rw-r--r--Firebase/Storage/FIRStorageUploadTask.m9
-rw-r--r--Firebase/Storage/Private/FIRStorageConstants_Private.h1
-rw-r--r--Firebase/Storage/Private/FIRStorageErrors.h18
-rw-r--r--Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h34
-rw-r--r--Firebase/Storage/Private/FIRStorageGetDownloadURLTask_Private.h31
-rw-r--r--Firebase/Storage/Public/FIRStorage.h3
-rw-r--r--Firebase/Storage/Public/FIRStorageMetadata.h14
-rw-r--r--FirebaseCore.podspec2
-rw-r--r--Firestore/CMakeLists.txt42
-rw-r--r--Firestore/Example/SwiftBuildTest/main.swift4
-rw-r--r--Firestore/Example/Tests/Core/FSTQueryListenerTests.mm3
-rw-r--r--Firestore/Example/Tests/Core/FSTSyncEngine+Testing.h2
-rw-r--r--Firestore/Example/Tests/GoogleTest/FSTGoogleTestTests.mm4
-rw-r--r--Firestore/Example/Tests/Integration/API/FIRValidationTests.mm2
-rw-r--r--Firestore/Example/Tests/Integration/FSTDatastoreTests.mm4
-rw-r--r--Firestore/Example/Tests/Local/FSTEagerGarbageCollectorTests.mm4
-rw-r--r--Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm2
-rw-r--r--Firestore/Example/Tests/Local/FSTLevelDBLocalStoreTests.mm5
-rw-r--r--Firestore/Example/Tests/Local/FSTLevelDBMigrationsTests.mm4
-rw-r--r--Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm4
-rw-r--r--Firestore/Example/Tests/Local/FSTLevelDBRemoteDocumentCacheTests.mm9
-rw-r--r--Firestore/Example/Tests/Local/FSTLevelDBTransactionTests.mm14
-rw-r--r--Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm17
-rw-r--r--Firestore/Example/Tests/Local/FSTLocalStoreTests.h4
-rw-r--r--Firestore/Example/Tests/Local/FSTMemoryLocalStoreTests.mm5
-rw-r--r--Firestore/Example/Tests/Local/FSTMutationQueueTests.mm4
-rw-r--r--Firestore/Example/Tests/Local/FSTQueryCacheTests.mm2
-rw-r--r--Firestore/Example/Tests/Local/StringViewTests.mm3
-rw-r--r--Firestore/Example/Tests/Model/FSTFieldValueTests.mm1
-rw-r--r--Firestore/Example/Tests/Model/FSTMutationTests.mm71
-rw-r--r--Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm30
-rw-r--r--Firestore/Example/Tests/SpecTests/FSTSpecTests.mm6
-rw-r--r--Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm6
-rw-r--r--Firestore/Example/Tests/Util/FSTHelpers.h8
-rw-r--r--Firestore/Example/Tests/Util/FSTHelpers.mm59
-rw-r--r--Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm7
-rw-r--r--Firestore/Protos/FrameworkMaker.xcodeproj/project.pbxproj2
-rw-r--r--Firestore/Protos/README.md10
-rw-r--r--Firestore/Protos/nanopb/firestore/local/target.pb.c5
-rw-r--r--Firestore/Protos/nanopb/firestore/local/target.pb.h12
-rw-r--r--Firestore/Protos/nanopb/google/api/http.pb.c5
-rw-r--r--Firestore/Protos/nanopb/google/api/http.pb.h10
-rw-r--r--Firestore/Protos/nanopb/google/firestore/v1beta1/query.pb.h9
-rw-r--r--Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.c15
-rw-r--r--Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.h16
-rw-r--r--Firestore/Protos/objc/google/api/HTTP.pbobjc.h75
-rw-r--r--Firestore/Protos/objc/google/api/HTTP.pbobjc.m10
-rw-r--r--Firestore/Protos/objc/google/firestore/v1beta1/Document.pbobjc.h4
-rw-r--r--Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbobjc.h5
-rw-r--r--Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.h58
-rw-r--r--Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.m19
-rw-r--r--Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.h3
-rw-r--r--Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.m4
-rw-r--r--Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.h57
-rw-r--r--Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.m33
-rw-r--r--Firestore/Protos/protos/google/api/http.proto72
-rw-r--r--Firestore/Protos/protos/google/firestore/v1beta1/common.proto3
-rw-r--r--Firestore/Protos/protos/google/firestore/v1beta1/document.proto7
-rw-r--r--Firestore/Protos/protos/google/firestore/v1beta1/firestore.proto76
-rw-r--r--Firestore/Protos/protos/google/firestore/v1beta1/query.proto6
-rw-r--r--Firestore/Protos/protos/google/firestore/v1beta1/write.proto45
-rw-r--r--Firestore/Protos/protos/google/protobuf/any.proto21
-rw-r--r--Firestore/Protos/protos/google/protobuf/timestamp.proto8
-rw-r--r--Firestore/Source/API/FIRDocumentReference.mm13
-rw-r--r--Firestore/Source/API/FIRFieldPath.mm3
-rw-r--r--Firestore/Source/API/FIRFieldValue+Internal.h20
-rw-r--r--Firestore/Source/API/FIRFieldValue.mm46
-rw-r--r--Firestore/Source/API/FIRFirestore.mm7
-rw-r--r--Firestore/Source/API/FIRFirestoreVersion.mm2
-rw-r--r--Firestore/Source/API/FIRWriteBatch.mm15
-rw-r--r--Firestore/Source/API/FSTUserDataConverter.h39
-rw-r--r--Firestore/Source/API/FSTUserDataConverter.mm306
-rw-r--r--Firestore/Source/Core/FSTFirestoreClient.mm3
-rw-r--r--Firestore/Source/Core/FSTListenSequence.mm2
-rw-r--r--Firestore/Source/Core/FSTQuery.mm1
-rw-r--r--Firestore/Source/Core/FSTSyncEngine.mm5
-rw-r--r--Firestore/Source/Core/FSTTransaction.h2
-rw-r--r--Firestore/Source/Core/FSTTransaction.mm36
-rw-r--r--Firestore/Source/Local/FSTLevelDB.mm5
-rw-r--r--Firestore/Source/Local/FSTLevelDBKey.h2
-rw-r--r--Firestore/Source/Local/FSTLevelDBMigrations.mm8
-rw-r--r--Firestore/Source/Local/FSTLevelDBMutationQueue.mm8
-rw-r--r--Firestore/Source/Local/FSTLevelDBQueryCache.mm5
-rw-r--r--Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm5
-rw-r--r--Firestore/Source/Local/FSTLocalSerializer.mm2
-rw-r--r--Firestore/Source/Local/FSTLocalStore.mm2
-rw-r--r--Firestore/Source/Local/FSTNoOpGarbageCollector.mm2
-rw-r--r--Firestore/Source/Local/StringView.h17
-rw-r--r--Firestore/Source/Model/FSTDocumentKey.h1
-rw-r--r--Firestore/Source/Model/FSTDocumentKey.mm1
-rw-r--r--Firestore/Source/Model/FSTFieldValue.mm4
-rw-r--r--Firestore/Source/Model/FSTMutation.h133
-rw-r--r--Firestore/Source/Model/FSTMutation.mm335
-rw-r--r--Firestore/Source/Public/FIRFieldValue.h23
-rw-r--r--Firestore/Source/Remote/FSTDatastore.mm25
-rw-r--r--Firestore/Source/Remote/FSTRemoteStore.mm2
-rw-r--r--Firestore/Source/Remote/FSTSerializerBeta.mm87
-rw-r--r--Firestore/Source/Remote/FSTStream.mm3
-rw-r--r--Firestore/Source/Util/FSTAssert.h2
-rw-r--r--Firestore/Source/Util/FSTDispatchQueue.mm27
-rw-r--r--Firestore/Source/Util/FSTUsageValidation.h2
-rw-r--r--Firestore/Source/Util/FSTUsageValidation.mm2
-rw-r--r--Firestore/core/.clang-tidy34
-rw-r--r--Firestore/core/include/firebase/firestore/document_reference.h8
-rw-r--r--Firestore/core/include/firebase/firestore/timestamp.h7
-rw-r--r--Firestore/core/src/firebase/firestore/auth/credentials_provider.h4
-rw-r--r--Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h2
-rw-r--r--Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.mm3
-rw-r--r--Firestore/core/src/firebase/firestore/auth/token.h2
-rw-r--r--Firestore/core/src/firebase/firestore/auth/user.cc2
-rw-r--r--Firestore/core/src/firebase/firestore/auth/user.h2
-rw-r--r--Firestore/core/src/firebase/firestore/core/database_info.h6
-rw-r--r--Firestore/core/src/firebase/firestore/geo_point.cc4
-rw-r--r--Firestore/core/src/firebase/firestore/immutable/array_sorted_map.h6
-rw-r--r--Firestore/core/src/firebase/firestore/immutable/map_entry.h2
-rw-r--r--Firestore/core/src/firebase/firestore/immutable/sorted_map.h4
-rw-r--r--Firestore/core/src/firebase/firestore/immutable/sorted_map_base.h2
-rw-r--r--Firestore/core/src/firebase/firestore/immutable/tree_sorted_map.h3
-rw-r--r--Firestore/core/src/firebase/firestore/local/leveldb_key.cc2
-rw-r--r--Firestore/core/src/firebase/firestore/local/leveldb_transaction.cc3
-rw-r--r--Firestore/core/src/firebase/firestore/local/leveldb_transaction.h8
-rw-r--r--Firestore/core/src/firebase/firestore/model/CMakeLists.txt5
-rw-r--r--Firestore/core/src/firebase/firestore/model/database_id.h6
-rw-r--r--Firestore/core/src/firebase/firestore/model/document.cc2
-rw-r--r--Firestore/core/src/firebase/firestore/model/field_mask.h95
-rw-r--r--Firestore/core/src/firebase/firestore/model/field_transform.h70
-rw-r--r--Firestore/core/src/firebase/firestore/model/field_value.cc8
-rw-r--r--Firestore/core/src/firebase/firestore/model/field_value.h5
-rw-r--r--Firestore/core/src/firebase/firestore/model/precondition.cc67
-rw-r--r--Firestore/core/src/firebase/firestore/model/precondition.h160
-rw-r--r--Firestore/core/src/firebase/firestore/model/snapshot_version.h23
-rw-r--r--Firestore/core/src/firebase/firestore/model/transform_operations.h164
-rw-r--r--Firestore/core/src/firebase/firestore/model/types.h2
-rw-r--r--Firestore/core/src/firebase/firestore/remote/serializer.cc388
-rw-r--r--Firestore/core/src/firebase/firestore/remote/serializer.h16
-rw-r--r--Firestore/core/src/firebase/firestore/timestamp.cc2
-rw-r--r--Firestore/core/src/firebase/firestore/util/CMakeLists.txt42
-rw-r--r--Firestore/core/src/firebase/firestore/util/assert_apple.mm6
-rw-r--r--Firestore/core/src/firebase/firestore/util/assert_stdio.cc3
-rw-r--r--Firestore/core/src/firebase/firestore/util/bits.h14
-rw-r--r--Firestore/core/src/firebase/firestore/util/comparator_holder.h2
-rw-r--r--Firestore/core/src/firebase/firestore/util/comparison.cc7
-rw-r--r--Firestore/core/src/firebase/firestore/util/comparison.h2
-rw-r--r--Firestore/core/src/firebase/firestore/util/firebase_assert.h18
-rw-r--r--Firestore/core/src/firebase/firestore/util/log.h2
-rw-r--r--Firestore/core/src/firebase/firestore/util/log_stdio.cc2
-rw-r--r--Firestore/core/src/firebase/firestore/util/ordered_code.cc7
-rw-r--r--Firestore/core/src/firebase/firestore/util/secure_random.h2
-rw-r--r--Firestore/core/src/firebase/firestore/util/secure_random_arc4random.cc2
-rw-r--r--Firestore/core/src/firebase/firestore/util/secure_random_openssl.cc4
-rw-r--r--Firestore/core/src/firebase/firestore/util/string_printf.cc2
-rw-r--r--Firestore/core/src/firebase/firestore/util/string_printf.h3
-rw-r--r--Firestore/core/test/firebase/firestore/immutable/array_sorted_map_test.cc4
-rw-r--r--Firestore/core/test/firebase/firestore/immutable/sorted_map_test.cc1
-rw-r--r--Firestore/core/test/firebase/firestore/immutable/tree_sorted_map_test.cc2
-rw-r--r--Firestore/core/test/firebase/firestore/model/CMakeLists.txt4
-rw-r--r--Firestore/core/test/firebase/firestore/model/document_key_test.cc6
-rw-r--r--Firestore/core/test/firebase/firestore/model/field_mask_test.cc56
-rw-r--r--Firestore/core/test/firebase/firestore/model/field_path_test.cc8
-rw-r--r--Firestore/core/test/firebase/firestore/model/field_transform_test.cc39
-rw-r--r--Firestore/core/test/firebase/firestore/model/field_value_test.cc5
-rw-r--r--Firestore/core/test/firebase/firestore/model/precondition_test.cc77
-rw-r--r--Firestore/core/test/firebase/firestore/model/resource_path_test.cc2
-rw-r--r--Firestore/core/test/firebase/firestore/model/transform_operations_test.cc54
-rw-r--r--Firestore/core/test/firebase/firestore/remote/datastore_test.cc5
-rw-r--r--Firestore/core/test/firebase/firestore/remote/serializer_test.cc7
-rw-r--r--Firestore/core/test/firebase/firestore/testutil/testutil.h29
-rw-r--r--Firestore/core/test/firebase/firestore/util/CMakeLists.txt54
-rw-r--r--Firestore/core/test/firebase/firestore/util/autoid_test.cc4
-rw-r--r--Firestore/core/test/firebase/firestore/util/bits_test.cc16
-rw-r--r--Firestore/core/test/firebase/firestore/util/comparison_test.cc5
-rw-r--r--Firestore/core/test/firebase/firestore/util/secure_random_test.cc2
-rw-r--r--Firestore/core/test/firebase/firestore/util/string_printf_test.cc2
-rw-r--r--Firestore/core/test/firebase/firestore/util/string_util_test.cc2
-rw-r--r--Functions/FirebaseFunctions/Public/FIRError.h2
-rwxr-xr-xscripts/build.sh27
-rw-r--r--scripts/cpplint.py38
-rwxr-xr-xscripts/lint.sh63
234 files changed, 3719 insertions, 1930 deletions
diff --git a/Carthage.md b/Carthage.md
index cab512e..8f9c331 100644
--- a/Carthage.md
+++ b/Carthage.md
@@ -26,8 +26,9 @@ more details and additional installation methods.
## Carthage Usage
-- Create a Cartfile with a **subset** of the following components. Note that
- **FirebaseAnalytics** must always be included.
+- Create a Cartfile with a **subset** of the following components - choosing the
+Firebase components that you want to include in your app. Note that
+**FirebaseAnalytics** must always be included.
```
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseABTestingBinary.json"
binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAdMobBinary.json"
diff --git a/Example/Auth/Sample/MainViewController.m b/Example/Auth/Sample/MainViewController.m
index e343508..d4915cd 100644
--- a/Example/Auth/Sample/MainViewController.m
+++ b/Example/Auth/Sample/MainViewController.m
@@ -429,10 +429,10 @@ static NSString *const kRemoveIDTokenListenerTitle = @"Remove Last ID Token Chan
*/
static NSString *const kSectionTitleApp = @"APP";
-/** @var kUpdateCurrentUserFromSavedTitle
- @brief The text of the "Upgrade to saved user" button.
+/** @var kSwitchToInMemoryUserTitle
+ @brief The text of the "Switch to in memory user" button.
*/
-static NSString *const kUpdateCurrentUserFromSavedTitle = @"Upgrade to saved user";
+static NSString *const kSwitchToInMemoryUserTitle = @"Switch to in memory user";
/** @var kCreateUserTitle
@brief The text of the "Create User" button.
@@ -750,7 +750,7 @@ typedef enum {
}],
]],
[StaticContentTableViewSection sectionWithTitle:kSectionTitleSignIn cells:@[
- [StaticContentTableViewCell cellWithTitle:kUpdateCurrentUserFromSavedTitle
+ [StaticContentTableViewCell cellWithTitle:kSwitchToInMemoryUserTitle
value:nil
action:^{ [weakSelf updateToSavedUser]; }],
[StaticContentTableViewCell cellWithTitle:kCreateUserTitle
@@ -2762,7 +2762,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
if (!_userInMemory) {
- NSLog(@"You need an in memory user to perform this action");
+ [self showMessagePrompt:[NSString stringWithFormat:@"You need an in-memory user to perform this"
+ "action, use the M+ button to save a user to memory.", nil]];
return;
}
diff --git a/Example/Auth/Tests/FIRAuthTests.m b/Example/Auth/Tests/FIRAuthTests.m
index 507fdf2..47a430b 100644
--- a/Example/Auth/Tests/FIRAuthTests.m
+++ b/Example/Auth/Tests/FIRAuthTests.m
@@ -20,9 +20,7 @@
#import <FirebaseCore/FIRAppInternal.h>
-#import <FirebaseAuth/FIREmailAuthProvider.h>
-#import <FirebaseAuth/FIRGoogleAuthProvider.h>
-#import <FirebaseAuth/FIRAdditionalUserInfo.h>
+#import <FirebaseAuth/FirebaseAuth.h>
#import "FIRAuth_Internal.h"
#import "FIRAuthOperationType.h"
diff --git a/Example/Auth/Tests/FIRUserTests.m b/Example/Auth/Tests/FIRUserTests.m
index 68b0614..96a8082 100644
--- a/Example/Auth/Tests/FIRUserTests.m
+++ b/Example/Auth/Tests/FIRUserTests.m
@@ -18,11 +18,7 @@
#import <XCTest/XCTest.h>
-#import <FirebaseAuth/FIRUser.h>
-#import <FirebaseAuth/FIREmailAuthProvider.h>
-#import <FirebaseAuth/FIRFacebookAuthProvider.h>
-#import <FirebaseAuth/FIRGoogleAuthProvider.h>
-#import <FirebaseAuth/FIRAdditionalUserInfo.h>
+#import <FirebaseAuth/FirebaseAuth.h>
#import "FIRAuth_Internal.h"
#import "FIRAuthErrorUtils.h"
diff --git a/Example/Core/Tests/FIRAppTest.m b/Example/Core/Tests/FIRAppTest.m
index 3784a6e..6825e6a 100644
--- a/Example/Core/Tests/FIRAppTest.m
+++ b/Example/Core/Tests/FIRAppTest.m
@@ -119,21 +119,11 @@ NSString *const kFIRTestAppName2 = @"test-app-name-2";
}
- (void)testConfigureWithCustomizedOptions {
-// valid customized options
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnonnull"
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:kGoogleAppID
- bundleID:kBundleID
- GCMSenderID:kGCMSenderID
- APIKey:kCustomizedAPIKey
- clientID:nil
- trackingID:nil
- androidClientID:nil
- databaseURL:nil
- storageBucket:nil
- deepLinkURLScheme:nil];
-#pragma clang diagnostic pop
+ // valid customized options
+ FIROptions *options =
+ [[FIROptions alloc] initWithGoogleAppID:kGoogleAppID GCMSenderID:kGCMSenderID];
+ options.bundleID = kBundleID;
+ options.APIKey = kCustomizedAPIKey;
NSDictionary *expectedUserInfo =
[self expectedUserInfoWithAppName:kFIRDefaultAppName isDefaultApp:YES];
OCMExpect([self.notificationCenterMock postNotificationName:kFIRAppReadyToConfigureSDKNotification
@@ -194,21 +184,11 @@ NSString *const kFIRTestAppName2 = @"test-app-name-2";
XCTAssertTrue([FIRApp allApps].count == 1);
self.app = [FIRApp appNamed:kFIRTestAppName1];
-// Configure a different app with valid customized options
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnonnull"
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- FIROptions *customizedOptions = [[FIROptions alloc] initWithGoogleAppID:kGoogleAppID
- bundleID:kBundleID
- GCMSenderID:kGCMSenderID
- APIKey:kCustomizedAPIKey
- clientID:nil
- trackingID:nil
- androidClientID:nil
- databaseURL:nil
- storageBucket:nil
- deepLinkURLScheme:nil];
-#pragma clang diagnostic pop
+ // Configure a different app with valid customized options
+ FIROptions *customizedOptions =
+ [[FIROptions alloc] initWithGoogleAppID:kGoogleAppID GCMSenderID:kGCMSenderID];
+ customizedOptions.bundleID = kBundleID;
+ customizedOptions.APIKey = kCustomizedAPIKey;
NSDictionary *expectedUserInfo2 =
[self expectedUserInfoWithAppName:kFIRTestAppName2 isDefaultApp:NO];
diff --git a/Example/Core/Tests/FIRLoggerTest.m b/Example/Core/Tests/FIRLoggerTest.m
index 5cc7465..31a495d 100644
--- a/Example/Core/Tests/FIRLoggerTest.m
+++ b/Example/Core/Tests/FIRLoggerTest.m
@@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#ifdef DEBUG
+// The tests depend upon library methods only built with #ifdef DEBUG
+
#import "FIRTestCase.h"
#import <FirebaseCore/FIRLogger.h>
@@ -267,3 +270,4 @@ static NSString *const kMessageCode = @"I-COR000001";
}
@end
+#endif
diff --git a/Example/Core/Tests/FIROptionsTest.m b/Example/Core/Tests/FIROptionsTest.m
index 5d66ca9..20aec94 100644
--- a/Example/Core/Tests/FIROptionsTest.m
+++ b/Example/Core/Tests/FIROptionsTest.m
@@ -81,51 +81,19 @@ extern NSString *const kFIRLibraryVersionID;
}
- (void)testInitCustomizedOptions {
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:kGoogleAppID
- bundleID:kBundleID
- GCMSenderID:kGCMSenderID
- APIKey:kAPIKey
- clientID:kClientID
- trackingID:kTrackingID
- androidClientID:(id _Nonnull)nil
- databaseURL:kDatabaseURL
- storageBucket:kStorageBucket
- deepLinkURLScheme:kDeepLinkURLScheme];
-#pragma clang pop
- [self assertOptionsMatchDefaults:options andProjectID:NO];
- XCTAssertEqualObjects(options.deepLinkURLScheme, kDeepLinkURLScheme);
- XCTAssertFalse(options.usingOptionsFromDefaultPlist);
-
- FIROptions *options2 =
+ FIROptions *options =
[[FIROptions alloc] initWithGoogleAppID:kGoogleAppID GCMSenderID:kGCMSenderID];
- options2.APIKey = kAPIKey;
- options2.bundleID = kBundleID;
- options2.clientID = kClientID;
- options2.databaseURL = kDatabaseURL;
- options2.deepLinkURLScheme = kDeepLinkURLScheme;
- options2.projectID = kProjectID;
- options2.storageBucket = kStorageBucket;
- options2.trackingID = kTrackingID;
- [self assertOptionsMatchDefaults:options2 andProjectID:YES];
- XCTAssertEqualObjects(options2.deepLinkURLScheme, kDeepLinkURLScheme);
+ options.APIKey = kAPIKey;
+ options.bundleID = kBundleID;
+ options.clientID = kClientID;
+ options.databaseURL = kDatabaseURL;
+ options.deepLinkURLScheme = kDeepLinkURLScheme;
+ options.projectID = kProjectID;
+ options.storageBucket = kStorageBucket;
+ options.trackingID = kTrackingID;
+ [self assertOptionsMatchDefaults:options andProjectID:YES];
+ XCTAssertEqualObjects(options.deepLinkURLScheme, kDeepLinkURLScheme);
XCTAssertFalse(options.usingOptionsFromDefaultPlist);
-
-// nil GoogleAppID should throw an exception
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnonnull"
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- XCTAssertThrows([[FIROptions alloc] initWithGoogleAppID:nil
- bundleID:kBundleID
- GCMSenderID:kGCMSenderID
- APIKey:kCustomizedAPIKey
- clientID:nil
- trackingID:nil
- androidClientID:nil
- databaseURL:nil
- storageBucket:nil
- deepLinkURLScheme:nil]);
-#pragma clang diagnostic pop
}
- (void)testInitWithContentsOfFile {
@@ -239,16 +207,9 @@ extern NSString *const kFIRLibraryVersionID;
XCTAssertEqualObjects(newOptions.deepLinkURLScheme, kDeepLinkURLScheme);
// customized options
- FIROptions *customizedOptions = [[FIROptions alloc] initWithGoogleAppID:kGoogleAppID
- bundleID:kBundleID
- GCMSenderID:kGCMSenderID
- APIKey:kAPIKey
- clientID:kClientID
- trackingID:kTrackingID
- androidClientID:(id _Nonnull)nil
- databaseURL:kDatabaseURL
- storageBucket:kStorageBucket
- deepLinkURLScheme:kDeepLinkURLScheme];
+ FIROptions *customizedOptions =
+ [[FIROptions alloc] initWithGoogleAppID:kGoogleAppID GCMSenderID:kGCMSenderID];
+ customizedOptions.deepLinkURLScheme = kDeepLinkURLScheme;
FIROptions *copyCustomizedOptions = [customizedOptions copy];
[copyCustomizedOptions setDeepLinkURLScheme:kNewDeepLinkURLScheme];
XCTAssertEqualObjects(customizedOptions.deepLinkURLScheme, kDeepLinkURLScheme);
diff --git a/Example/Core/Tests/FIRTestCase.m b/Example/Core/Tests/FIRTestCase.m
index b52886b..631075f 100644
--- a/Example/Core/Tests/FIRTestCase.m
+++ b/Example/Core/Tests/FIRTestCase.m
@@ -14,6 +14,7 @@
#import "FIRTestCase.h"
+NSString *const kAndroidClientID = @"correct_android_client_id";
NSString *const kAPIKey = @"correct_api_key";
NSString *const kCustomizedAPIKey = @"customized_api_key";
NSString *const kClientID = @"correct_client_id";
diff --git a/Example/Firebase.xcodeproj/project.pbxproj b/Example/Firebase.xcodeproj/project.pbxproj
index 5b887a9..9fa954c 100644
--- a/Example/Firebase.xcodeproj/project.pbxproj
+++ b/Example/Firebase.xcodeproj/project.pbxproj
@@ -130,15 +130,6 @@
AFAF36F71EC28C25004BDEE5 /* Shared.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AFAF36F41EC28C25004BDEE5 /* Shared.xcassets */; };
AFAF36F81EC28C25004BDEE5 /* Shared.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AFAF36F41EC28C25004BDEE5 /* Shared.xcassets */; };
AFAF36F91EC28C25004BDEE5 /* Shared.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AFAF36F41EC28C25004BDEE5 /* Shared.xcassets */; };
- AFC8BA9D1EBD230E00B8EEAE /* NotificationsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFC8BA9C1EBD230E00B8EEAE /* NotificationsController.swift */; };
- AFC8BA9F1EBD51A700B8EEAE /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFC8BA9E1EBD51A700B8EEAE /* Environment.swift */; };
- AFC8BAA71EC257D800B8EEAE /* FIRSampleAppUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = AFC8BAA31EC257D800B8EEAE /* FIRSampleAppUtilities.m */; };
- AFD5630E1EB1402300EA2233 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFD562FF1EB13DF200EA2233 /* AppDelegate.swift */; };
- AFD5630F1EB1402300EA2233 /* MessagingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFD563011EB13DF200EA2233 /* MessagingViewController.swift */; };
- AFD563151EB29EDE00EA2233 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = AFD563131EB1466100EA2233 /* GoogleService-Info.plist */; };
- AFD563171EBBEF7B00EA2233 /* Data+MessagingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFD563161EBBEF7B00EA2233 /* Data+MessagingExtensions.swift */; };
- D018534D1EDACED4003A645C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D01853491EDACED4003A645C /* LaunchScreen.storyboard */; };
- D018534E1EDACED4003A645C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D018534B1EDACED4003A645C /* Main.storyboard */; };
D01853721EDAD084003A645C /* Shared.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AFAF36F41EC28C25004BDEE5 /* Shared.xcassets */; };
D01853831EDAD113003A645C /* FIRAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D018537E1EDAD0E6003A645C /* FIRAppDelegate.m */; };
D01853841EDAD113003A645C /* FIRViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D01853801EDAD0E6003A645C /* FIRViewController.m */; };
@@ -194,12 +185,7 @@
D064E6B51ED9B31C001956DF /* FIRTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = DEE14D7C1E844677006FA992 /* FIRTestCase.m */; };
D067EF831ED9BDE00095C27F /* Shared.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AFAF36F41EC28C25004BDEE5 /* Shared.xcassets */; };
D067EF841ED9BDFF0095C27F /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = DEE14D711E844677006FA992 /* GoogleService-Info.plist */; };
- D09005311EDB32D600154410 /* OCMock-iOS/OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D09005301EDB32D600154410 /* OCMock-iOS/OCMock.framework */; settings = {ATTRIBUTES = (); }; };
- D09005331EDB32F100154410 /* OCMock-iOS/OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D09005301EDB32D600154410 /* OCMock-iOS/OCMock.framework */; settings = {ATTRIBUTES = (); }; };
- D09005351EDB330E00154410 /* OCMock-iOS/OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D09005301EDB32D600154410 /* OCMock-iOS/OCMock.framework */; settings = {ATTRIBUTES = (); }; };
D09005371EDB331C00154410 /* OCMock-iOS/OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D09005301EDB32D600154410 /* OCMock-iOS/OCMock.framework */; settings = {ATTRIBUTES = (); }; };
- D09005391EDB333A00154410 /* OCMock-iOS/OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D09005301EDB32D600154410 /* OCMock-iOS/OCMock.framework */; settings = {ATTRIBUTES = (); }; };
- D090053B1EDB334400154410 /* OCMock-iOS/OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D09005301EDB32D600154410 /* OCMock-iOS/OCMock.framework */; settings = {ATTRIBUTES = (); }; };
D090053D1EDB334D00154410 /* OCMock-iOS/OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D09005301EDB32D600154410 /* OCMock-iOS/OCMock.framework */; settings = {ATTRIBUTES = (); }; };
D0EDB2C51EDA04F800B6C31B /* Shared.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AFAF36F41EC28C25004BDEE5 /* Shared.xcassets */; };
D0EDB2D71EDA057800B6C31B /* FIRAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D0EDB2D21EDA056A00B6C31B /* FIRAppDelegate.m */; };
@@ -337,6 +323,22 @@
DE26D2931F705F4D004AE1D3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE26D2071F70333E004AE1D3 /* ViewController.swift */; };
DE26D2941F705F51004AE1D3 /* AuthCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE26D1FE1F70333E004AE1D3 /* AuthCredentials.swift */; };
DE26D2951F705F53004AE1D3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE26D1FD1F70333E004AE1D3 /* AppDelegate.swift */; };
+ DE47C0E2207AC87D00B1AEDF /* FIRSampleAppUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = AFC8BAA31EC257D800B8EEAE /* FIRSampleAppUtilities.m */; };
+ DE47C0E7207AC87D00B1AEDF /* Shared.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AFAF36F41EC28C25004BDEE5 /* Shared.xcassets */; };
+ DE47C114207AC94A00B1AEDF /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = DE47C107207AC94A00B1AEDF /* GoogleService-Info.plist */; };
+ DE47C115207AC94A00B1AEDF /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE47C109207AC94A00B1AEDF /* Environment.swift */; };
+ DE47C116207AC94A00B1AEDF /* MessagingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE47C10A207AC94A00B1AEDF /* MessagingViewController.swift */; };
+ DE47C117207AC94A00B1AEDF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE47C10C207AC94A00B1AEDF /* LaunchScreen.storyboard */; };
+ DE47C118207AC94A00B1AEDF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE47C10E207AC94A00B1AEDF /* Main.storyboard */; };
+ DE47C119207AC94A00B1AEDF /* Messaging-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = DE47C110207AC94A00B1AEDF /* Messaging-Info.plist */; };
+ DE47C11A207AC94A00B1AEDF /* Data+MessagingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE47C111207AC94A00B1AEDF /* Data+MessagingExtensions.swift */; };
+ DE47C11B207AC94A00B1AEDF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE47C112207AC94A00B1AEDF /* AppDelegate.swift */; };
+ DE47C11C207AC94A00B1AEDF /* NotificationsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE47C113207AC94A00B1AEDF /* NotificationsController.swift */; };
+ DE47C13F207ACAA900B1AEDF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE47C136207ACAA900B1AEDF /* LaunchScreen.storyboard */; };
+ DE47C140207ACAA900B1AEDF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DE47C138207ACAA900B1AEDF /* Main.storyboard */; };
+ DE47C142207ACAA900B1AEDF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DE47C13B207ACAA900B1AEDF /* main.m */; };
+ DE47C143207ACAA900B1AEDF /* FIRAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DE47C13C207ACAA900B1AEDF /* FIRAppDelegate.m */; };
+ DE47C144207ACAA900B1AEDF /* FIRViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DE47C13D207ACAA900B1AEDF /* FIRViewController.m */; };
DE750DBD1EB3DD5B00A75E47 /* FIRAuthAPNSTokenTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE750DB61EB3DD4000A75E47 /* FIRAuthAPNSTokenTests.m */; };
DE750DBE1EB3DD6800A75E47 /* FIRAuthAPNSTokenManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE750DB51EB3DD4000A75E47 /* FIRAuthAPNSTokenManagerTests.m */; };
DE750DBF1EB3DD6C00A75E47 /* FIRAuthAppCredentialManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE750DB71EB3DD4000A75E47 /* FIRAuthAppCredentialManagerTests.m */; };
@@ -456,6 +458,7 @@
DE9316031E8738E60083EDBF /* FIRMessagingSyncMessageManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DE9315D41E8738B70083EDBF /* FIRMessagingSyncMessageManagerTest.m */; };
DE9316041E8738E60083EDBF /* FIRMessagingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = DE9315D51E8738B70083EDBF /* FIRMessagingTest.m */; };
DE9316051E8738E60083EDBF /* FIRMessagingTestNotificationUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DE9315D71E8738B70083EDBF /* FIRMessagingTestNotificationUtilities.m */; };
+ DEA7795D207ACC8000245121 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = DE47C107207AC94A00B1AEDF /* GoogleService-Info.plist */; };
DEAAD3C31FBA1CD90053BF48 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DEAAD3BD1FBA1CD80053BF48 /* main.m */; };
DEAAD3CE1FBA1EFA0053BF48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DEAAD3C51FBA1EF90053BF48 /* Assets.xcassets */; };
DEAAD3CF1FBA1EFA0053BF48 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DEAAD3C81FBA1EFA0053BF48 /* AppDelegate.m */; };
@@ -816,36 +819,6 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
- D090052F1EDB32B700154410 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 16;
- files = (
- D09005311EDB32D600154410 /* OCMock-iOS/OCMock.framework in CopyFiles */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- D09005321EDB32EA00154410 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 16;
- files = (
- D09005331EDB32F100154410 /* OCMock-iOS/OCMock.framework in CopyFiles */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- D09005341EDB330800154410 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 16;
- files = (
- D09005351EDB330E00154410 /* OCMock-iOS/OCMock.framework in CopyFiles */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
D09005361EDB331700154410 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -856,26 +829,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
- D09005381EDB333700154410 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 16;
- files = (
- D09005391EDB333A00154410 /* OCMock-iOS/OCMock.framework in CopyFiles */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- D090053A1EDB334000154410 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 16;
- files = (
- D090053B1EDB334400154410 /* OCMock-iOS/OCMock.framework in CopyFiles */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
D090053C1EDB334800154410 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -960,20 +913,10 @@
923F824D206C4D8B00034974 /* SafariServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafariServices.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/SafariServices.framework; sourceTree = DEVELOPER_DIR; };
923F8250206C4DC500034974 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
AFAF36F41EC28C25004BDEE5 /* Shared.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Shared.xcassets; path = Shared/Shared.xcassets; sourceTree = "<group>"; };
- AFC8BA9C1EBD230E00B8EEAE /* NotificationsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationsController.swift; sourceTree = "<group>"; };
- AFC8BA9E1EBD51A700B8EEAE /* Environment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = "<group>"; };
AFC8BAA11EC257D700B8EEAE /* Messaging_Example-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Messaging_Example-Bridging-Header.h"; sourceTree = "<group>"; };
AFC8BAA21EC257D800B8EEAE /* FIRSampleAppUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FIRSampleAppUtilities.h; path = Shared/FIRSampleAppUtilities.h; sourceTree = "<group>"; };
AFC8BAA31EC257D800B8EEAE /* FIRSampleAppUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FIRSampleAppUtilities.m; path = Shared/FIRSampleAppUtilities.m; sourceTree = "<group>"; };
AFD562E51EB13C6D00EA2233 /* Messaging_Example_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Messaging_Example_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
- AFD562FF1EB13DF200EA2233 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
- AFD563001EB13DF200EA2233 /* Messaging-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Messaging-Info.plist"; sourceTree = "<group>"; };
- AFD563011EB13DF200EA2233 /* MessagingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagingViewController.swift; sourceTree = "<group>"; };
- AFD563131EB1466100EA2233 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "App/GoogleService-Info.plist"; sourceTree = "<group>"; };
- AFD563141EB29B8C00EA2233 /* Messaging_Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Messaging_Example.entitlements; sourceTree = "<group>"; };
- AFD563161EBBEF7B00EA2233 /* Data+MessagingExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+MessagingExtensions.swift"; sourceTree = "<group>"; };
- D018534A1EDACED4003A645C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
- D018534C1EDACED4003A645C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
D01853791EDAD084003A645C /* Auth_Example_macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Auth_Example_macOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
D018537C1EDAD0E6003A645C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
D018537D1EDAD0E6003A645C /* FIRAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FIRAppDelegate.h; sourceTree = "<group>"; };
@@ -1094,6 +1037,24 @@
DE26D26D1F705C35004AE1D3 /* Auth_EarlGreyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Auth_EarlGreyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
DE26D27D1F705EC7004AE1D3 /* SwiftSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
DE45C6641E7DA8CB009E6ACD /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+ DE47C0ED207AC87D00B1AEDF /* Messaging_Sample_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Messaging_Sample_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ DE47C107207AC94A00B1AEDF /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
+ DE47C109207AC94A00B1AEDF /* Environment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = "<group>"; };
+ DE47C10A207AC94A00B1AEDF /* MessagingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagingViewController.swift; sourceTree = "<group>"; };
+ DE47C10B207AC94A00B1AEDF /* Messaging_Example.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Messaging_Example.entitlements; sourceTree = "<group>"; };
+ DE47C10D207AC94A00B1AEDF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+ DE47C10F207AC94A00B1AEDF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+ DE47C110207AC94A00B1AEDF /* Messaging-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Messaging-Info.plist"; sourceTree = "<group>"; };
+ DE47C111207AC94A00B1AEDF /* Data+MessagingExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+MessagingExtensions.swift"; sourceTree = "<group>"; };
+ DE47C112207AC94A00B1AEDF /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+ DE47C113207AC94A00B1AEDF /* NotificationsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationsController.swift; sourceTree = "<group>"; };
+ DE47C134207ACAA900B1AEDF /* FIRAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRAppDelegate.h; sourceTree = "<group>"; };
+ DE47C135207ACAA900B1AEDF /* FIRViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRViewController.h; sourceTree = "<group>"; };
+ DE47C137207ACAA900B1AEDF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+ DE47C139207ACAA900B1AEDF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
+ DE47C13B207ACAA900B1AEDF /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ DE47C13C207ACAA900B1AEDF /* FIRAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRAppDelegate.m; sourceTree = "<group>"; };
+ DE47C13D207ACAA900B1AEDF /* FIRViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRViewController.m; sourceTree = "<group>"; };
DE53893E1FBB62E100199FC2 /* Auth_Tests_tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Auth_Tests_tvOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
DE53894C1FBB635400199FC2 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
DE53894D1FBB635400199FC2 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -1433,6 +1394,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ DE47C0E4207AC87D00B1AEDF /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
DE53893B1FBB62E100199FC2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -1666,6 +1634,7 @@
DE53893E1FBB62E100199FC2 /* Auth_Tests_tvOS.xctest */,
DE1FAE901FBCF5E100897AAA /* Auth_Example_tvOS.app */,
DEDFEFEC1FD1B8C100F7D466 /* Analytics_Tests_iOS.xctest */,
+ DE47C0ED207AC87D00B1AEDF /* Messaging_Sample_iOS.app */,
);
name = Products;
sourceTree = "<group>";
@@ -1705,15 +1674,6 @@
name = Shared;
sourceTree = "<group>";
};
- AFD562F71EB13CC700EA2233 /* App */ = {
- isa = PBXGroup;
- children = (
- AFD563131EB1466100EA2233 /* GoogleService-Info.plist */,
- D01853481EDACE1A003A645C /* iOS */,
- );
- name = App;
- sourceTree = "<group>";
- };
D01853461EDACC10003A645C /* iOS */ = {
isa = PBXGroup;
children = (
@@ -1743,23 +1703,6 @@
path = macOS;
sourceTree = "<group>";
};
- D01853481EDACE1A003A645C /* iOS */ = {
- isa = PBXGroup;
- children = (
- AFD563001EB13DF200EA2233 /* Messaging-Info.plist */,
- AFD563141EB29B8C00EA2233 /* Messaging_Example.entitlements */,
- AFD562FF1EB13DF200EA2233 /* AppDelegate.swift */,
- AFD563161EBBEF7B00EA2233 /* Data+MessagingExtensions.swift */,
- AFC8BA9E1EBD51A700B8EEAE /* Environment.swift */,
- AFD563011EB13DF200EA2233 /* MessagingViewController.swift */,
- AFC8BA9C1EBD230E00B8EEAE /* NotificationsController.swift */,
- D01853491EDACED4003A645C /* LaunchScreen.storyboard */,
- D018534B1EDACED4003A645C /* Main.storyboard */,
- );
- name = iOS;
- path = App/iOS;
- sourceTree = "<group>";
- };
D0D857F61ED9ADA8002342D2 /* iOS */ = {
isa = PBXGroup;
children = (
@@ -1946,6 +1889,53 @@
path = SwiftSample;
sourceTree = "<group>";
};
+ DE47C106207AC94A00B1AEDF /* Sample */ = {
+ isa = PBXGroup;
+ children = (
+ DE47C107207AC94A00B1AEDF /* GoogleService-Info.plist */,
+ DE47C108207AC94A00B1AEDF /* iOS */,
+ );
+ path = Sample;
+ sourceTree = "<group>";
+ };
+ DE47C108207AC94A00B1AEDF /* iOS */ = {
+ isa = PBXGroup;
+ children = (
+ DE47C109207AC94A00B1AEDF /* Environment.swift */,
+ DE47C10A207AC94A00B1AEDF /* MessagingViewController.swift */,
+ DE47C10B207AC94A00B1AEDF /* Messaging_Example.entitlements */,
+ DE47C10C207AC94A00B1AEDF /* LaunchScreen.storyboard */,
+ DE47C10E207AC94A00B1AEDF /* Main.storyboard */,
+ DE47C110207AC94A00B1AEDF /* Messaging-Info.plist */,
+ DE47C111207AC94A00B1AEDF /* Data+MessagingExtensions.swift */,
+ DE47C112207AC94A00B1AEDF /* AppDelegate.swift */,
+ DE47C113207AC94A00B1AEDF /* NotificationsController.swift */,
+ );
+ path = iOS;
+ sourceTree = "<group>";
+ };
+ DE47C131207ACAA900B1AEDF /* App */ = {
+ isa = PBXGroup;
+ children = (
+ DE47C133207ACAA900B1AEDF /* iOS */,
+ );
+ path = App;
+ sourceTree = "<group>";
+ };
+ DE47C133207ACAA900B1AEDF /* iOS */ = {
+ isa = PBXGroup;
+ children = (
+ DE47C134207ACAA900B1AEDF /* FIRAppDelegate.h */,
+ DE47C135207ACAA900B1AEDF /* FIRViewController.h */,
+ DE47C136207ACAA900B1AEDF /* LaunchScreen.storyboard */,
+ DE47C138207ACAA900B1AEDF /* Main.storyboard */,
+ DE47C13B207ACAA900B1AEDF /* main.m */,
+ DE47C13C207ACAA900B1AEDF /* FIRAppDelegate.m */,
+ DE47C13D207ACAA900B1AEDF /* FIRViewController.m */,
+ );
+ path = iOS;
+ sourceTree = "<group>";
+ };
DE53894B1FBB635400199FC2 /* tvOS */ = {
isa = PBXGroup;
children = (
@@ -2152,8 +2142,9 @@
DE9315B41E8738B70083EDBF /* Messaging */ = {
isa = PBXGroup;
children = (
+ DE47C131207ACAA900B1AEDF /* App */,
+ DE47C106207AC94A00B1AEDF /* Sample */,
AFC8BAA11EC257D700B8EEAE /* Messaging_Example-Bridging-Header.h */,
- AFD562F71EB13CC700EA2233 /* App */,
DE9315C21E8738B70083EDBF /* Tests */,
);
path = Messaging;
@@ -2651,6 +2642,23 @@
productReference = DE26D27D1F705EC7004AE1D3 /* SwiftSample.app */;
productType = "com.apple.product-type.application";
};
+ DE47C0DC207AC87D00B1AEDF /* Messaging_Sample_iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = DE47C0EA207AC87D00B1AEDF /* Build configuration list for PBXNativeTarget "Messaging_Sample_iOS" */;
+ buildPhases = (
+ DE47C0DD207AC87D00B1AEDF /* Sources */,
+ DE47C0E4207AC87D00B1AEDF /* Frameworks */,
+ DE47C0E5207AC87D00B1AEDF /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Messaging_Sample_iOS;
+ productName = Messaging_Example_iOS;
+ productReference = DE47C0ED207AC87D00B1AEDF /* Messaging_Sample_iOS.app */;
+ productType = "com.apple.product-type.application";
+ };
DE53893D1FBB62E100199FC2 /* Auth_Tests_tvOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = DE5389491FBB62E100199FC2 /* Build configuration list for PBXNativeTarget "Auth_Tests_tvOS" */;
@@ -2693,7 +2701,6 @@
DE7B8D191E8EF078009EB6DF /* Sources */,
DE7B8D1A1E8EF078009EB6DF /* Frameworks */,
DE7B8D1B1E8EF078009EB6DF /* Resources */,
- D09005341EDB330800154410 /* CopyFiles */,
);
buildRules = (
);
@@ -2729,7 +2736,6 @@
DE9314DA1E86C6BE0083EDBF /* Sources */,
DE9314DB1E86C6BE0083EDBF /* Frameworks */,
DE9314DC1E86C6BE0083EDBF /* Resources */,
- D090052F1EDB32B700154410 /* CopyFiles */,
);
buildRules = (
);
@@ -2748,7 +2754,6 @@
DE9315A31E8738460083EDBF /* Sources */,
DE9315A41E8738460083EDBF /* Frameworks */,
DE9315A51E8738460083EDBF /* Resources */,
- D09005381EDB333700154410 /* CopyFiles */,
);
buildRules = (
);
@@ -2854,7 +2859,6 @@
DEB13A0E1E73507E00AC236D /* Sources */,
DEB13A161E73507E00AC236D /* Frameworks */,
DEB13A1D1E73507E00AC236D /* Resources */,
- D090053A1EDB334000154410 /* CopyFiles */,
);
buildRules = (
);
@@ -2908,7 +2912,6 @@
DEE14D551E84464D006FA992 /* Sources */,
DEE14D561E84464D006FA992 /* Frameworks */,
DEE14D571E84464D006FA992 /* Resources */,
- D09005321EDB32EA00154410 /* CopyFiles */,
);
buildRules = (
);
@@ -3047,6 +3050,9 @@
DevelopmentTeam = EQHXZ8M8AV;
ProvisioningStyle = Automatic;
};
+ DE47C0DC207AC87D00B1AEDF = {
+ DevelopmentTeam = EQHXZ8M8AV;
+ };
DE53893D1FBB62E100199FC2 = {
CreatedOnToolsVersion = 9.1;
DevelopmentTeam = EQHXZ8M8AV;
@@ -3166,6 +3172,7 @@
DE1EC27E1FBA5E63007D18D8 /* Database_Tests_tvOS */,
AFD562E41EB13C6D00EA2233 /* Messaging_Example_iOS */,
DE9315A61E8738460083EDBF /* Messaging_Tests_iOS */,
+ DE47C0DC207AC87D00B1AEDF /* Messaging_Sample_iOS */,
DEB139E01E73506A00AC236D /* Storage_Example_iOS */,
DEB13A0A1E73507E00AC236D /* Storage_Tests_iOS */,
06121EBB1EC399C50008D70E /* Storage_IntegrationTests_iOS */,
@@ -3201,10 +3208,10 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- D018534D1EDACED4003A645C /* LaunchScreen.storyboard in Resources */,
+ DE47C13F207ACAA900B1AEDF /* LaunchScreen.storyboard in Resources */,
+ DEA7795D207ACC8000245121 /* GoogleService-Info.plist in Resources */,
AFAF36F81EC28C25004BDEE5 /* Shared.xcassets in Resources */,
- AFD563151EB29EDE00EA2233 /* GoogleService-Info.plist in Resources */,
- D018534E1EDACED4003A645C /* Main.storyboard in Resources */,
+ DE47C140207ACAA900B1AEDF /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3363,6 +3370,18 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ DE47C0E5207AC87D00B1AEDF /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ DE47C118207AC94A00B1AEDF /* Main.storyboard in Resources */,
+ DE47C0E7207AC87D00B1AEDF /* Shared.xcassets in Resources */,
+ DE47C114207AC94A00B1AEDF /* GoogleService-Info.plist in Resources */,
+ DE47C117207AC94A00B1AEDF /* LaunchScreen.storyboard in Resources */,
+ DE47C119207AC94A00B1AEDF /* Messaging-Info.plist in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
DE53893C1FBB62E100199FC2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -3545,12 +3564,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- AFD563171EBBEF7B00EA2233 /* Data+MessagingExtensions.swift in Sources */,
- AFD5630E1EB1402300EA2233 /* AppDelegate.swift in Sources */,
- AFC8BA9D1EBD230E00B8EEAE /* NotificationsController.swift in Sources */,
- AFD5630F1EB1402300EA2233 /* MessagingViewController.swift in Sources */,
- AFC8BAA71EC257D800B8EEAE /* FIRSampleAppUtilities.m in Sources */,
- AFC8BA9F1EBD51A700B8EEAE /* Environment.swift in Sources */,
+ DE47C142207ACAA900B1AEDF /* main.m in Sources */,
+ DE47C143207ACAA900B1AEDF /* FIRAppDelegate.m in Sources */,
+ DE47C144207ACAA900B1AEDF /* FIRViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3856,6 +3872,19 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ DE47C0DD207AC87D00B1AEDF /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ DE47C11A207AC94A00B1AEDF /* Data+MessagingExtensions.swift in Sources */,
+ DE47C115207AC94A00B1AEDF /* Environment.swift in Sources */,
+ DE47C116207AC94A00B1AEDF /* MessagingViewController.swift in Sources */,
+ DE47C0E2207AC87D00B1AEDF /* FIRSampleAppUtilities.m in Sources */,
+ DE47C11C207AC94A00B1AEDF /* NotificationsController.swift in Sources */,
+ DE47C11B207AC94A00B1AEDF /* AppDelegate.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
DE53893A1FBB62E100199FC2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -4342,22 +4371,6 @@
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
- D01853491EDACED4003A645C /* LaunchScreen.storyboard */ = {
- isa = PBXVariantGroup;
- children = (
- D018534A1EDACED4003A645C /* Base */,
- );
- name = LaunchScreen.storyboard;
- sourceTree = "<group>";
- };
- D018534B1EDACED4003A645C /* Main.storyboard */ = {
- isa = PBXVariantGroup;
- children = (
- D018534C1EDACED4003A645C /* Base */,
- );
- name = Main.storyboard;
- sourceTree = "<group>";
- };
D018537B1EDAD0E6003A645C /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
@@ -4402,6 +4415,38 @@
name = Localizable.strings;
sourceTree = "<group>";
};
+ DE47C10C207AC94A00B1AEDF /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ DE47C10D207AC94A00B1AEDF /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "<group>";
+ };
+ DE47C10E207AC94A00B1AEDF /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ DE47C10F207AC94A00B1AEDF /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "<group>";
+ };
+ DE47C136207ACAA900B1AEDF /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ DE47C137207ACAA900B1AEDF /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "<group>";
+ };
+ DE47C138207ACAA900B1AEDF /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ DE47C139207ACAA900B1AEDF /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "<group>";
+ };
DE7B8D2C1E8EF202009EB6DF /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
@@ -4683,11 +4728,11 @@
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CODE_SIGN_ENTITLEMENTS = Messaging/App/iOS/Messaging_Example.entitlements;
+ CODE_SIGN_ENTITLEMENTS = Messaging/Sample/iOS/Messaging_Example.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = EQHXZ8M8AV;
- INFOPLIST_FILE = "Messaging/App/iOS/Messaging-Info.plist";
+ INFOPLIST_FILE = "Messaging/Sample/iOS/Messaging-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.google.FirebaseMessagingSample.dev;
@@ -4707,12 +4752,12 @@
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CODE_SIGN_ENTITLEMENTS = Messaging/App/iOS/Messaging_Example.entitlements;
+ CODE_SIGN_ENTITLEMENTS = Messaging/Sample/iOS/Messaging_Example.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = EQHXZ8M8AV;
- INFOPLIST_FILE = "Messaging/App/iOS/Messaging-Info.plist";
+ INFOPLIST_FILE = "Messaging/Sample/iOS/Messaging-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.google.FirebaseMessagingSample.dev;
@@ -5762,6 +5807,54 @@
};
name = Release;
};
+ DE47C0EB207AC87D00B1AEDF /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CODE_SIGN_ENTITLEMENTS = Messaging/Sample/iOS/Messaging_Example.entitlements;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEVELOPMENT_TEAM = EQHXZ8M8AV;
+ INFOPLIST_FILE = "$(SRCROOT)/Messaging/Sample/iOS/Messaging-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.FirebaseMessagingSample.dev;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OBJC_BRIDGING_HEADER = "Messaging/Messaging_Example-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 3.0;
+ };
+ name = Debug;
+ };
+ DE47C0EC207AC87D00B1AEDF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CODE_SIGN_ENTITLEMENTS = Messaging/Sample/iOS/Messaging_Example.entitlements;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEVELOPMENT_TEAM = EQHXZ8M8AV;
+ INFOPLIST_FILE = "$(SRCROOT)/Messaging/Sample/iOS/Messaging-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = com.google.FirebaseMessagingSample.dev;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OBJC_BRIDGING_HEADER = "Messaging/Messaging_Example-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_VERSION = 3.0;
+ };
+ name = Release;
+ };
DE5389451FBB62E100199FC2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -5915,6 +6008,7 @@
"\"${PODS_ROOT}/../../Firebase/Database/Persistence\"",
"\"${PODS_ROOT}/../../Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary\"",
"\"${PODS_ROOT}/../../Firebase/Database/Core/View\"",
+ "\"${PODS_ROOT}/Headers/Private\"",
);
INFOPLIST_FILE = "Database/Tests/FirebaseTests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
@@ -5955,6 +6049,7 @@
"\"${PODS_ROOT}/../../Firebase/Database/Persistence\"",
"\"${PODS_ROOT}/../../Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary\"",
"\"${PODS_ROOT}/../../Firebase/Database/Core/View\"",
+ "\"${PODS_ROOT}/Headers/Private\"",
);
INFOPLIST_FILE = "Database/Tests/FirebaseTests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
@@ -6022,6 +6117,7 @@
"\"${PODS_ROOT}/../../Firebase/Auth/Source/RPCs\"",
"\"${PODS_ROOT}/../../Firebase/Auth/Source\"",
"\"${PODS_ROOT}/../../Firebase/Auth/Source/AuthProviders\"",
+ "\"${PODS_ROOT}/Headers/Private\"",
);
INFOPLIST_FILE = "Auth/Tests/Tests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
@@ -6047,6 +6143,7 @@
"\"${PODS_ROOT}/../../Firebase/Auth/Source/RPCs\"",
"\"${PODS_ROOT}/../../Firebase/Auth/Source\"",
"\"${PODS_ROOT}/../../Firebase/Auth/Source/AuthProviders\"",
+ "\"${PODS_ROOT}/Headers/Private\"",
);
INFOPLIST_FILE = "Auth/Tests/Tests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
@@ -6061,7 +6158,6 @@
DE9315B01E8738460083EDBF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@@ -6077,6 +6173,7 @@
"\"${PODS_ROOT}/Headers/Public\"",
"\"${PODS_ROOT}/Headers/Public/FirebaseAnalytics\"",
"\"${PODS_ROOT}/../../Firebase/Messaging\"",
+ "\"${PODS_ROOT}/Headers/Private\"",
);
INFOPLIST_FILE = Messaging/Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -6090,7 +6187,6 @@
DE9315B11E8738460083EDBF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@@ -6107,6 +6203,7 @@
"\"${PODS_ROOT}/Headers/Public\"",
"\"${PODS_ROOT}/Headers/Public/FirebaseAnalytics\"",
"\"${PODS_ROOT}/../../Firebase/Messaging\"",
+ "\"${PODS_ROOT}/Headers/Private\"",
);
INFOPLIST_FILE = Messaging/Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -6433,6 +6530,7 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_ROOT}/../../Firebase/Storage/Private\"",
+ "\"${PODS_ROOT}/Headers/Private\"",
);
INFOPLIST_FILE = "Storage/Tests/Tests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.google.Storage-Tests-iOS";
@@ -6452,6 +6550,7 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_ROOT}/../../Firebase/Storage/Private\"",
+ "\"${PODS_ROOT}/Headers/Private\"",
);
INFOPLIST_FILE = "Storage/Tests/Tests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "com.google.Storage-Tests-iOS";
@@ -6565,7 +6664,10 @@
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
- HEADER_SEARCH_PATHS = "$(inherited)";
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "${PODS_ROOT}/Headers/Private",
+ );
INFOPLIST_FILE = "Core/Tests/Tests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -6585,7 +6687,10 @@
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
- HEADER_SEARCH_PATHS = "$(inherited)";
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "${PODS_ROOT}/Headers/Private",
+ );
INFOPLIST_FILE = "Core/Tests/Tests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -6825,6 +6930,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ DE47C0EA207AC87D00B1AEDF /* Build configuration list for PBXNativeTarget "Messaging_Sample_iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ DE47C0EB207AC87D00B1AEDF /* Debug */,
+ DE47C0EC207AC87D00B1AEDF /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
DE5389491FBB62E100199FC2 /* Build configuration list for PBXNativeTarget "Auth_Tests_tvOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/Example/Firebase.xcodeproj/xcshareddata/xcschemes/Messaging_Sample_iOS.xcscheme b/Example/Firebase.xcodeproj/xcshareddata/xcschemes/Messaging_Sample_iOS.xcscheme
new file mode 100644
index 0000000..57e31f3
--- /dev/null
+++ b/Example/Firebase.xcodeproj/xcshareddata/xcschemes/Messaging_Sample_iOS.xcscheme
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0930"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "DE47C0DC207AC87D00B1AEDF"
+ BuildableName = "Messaging_Sample_iOS.app"
+ BlueprintName = "Messaging_Sample_iOS"
+ ReferencedContainer = "container:Firebase.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "DE47C0DC207AC87D00B1AEDF"
+ BuildableName = "Messaging_Sample_iOS.app"
+ BlueprintName = "Messaging_Sample_iOS"
+ ReferencedContainer = "container:Firebase.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "DE47C0DC207AC87D00B1AEDF"
+ BuildableName = "Messaging_Sample_iOS.app"
+ BlueprintName = "Messaging_Sample_iOS"
+ ReferencedContainer = "container:Firebase.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "DE47C0DC207AC87D00B1AEDF"
+ BuildableName = "Messaging_Sample_iOS.app"
+ BlueprintName = "Messaging_Sample_iOS"
+ ReferencedContainer = "container:Firebase.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/Example/Messaging/App/iOS/Base.lproj/LaunchScreen.storyboard b/Example/Messaging/App/iOS/Base.lproj/LaunchScreen.storyboard
index fdf3f97..66a7681 100644
--- a/Example/Messaging/App/iOS/Base.lproj/LaunchScreen.storyboard
+++ b/Example/Messaging/App/iOS/Base.lproj/LaunchScreen.storyboard
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
- <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--View Controller-->
@@ -14,9 +14,9 @@
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
- <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
diff --git a/Example/Messaging/App/iOS/Base.lproj/Main.storyboard b/Example/Messaging/App/iOS/Base.lproj/Main.storyboard
index 6df1a82..d164a23 100644
--- a/Example/Messaging/App/iOS/Base.lproj/Main.storyboard
+++ b/Example/Messaging/App/iOS/Base.lproj/Main.storyboard
@@ -1,48 +1,27 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="taE-sK-BOl">
- <device id="retina4_7" orientation="portrait">
- <adaptation id="fullscreen"/>
- </device>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="whP-gf-Uak">
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
- <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<scenes>
- <!--Firebase Cloud Messaging-->
- <scene sceneID="tne-QT-ifu">
+ <!--View Controller-->
+ <scene sceneID="wQg-tq-qST">
<objects>
- <viewController id="BYZ-38-t0r" customClass="MessagingViewController" customModule="Messaging_Example" customModuleProvider="target" sceneMemberID="viewController">
+ <viewController id="whP-gf-Uak" customClass="FIRViewController" sceneMemberID="viewController">
<layoutGuides>
- <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
- <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
+ <viewControllerLayoutGuide type="top" id="uEw-UM-LJ8"/>
+ <viewControllerLayoutGuide type="bottom" id="Mvr-aV-6Um"/>
</layoutGuides>
- <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
- <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <view key="view" contentMode="scaleToFill" id="TpU-gO-2f1">
+ <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
- <navigationItem key="navigationItem" title="Firebase Cloud Messaging" id="z1u-kE-qKb"/>
</viewController>
- <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="tc2-Qw-aMS" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
- <point key="canvasLocation" x="698" y="164"/>
- </scene>
- <!--Navigation Controller-->
- <scene sceneID="rmF-xz-rwn">
- <objects>
- <placeholder placeholderIdentifier="IBFirstResponder" id="Ju1-Bj-8eG" userLabel="First Responder" sceneMemberID="firstResponder"/>
- <navigationController id="taE-sK-BOl" sceneMemberID="viewController">
- <navigationBar key="navigationBar" contentMode="scaleToFill" id="iTL-Kg-11w">
- <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
- <autoresizingMask key="autoresizingMask"/>
- </navigationBar>
- <connections>
- <segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="04R-HZ-bi6"/>
- </connections>
- </navigationController>
- </objects>
- <point key="canvasLocation" x="-92" y="165"/>
+ <point key="canvasLocation" x="305" y="433"/>
</scene>
</scenes>
</document>
diff --git a/Example/Messaging/App/iOS/FIRAppDelegate.h b/Example/Messaging/App/iOS/FIRAppDelegate.h
new file mode 100644
index 0000000..1eb5040
--- /dev/null
+++ b/Example/Messaging/App/iOS/FIRAppDelegate.h
@@ -0,0 +1,23 @@
+/*
+ * 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 UIKit;
+
+@interface FIRAppDelegate : UIResponder <UIApplicationDelegate>
+
+@property(strong, nonatomic) UIWindow *window;
+
+@end
diff --git a/Example/Messaging/App/iOS/FIRAppDelegate.m b/Example/Messaging/App/iOS/FIRAppDelegate.m
new file mode 100644
index 0000000..535e529
--- /dev/null
+++ b/Example/Messaging/App/iOS/FIRAppDelegate.m
@@ -0,0 +1,58 @@
+// 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 "FIRAppDelegate.h"
+
+#import <FirebaseCore/FIRApp.h>
+
+@implementation FIRAppDelegate
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ [FIRApp configure];
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ // Sent when the application is about to move from active to inactive state. This can occur for
+ // certain types of temporary interruptions (such as an incoming phone call or SMS message) or
+ // when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame
+ // rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ // Use this method to release shared resources, save user data, invalidate timers, and store
+ // enough application state information to restore your application to its current state in case
+ // it is terminated later.
+ // If your application supports background execution, this method is called instead of
+ // applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ // Called as part of the transition from the background to the inactive state; here you can undo
+ // many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If
+ // the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Called when the application is about to terminate. Save data if appropriate. See also
+ // applicationDidEnterBackground:.
+}
+
+@end
diff --git a/Example/Messaging/App/iOS/FIRViewController.h b/Example/Messaging/App/iOS/FIRViewController.h
new file mode 100644
index 0000000..64b4b74
--- /dev/null
+++ b/Example/Messaging/App/iOS/FIRViewController.h
@@ -0,0 +1,21 @@
+/*
+ * 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 UIKit;
+
+@interface FIRViewController : UIViewController
+
+@end
diff --git a/Example/Messaging/App/iOS/FIRViewController.m b/Example/Messaging/App/iOS/FIRViewController.m
new file mode 100644
index 0000000..027aabf
--- /dev/null
+++ b/Example/Messaging/App/iOS/FIRViewController.m
@@ -0,0 +1,33 @@
+// 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 "FIRViewController.h"
+
+@interface FIRViewController ()
+
+@end
+
+@implementation FIRViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view, typically from a nib.
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+@end
diff --git a/Example/Messaging/App/iOS/main.m b/Example/Messaging/App/iOS/main.m
new file mode 100644
index 0000000..39c05a5
--- /dev/null
+++ b/Example/Messaging/App/iOS/main.m
@@ -0,0 +1,22 @@
+// 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 UIKit;
+#import "FIRAppDelegate.h"
+
+int main(int argc, char* argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([FIRAppDelegate class]));
+ }
+}
diff --git a/Example/Messaging/App/GoogleService-Info.plist b/Example/Messaging/Sample/GoogleService-Info.plist
index 3f7547f..3f7547f 100644
--- a/Example/Messaging/App/GoogleService-Info.plist
+++ b/Example/Messaging/Sample/GoogleService-Info.plist
diff --git a/Example/Messaging/App/iOS/AppDelegate.swift b/Example/Messaging/Sample/iOS/AppDelegate.swift
index 89a5120..89a5120 100644
--- a/Example/Messaging/App/iOS/AppDelegate.swift
+++ b/Example/Messaging/Sample/iOS/AppDelegate.swift
diff --git a/Example/Messaging/Sample/iOS/Base.lproj/LaunchScreen.storyboard b/Example/Messaging/Sample/iOS/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..fdf3f97
--- /dev/null
+++ b/Example/Messaging/Sample/iOS/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--View Controller-->
+ <scene sceneID="EHf-IW-A2E">
+ <objects>
+ <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+ <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="53" y="375"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/Example/Messaging/Sample/iOS/Base.lproj/Main.storyboard b/Example/Messaging/Sample/iOS/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..6df1a82
--- /dev/null
+++ b/Example/Messaging/Sample/iOS/Base.lproj/Main.storyboard
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="taE-sK-BOl">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--Firebase Cloud Messaging-->
+ <scene sceneID="tne-QT-ifu">
+ <objects>
+ <viewController id="BYZ-38-t0r" customClass="MessagingViewController" customModule="Messaging_Example" customModuleProvider="target" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
+ <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </view>
+ <navigationItem key="navigationItem" title="Firebase Cloud Messaging" id="z1u-kE-qKb"/>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="698" y="164"/>
+ </scene>
+ <!--Navigation Controller-->
+ <scene sceneID="rmF-xz-rwn">
+ <objects>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="Ju1-Bj-8eG" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ <navigationController id="taE-sK-BOl" sceneMemberID="viewController">
+ <navigationBar key="navigationBar" contentMode="scaleToFill" id="iTL-Kg-11w">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </navigationBar>
+ <connections>
+ <segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="04R-HZ-bi6"/>
+ </connections>
+ </navigationController>
+ </objects>
+ <point key="canvasLocation" x="-92" y="165"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/Example/Messaging/App/iOS/Data+MessagingExtensions.swift b/Example/Messaging/Sample/iOS/Data+MessagingExtensions.swift
index 99ded25..99ded25 100644
--- a/Example/Messaging/App/iOS/Data+MessagingExtensions.swift
+++ b/Example/Messaging/Sample/iOS/Data+MessagingExtensions.swift
diff --git a/Example/Messaging/App/iOS/Environment.swift b/Example/Messaging/Sample/iOS/Environment.swift
index 5219c64..5219c64 100644
--- a/Example/Messaging/App/iOS/Environment.swift
+++ b/Example/Messaging/Sample/iOS/Environment.swift
diff --git a/Example/Messaging/App/iOS/Messaging-Info.plist b/Example/Messaging/Sample/iOS/Messaging-Info.plist
index b43105e..b43105e 100644
--- a/Example/Messaging/App/iOS/Messaging-Info.plist
+++ b/Example/Messaging/Sample/iOS/Messaging-Info.plist
diff --git a/Example/Messaging/App/iOS/MessagingViewController.swift b/Example/Messaging/Sample/iOS/MessagingViewController.swift
index 9bd07c1..9bd07c1 100644
--- a/Example/Messaging/App/iOS/MessagingViewController.swift
+++ b/Example/Messaging/Sample/iOS/MessagingViewController.swift
diff --git a/Example/Messaging/App/iOS/Messaging_Example.entitlements b/Example/Messaging/Sample/iOS/Messaging_Example.entitlements
index 903def2..903def2 100644
--- a/Example/Messaging/App/iOS/Messaging_Example.entitlements
+++ b/Example/Messaging/Sample/iOS/Messaging_Example.entitlements
diff --git a/Example/Messaging/App/iOS/NotificationsController.swift b/Example/Messaging/Sample/iOS/NotificationsController.swift
index 7545b44..7545b44 100644
--- a/Example/Messaging/App/iOS/NotificationsController.swift
+++ b/Example/Messaging/Sample/iOS/NotificationsController.swift
diff --git a/Example/Messaging/Tests/FIRMessagingServiceTest.m b/Example/Messaging/Tests/FIRMessagingServiceTest.m
index 9afdced..073adad 100644
--- a/Example/Messaging/Tests/FIRMessagingServiceTest.m
+++ b/Example/Messaging/Tests/FIRMessagingServiceTest.m
@@ -146,12 +146,15 @@
XCTestExpectation *exceptionExpectation =
[self expectationWithDescription:@"Should throw exception for invalid token"];
@try {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
[messaging.pubsub subscribeWithToken:@"abcdef1234"
topic:nil
options:nil
handler:^(NSError *error) {
XCTFail(@"Should not invoke the handler");
}];
+#pragma clang diagnostic pop
}
@catch (NSException *exception) {
[exceptionExpectation fulfill];
@@ -169,12 +172,15 @@
XCTestExpectation *exceptionExpectation =
[self expectationWithDescription:@"Should throw exception for invalid token"];
@try {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
[messaging.pubsub unsubscribeWithToken:@"abcdef1234"
topic:nil
options:nil
handler:^(NSError *error) {
XCTFail(@"Should not invoke the handler");
}];
+#pragma clang diagnostic pop
}
@catch (NSException *exception) {
[exceptionExpectation fulfill];
diff --git a/Example/Podfile b/Example/Podfile
index a26f255..0d46941 100644
--- a/Example/Podfile
+++ b/Example/Podfile
@@ -52,7 +52,6 @@ target 'Messaging_Example_iOS' do
platform :ios, '8.0'
pod 'FirebaseMessaging' , :path => '../'
- pod 'FirebaseInstanceID'
target 'Messaging_Tests_iOS' do
inherit! :search_paths
@@ -60,6 +59,11 @@ target 'Messaging_Example_iOS' do
end
end
+target 'Messaging_Sample_iOS' do
+ platform :ios, '8.0'
+ pod 'FirebaseMessaging' , :path => '../'
+end
+
target 'Storage_Example_iOS' do
platform :ios, '8.0'
diff --git a/Example/Storage/App/iOS/FIRAppDelegate.m b/Example/Storage/App/iOS/FIRAppDelegate.m
index d8e4497..9568d06 100644
--- a/Example/Storage/App/iOS/FIRAppDelegate.m
+++ b/Example/Storage/App/iOS/FIRAppDelegate.m
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-@import FirebaseStorage;
-
#import "FIRAppDelegate.h"
@implementation FIRAppDelegate
diff --git a/Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m b/Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m
index 8e826c9..b20108a 100644
--- a/Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m
+++ b/Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m
@@ -12,10 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#import <FirebaseStorage/FIRStorageMetadata.h>
#import <XCTest/XCTest.h>
-#import <math.h>
-
#import "FirebaseStorage.h"
#import <FirebaseCore/FIRApp.h>
@@ -381,7 +378,7 @@ NSTimeInterval kFIRStorageIntegrationTestTimeout = 30;
/// Only allow 1kB size, which is smaller than our file
[ref dataWithMaxSize:1 * 1024
completion:^(NSData *data, NSError *error) {
- XCTAssertEqual(data, nil);
+ XCTAssertNil(data);
XCTAssertEqual(error.code, FIRStorageErrorCodeDownloadSizeExceeded);
[expectation fulfill];
}];
@@ -389,6 +386,33 @@ NSTimeInterval kFIRStorageIntegrationTestTimeout = 30;
[self waitForExpectations];
}
+- (void)testUnauthenticatedSimpleGetDownloadURL {
+ XCTestExpectation *expectation =
+ [self expectationWithDescription:@"testUnauthenticatedSimpleGetDownloadURL"];
+
+ FIRStorageReference *ref = [self.storage referenceWithPath:@"ios/public/1mb"];
+
+ // Download URL format is
+ // "https://firebasestorage.googleapis.com/v0/b/{bucket}/o/{path}?alt=media&token={token}"
+ NSString *downloadURLPattern =
+ @"^https:\\/\\/firebasestorage.googleapis.com\\/v0\\/b\\/[^\\/]*\\/o\\/"
+ @"ios%2Fpublic%2F1mb\\?alt=media&token=[a-z0-9-]*$";
+
+ [ref downloadURLWithCompletion:^(NSURL *downloadURL, NSError *error) {
+ XCTAssertNil(error);
+ NSRegularExpression *testRegex =
+ [NSRegularExpression regularExpressionWithPattern:downloadURLPattern options:0 error:nil];
+ NSString *urlString = [downloadURL absoluteString];
+ XCTAssertEqual([testRegex numberOfMatchesInString:urlString
+ options:0
+ range:NSMakeRange(0, [urlString length])],
+ 1);
+ [expectation fulfill];
+ }];
+
+ [self waitForExpectations];
+}
+
- (void)testUnauthenticatedSimpleGetFile {
XCTestExpectation *expectation =
[self expectationWithDescription:@"testUnauthenticatedSimpleGetData"];
diff --git a/Example/Storage/Tests/Unit/FIRStorageMetadataTests.m b/Example/Storage/Tests/Unit/FIRStorageMetadataTests.m
index 84b5271..6a83741 100644
--- a/Example/Storage/Tests/Unit/FIRStorageMetadataTests.m
+++ b/Example/Storage/Tests/Unit/FIRStorageMetadataTests.m
@@ -15,6 +15,8 @@
#import <FirebaseStorage/FIRStorageMetadata.h>
#import <XCTest/XCTest.h>
+#import "FIRStorageGetDownloadURLTask.h"
+#import "FIRStorageGetDownloadURLTask_Private.h"
#import "FIRStorageMetadata.h"
#import "FIRStorageMetadata_Private.h"
#import "FIRStorageUtils.h"
@@ -39,7 +41,6 @@
kFIRStorageMetadataContentLanguage : @"en-us",
kFIRStorageMetadataContentType : @"application/octet-stream",
kFIRStorageMetadataCustomMetadata : @{@"foo" : @{@"bar" : @"baz"}},
- kFIRStorageMetadataDownloadTokens : @"1234567890",
kFIRStorageMetadataGeneration : @"12345",
kFIRStorageMetadataMetageneration : @"67890",
kFIRStorageMetadataName : @"path/to/object",
@@ -58,12 +59,6 @@
XCTAssertEqualObjects(metadata.contentType, metaDict[kFIRStorageMetadataContentType]);
XCTAssertEqualObjects(metadata.customMetadata, metaDict[kFIRStorageMetadataCustomMetadata]);
XCTAssertEqualObjects(metadata.md5Hash, metaDict[kFIRStorageMetadataMd5Hash]);
- NSString *URLFormat = @"https://firebasestorage.googleapis.com/v0/b/%@/o/%@?alt=media&token=%@";
- NSString *URLString = [NSString
- stringWithFormat:URLFormat, metaDict[kFIRStorageMetadataBucket],
- [FIRStorageUtils GCSEscapedString:metaDict[kFIRStorageMetadataName]],
- metaDict[kFIRStorageMetadataDownloadTokens]];
- XCTAssertEqualObjects([metadata.downloadURL description], URLString);
NSString *generation = [NSString stringWithFormat:@"%lld", metadata.generation];
XCTAssertEqualObjects(generation, metaDict[kFIRStorageMetadataGeneration]);
NSString *metageneration = [NSString stringWithFormat:@"%lld", metadata.metageneration];
@@ -86,7 +81,6 @@
kFIRStorageMetadataContentLanguage : @"en-us",
kFIRStorageMetadataContentType : @"application/octet-stream",
kFIRStorageMetadataCustomMetadata : @{@"foo" : @{@"bar" : @"baz"}},
- kFIRStorageMetadataDownloadTokens : @"1234567890",
kFIRStorageMetadataGeneration : @"12345",
kFIRStorageMetadataMetageneration : @"67890",
kFIRStorageMetadataName : @"path/to/object",
@@ -97,7 +91,7 @@
};
FIRStorageMetadata *metadata = [[FIRStorageMetadata alloc] initWithDictionary:metaDict];
NSDictionary *dictRepresentation = [metadata dictionaryRepresentation];
- XCTAssertNotEqual(dictRepresentation, nil);
+ XCTAssertNotNil(dictRepresentation);
XCTAssertEqualObjects(dictRepresentation[kFIRStorageMetadataBucket],
metaDict[kFIRStorageMetadataBucket]);
XCTAssertEqualObjects(dictRepresentation[kFIRStorageMetadataCacheControl],
@@ -130,60 +124,28 @@
metaDict[kFIRStorageMetadataMd5Hash]);
}
-- (void)testInitialzeNoDownloadTokensGetToken {
- NSDictionary *metaDict = @{
- kFIRStorageMetadataBucket : @"bucket",
- kFIRStorageMetadataName : @"path/to/object",
- };
- FIRStorageMetadata *metadata = [[FIRStorageMetadata alloc] initWithDictionary:metaDict];
- XCTAssertNotNil(metadata);
- XCTAssertEqual(metadata.downloadURL, nil);
- XCTAssertEqual(metadata.downloadURLs, nil);
-}
-
-- (void)testInitialzeMultipleDownloadTokensGetToken {
+- (void)testInitializeEmptyDownloadURL {
NSDictionary *metaDict = @{
kFIRStorageMetadataBucket : @"bucket",
- kFIRStorageMetadataDownloadTokens : @"12345,67890",
kFIRStorageMetadataName : @"path/to/object",
};
- FIRStorageMetadata *metadata = [[FIRStorageMetadata alloc] initWithDictionary:metaDict];
- XCTAssertNotNil(metadata);
- NSString *URLformat = @"https://firebasestorage.googleapis.com/v0/b/%@/o/%@?alt=media&token=%@";
- NSString *URLString0 = [NSString
- stringWithFormat:URLformat, metaDict[kFIRStorageMetadataBucket],
- [FIRStorageUtils GCSEscapedString:metaDict[kFIRStorageMetadataName]],
- @"12345"];
- NSString *URLString1 = [NSString
- stringWithFormat:URLformat, metaDict[kFIRStorageMetadataBucket],
- [FIRStorageUtils GCSEscapedString:metaDict[kFIRStorageMetadataName]],
- @"67890"];
- XCTAssertEqualObjects([metadata.downloadURL absoluteString], URLString0);
- XCTAssertEqualObjects([metadata.downloadURLs[0] absoluteString], URLString0);
- XCTAssertEqualObjects([metadata.downloadURLs[1] absoluteString], URLString1);
+ NSURL *actualURL = [FIRStorageGetDownloadURLTask downloadURLFromMetadataDictionary:metaDict];
+ XCTAssertNil(actualURL);
}
-- (void)testMultipleDownloadURLsGetToken {
+- (void)testInitializeDownloadURLFromToken {
NSDictionary *metaDict = @{
kFIRStorageMetadataBucket : @"bucket",
+ kFIRStorageMetadataDownloadTokens : @"12345,ignored",
kFIRStorageMetadataName : @"path/to/object",
};
- FIRStorageMetadata *metadata = [[FIRStorageMetadata alloc] initWithDictionary:metaDict];
NSString *URLformat = @"https://firebasestorage.googleapis.com/v0/b/%@/o/%@?alt=media&token=%@";
- NSString *URLString0 = [NSString
+ NSString *expectedURL = [NSString
stringWithFormat:URLformat, metaDict[kFIRStorageMetadataBucket],
[FIRStorageUtils GCSEscapedString:metaDict[kFIRStorageMetadataName]],
@"12345"];
- NSString *URLString1 = [NSString
- stringWithFormat:URLformat, metaDict[kFIRStorageMetadataBucket],
- [FIRStorageUtils GCSEscapedString:metaDict[kFIRStorageMetadataName]],
- @"67890"];
- NSURL *URL0 = [NSURL URLWithString:URLString0];
- NSURL *URL1 = [NSURL URLWithString:URLString1];
- NSArray *downloadURLs = @[ URL0, URL1 ];
- [metadata setValue:downloadURLs forKey:@"downloadURLs"];
- NSDictionary *newMetaDict = metadata.dictionaryRepresentation;
- XCTAssertEqualObjects(newMetaDict[kFIRStorageMetadataDownloadTokens], @"12345,67890");
+ NSURL *actualURL = [FIRStorageGetDownloadURLTask downloadURLFromMetadataDictionary:metaDict];
+ XCTAssertEqualObjects([actualURL absoluteString], expectedURL);
}
- (void)testInitialzeMetadataWithFile {
diff --git a/Firebase/Auth/Source/Public/FIRAuth.h b/Firebase/Auth/Source/Public/FIRAuth.h
index 7d5ea42..236dd10 100644
--- a/Firebase/Auth/Source/Public/FIRAuth.h
+++ b/Firebase/Auth/Source/Public/FIRAuth.h
@@ -33,7 +33,7 @@
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRUserUpdateCallback
- @brief The type of block invoked when a request to update a current user is completed.
+ @brief The type of block invoked when a request to update the current user is completed.
*/
typedef void (^FIRUserUpdateCallback)(NSError *_Nullable error) NS_SWIFT_NAME(UserUpdateCallback);
diff --git a/Firebase/Core/CHANGELOG.md b/Firebase/Core/CHANGELOG.md
index 4289cae..f4707ea 100644
--- a/Firebase/Core/CHANGELOG.md
+++ b/Firebase/Core/CHANGELOG.md
@@ -1,4 +1,6 @@
# Unreleased
+- [changed] Removed `UIKit` import from `FIRApp.h`.
+- [changed] Removed deprecated methods.
# 2018-03-06 -- v4.0.16 -- M22
- [changed] Addresses CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF warnings that surface in newer versions of Xcode and CocoaPods.
diff --git a/Firebase/Core/FIRApp.m b/Firebase/Core/FIRApp.m
index c2ce28e..c43db6e 100644
--- a/Firebase/Core/FIRApp.m
+++ b/Firebase/Core/FIRApp.m
@@ -133,23 +133,6 @@ static NSMutableDictionary *sLibraryVersions;
[FIRApp sendNotificationsToSDKs:sDefaultApp];
sDefaultApp.alreadySentConfigureNotification = YES;
}
-
- if (![FIRAppEnvironmentUtil isFromAppStore]) {
- // Support for iOS 7 has been deprecated, but will continue to function for the time being.
- // Log a notice for developers who are still targeting iOS 7 as the minimum OS version
- // supported.
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
- NSDictionary<NSString *, id> *info = [[NSBundle mainBundle] infoDictionary];
-
- NSString *minVersion = info[@"MinimumOSVersion"];
- if ([minVersion hasPrefix:@"7."]) {
- FIRLogNotice(kFIRLoggerCore, @"I-COR000026",
- @"Support for iOS 7 is deprecated and will "
- @"stop working in the future. Please upgrade your app to target iOS 8 or "
- @"above.");
- }
- });
- }
}
}
@@ -315,13 +298,6 @@ static NSMutableDictionary *sLibraryVersions;
return NO;
}
- if (NSClassFromString(@"FIRAppIndexing") != nil) {
- FIRLogDebug(kFIRLoggerCore, @"I-COR000024",
- @"Firebase App Indexing on iOS is deprecated. "
- @"You don't need to take any action at this time. Learn more about Firebase App "
- @"Indexing at https://firebase.google.com/docs/app-indexing/.");
- }
-
// Initialize the Analytics once there is a valid options under default app. Analytics should
// always initialize first by itself before the other SDKs.
if ([self.name isEqualToString:kFIRDefaultAppName]) {
diff --git a/Firebase/Core/FIRConfiguration.m b/Firebase/Core/FIRConfiguration.m
index 02617ef..cd64862 100644
--- a/Firebase/Core/FIRConfiguration.m
+++ b/Firebase/Core/FIRConfiguration.m
@@ -35,12 +35,6 @@ extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel);
return self;
}
-// This is deprecated, use setLoggerLevel instead.
-- (void)setLogLevel:(FIRLogLevel)logLevel {
- NSAssert(logLevel <= kFIRLogLevelMax, @"Invalid log level, %ld", (long)logLevel);
- _logLevel = logLevel;
-}
-
- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel {
NSAssert(loggerLevel <= FIRLoggerLevelMax && loggerLevel >= FIRLoggerLevelMin,
@"Invalid logger level, %ld", (long)loggerLevel);
diff --git a/Firebase/Core/FIROptions.m b/Firebase/Core/FIROptions.m
index 135ed3b..8dcd749 100644
--- a/Firebase/Core/FIROptions.m
+++ b/Firebase/Core/FIROptions.m
@@ -194,45 +194,6 @@ static NSDictionary *sDefaultOptionsDictionary = nil;
#pragma mark - Public instance methods
-- (instancetype)initWithGoogleAppID:(NSString *)googleAppID
- bundleID:(NSString *)bundleID
- GCMSenderID:(NSString *)GCMSenderID
- APIKey:(NSString *)APIKey
- clientID:(NSString *)clientID
- trackingID:(NSString *)trackingID
- androidClientID:(NSString *)androidClientID
- databaseURL:(NSString *)databaseURL
- storageBucket:(NSString *)storageBucket
- deepLinkURLScheme:(NSString *)deepLinkURLScheme {
- self = [super init];
- if (self) {
- if (!googleAppID) {
- [NSException raise:kFirebaseCoreErrorDomain format:@"Please specify a valid Google App ID."];
- } else if (!GCMSenderID) {
- [NSException raise:kFirebaseCoreErrorDomain format:@"Please specify a valid GCM Sender ID."];
- }
-
- // `bundleID` is a required property, default to the main `bundleIdentifier` if it's `nil`.
- if (!bundleID) {
- bundleID = [[NSBundle mainBundle] bundleIdentifier];
- }
-
- NSMutableDictionary *mutableOptionsDict = [NSMutableDictionary dictionary];
- [mutableOptionsDict setValue:googleAppID forKey:kFIRGoogleAppID];
- [mutableOptionsDict setValue:bundleID forKey:kFIRBundleID];
- [mutableOptionsDict setValue:GCMSenderID forKey:kFIRGCMSenderID];
- [mutableOptionsDict setValue:APIKey forKey:kFIRAPIKey];
- [mutableOptionsDict setValue:clientID forKey:kFIRClientID];
- [mutableOptionsDict setValue:trackingID forKey:kFIRTrackingID];
- [mutableOptionsDict setValue:androidClientID forKey:kFIRAndroidClientID];
- [mutableOptionsDict setValue:databaseURL forKey:kFIRDatabaseURL];
- [mutableOptionsDict setValue:storageBucket forKey:kFIRStorageBucket];
- self.optionsDictionary = mutableOptionsDict;
- self.deepLinkURLScheme = deepLinkURLScheme;
- }
- return self;
-}
-
- (instancetype)initWithContentsOfFile:(NSString *)plistPath {
self = [super init];
if (self) {
diff --git a/Firebase/Core/Public/FIRApp.h b/Firebase/Core/Public/FIRApp.h
index 9610455..fb18b75 100644
--- a/Firebase/Core/Public/FIRApp.h
+++ b/Firebase/Core/Public/FIRApp.h
@@ -16,11 +16,6 @@
#import <Foundation/Foundation.h>
-#if TARGET_OS_IOS
-// TODO: Remove UIKit import on next breaking change release
-#import <UIKit/UIKit.h>
-#endif
-
@class FIROptions;
NS_ASSUME_NONNULL_BEGIN
@@ -90,19 +85,11 @@ NS_SWIFT_NAME(FirebaseApp)
*/
+ (nullable FIRApp *)appNamed:(NSString *)name NS_SWIFT_NAME(app(name:));
-#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
/**
* Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This
* method is thread safe.
*/
@property(class, readonly, nullable) NSDictionary<NSString *, FIRApp *> *allApps;
-#else
-/**
- * Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This
- * method is thread safe.
- */
-+ (nullable NSDictionary<NSString *, FIRApp *> *)allApps NS_SWIFT_NAME(allApps());
-#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
/**
* Cleans up the current FIRApp, freeing associated data and returning its name to the pool for
diff --git a/Firebase/Core/Public/FIRConfiguration.h b/Firebase/Core/Public/FIRConfiguration.h
index 05bd261..95bba5e 100644
--- a/Firebase/Core/Public/FIRConfiguration.h
+++ b/Firebase/Core/Public/FIRConfiguration.h
@@ -19,25 +19,6 @@
#import "FIRAnalyticsConfiguration.h"
#import "FIRLoggerLevel.h"
-/**
- * The log levels used by FIRConfiguration.
- */
-typedef NS_ENUM(NSInteger, FIRLogLevel) {
- /** Error */
- kFIRLogLevelError __deprecated = 0,
- /** Warning */
- kFIRLogLevelWarning __deprecated,
- /** Info */
- kFIRLogLevelInfo __deprecated,
- /** Debug */
- kFIRLogLevelDebug __deprecated,
- /** Assert */
- kFIRLogLevelAssert __deprecated,
- /** Max */
- kFIRLogLevelMax __deprecated = kFIRLogLevelAssert
-} DEPRECATED_MSG_ATTRIBUTE(
- "Use -FIRDebugEnabled and -FIRDebugDisabled or setLoggerLevel. See FIRApp.h for more details.");
-
NS_ASSUME_NONNULL_BEGIN
/**
@@ -47,21 +28,12 @@ NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(FirebaseConfiguration)
@interface FIRConfiguration : NSObject
-#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
/** Returns the shared configuration object. */
@property(class, nonatomic, readonly) FIRConfiguration *sharedInstance NS_SWIFT_NAME(shared);
-#else
-/** Returns the shared configuration object. */
-+ (FIRConfiguration *)sharedInstance NS_SWIFT_NAME(shared());
-#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
/** The configuration class for Firebase Analytics. */
@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration;
-/** Global log level. Defaults to kFIRLogLevelError. */
-@property(nonatomic, readwrite, assign) FIRLogLevel logLevel DEPRECATED_MSG_ATTRIBUTE(
- "Use -FIRDebugEnabled and -FIRDebugDisabled or setLoggerLevel. See FIRApp.h for more details.");
-
/**
* Sets the logging level for internal Firebase logging. Firebase will only log messages
* that are logged at or below loggerLevel. The messages are logged both to the Xcode
diff --git a/Firebase/Core/Public/FIROptions.h b/Firebase/Core/Public/FIROptions.h
index b4e3b3b..87a01dd 100644
--- a/Firebase/Core/Public/FIROptions.h
+++ b/Firebase/Core/Public/FIROptions.h
@@ -91,25 +91,6 @@ NS_SWIFT_NAME(FirebaseOptions)
@property(nonatomic, copy, nullable) NSString *storageBucket;
/**
- * Initializes a customized instance of FIROptions with keys. googleAppID, bundleID and GCMSenderID
- * are required. Other keys may required for configuring specific services.
- */
-- (instancetype)initWithGoogleAppID:(NSString *)googleAppID
- bundleID:(NSString *)bundleID
- GCMSenderID:(NSString *)GCMSenderID
- APIKey:(NSString *)APIKey
- clientID:(NSString *)clientID
- trackingID:(NSString *)trackingID
- androidClientID:(NSString *)androidClientID
- databaseURL:(NSString *)databaseURL
- storageBucket:(NSString *)storageBucket
- deepLinkURLScheme:(NSString *)deepLinkURLScheme
- DEPRECATED_MSG_ATTRIBUTE(
- "Use `-[[FIROptions alloc] initWithGoogleAppID:GCMSenderID:]` "
- "(`FirebaseOptions(googleAppID:gcmSenderID:)` in Swift)` and property "
- "setters instead.");
-
-/**
* Initializes a customized instance of FIROptions from the file at the given plist file path. This
* will read the file synchronously from disk.
* For example,
diff --git a/Firebase/Core/third_party/FIRAppEnvironmentUtil.m b/Firebase/Core/third_party/FIRAppEnvironmentUtil.m
index 90e66f0..faee38b 100644
--- a/Firebase/Core/third_party/FIRAppEnvironmentUtil.m
+++ b/Firebase/Core/third_party/FIRAppEnvironmentUtil.m
@@ -13,9 +13,6 @@
// limitations under the License.
#import <Foundation/Foundation.h>
-#if TARGET_OS_IOS || TARGET_OS_TV
-#import <UIKit/UIKit.h>
-#endif
#import "FIRAppEnvironmentUtil.h"
@@ -207,11 +204,7 @@ static BOOL isAppEncrypted() {
}
+ (NSString *)systemVersion {
- #if TARGET_OS_IOS || TARGET_OS_TV
- return [UIDevice currentDevice].systemVersion;
- #elif TARGET_OS_OSX
return [NSProcessInfo processInfo].operatingSystemVersionString;
- #endif
}
+ (BOOL)isAppExtension {
diff --git a/Firebase/Database/Core/FPersistentConnection.m b/Firebase/Database/Core/FPersistentConnection.m
index 870727c..c32d18c 100644
--- a/Firebase/Database/Core/FPersistentConnection.m
+++ b/Firebase/Database/Core/FPersistentConnection.m
@@ -735,18 +735,22 @@ static void reachabilityCallback(SCNetworkReachabilityRef ref, SCNetworkReachabi
}
- (void) cancelSentTransactions {
- NSMutableArray* toPrune = [[NSMutableArray alloc] init];
+ NSMutableDictionary<NSNumber*, FOutstandingPut*>* cancelledOutstandingPuts = [[NSMutableDictionary alloc] init];
+
for (NSNumber* index in self.outstandingPuts) {
FOutstandingPut* put = self.outstandingPuts[index];
if (put.request[kFWPRequestHash] && put.sent) {
- // This is a sent transaction put
- put.onCompleteBlock(kFTransactionDisconnect, @"Client was disconnected while running a transaction");
- [toPrune addObject:index];
+ // This is a sent transaction put.
+ cancelledOutstandingPuts[index] = put;
}
}
- for (NSNumber* index in toPrune) {
+
+ [cancelledOutstandingPuts enumerateKeysAndObjectsUsingBlock:^(NSNumber *index, FOutstandingPut *outstandingPut, BOOL *stop) {
+ // `onCompleteBlock:` may invoke `rerunTransactionsForPath:` and enqueue new writes. We defer calling
+ // it until we have finished enumerating all existing writes.
+ outstandingPut.onCompleteBlock(kFTransactionDisconnect, @"Client was disconnected while running a transaction");
[self.outstandingPuts removeObjectForKey:index];
- }
+ }];
}
- (void) onDataPushWithAction:(NSString *)action andBody:(NSDictionary *)body {
diff --git a/Firebase/Database/Core/FRepo.m b/Firebase/Database/Core/FRepo.m
index 1c4b956..ae1d8e8 100644
--- a/Firebase/Database/Core/FRepo.m
+++ b/Firebase/Database/Core/FRepo.m
@@ -513,11 +513,11 @@
}
- (void)onConnect:(FPersistentConnection *)fpconnection {
- [self updateInfo:kDotInfoConnected withValue:@true];
+ [self updateInfo:kDotInfoConnected withValue:@YES];
}
- (void)onDisconnect:(FPersistentConnection *)fpconnection {
- [self updateInfo:kDotInfoConnected withValue:@false];
+ [self updateInfo:kDotInfoConnected withValue:@NO];
[self runOnDisconnectEvents];
}
diff --git a/Firebase/Messaging/FIRMMessageCode.h b/Firebase/Messaging/FIRMMessageCode.h
index 1ec3a39..c1b8ffb 100644
--- a/Firebase/Messaging/FIRMMessageCode.h
+++ b/Firebase/Messaging/FIRMMessageCode.h
@@ -37,7 +37,7 @@ typedef NS_ENUM(NSInteger, FIRMessagingMessageCode) {
kFIRMessagingMessageCodeMessaging013 = 2013, // I-FCM002013
kFIRMessagingMessageCodeMessaging014 = 2014, // I-FCM002014
kFIRMessagingMessageCodeMessaging015 = 2015, // I-FCM002015
- kFIRMessagingMessageCodeMessaging016 = 2016, // I-FCM002016
+ kFIRMessagingMessageCodeMessaging016 = 2016, // I-FCM002016 - no longer used
kFIRMessagingMessageCodeMessaging017 = 2017, // I-FCM002017
kFIRMessagingMessageCodeMessaging018 = 2018, // I-FCM002018
kFIRMessagingMessageCodeRemoteMessageDelegateMethodNotImplemented = 2019, // I-FCM002019
diff --git a/Firebase/Messaging/FIRMessaging.m b/Firebase/Messaging/FIRMessaging.m
index e02a125..8fafab8 100644
--- a/Firebase/Messaging/FIRMessaging.m
+++ b/Firebase/Messaging/FIRMessaging.m
@@ -73,29 +73,11 @@ NSString * const FIRMessagingRegistrationTokenRefreshedNotification =
NSString *const kFIRMessagingUserDefaultsKeyAutoInitEnabled =
@"com.firebase.messaging.auto-init.enabled"; // Auto Init Enabled key stored in NSUserDefaults
+NSString *const kFIRMessagingAPNSTokenType = @"APNSTokenType"; // APNS Token type key stored in user info.
+
static NSString *const kFIRMessagingPlistAutoInitEnabled =
@"FirebaseMessagingAutoInitEnabled"; // Auto Init Enabled key stored in Info.plist
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-/// A private helper to convert enum values without depending on their numerical values
-/// (avoid casting). This can be removed when InstanceID's deprecated APNS type enum is
-/// removed.
-FIRInstanceIDAPNSTokenType FIRIIDAPNSTokenTypeFromAPNSTokenType(FIRMessagingAPNSTokenType type) {
- switch (type) {
- case FIRMessagingAPNSTokenTypeProd:
- return FIRInstanceIDAPNSTokenTypeProd;
- case FIRMessagingAPNSTokenTypeSandbox:
- return FIRInstanceIDAPNSTokenTypeSandbox;
- case FIRMessagingAPNSTokenTypeUnknown:
- return FIRInstanceIDAPNSTokenTypeUnknown;
-
- default:
- return FIRInstanceIDAPNSTokenTypeUnknown;
- }
-}
-#pragma clang diagnostic pop
-
@interface FIRMessagingMessageInfo ()
@property(nonatomic, readwrite, assign) FIRMessagingMessageStatus status;
@@ -142,7 +124,9 @@ FIRInstanceIDAPNSTokenType FIRIIDAPNSTokenTypeFromAPNSTokenType(FIRMessagingAPNS
@end
@interface FIRMessaging ()<FIRMessagingClientDelegate, FIRMessagingReceiverDelegate,
- FIRReachabilityDelegate>
+ FIRReachabilityDelegate> {
+ BOOL _shouldEstablishDirectChannel;
+}
// FIRApp properties
@property(nonatomic, readwrite, copy) NSString *fcmSenderID;
@@ -206,14 +190,6 @@ FIRInstanceIDAPNSTokenType FIRIIDAPNSTokenTypeFromAPNSTokenType(FIRMessagingAPNS
[self teardown];
}
-- (void)setRemoteMessageDelegate:(id<FIRMessagingDelegate>)delegate {
- _delegate = delegate;
-}
-
-- (id<FIRMessagingDelegate>)remoteMessageDelegate {
- return self.delegate;
-}
-
#pragma mark - Config
- (void)start {
@@ -264,11 +240,6 @@ FIRInstanceIDAPNSTokenType FIRIIDAPNSTokenTypeFromAPNSTokenType(FIRMessagingAPNS
name:kFIRMessagingRegistrationTokenRefreshNotification
object:nil];
[center addObserver:self
- selector:@selector(didReceiveAPNSToken:)
- name:kFIRMessagingAPNSTokenNotification
- object:nil];
-
- [center addObserver:self
selector:@selector(applicationStateChanged)
name:UIApplicationDidBecomeActiveNotification
object:nil];
@@ -477,11 +448,13 @@ FIRInstanceIDAPNSTokenType FIRIIDAPNSTokenTypeFromAPNSTokenType(FIRMessagingAPNS
}
self.apnsTokenData = apnsToken;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [self.instanceID setAPNSToken:apnsToken
- type:FIRIIDAPNSTokenTypeFromAPNSTokenType(type)];
-#pragma clang diagnostic pop
+ // Notify InstanceID that APNS Token has been set.
+ NSDictionary *userInfo = @{kFIRMessagingAPNSTokenType : @(type)};
+ NSNotification *notification =
+ [NSNotification notificationWithName:kFIRMessagingAPNSTokenNotification
+ object:[apnsToken copy]
+ userInfo:userInfo];
+ [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
}
#pragma mark - FCM
@@ -578,18 +551,16 @@ FIRInstanceIDAPNSTokenType FIRIIDAPNSTokenTypeFromAPNSTokenType(FIRMessagingAPNS
[self validateDelegateConformsToTokenAvailabilityMethods];
}
-// Check if the delegate conforms to either |didReceiveRegistrationToken:| or
-// |didRefreshRegistrationToken:|, and display a warning to the developer if not.
+// Check if the delegate conforms to |didReceiveRegistrationToken:|
+// and display a warning to the developer if not.
// NOTE: Once |didReceiveRegistrationToken:| can be made a required method, this
// check can be removed.
- (void)validateDelegateConformsToTokenAvailabilityMethods {
if (self.delegate &&
- ![self.delegate respondsToSelector:@selector(messaging:didReceiveRegistrationToken:)] &&
- ![self.delegate respondsToSelector:@selector(messaging:didRefreshRegistrationToken:)]) {
+ ![self.delegate respondsToSelector:@selector(messaging:didReceiveRegistrationToken:)]) {
FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTokenDelegateMethodsNotImplemented,
@"The object %@ does not respond to "
- @"-messaging:didReceiveRegistrationToken:, nor "
- @"-messaging:didRefreshRegistrationToken:. Please implement "
+ @"-messaging:didReceiveRegistrationToken:. Please implement "
@"-messaging:didReceiveRegistrationToken: to be provided with an FCM "
@"token.", self.delegate.description);
}
@@ -792,12 +763,6 @@ FIRInstanceIDAPNSTokenType FIRIIDAPNSTokenTypeFromAPNSTokenType(FIRMessagingAPNS
return [self currentLocale];
}
-- (void)setAPNSToken:(NSData *)apnsToken error:(NSError *)error {
- if (apnsToken) {
- self.apnsTokenData = [apnsToken copy];
- }
-}
-
#pragma mark - FIRMessagingReceiverDelegate
- (void)receiver:(FIRMessagingReceiver *)receiver
@@ -807,11 +772,6 @@ FIRInstanceIDAPNSTokenType FIRIIDAPNSTokenTypeFromAPNSTokenType(FIRMessagingAPNS
#pragma clang diagnostic ignored "-Wunguarded-availability"
[self.delegate messaging:self didReceiveMessage:remoteMessage];
#pragma pop
- } else if ([self.delegate respondsToSelector:@selector(applicationReceivedRemoteMessage:)]) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- [self.delegate applicationReceivedRemoteMessage:remoteMessage];
-#pragma clang diagnostic pop
} else {
// Delegate methods weren't implemented, so messages are being dropped, log a warning
FIRMessagingLoggerWarn(kFIRMessagingMessageCodeRemoteMessageDelegateMethodNotImplemented,
@@ -888,29 +848,11 @@ FIRInstanceIDAPNSTokenType FIRIIDAPNSTokenTypeFromAPNSTokenType(FIRMessagingAPNS
if (self.defaultFcmToken && ![self.defaultFcmToken isEqualToString:oldToken]) {
[self notifyDelegateOfFCMTokenAvailability];
}
- // Call deprecated refresh method, because it should still work (until it is removed).
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- if ([self.delegate respondsToSelector:@selector(messaging:didRefreshRegistrationToken:)]) {
- [self.delegate messaging:self didRefreshRegistrationToken:token];
- }
-#pragma clang diagnostic pop
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:FIRMessagingRegistrationTokenRefreshedNotification object:nil];
}
}
-- (void)didReceiveAPNSToken:(NSNotification *)notification {
- NSData *apnsToken = notification.object;
- if (![apnsToken isKindOfClass:[NSData class]]) {
- FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging016, @"Invalid APNS token type %@",
- NSStringFromClass([notification.object class]));
- return;
- }
- // Set this value directly, and since this came from InstanceID, don't set it back to InstanceID
- self.apnsTokenData = [apnsToken copy];
-}
-
#pragma mark - Application Support Directory
+ (BOOL)hasApplicationSupportSubDirectory:(NSString *)subDirectoryName {
diff --git a/Firebase/Messaging/FIRMessagingPubSub.h b/Firebase/Messaging/FIRMessagingPubSub.h
index a2141e4..1c615d1 100644
--- a/Firebase/Messaging/FIRMessagingPubSub.h
+++ b/Firebase/Messaging/FIRMessagingPubSub.h
@@ -16,6 +16,8 @@
#import "FIRMessaging.h"
+NS_ASSUME_NONNULL_BEGIN
+
@class FIRMessagingClient;
@class FIRMessagingPubSubCache;
@@ -68,7 +70,7 @@
*/
- (void)subscribeWithToken:(NSString *)token
topic:(NSString *)topic
- options:(NSDictionary *)options
+ options:(nullable NSDictionary *)options
handler:(FIRMessagingTopicOperationCompletion)handler;
/**
@@ -90,7 +92,7 @@
*/
- (void)unsubscribeWithToken:(NSString *)token
topic:(NSString *)topic
- options:(NSDictionary *)options
+ options:(nullable NSDictionary *)options
handler:(FIRMessagingTopicOperationCompletion)handler;
/**
@@ -155,3 +157,5 @@
+ (BOOL)isValidTopicWithPrefix:(NSString *)topic;
@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m b/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m
index 0b8d92b..e9d4791 100644
--- a/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m
+++ b/Firebase/Messaging/FIRMessagingRemoteNotificationsProxy.m
@@ -30,6 +30,7 @@ static NSString *kUserNotificationWillPresentSelectorString =
@"userNotificationCenter:willPresentNotification:withCompletionHandler:";
static NSString *kUserNotificationDidReceiveResponseSelectorString =
@"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:";
+static NSString *kReceiveDataMessageSelectorString = @"messaging:didReceiveMessage:";
@interface FIRMessagingRemoteNotificationsProxy ()
@@ -141,9 +142,6 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
SEL remoteNotificationWithFetchHandlerSelector =
@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:);
- // For data message from MCS.
- SEL receiveDataMessageSelector = NSSelectorFromString(@"applicationReceivedRemoteMessage:");
-
// For recording when APNS tokens are registered (or fail to register)
SEL registerForAPNSFailSelector =
@selector(application:didFailToRegisterForRemoteNotificationsWithError:);
@@ -172,11 +170,13 @@ static NSString *kUserNotificationDidReceiveResponseSelectorString =
didSwizzleAppDelegate = YES;
}
+ // For data message from MCS.
+ SEL receiveDataMessageSelector = NSSelectorFromString(kReceiveDataMessageSelectorString);
if ([appDelegate respondsToSelector:receiveDataMessageSelector]) {
[self swizzleSelector:receiveDataMessageSelector
- inClass:appDelegateClass
- withImplementation:(IMP)FCM_swizzle_applicationReceivedRemoteMessage
- inProtocol:@protocol(UIApplicationDelegate)];
+ inClass:appDelegateClass
+ withImplementation:(IMP)FCM_swizzle_messagingDidReceiveMessage
+ inProtocol:@protocol(UIApplicationDelegate)];
didSwizzleAppDelegate = YES;
}
@@ -669,14 +669,15 @@ id userInfoFromNotification(id notification) {
return notificationUserInfo;
}
-void FCM_swizzle_applicationReceivedRemoteMessage(
- id self, SEL _cmd, FIRMessagingRemoteMessage *remoteMessage) {
+void FCM_swizzle_messagingDidReceiveMessage(id self, SEL _cmd, FIRMessaging *message,
+ FIRMessagingRemoteMessage *remoteMessage) {
[[FIRMessaging messaging] appDidReceiveMessage:remoteMessage.appData];
IMP original_imp =
[[FIRMessagingRemoteNotificationsProxy sharedProxy] originalImplementationForSelector:_cmd];
if (original_imp) {
- ((void (*)(id, SEL, FIRMessagingRemoteMessage *))original_imp)(self, _cmd, remoteMessage);
+ ((void (*)(id, SEL, FIRMessaging *, FIRMessagingRemoteMessage *))original_imp)(
+ self, _cmd, message, remoteMessage);
}
}
diff --git a/Firebase/Messaging/FIRMessaging_Private.h b/Firebase/Messaging/FIRMessaging_Private.h
index 496fea4..46daee0 100644
--- a/Firebase/Messaging/FIRMessaging_Private.h
+++ b/Firebase/Messaging/FIRMessaging_Private.h
@@ -52,7 +52,4 @@ FOUNDATION_EXPORT NSString *const kFIRMessagingUserDefaultsKeyAutoInitEnabled;
- (BOOL)isNetworkAvailable;
- (FIRMessagingNetworkStatus)networkType;
-// Set the APNS token for FCM.
-- (void)setAPNSToken:(NSData *)apnsToken error:(NSError *)error;
-
@end
diff --git a/Firebase/Messaging/Public/FIRMessaging.h b/Firebase/Messaging/Public/FIRMessaging.h
index 479f68e..3ad15da 100644
--- a/Firebase/Messaging/Public/FIRMessaging.h
+++ b/Firebase/Messaging/Public/FIRMessaging.h
@@ -16,6 +16,8 @@
#import <Foundation/Foundation.h>
+NS_ASSUME_NONNULL_BEGIN
+
/**
* @related FIRMessaging
*
@@ -78,7 +80,7 @@ typedef void(^FIRMessagingConnectCompletion)(NSError * __nullable error)
* successfully to the server. The notification object will be the messageID
* of the successfully delivered message.
*/
-FOUNDATION_EXPORT const NSNotificationName __nonnull FIRMessagingSendSuccessNotification
+FOUNDATION_EXPORT const NSNotificationName FIRMessagingSendSuccessNotification
NS_SWIFT_NAME(MessagingSendSuccess);
/**
@@ -87,7 +89,7 @@ FOUNDATION_EXPORT const NSNotificationName __nonnull FIRMessagingSendSuccessNoti
* message. The userInfo dictionary will contain the relevant error
* information for the failure.
*/
-FOUNDATION_EXPORT const NSNotificationName __nonnull FIRMessagingSendErrorNotification
+FOUNDATION_EXPORT const NSNotificationName FIRMessagingSendErrorNotification
NS_SWIFT_NAME(MessagingSendError);
/**
@@ -98,7 +100,7 @@ FOUNDATION_EXPORT const NSNotificationName __nonnull FIRMessagingSendErrorNotifi
* It is recommended to retrieve any missing messages directly from the
* server.
*/
-FOUNDATION_EXPORT const NSNotificationName __nonnull FIRMessagingMessagesDeletedNotification
+FOUNDATION_EXPORT const NSNotificationName FIRMessagingMessagesDeletedNotification
NS_SWIFT_NAME(MessagingMessagesDeleted);
/**
@@ -106,7 +108,7 @@ FOUNDATION_EXPORT const NSNotificationName __nonnull FIRMessagingMessagesDeleted
* an FCM socket connection. You can query the connection state in this
* notification by checking the `isDirectChannelEstablished` property of FIRMessaging.
*/
-FOUNDATION_EXPORT const NSNotificationName __nonnull FIRMessagingConnectionStateChangedNotification
+FOUNDATION_EXPORT const NSNotificationName FIRMessagingConnectionStateChangedNotification
NS_SWIFT_NAME(MessagingConnectionStateChanged);
/**
@@ -114,7 +116,7 @@ FOUNDATION_EXPORT const NSNotificationName __nonnull FIRMessagingConnectionState
* FIRMessaging delegate method `messaging:didReceiveRegistrationToken:` to receive current and
* updated tokens.
*/
-FOUNDATION_EXPORT const NSNotificationName __nonnull
+FOUNDATION_EXPORT const NSNotificationName
FIRMessagingRegistrationTokenRefreshedNotification
NS_SWIFT_NAME(MessagingRegistrationTokenRefreshed);
#else
@@ -123,7 +125,7 @@ FOUNDATION_EXPORT const NSNotificationName __nonnull
* successfully to the server. The notification object will be the messageID
* of the successfully delivered message.
*/
-FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingSendSuccessNotification
+FOUNDATION_EXPORT NSString *const FIRMessagingSendSuccessNotification
NS_SWIFT_NAME(MessagingSendSuccessNotification);
/**
@@ -132,7 +134,7 @@ FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingSendSuccessNotification
* message. The userInfo dictionary will contain the relevant error
* information for the failure.
*/
-FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingSendErrorNotification
+FOUNDATION_EXPORT NSString *const FIRMessagingSendErrorNotification
NS_SWIFT_NAME(MessagingSendErrorNotification);
/**
@@ -143,7 +145,7 @@ FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingSendErrorNotification
* It is recommended to retrieve any missing messages directly from the
* server.
*/
-FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingMessagesDeletedNotification
+FOUNDATION_EXPORT NSString *const FIRMessagingMessagesDeletedNotification
NS_SWIFT_NAME(MessagingMessagesDeletedNotification);
/**
@@ -151,7 +153,7 @@ FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingMessagesDeletedNotifica
* an FCM socket connection. You can query the connection state in this
* notification by checking the `isDirectChannelEstablished` property of FIRMessaging.
*/
-FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingConnectionStateChangedNotification
+FOUNDATION_EXPORT NSString *const FIRMessagingConnectionStateChangedNotification
NS_SWIFT_NAME(MessagingConnectionStateChangedNotification);
/**
@@ -159,7 +161,7 @@ FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingConnectionStateChangedN
* FIRMessaging delegate method `messaging:didReceiveRegistrationToken:` to receive current and
* updated tokens.
*/
-FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingRegistrationTokenRefreshedNotification
+FOUNDATION_EXPORT NSString *const FIRMessagingRegistrationTokenRefreshedNotification
NS_SWIFT_NAME(MessagingRegistrationTokenRefreshedNotification);
#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
@@ -232,15 +234,13 @@ NS_SWIFT_NAME(MessagingRemoteMessage)
@interface FIRMessagingRemoteMessage : NSObject
/// The downstream message received by the application.
-@property(nonatomic, readonly, strong, nonnull) NSDictionary *appData;
+@property(nonatomic, readonly, strong) NSDictionary *appData;
@end
@class FIRMessaging;
/**
- * A protocol to handle events from FCM for devices running iOS 10 or above.
+ * A protocol to handle token update or data message delivery from FCM.
*
- * To support devices running iOS 9 or below, use the local and remote notifications handlers
- * defined in UIApplicationDelegate protocol.
*/
NS_SWIFT_NAME(MessagingDelegate)
@protocol FIRMessagingDelegate <NSObject>
@@ -253,32 +253,18 @@ NS_SWIFT_NAME(MessagingDelegate)
/// * Uploading the FCM token to your application server, so targeted notifications can be sent.
///
/// * Subscribing to any topics.
-- (void)messaging:(nonnull FIRMessaging *)messaging
- didReceiveRegistrationToken:(nonnull NSString *)fcmToken
+- (void)messaging:(FIRMessaging *)messaging
+ didReceiveRegistrationToken:(NSString *)fcmToken
NS_SWIFT_NAME(messaging(_:didReceiveRegistrationToken:));
-/// This method will be called whenever FCM receives a new, default FCM token for your
-/// Firebase project's Sender ID. This method is deprecated. Please use
-/// `messaging:didReceiveRegistrationToken:`.
-- (void)messaging:(nonnull FIRMessaging *)messaging
- didRefreshRegistrationToken:(nonnull NSString *)fcmToken
- NS_SWIFT_NAME(messaging(_:didRefreshRegistrationToken:))
- __deprecated_msg("Please use messaging:didReceiveRegistrationToken:, which is called for both \
- current and refreshed tokens.");
-
/// This method is called on iOS 10 devices to handle data messages received via FCM through its
/// direct channel (not via APNS). For iOS 9 and below, the FCM data message is delivered via the
/// UIApplicationDelegate's -application:didReceiveRemoteNotification: method.
-- (void)messaging:(nonnull FIRMessaging *)messaging
- didReceiveMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage
+- (void)messaging:(FIRMessaging *)messaging
+ didReceiveMessage:(FIRMessagingRemoteMessage *)remoteMessage
NS_SWIFT_NAME(messaging(_:didReceive:))
__IOS_AVAILABLE(10.0);
-/// The callback to handle data message received via FCM for devices running iOS 10 or above.
-- (void)applicationReceivedRemoteMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage
- NS_SWIFT_NAME(application(received:))
- __deprecated_msg("Use FIRMessagingDelegate’s -messaging:didReceiveMessage:");
-
@end
/**
@@ -300,35 +286,24 @@ NS_SWIFT_NAME(Messaging)
@property(nonatomic, weak, nullable) id<FIRMessagingDelegate> delegate;
/**
- * Delegate to handle remote data messages received via FCM for devices running iOS 10 or above.
- */
-@property(nonatomic, weak, nullable) id<FIRMessagingDelegate> remoteMessageDelegate
- __deprecated_msg("Use 'delegate' property");
-
-/**
* When set to `YES`, Firebase Messaging will automatically establish a socket-based, direct
* channel to the FCM server. Enable this only if you are sending upstream messages or
* receiving non-APNS, data-only messages in foregrounded apps.
* Default is `NO`.
*/
-@property(nonatomic) BOOL shouldEstablishDirectChannel;
-
-/**
- * Returns `YES` if the direct channel to the FCM server is active, and `NO` otherwise.
- */
-@property(nonatomic, readonly) BOOL isDirectChannelEstablished;
+@property(nonatomic, assign, getter=isDirectChannelEstablished) BOOL shouldEstablishDirectChannel;
/**
* FIRMessaging
*
* @return An instance of FIRMessaging.
*/
-+ (nonnull instancetype)messaging NS_SWIFT_NAME(messaging());
++ (instancetype)messaging NS_SWIFT_NAME(messaging());
/**
* Unavailable. Use +messaging instead.
*/
-- (nonnull instancetype)init __attribute__((unavailable("Use +messaging instead.")));
+- (instancetype)init __attribute__((unavailable("Use +messaging instead.")));
#pragma mark - APNS
@@ -358,7 +333,7 @@ NS_SWIFT_NAME(Messaging)
* FIRMessagingAPNSTokenTypeUnknown to have the type automatically
* detected based on your provisioning profile.
*/
-- (void)setAPNSToken:(nonnull NSData *)apnsToken type:(FIRMessagingAPNSTokenType)type;
+- (void)setAPNSToken:(NSData *)apnsToken type:(FIRMessagingAPNSTokenType)type;
#pragma mark - FCM Tokens
@@ -413,8 +388,8 @@ NS_SWIFT_NAME(Messaging)
* @param senderID The Sender ID for a particular Firebase project.
* @param completion The completion handler to handle the token request.
*/
-- (void)retrieveFCMTokenForSenderID:(nonnull NSString *)senderID
- completion:(nonnull FIRMessagingFCMTokenFetchCompletion)completion
+- (void)retrieveFCMTokenForSenderID:(NSString *)senderID
+ completion:(FIRMessagingFCMTokenFetchCompletion)completion
NS_SWIFT_NAME(retrieveFCMToken(forSenderID:completion:));
@@ -425,8 +400,8 @@ NS_SWIFT_NAME(Messaging)
* @param senderID The senderID for a particular Firebase project.
* @param completion The completion handler to handle the token deletion.
*/
-- (void)deleteFCMTokenForSenderID:(nonnull NSString *)senderID
- completion:(nonnull FIRMessagingDeleteFCMTokenCompletion)completion
+- (void)deleteFCMTokenForSenderID:(NSString *)senderID
+ completion:(FIRMessagingDeleteFCMTokenCompletion)completion
NS_SWIFT_NAME(deleteFCMToken(forSenderID:completion:));
@@ -444,7 +419,7 @@ NS_SWIFT_NAME(Messaging)
* the same time, FIRMessaging performs exponential backoff to retry
* establishing a connection and invoke the handler when successful.
*/
-- (void)connectWithCompletion:(nonnull FIRMessagingConnectCompletion)handler
+- (void)connectWithCompletion:(FIRMessagingConnectCompletion)handler
NS_SWIFT_NAME(connect(handler:))
__deprecated_msg("Please use the shouldEstablishDirectChannel property instead.");
@@ -466,7 +441,7 @@ NS_SWIFT_NAME(Messaging)
*
* @param topic The name of the topic, for example, @"sports".
*/
-- (void)subscribeToTopic:(nonnull NSString *)topic NS_SWIFT_NAME(subscribe(toTopic:));
+- (void)subscribeToTopic:(NSString *)topic NS_SWIFT_NAME(subscribe(toTopic:));
/**
* Asynchronously subscribe to the provided topic, retrying on failure.
@@ -484,7 +459,7 @@ NS_SWIFT_NAME(Messaging)
*
* @param topic The name of the topic, for example @"sports".
*/
-- (void)unsubscribeFromTopic:(nonnull NSString *)topic NS_SWIFT_NAME(unsubscribe(fromTopic:));
+- (void)unsubscribeFromTopic:(NSString *)topic NS_SWIFT_NAME(unsubscribe(fromTopic:));
/**
* Asynchronously unsubscribe from the provided topic, retrying on failure.
@@ -522,9 +497,9 @@ NS_SWIFT_NAME(Messaging)
* if the message has been dropped because of TTL; this can happen
* on the server side, and it would require extra communication.
*/
-- (void)sendMessage:(nonnull NSDictionary *)message
- to:(nonnull NSString *)receiver
- withMessageID:(nonnull NSString *)messageID
+- (void)sendMessage:(NSDictionary *)message
+ to:(NSString *)receiver
+ withMessageID:(NSString *)messageID
timeToLive:(int64_t)ttl;
#pragma mark - Analytics
@@ -540,6 +515,8 @@ NS_SWIFT_NAME(Messaging)
*
* @return Information about the downstream message.
*/
-- (nonnull FIRMessagingMessageInfo *)appDidReceiveMessage:(nonnull NSDictionary *)message;
+- (FIRMessagingMessageInfo *)appDidReceiveMessage:(NSDictionary *)message;
@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Storage/CHANGELOG.md b/Firebase/Storage/CHANGELOG.md
index 5054cf2..135de40 100644
--- a/Firebase/Storage/CHANGELOG.md
+++ b/Firebase/Storage/CHANGELOG.md
@@ -1,5 +1,9 @@
+# v3.0.0
+- [removed] Removed `downloadURLs` property on `StorageMetadata`. Use `StorageReference.downloadURL(completion:)` to obtain a current download URL.
+- [changed] The `maxOperationRetryTime` timeout now applies to calls to `StorageReference.getMetadata(completion:)` and `StorageReference.updateMetadata(completion:)`. These calls previously used the `maxDownloadRetryTime` and `maxUploadRetryTime` timeouts.
+
# v2.2.0
-- [changed] Deprecated `downloadURLs` property on `StorageMetadata`. Use `StorageReference.downloadURLWithCompletion()` to obtain a current download URL.
+- [changed] Deprecated `downloadURLs` property on `StorageMetadata`. Use `StorageReference.downloadURL(completion:)` to obtain a current download URL.
# v2.1.3
- [changed] Addresses CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF warnings that surface in newer versions of Xcode and CocoaPods.
diff --git a/Firebase/Storage/FIRStorageErrors.m b/Firebase/Storage/FIRStorageErrors.m
index ecfae02..651bfd1 100644
--- a/Firebase/Storage/FIRStorageErrors.m
+++ b/Firebase/Storage/FIRStorageErrors.m
@@ -170,4 +170,21 @@
return clientError;
}
++ (NSError *)errorWithInvalidRequest:(NSData *)request {
+ NSString *requestString = [[NSString alloc] initWithData:request encoding:NSUTF8StringEncoding];
+ NSString *invalidDataString =
+ [NSString stringWithFormat:kFIRStorageInvalidDataFormat, requestString];
+ NSDictionary *dict;
+ if (invalidDataString.length > 0) {
+ dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString};
+ }
+ return [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict];
+}
+
++ (NSError *)errorWithCustomMessage:(NSString *)errorMessage {
+ return [NSError errorWithDomain:FIRStorageErrorDomain
+ code:FIRStorageErrorCodeUnknown
+ userInfo:@{NSLocalizedDescriptionKey : errorMessage}];
+}
+
@end
diff --git a/Firebase/Storage/FIRStorageGetDownloadURLTask.m b/Firebase/Storage/FIRStorageGetDownloadURLTask.m
new file mode 100644
index 0000000..02d202e
--- /dev/null
+++ b/Firebase/Storage/FIRStorageGetDownloadURLTask.m
@@ -0,0 +1,117 @@
+// Copyright 2018 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 "FIRStorageGetDownloadURLTask.h"
+
+#import "FIRStorageTask_Private.h"
+
+@implementation FIRStorageGetDownloadURLTask {
+ @private
+ FIRStorageVoidURLError _completion;
+}
+
+@synthesize fetcher = _fetcher;
+@synthesize fetcherCompletion = _fetcherCompletion;
+
+- (instancetype)initWithReference:(FIRStorageReference *)reference
+ fetcherService:(GTMSessionFetcherService *)service
+ completion:(FIRStorageVoidURLError)completion {
+ self = [super initWithReference:reference fetcherService:service];
+ if (self) {
+ _completion = [completion copy];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [_fetcher stopFetching];
+}
+
++ (NSURL *)downloadURLFromMetadataDictionary:(NSDictionary *)dictionary {
+ NSString *downloadTokens = dictionary[kFIRStorageMetadataDownloadTokens];
+
+ if (downloadTokens && downloadTokens.length > 0) {
+ NSArray<NSString *> *downloadTokenArray = [downloadTokens componentsSeparatedByString:@","];
+ NSString *bucket = dictionary[kFIRStorageMetadataBucket];
+ NSString *path = dictionary[kFIRStorageMetadataName];
+ NSString *fullPath = [NSString stringWithFormat:kFIRStorageFullPathFormat, bucket,
+ [FIRStorageUtils GCSEscapedString:path]];
+
+ NSURLComponents *components = [[NSURLComponents alloc] init];
+ components.scheme = kFIRStorageScheme;
+ components.host = kFIRStorageHost;
+ components.percentEncodedPath = fullPath;
+
+ // The backend can return an arbitrary number of download tokens, but we only expose the first
+ // token via the download URL.
+ NSURLQueryItem *altItem = [[NSURLQueryItem alloc] initWithName:@"alt" value:@"media"];
+ NSURLQueryItem *tokenItem =
+ [[NSURLQueryItem alloc] initWithName:@"token" value:downloadTokenArray[0]];
+ components.queryItems = @[ altItem, tokenItem ];
+
+ return [components URL];
+ }
+
+ return nil;
+}
+
+- (void)enqueue {
+ NSMutableURLRequest *request = [self.baseRequest mutableCopy];
+ request.HTTPMethod = @"GET";
+ request.timeoutInterval = self.reference.storage.maxOperationRetryTime;
+
+ FIRStorageVoidURLError callback = _completion;
+ _completion = nil;
+
+ GTMSessionFetcher *fetcher = [self.fetcherService fetcherWithRequest:request];
+ _fetcher = fetcher;
+ fetcher.comment = @"GetDownloadURLTask";
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-retain-cycles"
+ _fetcherCompletion = ^(NSData *data, NSError *error) {
+ NSURL *downloadURL;
+ if (error) {
+ if (!self.error) {
+ self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
+ }
+ } else {
+ NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data];
+ if (responseDictionary != nil) {
+ downloadURL =
+ [FIRStorageGetDownloadURLTask downloadURLFromMetadataDictionary:responseDictionary];
+ if (!downloadURL) {
+ self.error =
+ [FIRStorageErrors errorWithCustomMessage:@"Failed to retrieve a download URL."];
+ }
+ } else {
+ self.error = [FIRStorageErrors errorWithInvalidRequest:data];
+ }
+ }
+
+ if (callback) {
+ callback(downloadURL, self.error);
+ }
+
+ self->_fetcherCompletion = nil;
+ };
+#pragma clang diagnostic pop
+
+ __weak FIRStorageGetDownloadURLTask *weakSelf = self;
+ [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
+ weakSelf.fetcherCompletion(data, error);
+ }];
+}
+
+@end
diff --git a/Firebase/Storage/FIRStorageGetMetadataTask.m b/Firebase/Storage/FIRStorageGetMetadataTask.m
index 2623652..752c410 100644
--- a/Firebase/Storage/FIRStorageGetMetadataTask.m
+++ b/Firebase/Storage/FIRStorageGetMetadataTask.m
@@ -46,7 +46,7 @@
- (void)enqueue {
NSMutableURLRequest *request = [self.baseRequest mutableCopy];
request.HTTPMethod = @"GET";
- request.timeoutInterval = self.reference.storage.maxDownloadRetryTime;
+ request.timeoutInterval = self.reference.storage.maxOperationRetryTime;
FIRStorageVoidMetadataError callback = _completion;
_completion = nil;
@@ -58,37 +58,23 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
_fetcherCompletion = ^(NSData *data, NSError *error) {
+ FIRStorageMetadata *metadata;
if (error) {
if (!self.error) {
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
}
- if (callback) {
- callback(nil, self.error);
+ } else {
+ NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data];
+ if (responseDictionary != nil) {
+ metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary];
+ [metadata setType:FIRStorageMetadataTypeFile];
+ } else {
+ self.error = [FIRStorageErrors errorWithInvalidRequest:data];
}
- self->_fetcherCompletion = nil;
- return;
}
- NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data];
- if (responseDictionary != nil) {
- FIRStorageMetadata *metadata =
- [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary];
- [metadata setType:FIRStorageMetadataTypeFile];
- if (callback) {
- callback(metadata, nil);
- }
- } else {
- NSString *returnedData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- NSString *invalidDataString =
- [NSString stringWithFormat:kFIRStorageInvalidDataFormat, returnedData];
- NSDictionary *dict;
- if (invalidDataString.length > 0) {
- dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString};
- }
- self.error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict];
- if (callback) {
- callback(nil, self.error);
- }
+ if (callback) {
+ callback(metadata, self.error);
}
self->_fetcherCompletion = nil;
};
diff --git a/Firebase/Storage/FIRStorageMetadata.m b/Firebase/Storage/FIRStorageMetadata.m
index ab25076..764907c 100644
--- a/Firebase/Storage/FIRStorageMetadata.m
+++ b/Firebase/Storage/FIRStorageMetadata.m
@@ -41,7 +41,6 @@
_contentType = dictionary[kFIRStorageMetadataContentType];
_customMetadata = dictionary[kFIRStorageMetadataCustomMetadata];
_size = [dictionary[kFIRStorageMetadataSize] longLongValue];
- _downloadURLs = dictionary[kFIRStorageMetadataDownloadURLs];
_generation = [dictionary[kFIRStorageMetadataGeneration] longLongValue];
_metageneration = [dictionary[kFIRStorageMetadataMetageneration] longLongValue];
_timeCreated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataTimeCreated]];
@@ -50,26 +49,6 @@
// GCS "name" is our path, our "name" is just the last path component of the path
_path = dictionary[kFIRStorageMetadataName];
_name = [_path lastPathComponent];
- NSString *downloadTokens = dictionary[kFIRStorageMetadataDownloadTokens];
- if (downloadTokens) {
- NSArray<NSString *> *downloadStringArray = [downloadTokens componentsSeparatedByString:@","];
- NSMutableArray<NSURL *> *downloadURLArray =
- [[NSMutableArray alloc] initWithCapacity:[downloadStringArray count]];
- [downloadStringArray enumerateObjectsUsingBlock:^(NSString *_Nonnull token, NSUInteger idx,
- BOOL *_Nonnull stop) {
- NSURLComponents *components = [[NSURLComponents alloc] init];
- components.scheme = kFIRStorageScheme;
- components.host = kFIRStorageHost;
- NSString *path = [FIRStorageUtils GCSEscapedString:self->_path];
- NSString *fullPath =
- [NSString stringWithFormat:kFIRStorageFullPathFormat, self->_bucket, path];
- components.percentEncodedPath = fullPath;
- components.query = [NSString stringWithFormat:@"alt=media&token=%@", token];
-
- [downloadURLArray insertObject:[components URL] atIndex:idx];
- }];
- _downloadURLs = downloadURLArray;
- }
}
return self;
}
@@ -147,29 +126,6 @@
metadataDictionary[kFIRStorageMetadataCustomMetadata] = _customMetadata;
}
- if (_downloadURLs) {
- NSMutableArray *downloadTokens = [[NSMutableArray alloc] init];
- [_downloadURLs
- enumerateObjectsUsingBlock:^(NSURL *_Nonnull URL, NSUInteger idx, BOOL *_Nonnull stop) {
- NSArray *queryItems = [URL.query componentsSeparatedByString:@"&"];
- [queryItems enumerateObjectsUsingBlock:^(NSString *queryString, NSUInteger idx,
- BOOL *_Nonnull stop) {
- NSString *key;
- NSString *value;
- NSScanner *scanner = [NSScanner scannerWithString:queryString];
- [scanner scanUpToString:@"=" intoString:&key];
- [scanner scanString:@"=" intoString:NULL];
- [scanner scanUpToString:@"\n" intoString:&value];
- if ([key isEqual:@"token"]) {
- [downloadTokens addObject:value];
- *stop = YES;
- }
- }];
- }];
- NSString *downloadTokenString = [downloadTokens componentsJoinedByString:@","];
- metadataDictionary[kFIRStorageMetadataDownloadTokens] = downloadTokenString;
- }
-
if (_generation) {
NSString *generationString = [NSString stringWithFormat:@"%lld", _generation];
metadataDictionary[kFIRStorageMetadataGeneration] = generationString;
@@ -207,10 +163,6 @@
return _type == FIRStorageMetadataTypeFolder;
}
-- (nullable NSURL *)downloadURL {
- return [_downloadURLs firstObject];
-}
-
#pragma mark - Private methods
+ (void)removeMatchingMetadata:(NSMutableDictionary *)metadata
diff --git a/Firebase/Storage/FIRStorageReference.m b/Firebase/Storage/FIRStorageReference.m
index 7bc1934..5b70a9c 100644
--- a/Firebase/Storage/FIRStorageReference.m
+++ b/Firebase/Storage/FIRStorageReference.m
@@ -17,6 +17,7 @@
#import "FIRStorageConstants_Private.h"
#import "FIRStorageDeleteTask.h"
#import "FIRStorageDownloadTask_Private.h"
+#import "FIRStorageGetDownloadURLTask.h"
#import "FIRStorageGetMetadataTask.h"
#import "FIRStorageMetadata_Private.h"
#import "FIRStorageReference_Private.h"
@@ -319,16 +320,11 @@
}
- (void)downloadURLWithCompletion:(FIRStorageVoidURLError)completion {
- dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue;
- if (!callbackQueue) {
- callbackQueue = dispatch_get_main_queue();
- }
-
- return [self metadataWithCompletion:^(FIRStorageMetadata *metadata, NSError *error) {
- dispatch_async(callbackQueue, ^{
- completion(metadata.downloadURL, error);
- });
- }];
+ FIRStorageGetDownloadURLTask *task =
+ [[FIRStorageGetDownloadURLTask alloc] initWithReference:self
+ fetcherService:_storage.fetcherServiceForApp
+ completion:completion];
+ [task enqueue];
}
#pragma mark - Metadata Operations
diff --git a/Firebase/Storage/FIRStorageUpdateMetadataTask.m b/Firebase/Storage/FIRStorageUpdateMetadataTask.m
index fa5955a..cea4e7d 100644
--- a/Firebase/Storage/FIRStorageUpdateMetadataTask.m
+++ b/Firebase/Storage/FIRStorageUpdateMetadataTask.m
@@ -48,7 +48,7 @@
NSDictionary *updateDictionary = [_updateMetadata updatedMetadata];
NSData *updateData = [NSData frs_dataFromJSONDictionary:updateDictionary];
request.HTTPMethod = @"PATCH";
- request.timeoutInterval = self.reference.storage.maxUploadRetryTime;
+ request.timeoutInterval = self.reference.storage.maxOperationRetryTime;
request.HTTPBody = updateData;
NSString *typeString = @"application/json; charset=UTF-8";
[request setValue:typeString forHTTPHeaderField:@"Content-Type"];
@@ -64,37 +64,23 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
_fetcherCompletion = ^(NSData *data, NSError *error) {
+ FIRStorageMetadata *metadata;
if (error) {
if (!self.error) {
self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference];
}
- if (callback) {
- callback(nil, self.error);
+ } else {
+ NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data];
+ if (responseDictionary) {
+ metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary];
+ [metadata setType:FIRStorageMetadataTypeFile];
+ } else {
+ self.error = [FIRStorageErrors errorWithInvalidRequest:data];
}
- self->_fetcherCompletion = nil;
- return;
}
- NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data];
- if (responseDictionary) {
- FIRStorageMetadata *metadata =
- [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary];
- [metadata setType:FIRStorageMetadataTypeFile];
- if (callback) {
- callback(metadata, nil);
- }
- } else {
- NSString *returnedData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- NSString *invalidDataString =
- [NSString stringWithFormat:kFIRStorageInvalidDataFormat, returnedData];
- NSDictionary *dict;
- if (invalidDataString.length > 0) {
- dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString};
- }
- self.error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict];
- if (callback) {
- callback(nil, self.error);
- }
+ if (callback) {
+ callback(metadata, self.error);
}
self->_fetcherCompletion = nil;
};
diff --git a/Firebase/Storage/FIRStorageUploadTask.m b/Firebase/Storage/FIRStorageUploadTask.m
index f84c2c7..2c4daa9 100644
--- a/Firebase/Storage/FIRStorageUploadTask.m
+++ b/Firebase/Storage/FIRStorageUploadTask.m
@@ -154,14 +154,7 @@
[metadata setType:FIRStorageMetadataTypeFile];
self.metadata = metadata;
} else {
- NSString *returnedData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- NSString *invalidDataString =
- [NSString stringWithFormat:kFIRStorageInvalidDataFormat, returnedData];
- NSDictionary *dict;
- if (invalidDataString.length > 0) {
- dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString};
- }
- self.error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict];
+ self.error = [FIRStorageErrors errorWithInvalidRequest:data];
}
[self fireHandlersForStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot];
diff --git a/Firebase/Storage/Private/FIRStorageConstants_Private.h b/Firebase/Storage/Private/FIRStorageConstants_Private.h
index 498c687..cf12337 100644
--- a/Firebase/Storage/Private/FIRStorageConstants_Private.h
+++ b/Firebase/Storage/Private/FIRStorageConstants_Private.h
@@ -55,7 +55,6 @@ FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentLanguage;
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentType;
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataCustomMetadata;
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataSize;
-FOUNDATION_EXPORT NSString *const kFIRStorageMetadataDownloadURLs;
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataGeneration;
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataMetageneration;
FOUNDATION_EXPORT NSString *const kFIRStorageMetadataTimeCreated;
diff --git a/Firebase/Storage/Private/FIRStorageErrors.h b/Firebase/Storage/Private/FIRStorageErrors.h
index 7c236d9..a76a6aa 100644
--- a/Firebase/Storage/Private/FIRStorageErrors.h
+++ b/Firebase/Storage/Private/FIRStorageErrors.h
@@ -44,11 +44,27 @@ NS_ASSUME_NONNULL_BEGIN
* Creates a Firebase Storage error from a specific GCS error and FIRStorageReference.
* @param error Server error to wrap and return as a Firebase Storage error.
* @param reference FIRStorageReference which provides context about the request being made.
- * @return Returns an Firebase Storage error, or nil if no error is provided.
+ * @return Returns a Firebase Storage error, or nil if no error is provided.
*/
+ (nullable NSError *)errorWithServerError:(nullable NSError *)error
reference:(nullable FIRStorageReference *)reference;
+/**
+ * Creates a Firebase Storage error from an invalid request.
+ *
+ * @param request The NSData representation of the invalid user request.
+ * @return Returns the corresponding Firebase Storage error.
+ */
++ (NSError *)errorWithInvalidRequest:(NSData *)request;
+
+/**
+ * Creates a Firebase Storage error with a custom error message.
+ *
+ * @param errorMessage A custom error message.
+ * @return Returns the corresponding Firebase Storage error.
+ */
++ (NSError *)errorWithCustomMessage:(NSString *)errorMessage;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h b/Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h
new file mode 100644
index 0000000..8cd9eb3
--- /dev/null
+++ b/Firebase/Storage/Private/FIRStorageGetDownloadURLTask.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018 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 "FIRStorageTask.h"
+
+@class GTMSessionFetcherService;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Task which provides the ability to get a download URL for an object in Firebase Storage.
+ */
+@interface FIRStorageGetDownloadURLTask : FIRStorageTask <FIRStorageTaskManagement>
+
+- (instancetype)initWithReference:(FIRStorageReference *)reference
+ fetcherService:(GTMSessionFetcherService *)service
+ completion:(FIRStorageVoidURLError)completion;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Storage/Private/FIRStorageGetDownloadURLTask_Private.h b/Firebase/Storage/Private/FIRStorageGetDownloadURLTask_Private.h
new file mode 100644
index 0000000..0da04a4
--- /dev/null
+++ b/Firebase/Storage/Private/FIRStorageGetDownloadURLTask_Private.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2018 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 "FIRStorageGetDownloadURLTask.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Task which provides the ability to get a download URL for an object in Firebase Storage.
+ */
+@interface FIRStorageGetDownloadURLTask ()
+
+/** Extracts a download URL from the StorageMetadata dictonary representation. */
++ (nullable NSURL *)downloadURLFromMetadataDictionary:(NSDictionary *)dictionary;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Storage/Public/FIRStorage.h b/Firebase/Storage/Public/FIRStorage.h
index f70b875..baa8122 100644
--- a/Firebase/Storage/Public/FIRStorage.h
+++ b/Firebase/Storage/Public/FIRStorage.h
@@ -24,7 +24,8 @@
NS_ASSUME_NONNULL_BEGIN
/** Project version string for FirebaseStorage. */
-FOUNDATION_EXPORT const unsigned char *const FIRStorageVersionString;
+FOUNDATION_EXPORT const unsigned char *const FIRStorageVersionString
+ NS_SWIFT_NAME(StorageVersionString);
/**
* FirebaseStorage is a service that supports uploading and downloading binary objects,
diff --git a/Firebase/Storage/Public/FIRStorageMetadata.h b/Firebase/Storage/Public/FIRStorageMetadata.h
index 2e3cc13..63b8798 100644
--- a/Firebase/Storage/Public/FIRStorageMetadata.h
+++ b/Firebase/Storage/Public/FIRStorageMetadata.h
@@ -113,12 +113,6 @@ NS_SWIFT_NAME(StorageMetadata)
@property(strong, nonatomic, readonly, nullable) FIRStorageReference *storageReference;
/**
- * An array containing all download URLs available for the object.
- */
-@property(strong, nonatomic, readonly, nullable) NSArray<NSURL *> *downloadURLs __deprecated_msg(
- "Use `StorageReference.downloadURLWithCompletion()` to obtain a current download URL.");
-
-/**
* Creates an instanece of FIRStorageMetadata from the contents of a dictionary.
* @return An instance of FIRStorageMetadata that represents the contents of a dictionary.
*/
@@ -141,14 +135,6 @@ NS_SWIFT_NAME(StorageMetadata)
*/
@property(readonly, getter=isFolder) BOOL folder;
-/**
- * Retrieves a download URL for the given object, or nil if none exist.
- * Note that if there are many valid download tokens, this will always return the first
- * valid token created.
- */
-- (nullable NSURL *)downloadURL __deprecated_msg(
- "Use `StorageReference.downloadURLWithCompletion()` to obtain a current download URL.");
-
@end
NS_ASSUME_NONNULL_END
diff --git a/FirebaseCore.podspec b/FirebaseCore.podspec
index c1bf223..d25a979 100644
--- a/FirebaseCore.podspec
+++ b/FirebaseCore.podspec
@@ -26,7 +26,7 @@ Firebase Core includes FIRApp and FIROptions which provide central configuration
s.source_files = 'Firebase/Core/**/*.[mh]'
s.public_header_files = 'Firebase/Core/Public/*.h', 'Firebase/Core/Private/*.h'
- s.private_header_files = 'Firebase/Core/Private/*.h'
+ s.private_header_files = 'Firebase/Core/Private/*.h', 'Firebase/Core/third_party/*.h'
s.frameworks = [
'Foundation',
'SystemConfiguration'
diff --git a/Firestore/CMakeLists.txt b/Firestore/CMakeLists.txt
index d605411..80308bb 100644
--- a/Firestore/CMakeLists.txt
+++ b/Firestore/CMakeLists.txt
@@ -15,6 +15,48 @@
cmake_minimum_required(VERSION 2.8.11)
project(firestore C CXX)
+option(WITH_ASAN "Build with Address Sanitizer" OFF)
+# TODO(varconst): msan
+# Memory sanitizer is more complicated:
+# - it requires all dependencies to be compiled with msan enabled (see
+# https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo);
+# - AppleClang doesn't support it.
+option(WITH_TSAN "Build with Thread Sanitizer (mutually exculsive with other sanitizers)" OFF)
+option(WITH_UBSAN "Build with Undefined Behavior sanitizer" OFF)
+
+macro(add_to_compile_and_link_flags flag)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${flag}")
+endmacro()
+
+if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ if(WITH_ASAN)
+ add_to_compile_and_link_flags("-fsanitize=address")
+ endif()
+
+ if(WITH_TSAN)
+ if(WITH_ASAN OR WITH_UBSAN)
+ message(FATAL_ERROR "Cannot combine TSan with other santizers")
+ endif()
+ add_to_compile_and_link_flags("-fsanitize=thread")
+ endif()
+
+ if(WITH_UBSAN)
+ add_to_compile_and_link_flags("-fsanitize=undefined")
+ endif()
+
+ if (WITH_ASAN OR WITH_TSAN OR WITH_UBSAN)
+ # Recommended to "get nicer stack traces in error messages"
+ # TODO(varconst): double-check that TSan actually needs this flag (it's
+ # explicitly recommended in the docs for ASan and UBSan)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer")
+ endif()
+else()
+ if(WITH_ASAN OR WITH_TSAN OR WITH_UBSAN)
+ message(FATAL_ERROR "Only Clang and GCC support sanitizers")
+ endif()
+endif()
+
set(FIREBASE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
# CMAKE_INSTALL_PREFIX should be passed in to this build so that it can find
diff --git a/Firestore/Example/SwiftBuildTest/main.swift b/Firestore/Example/SwiftBuildTest/main.swift
index 3087085..691adf6 100644
--- a/Firestore/Example/SwiftBuildTest/main.swift
+++ b/Firestore/Example/SwiftBuildTest/main.swift
@@ -100,6 +100,10 @@ func writeDocument(at docRef: DocumentReference) {
let updateData = [
"bar.baz": 42,
FieldPath(["foobar"]): 42,
+ "server_timestamp": FieldValue.serverTimestamp(),
+ "array_union": FieldValue.arrayUnion(["a", "b"]),
+ "array_remove": FieldValue.arrayRemove(["a", "b"]),
+ "field_delete": FieldValue.delete(),
] as [AnyHashable: Any]
docRef.setData(setData)
diff --git a/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm b/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm
index bc253d0..0454152 100644
--- a/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm
+++ b/Firestore/Example/Tests/Core/FSTQueryListenerTests.mm
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-#import "Firestore/Source/Core/FSTEventManager.h"
-
#import <XCTest/XCTest.h>
+#import "Firestore/Source/Core/FSTEventManager.h"
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Core/FSTView.h"
#import "Firestore/Source/Model/FSTDocument.h"
diff --git a/Firestore/Example/Tests/Core/FSTSyncEngine+Testing.h b/Firestore/Example/Tests/Core/FSTSyncEngine+Testing.h
index 6e7c45b..5d5c981 100644
--- a/Firestore/Example/Tests/Core/FSTSyncEngine+Testing.h
+++ b/Firestore/Example/Tests/Core/FSTSyncEngine+Testing.h
@@ -16,6 +16,8 @@
#import <Foundation/Foundation.h>
+#include <map>
+
#import "Firestore/Source/Core/FSTSyncEngine.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
diff --git a/Firestore/Example/Tests/GoogleTest/FSTGoogleTestTests.mm b/Firestore/Example/Tests/GoogleTest/FSTGoogleTestTests.mm
index 18dfaf3..ec14880 100644
--- a/Firestore/Example/Tests/GoogleTest/FSTGoogleTestTests.mm
+++ b/Firestore/Example/Tests/GoogleTest/FSTGoogleTestTests.mm
@@ -17,9 +17,9 @@
#import <XCTest/XCTest.h>
#import <objc/runtime.h>
-#include <gtest/gtest.h>
+#import "Firestore/Source/Util/FSTAssert.h"
-#include "Firestore/Source/Util/FSTAssert.h"
+#include "gtest/gtest.h"
/**
* An XCTest test case that finds C++ test cases written in the GoogleTest framework, runs them, and
diff --git a/Firestore/Example/Tests/Integration/API/FIRValidationTests.mm b/Firestore/Example/Tests/Integration/API/FIRValidationTests.mm
index 0ad30fd..82c57c3 100644
--- a/Firestore/Example/Tests/Integration/API/FIRValidationTests.mm
+++ b/Firestore/Example/Tests/Integration/API/FIRValidationTests.mm
@@ -282,7 +282,7 @@
[self expectSet:@{@"foo" : [FIRFieldValue fieldValueForDelete]}
toFailWithReason:
@"FieldValue.delete() can only be used with updateData() and setData() with "
- @"SetOptions.merge()."];
+ @"SetOptions.merge() (found in field foo)"];
}
- (void)testUpdatesWithNestedFieldValueDeleteFail {
diff --git a/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm b/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm
index 430366f..ad911ce 100644
--- a/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm
+++ b/Firestore/Example/Tests/Integration/FSTDatastoreTests.mm
@@ -42,12 +42,14 @@
#include "Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.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/precondition.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
namespace util = firebase::firestore::util;
using firebase::firestore::auth::EmptyCredentialsProvider;
using firebase::firestore::core::DatabaseInfo;
using firebase::firestore::model::DatabaseId;
+using firebase::firestore::model::Precondition;
using firebase::firestore::model::TargetId;
NS_ASSUME_NONNULL_BEGIN
@@ -238,7 +240,7 @@ NS_ASSUME_NONNULL_BEGIN
initWithKey:[FSTDocumentKey keyWithPathString:@"rooms/eros"]
value:[[FSTObjectValue alloc]
initWithDictionary:@{@"name" : [FSTStringValue stringValue:@"Eros"]}]
- precondition:[FSTPrecondition none]];
+ precondition:Precondition::None()];
}
@end
diff --git a/Firestore/Example/Tests/Local/FSTEagerGarbageCollectorTests.mm b/Firestore/Example/Tests/Local/FSTEagerGarbageCollectorTests.mm
index 2cf530c..615b3f6 100644
--- a/Firestore/Example/Tests/Local/FSTEagerGarbageCollectorTests.mm
+++ b/Firestore/Example/Tests/Local/FSTEagerGarbageCollectorTests.mm
@@ -16,10 +16,10 @@
#import "Firestore/Source/Local/FSTEagerGarbageCollector.h"
-#include <set>
-
#import <XCTest/XCTest.h>
+#include <set>
+
#import "Firestore/Source/Local/FSTReferenceSet.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
diff --git a/Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm
index f23b7c5..c4b7e29 100644
--- a/Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLevelDBKeyTests.mm
@@ -18,6 +18,8 @@
#import <XCTest/XCTest.h>
+#include <string>
+
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
diff --git a/Firestore/Example/Tests/Local/FSTLevelDBLocalStoreTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBLocalStoreTests.mm
index 97e3c5b..29caa84 100644
--- a/Firestore/Example/Tests/Local/FSTLevelDBLocalStoreTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLevelDBLocalStoreTests.mm
@@ -14,13 +14,10 @@
* limitations under the License.
*/
-#import "Firestore/Source/Local/FSTLocalStore.h"
-
-#import <XCTest/XCTest.h>
+#import "Firestore/Example/Tests/Local/FSTLocalStoreTests.h"
#import "Firestore/Source/Local/FSTLevelDB.h"
-#import "Firestore/Example/Tests/Local/FSTLocalStoreTests.h"
#import "Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Example/Tests/Local/FSTLevelDBMigrationsTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBMigrationsTests.mm
index 14910ce..3da8083 100644
--- a/Firestore/Example/Tests/Local/FSTLevelDBMigrationsTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLevelDBMigrationsTests.mm
@@ -16,11 +16,15 @@
#import <XCTest/XCTest.h>
+#include <memory>
+#include <string>
+
#import "Firestore/Protos/objc/firestore/local/Target.pbobjc.h"
#import "Firestore/Source/Local/FSTLevelDB.h"
#import "Firestore/Source/Local/FSTLevelDBKey.h"
#import "Firestore/Source/Local/FSTLevelDBMigrations.h"
#import "Firestore/Source/Local/FSTLevelDBQueryCache.h"
+
#include "Firestore/core/src/firebase/firestore/util/ordered_code.h"
#include "leveldb/db.h"
diff --git a/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm
index cd8176e..60d9800 100644
--- a/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLevelDBMutationQueueTests.mm
@@ -17,7 +17,8 @@
#import "Firestore/Source/Local/FSTLevelDBMutationQueue.h"
#import <XCTest/XCTest.h>
-#include <leveldb/db.h>
+
+#include <string>
#import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h"
#import "Firestore/Source/Local/FSTLevelDB.h"
@@ -28,6 +29,7 @@
#include "Firestore/core/src/firebase/firestore/auth/user.h"
#include "Firestore/core/src/firebase/firestore/util/ordered_code.h"
+#include "leveldb/db.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Example/Tests/Local/FSTLevelDBRemoteDocumentCacheTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBRemoteDocumentCacheTests.mm
index d69e613..7baf1ef 100644
--- a/Firestore/Example/Tests/Local/FSTLevelDBRemoteDocumentCacheTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLevelDBRemoteDocumentCacheTests.mm
@@ -14,16 +14,15 @@
* limitations under the License.
*/
-#import "Firestore/Example/Tests/Local/FSTRemoteDocumentCacheTests.h"
-
-#include <leveldb/db.h>
+#include <string>
+#import "Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.h"
+#import "Firestore/Example/Tests/Local/FSTRemoteDocumentCacheTests.h"
#import "Firestore/Source/Local/FSTLevelDB.h"
#import "Firestore/Source/Local/FSTLevelDBKey.h"
-#import "Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.h"
-
#include "Firestore/core/src/firebase/firestore/util/ordered_code.h"
+#include "leveldb/db.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Example/Tests/Local/FSTLevelDBTransactionTests.mm b/Firestore/Example/Tests/Local/FSTLevelDBTransactionTests.mm
index a32ce9f..29f5d6c 100644
--- a/Firestore/Example/Tests/Local/FSTLevelDBTransactionTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLevelDBTransactionTests.mm
@@ -14,15 +14,23 @@
* limitations under the License.
*/
+#import <XCTest/XCTest.h>
+
+#include <memory>
+#include <string>
+
+// This is out of order to satisfy the linter, which doesn't realize this is
+// the header corresponding to this test.
+// TODO(wilhuff): move this to the top once the test filename matches
#include "Firestore/core/src/firebase/firestore/local/leveldb_transaction.h"
-#import <XCTest/XCTest.h>
-#include <absl/strings/string_view.h>
-#include <leveldb/db.h>
#import "Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.h"
#import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h"
#import "Firestore/Protos/objc/firestore/local/Target.pbobjc.h"
+
#include "Firestore/core/src/firebase/firestore/local/leveldb_key.h"
+#include "absl/strings/string_view.h"
+#include "leveldb/db.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm b/Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm
index d94925d..362f46f 100644
--- a/Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm
+++ b/Firestore/Example/Tests/Local/FSTLocalSerializerTests.mm
@@ -41,11 +41,15 @@
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.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;
+using firebase::firestore::model::FieldMask;
+using firebase::firestore::model::Precondition;
NS_ASSUME_NONNULL_BEGIN
@@ -76,13 +80,12 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testEncodesMutationBatch {
FSTMutation *set = FSTTestSetMutation(@"foo/bar", @{ @"a" : @"b", @"num" : @1 });
- FSTMutation *patch = [[FSTPatchMutation alloc]
- initWithKey:FSTTestDocKey(@"bar/baz")
- fieldMask:[[FSTFieldMask alloc] initWithFields:{testutil::Field("a")}]
- value:FSTTestObjectValue(
- @{ @"a" : @"b",
- @"num" : @1 })
- precondition:[FSTPrecondition preconditionWithExists:YES]];
+ FSTMutation *patch = [[FSTPatchMutation alloc] initWithKey:FSTTestDocKey(@"bar/baz")
+ fieldMask:FieldMask{testutil::Field("a")}
+ value:FSTTestObjectValue(
+ @{ @"a" : @"b",
+ @"num" : @1 })
+ precondition:Precondition::Exists(true)];
FSTMutation *del = FSTTestDeleteMutation(@"baz/quux");
FIRTimestamp *writeTime = [FIRTimestamp timestamp];
FSTMutationBatch *model = [[FSTMutationBatch alloc] initWithBatchID:42
diff --git a/Firestore/Example/Tests/Local/FSTLocalStoreTests.h b/Firestore/Example/Tests/Local/FSTLocalStoreTests.h
index 8e06d82..e514954 100644
--- a/Firestore/Example/Tests/Local/FSTLocalStoreTests.h
+++ b/Firestore/Example/Tests/Local/FSTLocalStoreTests.h
@@ -16,7 +16,9 @@
#import <XCTest/XCTest.h>
-@class FSTLocalStore;
+#import "Firestore/Source/Local/FSTLocalStore.h"
+
+@protocol FSTPersistence;
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Example/Tests/Local/FSTMemoryLocalStoreTests.mm b/Firestore/Example/Tests/Local/FSTMemoryLocalStoreTests.mm
index b78239e..7708eed 100644
--- a/Firestore/Example/Tests/Local/FSTMemoryLocalStoreTests.mm
+++ b/Firestore/Example/Tests/Local/FSTMemoryLocalStoreTests.mm
@@ -14,13 +14,10 @@
* limitations under the License.
*/
-#import "Firestore/Source/Local/FSTLocalStore.h"
-
-#import <XCTest/XCTest.h>
+#import "Firestore/Example/Tests/Local/FSTLocalStoreTests.h"
#import "Firestore/Source/Local/FSTMemoryPersistence.h"
-#import "Firestore/Example/Tests/Local/FSTLocalStoreTests.h"
#import "Firestore/Example/Tests/Local/FSTPersistenceTestHelpers.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm b/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm
index b228657..5b5bdd1 100644
--- a/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm
+++ b/Firestore/Example/Tests/Local/FSTMutationQueueTests.mm
@@ -17,6 +17,9 @@
#import "Firestore/Example/Tests/Local/FSTMutationQueueTests.h"
#import <FirebaseFirestore/FIRTimestamp.h>
+
+#include <set>
+
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Local/FSTEagerGarbageCollector.h"
#import "Firestore/Source/Local/FSTMutationQueue.h"
@@ -246,7 +249,6 @@ NS_ASSUME_NONNULL_BEGIN
return newBatches;
});
self.persistence.run("testNextMutationBatchAfterBatchIDSkipsAcknowledgedBatches", [&]() {
-
[self.mutationQueue acknowledgeBatch:batches[0] streamToken:nil];
XCTAssertEqualObjects([self.mutationQueue nextMutationBatchAfterBatchID:kFSTBatchIDUnknown],
batches[1]);
diff --git a/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm b/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm
index 956afa9..429a83a 100644
--- a/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm
+++ b/Firestore/Example/Tests/Local/FSTQueryCacheTests.mm
@@ -16,6 +16,8 @@
#import "Firestore/Example/Tests/Local/FSTQueryCacheTests.h"
+#include <set>
+
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Core/FSTSnapshotVersion.h"
#import "Firestore/Source/Local/FSTEagerGarbageCollector.h"
diff --git a/Firestore/Example/Tests/Local/StringViewTests.mm b/Firestore/Example/Tests/Local/StringViewTests.mm
index b30b43d..7c86924 100644
--- a/Firestore/Example/Tests/Local/StringViewTests.mm
+++ b/Firestore/Example/Tests/Local/StringViewTests.mm
@@ -17,7 +17,8 @@
#import "Firestore/Source/Local/StringView.h"
#import <XCTest/XCTest.h>
-#include <leveldb/slice.h>
+
+#include "leveldb/slice.h"
using Firestore::StringView;
diff --git a/Firestore/Example/Tests/Model/FSTFieldValueTests.mm b/Firestore/Example/Tests/Model/FSTFieldValueTests.mm
index 98504b5..d16a01d 100644
--- a/Firestore/Example/Tests/Model/FSTFieldValueTests.mm
+++ b/Firestore/Example/Tests/Model/FSTFieldValueTests.mm
@@ -22,7 +22,6 @@
#import "Firestore/Source/API/FIRFirestore+Internal.h"
#import "Firestore/Source/API/FSTUserDataConverter.h"
-#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Example/Tests/API/FSTAPIHelpers.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
diff --git a/Firestore/Example/Tests/Model/FSTMutationTests.mm b/Firestore/Example/Tests/Model/FSTMutationTests.mm
index 1f9193e..56bf1c2 100644
--- a/Firestore/Example/Tests/Model/FSTMutationTests.mm
+++ b/Firestore/Example/Tests/Model/FSTMutationTests.mm
@@ -16,19 +16,32 @@
#import "Firestore/Source/Model/FSTMutation.h"
+#import <FirebaseFirestore/FIRFieldValue.h>
#import <FirebaseFirestore/FIRTimestamp.h>
#import <XCTest/XCTest.h>
+#include <vector>
+
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTFieldValue.h"
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
+#include "Firestore/core/src/firebase/firestore/model/field_transform.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
+#include "Firestore/core/src/firebase/firestore/model/transform_operations.h"
#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
namespace testutil = firebase::firestore::testutil;
+using firebase::firestore::model::ArrayTransform;
using firebase::firestore::model::DocumentKey;
+using firebase::firestore::model::FieldMask;
+using firebase::firestore::model::FieldPath;
+using firebase::firestore::model::FieldTransform;
+using firebase::firestore::model::Precondition;
+using firebase::firestore::model::TransformOperation;
@interface FSTMutationTests : XCTestCase
@end
@@ -69,11 +82,10 @@ using firebase::firestore::model::DocumentKey;
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
DocumentKey key = testutil::Key("collection/key");
- FSTFieldMask *mask = [[FSTFieldMask alloc] initWithFields:{testutil::Field("foo.bar")}];
FSTMutation *patch = [[FSTPatchMutation alloc] initWithKey:key
- fieldMask:mask
+ fieldMask:{testutil::Field("foo.bar")}
value:[FSTObjectValue objectValue]
- precondition:[FSTPrecondition none]];
+ precondition:Precondition::None()];
FSTMaybeDocument *patchedDoc =
[patch applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
@@ -101,11 +113,12 @@ using firebase::firestore::model::DocumentKey;
XCTAssertEqualObjects(patchedDoc, baseDoc);
}
-- (void)testAppliesLocalTransformsToDocuments {
+- (void)testAppliesLocalServerTimestampTransformToDocuments {
NSDictionary *docData = @{ @"foo" : @{@"bar" : @"bar-value"}, @"baz" : @"baz-value" };
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
- FSTMutation *transform = FSTTestTransformMutation(@"collection/key", @[ @"foo.bar" ]);
+ FSTMutation *transform = FSTTestTransformMutation(
+ @"collection/key", @{@"foo.bar" : [FIRFieldValue fieldValueForServerTimestamp]});
FSTMaybeDocument *transformedDoc =
[transform applyTo:baseDoc baseDocument:baseDoc localWriteTime:_timestamp];
@@ -127,11 +140,57 @@ using firebase::firestore::model::DocumentKey;
XCTAssertEqualObjects(transformedDoc, expectedDoc);
}
+// NOTE: This is more a test of FSTUserDataConverter code than FSTMutation code but we don't have
+// unit tests for it currently. We could consider removing this test once we have integration tests.
+- (void)testCreateArrayUnionTransform {
+ FSTTransformMutation *transform = FSTTestTransformMutation(@"collection/key", @{
+ @"foo" : [FIRFieldValue fieldValueForArrayUnion:@[ @"tag" ]],
+ @"bar.baz" : [FIRFieldValue fieldValueForArrayUnion:@[ @YES, @[ @1, @2 ], @{@"a" : @"b"} ]]
+ });
+ XCTAssertEqual(transform.fieldTransforms.size(), 2);
+
+ const FieldTransform &first = transform.fieldTransforms[0];
+ XCTAssertEqual(first.path(), FieldPath({"foo"}));
+ {
+ std::vector<FSTFieldValue *> expectedElements{FSTTestFieldValue(@"tag")};
+ ArrayTransform expected(TransformOperation::Type::ArrayUnion, expectedElements);
+ XCTAssertEqual(static_cast<const ArrayTransform &>(first.transformation()), expected);
+ }
+
+ const FieldTransform &second = transform.fieldTransforms[1];
+ XCTAssertEqual(second.path(), FieldPath({"bar", "baz"}));
+ {
+ std::vector<FSTFieldValue *> expectedElements {
+ FSTTestFieldValue(@YES), FSTTestFieldValue(@[ @1, @2 ]), FSTTestFieldValue(@{@"a" : @"b"})
+ };
+ ArrayTransform expected(TransformOperation::Type::ArrayUnion, expectedElements);
+ XCTAssertEqual(static_cast<const ArrayTransform &>(second.transformation()), expected);
+ }
+}
+
+// NOTE: This is more a test of FSTUserDataConverter code than FSTMutation code but we don't have
+// unit tests for it currently. We could consider removing this test once we have integration tests.
+- (void)testCreateArrayRemoveTransform {
+ FSTTransformMutation *transform = FSTTestTransformMutation(@"collection/key", @{
+ @"foo" : [FIRFieldValue fieldValueForArrayRemove:@[ @"tag" ]],
+ });
+ XCTAssertEqual(transform.fieldTransforms.size(), 1);
+
+ const FieldTransform &first = transform.fieldTransforms[0];
+ XCTAssertEqual(first.path(), FieldPath({"foo"}));
+ {
+ std::vector<FSTFieldValue *> expectedElements{FSTTestFieldValue(@"tag")};
+ const ArrayTransform expected(TransformOperation::Type::ArrayRemove, expectedElements);
+ XCTAssertEqual(static_cast<const ArrayTransform &>(first.transformation()), expected);
+ }
+}
+
- (void)testAppliesServerAckedTransformsToDocuments {
NSDictionary *docData = @{ @"foo" : @{@"bar" : @"bar-value"}, @"baz" : @"baz-value" };
FSTDocument *baseDoc = FSTTestDoc("collection/key", 0, docData, NO);
- FSTMutation *transform = FSTTestTransformMutation(@"collection/key", @[ @"foo.bar" ]);
+ FSTMutation *transform = FSTTestTransformMutation(
+ @"collection/key", @{@"foo.bar" : [FIRFieldValue fieldValueForServerTimestamp]});
FSTMutationResult *mutationResult = [[FSTMutationResult alloc]
initWithVersion:FSTTestVersion(1)
diff --git a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
index 64f4777..a648cd8 100644
--- a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
+++ b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
@@ -17,12 +17,15 @@
#import "Firestore/Source/Remote/FSTSerializerBeta.h"
#import <FirebaseFirestore/FIRFieldPath.h>
+#import <FirebaseFirestore/FIRFieldValue.h>
#import <FirebaseFirestore/FIRFirestoreErrors.h>
#import <FirebaseFirestore/FIRGeoPoint.h>
#import <FirebaseFirestore/FIRTimestamp.h>
#import <GRPCClient/GRPCCall.h>
#import <XCTest/XCTest.h>
+#include <vector>
+
#import "Firestore/Protos/objc/firestore/local/MaybeDocument.pbobjc.h"
#import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h"
#import "Firestore/Protos/objc/google/firestore/v1beta1/Common.pbobjc.h"
@@ -46,12 +49,18 @@
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
+#include "Firestore/core/src/firebase/firestore/model/field_transform.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.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;
+using firebase::firestore::model::FieldMask;
+using firebase::firestore::model::FieldTransform;
+using firebase::firestore::model::Precondition;
NS_ASSUME_NONNULL_BEGIN
@@ -63,9 +72,9 @@ NS_ASSUME_NONNULL_BEGIN
- (GCFSValue *)encodedString:(NSString *)value;
- (GCFSValue *)encodedDate:(NSDate *)value;
-- (GCFSDocumentMask *)encodedFieldMask:(FSTFieldMask *)fieldMask;
+- (GCFSDocumentMask *)encodedFieldMask:(const FieldMask &)fieldMask;
- (NSMutableArray<GCFSDocumentTransform_FieldTransform *> *)encodedFieldTransforms:
- (NSArray<FSTFieldTransform *> *)fieldTransforms;
+ (const std::vector<FieldTransform> &)fieldTransforms;
- (GCFSStructuredQuery_Filter *)encodedRelationFilter:(FSTRelationFilter *)filter;
@end
@@ -359,7 +368,10 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesTransformMutation {
- FSTTransformMutation *mutation = FSTTestTransformMutation(@"docs/1", @[ @"a", @"bar.baz" ]);
+ FSTTransformMutation *mutation = FSTTestTransformMutation(@"docs/1", @{
+ @"a" : [FIRFieldValue fieldValueForServerTimestamp],
+ @"bar.baz" : [FIRFieldValue fieldValueForServerTimestamp]
+ });
GCFSWrite *proto = [GCFSWrite message];
proto.transform = [GCFSDocumentTransform message];
proto.transform.document = [self.serializer encodedDocumentKey:mutation.key];
@@ -371,12 +383,12 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)testEncodesSetMutationWithPrecondition {
- FSTSetMutation *mutation = [[FSTSetMutation alloc]
- initWithKey:FSTTestDocKey(@"foo/bar")
- value:FSTTestObjectValue(
- @{ @"a" : @"b",
- @"num" : @1 })
- precondition:[FSTPrecondition preconditionWithUpdateTime:FSTTestVersion(4)]];
+ FSTSetMutation *mutation =
+ [[FSTSetMutation alloc] initWithKey:FSTTestDocKey(@"foo/bar")
+ value:FSTTestObjectValue(
+ @{ @"a" : @"b",
+ @"num" : @1 })
+ precondition:Precondition::UpdateTime(testutil::Version(4))];
GCFSWrite *proto = [GCFSWrite message];
proto.update = [self.serializer encodedDocumentWithFields:mutation.value key:mutation.key];
proto.currentDocument.updateTime =
diff --git a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm
index f66e6c7..128f825 100644
--- a/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm
+++ b/Firestore/Example/Tests/SpecTests/FSTSpecTests.mm
@@ -16,12 +16,12 @@
#import "Firestore/Example/Tests/SpecTests/FSTSpecTests.h"
-#include <map>
-#include <utility>
-
#import <FirebaseFirestore/FIRFirestoreErrors.h>
#import <GRPCClient/GRPCCall.h>
+#include <map>
+#include <utility>
+
#import "Firestore/Source/Core/FSTEventManager.h"
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Core/FSTSnapshotVersion.h"
diff --git a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm
index 91140bf..f167ce5 100644
--- a/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm
+++ b/Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.mm
@@ -16,12 +16,12 @@
#import "Firestore/Example/Tests/SpecTests/FSTSyncEngineTestDriver.h"
-#include <map>
-#include <unordered_map>
-
#import <FirebaseFirestore/FIRFirestoreErrors.h>
#import <GRPCClient/GRPCCall.h>
+#include <map>
+#include <unordered_map>
+
#import "Firestore/Source/Core/FSTEventManager.h"
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Core/FSTSnapshotVersion.h"
diff --git a/Firestore/Example/Tests/Util/FSTHelpers.h b/Firestore/Example/Tests/Util/FSTHelpers.h
index d05c1f1..9b5f96a 100644
--- a/Firestore/Example/Tests/Util/FSTHelpers.h
+++ b/Firestore/Example/Tests/Util/FSTHelpers.h
@@ -245,8 +245,12 @@ FSTPatchMutation *FSTTestPatchMutation(
NSDictionary<NSString *, id> *values,
const std::vector<firebase::firestore::model::FieldPath> &updateMask);
-FSTTransformMutation *FSTTestTransformMutation(NSString *path,
- NSArray<NSString *> *serverTimestampFields);
+/**
+ * Creates a FSTTransformMutation by parsing any FIRFieldValue sentinels in the provided data. The
+ * data is expected to use dotted-notation for nested fields (i.e.
+ * @{ @"foo.bar": [FIRFieldValue ...] } and must not contain any non-sentinel data.
+ */
+FSTTransformMutation *FSTTestTransformMutation(NSString *path, NSDictionary<NSString *, id> *data);
/** Creates a delete mutation for the document key at the given path. */
FSTDeleteMutation *FSTTestDeleteMutation(NSString *path);
diff --git a/Firestore/Example/Tests/Util/FSTHelpers.mm b/Firestore/Example/Tests/Util/FSTHelpers.mm
index 5751739..e1ed18c 100644
--- a/Firestore/Example/Tests/Util/FSTHelpers.mm
+++ b/Firestore/Example/Tests/Util/FSTHelpers.mm
@@ -16,15 +16,16 @@
#import "Firestore/Example/Tests/Util/FSTHelpers.h"
-#include <inttypes.h>
-#include <list>
-#include <map>
-#include <vector>
-
#import <FirebaseFirestore/FIRFieldPath.h>
#import <FirebaseFirestore/FIRGeoPoint.h>
#import <FirebaseFirestore/FIRTimestamp.h>
+#include <cinttypes>
+#include <list>
+#include <map>
+#include <utility>
+#include <vector>
+
#import "Firestore/Source/API/FIRFieldPath+Internal.h"
#import "Firestore/Source/API/FSTUserDataConverter.h"
#import "Firestore/Source/Core/FSTQuery.h"
@@ -44,18 +45,28 @@
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
+#include "Firestore/core/src/firebase/firestore/model/field_transform.h"
#include "Firestore/core/src/firebase/firestore/model/field_value.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
+#include "Firestore/core/src/firebase/firestore/model/transform_operations.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+#include "absl/memory/memory.h"
namespace util = firebase::firestore::util;
namespace testutil = firebase::firestore::testutil;
using firebase::firestore::model::DatabaseId;
using firebase::firestore::model::DocumentKey;
+using firebase::firestore::model::FieldMask;
using firebase::firestore::model::FieldPath;
+using firebase::firestore::model::FieldTransform;
using firebase::firestore::model::FieldValue;
+using firebase::firestore::model::Precondition;
using firebase::firestore::model::ResourcePath;
+using firebase::firestore::model::ServerTimestampTransform;
+using firebase::firestore::model::TransformOperation;
NS_ASSUME_NONNULL_BEGIN
@@ -111,7 +122,7 @@ NSDateComponents *FSTTestDateComponents(
return comps;
}
-FSTFieldValue *FSTTestFieldValue(id _Nullable value) {
+FSTUserDataConverter *FSTTestUserDataConverter() {
// This owns the DatabaseIds since we do not have FirestoreClient instance to own them.
static DatabaseId database_id{"project", DatabaseId::kDefault};
FSTUserDataConverter *converter =
@@ -119,6 +130,11 @@ FSTFieldValue *FSTTestFieldValue(id _Nullable value) {
preConverter:^id _Nullable(id _Nullable input) {
return input;
}];
+ return converter;
+}
+
+FSTFieldValue *FSTTestFieldValue(id _Nullable value) {
+ FSTUserDataConverter *converter = FSTTestUserDataConverter();
// HACK: We use parsedQueryValue: since it accepts scalars as well as arrays / objects, and
// our tests currently use FSTTestFieldValue() pretty generically so we don't know the intent.
return [converter parsedQueryValue:value];
@@ -241,7 +257,7 @@ FSTDocumentSet *FSTTestDocSet(NSComparator comp, NSArray<FSTDocument *> *docs) {
FSTSetMutation *FSTTestSetMutation(NSString *path, NSDictionary<NSString *, id> *values) {
return [[FSTSetMutation alloc] initWithKey:FSTTestDocKey(path)
value:FSTTestObjectValue(values)
- precondition:[FSTPrecondition none]];
+ precondition:Precondition::None()];
}
FSTPatchMutation *FSTTestPatchMutation(const absl::string_view path,
@@ -260,32 +276,27 @@ FSTPatchMutation *FSTTestPatchMutation(const absl::string_view path,
}
}];
- FSTDocumentKey *key = [FSTDocumentKey keyWithPath:testutil::Resource(path)];
- FSTFieldMask *mask = [[FSTFieldMask alloc] initWithFields:merge ? updateMask : fieldMaskPaths];
+ DocumentKey key = testutil::Key(path);
+ FieldMask mask(merge ? updateMask : fieldMaskPaths);
return [[FSTPatchMutation alloc] initWithKey:key
fieldMask:mask
value:objectValue
- precondition:[FSTPrecondition preconditionWithExists:YES]];
+ precondition:Precondition::Exists(true)];
}
-// For now this only creates TransformMutations with server timestamps.
-FSTTransformMutation *FSTTestTransformMutation(NSString *path,
- NSArray<NSString *> *serverTimestampFields) {
+FSTTransformMutation *FSTTestTransformMutation(NSString *path, NSDictionary<NSString *, id> *data) {
FSTDocumentKey *key = [FSTDocumentKey keyWithPath:testutil::Resource(util::MakeStringView(path))];
- NSMutableArray<FSTFieldTransform *> *fieldTransforms = [NSMutableArray array];
- for (NSString *field in serverTimestampFields) {
- const FieldPath fieldPath = testutil::Field(util::MakeStringView(field));
- id<FSTTransformOperation> transformOp = [FSTServerTimestampTransform serverTimestampTransform];
- FSTFieldTransform *transform =
- [[FSTFieldTransform alloc] initWithPath:fieldPath transform:transformOp];
- [fieldTransforms addObject:transform];
- }
- return [[FSTTransformMutation alloc] initWithKey:key fieldTransforms:fieldTransforms];
+ FSTUserDataConverter *converter = FSTTestUserDataConverter();
+ FSTParsedUpdateData *result = [converter parsedUpdateData:data];
+ FSTCAssert(result.data.value.count == 0,
+ @"FSTTestTransformMutation() only expects transforms; no other data");
+ return [[FSTTransformMutation alloc] initWithKey:key
+ fieldTransforms:std::move(result.fieldTransforms)];
}
FSTDeleteMutation *FSTTestDeleteMutation(NSString *path) {
- return [[FSTDeleteMutation alloc] initWithKey:FSTTestDocKey(path)
- precondition:[FSTPrecondition none]];
+ return
+ [[FSTDeleteMutation alloc] initWithKey:FSTTestDocKey(path) precondition:Precondition::None()];
}
FSTMaybeDocumentDictionary *FSTTestDocUpdates(NSArray<FSTMaybeDocument *> *docs) {
diff --git a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm
index 611bcc8..79163da 100644
--- a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm
+++ b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm
@@ -16,14 +16,15 @@
#import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h"
-#include <memory>
-#include <utility>
-
#import <FirebaseCore/FIRLogger.h>
#import <FirebaseFirestore/FirebaseFirestore-umbrella.h>
#import <GRPCClient/GRPCCall+ChannelArg.h>
#import <GRPCClient/GRPCCall+Tests.h>
+#include <memory>
+#include <string>
+#include <utility>
+
#include "Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
#include "Firestore/core/src/firebase/firestore/util/autoid.h"
diff --git a/Firestore/Protos/FrameworkMaker.xcodeproj/project.pbxproj b/Firestore/Protos/FrameworkMaker.xcodeproj/project.pbxproj
index 2efcb21..4a1e9d4 100644
--- a/Firestore/Protos/FrameworkMaker.xcodeproj/project.pbxproj
+++ b/Firestore/Protos/FrameworkMaker.xcodeproj/project.pbxproj
@@ -205,7 +205,7 @@
);
name = "[CP] Copy Pods Resources";
outputPaths = (
- "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
diff --git a/Firestore/Protos/README.md b/Firestore/Protos/README.md
index 6137ff6..fbede5b 100644
--- a/Firestore/Protos/README.md
+++ b/Firestore/Protos/README.md
@@ -1,6 +1,11 @@
## Usage
-First, build protobuf and nanopb
+First, make sure you have necessary prereqs for building:
+```
+brew install automake libtool protobuf
+```
+
+Take a nap while that completes. Then, build protobuf and nanopb:
```
cd firebase-ios-sdk
mkdir -p build
@@ -15,7 +20,8 @@ cd firebase-ios-sdk/Firestore/Protos
./build-protos.sh
```
-Verify diffs, tests and make PR
+Verify diffs (you'll likely need to re-add copyright notices, etc.), make sure
+tests still pass, and create a PR.
### Script Details
diff --git a/Firestore/Protos/nanopb/firestore/local/target.pb.c b/Firestore/Protos/nanopb/firestore/local/target.pb.c
index 2805ceb..d00d4a6 100644
--- a/Firestore/Protos/nanopb/firestore/local/target.pb.c
+++ b/Firestore/Protos/nanopb/firestore/local/target.pb.c
@@ -15,7 +15,7 @@
*/
/* Automatically generated nanopb constant definitions */
-/* Generated by nanopb-0.3.8 at Fri Feb 2 17:48:02 2018. */
+/* Generated by nanopb-0.3.8 at Mon Apr 9 15:08:47 2018. */
#include "target.pb.h"
@@ -36,10 +36,11 @@ const pb_field_t firestore_client_Target_fields[7] = {
PB_LAST_FIELD
};
-const pb_field_t firestore_client_TargetGlobal_fields[4] = {
+const pb_field_t firestore_client_TargetGlobal_fields[5] = {
PB_FIELD( 1, INT32 , SINGULAR, STATIC , FIRST, firestore_client_TargetGlobal, highest_target_id, highest_target_id, 0),
PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, firestore_client_TargetGlobal, highest_listen_sequence_number, highest_target_id, 0),
PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, firestore_client_TargetGlobal, last_remote_snapshot_version, highest_listen_sequence_number, &google_protobuf_Timestamp_fields),
+ PB_FIELD( 4, INT32 , SINGULAR, STATIC , OTHER, firestore_client_TargetGlobal, target_count, last_remote_snapshot_version, 0),
PB_LAST_FIELD
};
diff --git a/Firestore/Protos/nanopb/firestore/local/target.pb.h b/Firestore/Protos/nanopb/firestore/local/target.pb.h
index 8cc146f..37b64a2 100644
--- a/Firestore/Protos/nanopb/firestore/local/target.pb.h
+++ b/Firestore/Protos/nanopb/firestore/local/target.pb.h
@@ -15,7 +15,7 @@
*/
/* Automatically generated nanopb header */
-/* Generated by nanopb-0.3.8 at Fri Feb 2 17:48:02 2018. */
+/* Generated by nanopb-0.3.8 at Mon Apr 9 15:08:47 2018. */
#ifndef PB_FIRESTORE_CLIENT_TARGET_PB_H_INCLUDED
#define PB_FIRESTORE_CLIENT_TARGET_PB_H_INCLUDED
@@ -52,6 +52,7 @@ typedef struct _firestore_client_TargetGlobal {
int32_t highest_target_id;
int64_t highest_listen_sequence_number;
google_protobuf_Timestamp last_remote_snapshot_version;
+ int32_t target_count;
/* @@protoc_insertion_point(struct:firestore_client_TargetGlobal) */
} firestore_client_TargetGlobal;
@@ -59,9 +60,9 @@ typedef struct _firestore_client_TargetGlobal {
/* Initializer values for message structs */
#define firestore_client_Target_init_default {0, google_protobuf_Timestamp_init_default, {{NULL}, NULL}, 0, 0, {google_firestore_v1beta1_Target_QueryTarget_init_default}}
-#define firestore_client_TargetGlobal_init_default {0, 0, google_protobuf_Timestamp_init_default}
+#define firestore_client_TargetGlobal_init_default {0, 0, google_protobuf_Timestamp_init_default, 0}
#define firestore_client_Target_init_zero {0, google_protobuf_Timestamp_init_zero, {{NULL}, NULL}, 0, 0, {google_firestore_v1beta1_Target_QueryTarget_init_zero}}
-#define firestore_client_TargetGlobal_init_zero {0, 0, google_protobuf_Timestamp_init_zero}
+#define firestore_client_TargetGlobal_init_zero {0, 0, google_protobuf_Timestamp_init_zero, 0}
/* Field tags (for use in manual encoding/decoding) */
#define firestore_client_Target_query_tag 5
@@ -73,14 +74,15 @@ typedef struct _firestore_client_TargetGlobal {
#define firestore_client_TargetGlobal_highest_target_id_tag 1
#define firestore_client_TargetGlobal_highest_listen_sequence_number_tag 2
#define firestore_client_TargetGlobal_last_remote_snapshot_version_tag 3
+#define firestore_client_TargetGlobal_target_count_tag 4
/* Struct field encoding specification for nanopb */
extern const pb_field_t firestore_client_Target_fields[7];
-extern const pb_field_t firestore_client_TargetGlobal_fields[4];
+extern const pb_field_t firestore_client_TargetGlobal_fields[5];
/* Maximum encoded size of messages (where known) */
/* firestore_client_Target_size depends on runtime parameters */
-#define firestore_client_TargetGlobal_size 46
+#define firestore_client_TargetGlobal_size 57
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
diff --git a/Firestore/Protos/nanopb/google/api/http.pb.c b/Firestore/Protos/nanopb/google/api/http.pb.c
index 5219163..7a2cd21 100644
--- a/Firestore/Protos/nanopb/google/api/http.pb.c
+++ b/Firestore/Protos/nanopb/google/api/http.pb.c
@@ -15,7 +15,7 @@
*/
/* Automatically generated nanopb constant definitions */
-/* Generated by nanopb-0.3.8 at Fri Feb 2 17:48:02 2018. */
+/* Generated by nanopb-0.3.8 at Thu Apr 12 07:27:15 2018. */
#include "http.pb.h"
@@ -26,8 +26,9 @@
-const pb_field_t google_api_Http_fields[2] = {
+const pb_field_t google_api_Http_fields[3] = {
PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, google_api_Http, rules, rules, &google_api_HttpRule_fields),
+ PB_FIELD( 2, BOOL , SINGULAR, STATIC , OTHER, google_api_Http, fully_decode_reserved_expansion, rules, 0),
PB_LAST_FIELD
};
diff --git a/Firestore/Protos/nanopb/google/api/http.pb.h b/Firestore/Protos/nanopb/google/api/http.pb.h
index e29758c..a7bbc46 100644
--- a/Firestore/Protos/nanopb/google/api/http.pb.h
+++ b/Firestore/Protos/nanopb/google/api/http.pb.h
@@ -15,7 +15,7 @@
*/
/* Automatically generated nanopb header */
-/* Generated by nanopb-0.3.8 at Fri Feb 2 17:48:02 2018. */
+/* Generated by nanopb-0.3.8 at Thu Apr 12 07:27:15 2018. */
#ifndef PB_GOOGLE_API_HTTP_PB_H_INCLUDED
#define PB_GOOGLE_API_HTTP_PB_H_INCLUDED
@@ -39,6 +39,7 @@ typedef struct _google_api_CustomHttpPattern {
typedef struct _google_api_Http {
pb_callback_t rules;
+ bool fully_decode_reserved_expansion;
/* @@protoc_insertion_point(struct:google_api_Http) */
} google_api_Http;
@@ -58,10 +59,10 @@ typedef struct _google_api_HttpRule {
/* Default values for struct fields */
/* Initializer values for message structs */
-#define google_api_Http_init_default {{{NULL}, NULL}}
+#define google_api_Http_init_default {{{NULL}, NULL}, 0}
#define google_api_HttpRule_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, google_api_CustomHttpPattern_init_default, {{NULL}, NULL}}
#define google_api_CustomHttpPattern_init_default {{{NULL}, NULL}, {{NULL}, NULL}}
-#define google_api_Http_init_zero {{{NULL}, NULL}}
+#define google_api_Http_init_zero {{{NULL}, NULL}, 0}
#define google_api_HttpRule_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, google_api_CustomHttpPattern_init_zero, {{NULL}, NULL}}
#define google_api_CustomHttpPattern_init_zero {{{NULL}, NULL}, {{NULL}, NULL}}
@@ -69,6 +70,7 @@ typedef struct _google_api_HttpRule {
#define google_api_CustomHttpPattern_kind_tag 1
#define google_api_CustomHttpPattern_path_tag 2
#define google_api_Http_rules_tag 1
+#define google_api_Http_fully_decode_reserved_expansion_tag 2
#define google_api_HttpRule_selector_tag 1
#define google_api_HttpRule_get_tag 2
#define google_api_HttpRule_put_tag 3
@@ -80,7 +82,7 @@ typedef struct _google_api_HttpRule {
#define google_api_HttpRule_additional_bindings_tag 11
/* Struct field encoding specification for nanopb */
-extern const pb_field_t google_api_Http_fields[2];
+extern const pb_field_t google_api_Http_fields[3];
extern const pb_field_t google_api_HttpRule_fields[10];
extern const pb_field_t google_api_CustomHttpPattern_fields[3];
diff --git a/Firestore/Protos/nanopb/google/firestore/v1beta1/query.pb.h b/Firestore/Protos/nanopb/google/firestore/v1beta1/query.pb.h
index faad2a2..75b8168 100644
--- a/Firestore/Protos/nanopb/google/firestore/v1beta1/query.pb.h
+++ b/Firestore/Protos/nanopb/google/firestore/v1beta1/query.pb.h
@@ -15,7 +15,7 @@
*/
/* Automatically generated nanopb header */
-/* Generated by nanopb-0.3.8 at Fri Feb 2 17:48:02 2018. */
+/* Generated by nanopb-0.3.8 at Thu Apr 12 07:27:15 2018. */
#ifndef PB_GOOGLE_FIRESTORE_V1BETA1_QUERY_PB_H_INCLUDED
#define PB_GOOGLE_FIRESTORE_V1BETA1_QUERY_PB_H_INCLUDED
@@ -60,11 +60,12 @@ typedef enum _google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator {
google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_LESS_THAN_OR_EQUAL = 2,
google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_GREATER_THAN = 3,
google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_GREATER_THAN_OR_EQUAL = 4,
- google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_EQUAL = 5
+ google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_EQUAL = 5,
+ google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_ARRAY_CONTAINS = 7
} google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator;
#define _google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_MIN google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_OPERATOR_UNSPECIFIED
-#define _google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_MAX google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_EQUAL
-#define _google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_ARRAYSIZE ((google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator)(google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_EQUAL+1))
+#define _google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_MAX google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_ARRAY_CONTAINS
+#define _google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_ARRAYSIZE ((google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator)(google_firestore_v1beta1_StructuredQuery_FieldFilter_Operator_ARRAY_CONTAINS+1))
typedef enum _google_firestore_v1beta1_StructuredQuery_UnaryFilter_Operator {
google_firestore_v1beta1_StructuredQuery_UnaryFilter_Operator_OPERATOR_UNSPECIFIED = 0,
diff --git a/Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.c b/Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.c
index 462eca6..26542e0 100644
--- a/Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.c
+++ b/Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.c
@@ -15,7 +15,7 @@
*/
/* Automatically generated nanopb constant definitions */
-/* Generated by nanopb-0.3.8 at Fri Feb 2 17:48:02 2018. */
+/* Generated by nanopb-0.3.8 at Thu Apr 12 07:27:15 2018. */
#include "write.pb.h"
@@ -26,13 +26,12 @@
-const pb_field_t google_firestore_v1beta1_Write_fields[7] = {
+const pb_field_t google_firestore_v1beta1_Write_fields[6] = {
PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, google_firestore_v1beta1_Write, update, update, &google_firestore_v1beta1_Document_fields),
PB_FIELD( 2, STRING , SINGULAR, CALLBACK, OTHER, google_firestore_v1beta1_Write, delete_, update, 0),
PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, google_firestore_v1beta1_Write, update_mask, delete_, &google_firestore_v1beta1_DocumentMask_fields),
PB_FIELD( 4, MESSAGE , SINGULAR, STATIC , OTHER, google_firestore_v1beta1_Write, current_document, update_mask, &google_firestore_v1beta1_Precondition_fields),
- PB_FIELD( 5, STRING , SINGULAR, CALLBACK, OTHER, google_firestore_v1beta1_Write, verify, current_document, 0),
- PB_FIELD( 6, MESSAGE , SINGULAR, STATIC , OTHER, google_firestore_v1beta1_Write, transform, verify, &google_firestore_v1beta1_DocumentTransform_fields),
+ PB_FIELD( 6, MESSAGE , SINGULAR, STATIC , OTHER, google_firestore_v1beta1_Write, transform, current_document, &google_firestore_v1beta1_DocumentTransform_fields),
PB_LAST_FIELD
};
@@ -42,9 +41,11 @@ const pb_field_t google_firestore_v1beta1_DocumentTransform_fields[3] = {
PB_LAST_FIELD
};
-const pb_field_t google_firestore_v1beta1_DocumentTransform_FieldTransform_fields[3] = {
+const pb_field_t google_firestore_v1beta1_DocumentTransform_FieldTransform_fields[5] = {
PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, google_firestore_v1beta1_DocumentTransform_FieldTransform, field_path, field_path, 0),
PB_ONEOF_FIELD(transform_type, 2, ENUM , ONEOF, STATIC , OTHER, google_firestore_v1beta1_DocumentTransform_FieldTransform, set_to_server_value, field_path, 0),
+ PB_ONEOF_FIELD(transform_type, 6, MESSAGE , ONEOF, STATIC , UNION, google_firestore_v1beta1_DocumentTransform_FieldTransform, append_missing_elements, field_path, &google_firestore_v1beta1_ArrayValue_fields),
+ PB_ONEOF_FIELD(transform_type, 7, MESSAGE , ONEOF, STATIC , UNION, google_firestore_v1beta1_DocumentTransform_FieldTransform, remove_all_from_array, field_path, &google_firestore_v1beta1_ArrayValue_fields),
PB_LAST_FIELD
};
@@ -92,7 +93,7 @@ const pb_field_t google_firestore_v1beta1_ExistenceFilter_fields[3] = {
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
-PB_STATIC_ASSERT((pb_membersize(google_firestore_v1beta1_Write, update) < 65536 && pb_membersize(google_firestore_v1beta1_Write, transform) < 65536 && pb_membersize(google_firestore_v1beta1_Write, update_mask) < 65536 && pb_membersize(google_firestore_v1beta1_Write, current_document) < 65536 && pb_membersize(google_firestore_v1beta1_WriteResult, update_time) < 65536 && pb_membersize(google_firestore_v1beta1_DocumentChange, document) < 65536 && pb_membersize(google_firestore_v1beta1_DocumentDelete, read_time) < 65536 && pb_membersize(google_firestore_v1beta1_DocumentRemove, read_time) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_firestore_v1beta1_Write_google_firestore_v1beta1_DocumentTransform_google_firestore_v1beta1_DocumentTransform_FieldTransform_google_firestore_v1beta1_WriteResult_google_firestore_v1beta1_DocumentChange_google_firestore_v1beta1_DocumentDelete_google_firestore_v1beta1_DocumentRemove_google_firestore_v1beta1_ExistenceFilter)
+PB_STATIC_ASSERT((pb_membersize(google_firestore_v1beta1_Write, update) < 65536 && pb_membersize(google_firestore_v1beta1_Write, transform) < 65536 && pb_membersize(google_firestore_v1beta1_Write, update_mask) < 65536 && pb_membersize(google_firestore_v1beta1_Write, current_document) < 65536 && pb_membersize(google_firestore_v1beta1_DocumentTransform_FieldTransform, transform_type.append_missing_elements) < 65536 && pb_membersize(google_firestore_v1beta1_DocumentTransform_FieldTransform, transform_type.remove_all_from_array) < 65536 && pb_membersize(google_firestore_v1beta1_WriteResult, update_time) < 65536 && pb_membersize(google_firestore_v1beta1_DocumentChange, document) < 65536 && pb_membersize(google_firestore_v1beta1_DocumentDelete, read_time) < 65536 && pb_membersize(google_firestore_v1beta1_DocumentRemove, read_time) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_firestore_v1beta1_Write_google_firestore_v1beta1_DocumentTransform_google_firestore_v1beta1_DocumentTransform_FieldTransform_google_firestore_v1beta1_WriteResult_google_firestore_v1beta1_DocumentChange_google_firestore_v1beta1_DocumentDelete_google_firestore_v1beta1_DocumentRemove_google_firestore_v1beta1_ExistenceFilter)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
@@ -103,7 +104,7 @@ PB_STATIC_ASSERT((pb_membersize(google_firestore_v1beta1_Write, update) < 65536
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
-PB_STATIC_ASSERT((pb_membersize(google_firestore_v1beta1_Write, update) < 256 && pb_membersize(google_firestore_v1beta1_Write, transform) < 256 && pb_membersize(google_firestore_v1beta1_Write, update_mask) < 256 && pb_membersize(google_firestore_v1beta1_Write, current_document) < 256 && pb_membersize(google_firestore_v1beta1_WriteResult, update_time) < 256 && pb_membersize(google_firestore_v1beta1_DocumentChange, document) < 256 && pb_membersize(google_firestore_v1beta1_DocumentDelete, read_time) < 256 && pb_membersize(google_firestore_v1beta1_DocumentRemove, read_time) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_firestore_v1beta1_Write_google_firestore_v1beta1_DocumentTransform_google_firestore_v1beta1_DocumentTransform_FieldTransform_google_firestore_v1beta1_WriteResult_google_firestore_v1beta1_DocumentChange_google_firestore_v1beta1_DocumentDelete_google_firestore_v1beta1_DocumentRemove_google_firestore_v1beta1_ExistenceFilter)
+PB_STATIC_ASSERT((pb_membersize(google_firestore_v1beta1_Write, update) < 256 && pb_membersize(google_firestore_v1beta1_Write, transform) < 256 && pb_membersize(google_firestore_v1beta1_Write, update_mask) < 256 && pb_membersize(google_firestore_v1beta1_Write, current_document) < 256 && pb_membersize(google_firestore_v1beta1_DocumentTransform_FieldTransform, transform_type.append_missing_elements) < 256 && pb_membersize(google_firestore_v1beta1_DocumentTransform_FieldTransform, transform_type.remove_all_from_array) < 256 && pb_membersize(google_firestore_v1beta1_WriteResult, update_time) < 256 && pb_membersize(google_firestore_v1beta1_DocumentChange, document) < 256 && pb_membersize(google_firestore_v1beta1_DocumentDelete, read_time) < 256 && pb_membersize(google_firestore_v1beta1_DocumentRemove, read_time) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_firestore_v1beta1_Write_google_firestore_v1beta1_DocumentTransform_google_firestore_v1beta1_DocumentTransform_FieldTransform_google_firestore_v1beta1_WriteResult_google_firestore_v1beta1_DocumentChange_google_firestore_v1beta1_DocumentDelete_google_firestore_v1beta1_DocumentRemove_google_firestore_v1beta1_ExistenceFilter)
#endif
diff --git a/Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.h b/Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.h
index a44b6d4..5a272b2 100644
--- a/Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.h
+++ b/Firestore/Protos/nanopb/google/firestore/v1beta1/write.pb.h
@@ -15,7 +15,7 @@
*/
/* Automatically generated nanopb header */
-/* Generated by nanopb-0.3.8 at Fri Feb 2 17:48:02 2018. */
+/* Generated by nanopb-0.3.8 at Thu Apr 12 07:27:15 2018. */
#ifndef PB_GOOGLE_FIRESTORE_V1BETA1_WRITE_PB_H_INCLUDED
#define PB_GOOGLE_FIRESTORE_V1BETA1_WRITE_PB_H_INCLUDED
@@ -80,6 +80,8 @@ typedef struct _google_firestore_v1beta1_DocumentTransform_FieldTransform {
pb_size_t which_transform_type;
union {
google_firestore_v1beta1_DocumentTransform_FieldTransform_ServerValue set_to_server_value;
+ google_firestore_v1beta1_ArrayValue append_missing_elements;
+ google_firestore_v1beta1_ArrayValue remove_all_from_array;
} transform_type;
/* @@protoc_insertion_point(struct:google_firestore_v1beta1_DocumentTransform_FieldTransform) */
} google_firestore_v1beta1_DocumentTransform_FieldTransform;
@@ -95,7 +97,6 @@ typedef struct _google_firestore_v1beta1_Write {
pb_callback_t delete_;
google_firestore_v1beta1_DocumentMask update_mask;
google_firestore_v1beta1_Precondition current_document;
- pb_callback_t verify;
google_firestore_v1beta1_DocumentTransform transform;
/* @@protoc_insertion_point(struct:google_firestore_v1beta1_Write) */
} google_firestore_v1beta1_Write;
@@ -109,7 +110,7 @@ typedef struct _google_firestore_v1beta1_WriteResult {
/* Default values for struct fields */
/* Initializer values for message structs */
-#define google_firestore_v1beta1_Write_init_default {google_firestore_v1beta1_Document_init_default, {{NULL}, NULL}, google_firestore_v1beta1_DocumentMask_init_default, google_firestore_v1beta1_Precondition_init_default, {{NULL}, NULL}, google_firestore_v1beta1_DocumentTransform_init_default}
+#define google_firestore_v1beta1_Write_init_default {google_firestore_v1beta1_Document_init_default, {{NULL}, NULL}, google_firestore_v1beta1_DocumentMask_init_default, google_firestore_v1beta1_Precondition_init_default, google_firestore_v1beta1_DocumentTransform_init_default}
#define google_firestore_v1beta1_DocumentTransform_init_default {{{NULL}, NULL}, {{NULL}, NULL}}
#define google_firestore_v1beta1_DocumentTransform_FieldTransform_init_default {{{NULL}, NULL}, 0, {(google_firestore_v1beta1_DocumentTransform_FieldTransform_ServerValue)0}}
#define google_firestore_v1beta1_WriteResult_init_default {google_protobuf_Timestamp_init_default, {{NULL}, NULL}}
@@ -117,7 +118,7 @@ typedef struct _google_firestore_v1beta1_WriteResult {
#define google_firestore_v1beta1_DocumentDelete_init_default {{{NULL}, NULL}, google_protobuf_Timestamp_init_default, {{NULL}, NULL}}
#define google_firestore_v1beta1_DocumentRemove_init_default {{{NULL}, NULL}, {{NULL}, NULL}, google_protobuf_Timestamp_init_default}
#define google_firestore_v1beta1_ExistenceFilter_init_default {0, 0}
-#define google_firestore_v1beta1_Write_init_zero {google_firestore_v1beta1_Document_init_zero, {{NULL}, NULL}, google_firestore_v1beta1_DocumentMask_init_zero, google_firestore_v1beta1_Precondition_init_zero, {{NULL}, NULL}, google_firestore_v1beta1_DocumentTransform_init_zero}
+#define google_firestore_v1beta1_Write_init_zero {google_firestore_v1beta1_Document_init_zero, {{NULL}, NULL}, google_firestore_v1beta1_DocumentMask_init_zero, google_firestore_v1beta1_Precondition_init_zero, google_firestore_v1beta1_DocumentTransform_init_zero}
#define google_firestore_v1beta1_DocumentTransform_init_zero {{{NULL}, NULL}, {{NULL}, NULL}}
#define google_firestore_v1beta1_DocumentTransform_FieldTransform_init_zero {{{NULL}, NULL}, 0, {(google_firestore_v1beta1_DocumentTransform_FieldTransform_ServerValue)0}}
#define google_firestore_v1beta1_WriteResult_init_zero {google_protobuf_Timestamp_init_zero, {{NULL}, NULL}}
@@ -139,12 +140,13 @@ typedef struct _google_firestore_v1beta1_WriteResult {
#define google_firestore_v1beta1_DocumentRemove_removed_target_ids_tag 2
#define google_firestore_v1beta1_DocumentRemove_read_time_tag 4
#define google_firestore_v1beta1_DocumentTransform_FieldTransform_set_to_server_value_tag 2
+#define google_firestore_v1beta1_DocumentTransform_FieldTransform_append_missing_elements_tag 6
+#define google_firestore_v1beta1_DocumentTransform_FieldTransform_remove_all_from_array_tag 7
#define google_firestore_v1beta1_DocumentTransform_FieldTransform_field_path_tag 1
#define google_firestore_v1beta1_ExistenceFilter_target_id_tag 1
#define google_firestore_v1beta1_ExistenceFilter_count_tag 2
#define google_firestore_v1beta1_Write_update_tag 1
#define google_firestore_v1beta1_Write_delete_tag 2
-#define google_firestore_v1beta1_Write_verify_tag 5
#define google_firestore_v1beta1_Write_transform_tag 6
#define google_firestore_v1beta1_Write_update_mask_tag 3
#define google_firestore_v1beta1_Write_current_document_tag 4
@@ -152,9 +154,9 @@ typedef struct _google_firestore_v1beta1_WriteResult {
#define google_firestore_v1beta1_WriteResult_transform_results_tag 2
/* Struct field encoding specification for nanopb */
-extern const pb_field_t google_firestore_v1beta1_Write_fields[7];
+extern const pb_field_t google_firestore_v1beta1_Write_fields[6];
extern const pb_field_t google_firestore_v1beta1_DocumentTransform_fields[3];
-extern const pb_field_t google_firestore_v1beta1_DocumentTransform_FieldTransform_fields[3];
+extern const pb_field_t google_firestore_v1beta1_DocumentTransform_FieldTransform_fields[5];
extern const pb_field_t google_firestore_v1beta1_WriteResult_fields[3];
extern const pb_field_t google_firestore_v1beta1_DocumentChange_fields[4];
extern const pb_field_t google_firestore_v1beta1_DocumentDelete_fields[4];
diff --git a/Firestore/Protos/objc/google/api/HTTP.pbobjc.h b/Firestore/Protos/objc/google/api/HTTP.pbobjc.h
index 9cc00dc..c9e5bb5 100644
--- a/Firestore/Protos/objc/google/api/HTTP.pbobjc.h
+++ b/Firestore/Protos/objc/google/api/HTTP.pbobjc.h
@@ -67,10 +67,11 @@ NS_ASSUME_NONNULL_BEGIN
typedef GPB_ENUM(GAPIHttp_FieldNumber) {
GAPIHttp_FieldNumber_RulesArray = 1,
+ GAPIHttp_FieldNumber_FullyDecodeReservedExpansion = 2,
};
/**
- * Defines the HTTP configuration for a service. It contains a list of
+ * Defines the HTTP configuration for an API service. It contains a list of
* [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
* to one or more HTTP REST API methods.
**/
@@ -85,6 +86,16 @@ typedef GPB_ENUM(GAPIHttp_FieldNumber) {
/** The number of items in @c rulesArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger rulesArray_Count;
+/**
+ * When set to true, URL path parmeters will be fully URI-decoded except in
+ * cases of single segment matches in reserved expansion, where "%2F" will be
+ * left encoded.
+ *
+ * The default behavior is to not decode RFC 6570 reserved characters in multi
+ * segment matches.
+ **/
+@property(nonatomic, readwrite) BOOL fullyDecodeReservedExpansion;
+
@end
#pragma mark - GAPIHttpRule
@@ -113,11 +124,11 @@ typedef GPB_ENUM(GAPIHttpRule_Pattern_OneOfCase) {
/**
* `HttpRule` defines the mapping of an RPC method to one or more HTTP
- * REST APIs. The mapping determines what portions of the request
- * message are populated from the path, query parameters, or body of
- * the HTTP request. The mapping is typically specified as an
- * `google.api.http` annotation, see "google/api/annotations.proto"
- * for details.
+ * REST API methods. The mapping specifies how different portions of the RPC
+ * request message are mapped to URL path, URL query parameters, and
+ * HTTP request body. The mapping is typically specified as an
+ * `google.api.http` annotation on the RPC method,
+ * see "google/api/annotations.proto" for details.
*
* The mapping consists of a field specifying the path template and
* method kind. The path template can refer to fields in the request
@@ -165,6 +176,11 @@ typedef GPB_ENUM(GAPIHttpRule_Pattern_OneOfCase) {
* parameters. Assume the following definition of the request message:
*
*
+ * service Messaging {
+ * rpc GetMessage(GetMessageRequest) returns (Message) {
+ * option (google.api.http).get = "/v1/messages/{message_id}";
+ * }
+ * }
* message GetMessageRequest {
* message SubMessage {
* string subfield = 1;
@@ -277,7 +293,7 @@ typedef GPB_ENUM(GAPIHttpRule_Pattern_OneOfCase) {
* to the request message are as follows:
*
* 1. The `body` field specifies either `*` or a field path, or is
- * omitted. If omitted, it assumes there is no HTTP body.
+ * omitted. If omitted, it indicates there is no HTTP request body.
* 2. Leaf fields (recursive expansion of nested messages in the
* request) can be classified into three types:
* (a) Matched in the URL template.
@@ -296,28 +312,34 @@ typedef GPB_ENUM(GAPIHttpRule_Pattern_OneOfCase) {
* FieldPath = IDENT { "." IDENT } ;
* Verb = ":" LITERAL ;
*
- * The syntax `*` matches a single path segment. It follows the semantics of
- * [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String
- * Expansion.
+ * The syntax `*` matches a single path segment. The syntax `**` matches zero
+ * or more path segments, which must be the last part of the path except the
+ * `Verb`. The syntax `LITERAL` matches literal text in the path.
*
- * The syntax `**` matches zero or more path segments. It follows the semantics
- * of [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.3 Reserved
- * Expansion. NOTE: it must be the last segment in the path except the Verb.
- *
- * The syntax `LITERAL` matches literal text in the URL path.
- *
- * The syntax `Variable` matches the entire path as specified by its template;
- * this nested template must not contain further variables. If a variable
+ * The syntax `Variable` matches part of the URL path as specified by its
+ * template. A variable template must not contain other variables. If a variable
* matches a single path segment, its template may be omitted, e.g. `{var}`
* is equivalent to `{var=*}`.
*
+ * If a variable contains exactly one path segment, such as `"{var}"` or
+ * `"{var=*}"`, when such a variable is expanded into a URL path, all characters
+ * except `[-_.~0-9a-zA-Z]` are percent-encoded. Such variables show up in the
+ * Discovery Document as `{var}`.
+ *
+ * If a variable contains one or more path segments, such as `"{var=foo/\*}"`
+ * or `"{var=**}"`, when such a variable is expanded into a URL path, all
+ * characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. Such variables
+ * show up in the Discovery Document as `{+var}`.
+ *
+ * NOTE: While the single segment variable matches the semantics of
+ * [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2
+ * Simple String Expansion, the multi segment variable **does not** match
+ * RFC 6570 Reserved Expansion. The reason is that the Reserved Expansion
+ * does not expand special characters like `?` and `#`, which would lead
+ * to invalid URLs.
+ *
* NOTE: the field paths in variables and in the `body` must not refer to
* repeated fields or map fields.
- *
- * Use CustomHttpPattern to specify any HTTP method that is not included in the
- * `pattern` field, such as HEAD, or "*" to leave the HTTP method unspecified for
- * a given URL path rule. The wild-card rule is useful for services that provide
- * content to Web (HTML) clients.
**/
@interface GAPIHttpRule : GPBMessage
@@ -350,7 +372,12 @@ typedef GPB_ENUM(GAPIHttpRule_Pattern_OneOfCase) {
/** Used for updating a resource. */
@property(nonatomic, readwrite, copy, null_resettable) NSString *patch;
-/** Custom pattern is used for defining custom verbs. */
+/**
+ * The custom pattern is used for specifying an HTTP method that is not
+ * included in the `pattern` field, such as HEAD, or "*" to leave the
+ * HTTP method unspecified for this rule. The wild-card rule is useful
+ * for services that provide content to Web (HTML) clients.
+ **/
@property(nonatomic, readwrite, strong, null_resettable) GAPICustomHttpPattern *custom;
/**
diff --git a/Firestore/Protos/objc/google/api/HTTP.pbobjc.m b/Firestore/Protos/objc/google/api/HTTP.pbobjc.m
index 5adf41c..67d8732 100644
--- a/Firestore/Protos/objc/google/api/HTTP.pbobjc.m
+++ b/Firestore/Protos/objc/google/api/HTTP.pbobjc.m
@@ -65,6 +65,7 @@ static GPBFileDescriptor *GAPIHTTPRoot_FileDescriptor(void) {
@implementation GAPIHttp
@dynamic rulesArray, rulesArray_Count;
+@dynamic fullyDecodeReservedExpansion;
typedef struct GAPIHttp__storage_ {
uint32_t _has_storage_[1];
@@ -86,6 +87,15 @@ typedef struct GAPIHttp__storage_ {
.flags = GPBFieldRepeated,
.dataType = GPBDataTypeMessage,
},
+ {
+ .name = "fullyDecodeReservedExpansion",
+ .dataTypeSpecific.className = NULL,
+ .number = GAPIHttp_FieldNumber_FullyDecodeReservedExpansion,
+ .hasIndex = 0,
+ .offset = 1, // Stored in _has_storage_ to save space.
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeBool,
+ },
};
GPBDescriptor *localDescriptor =
[GPBDescriptor allocDescriptorForClass:[GAPIHttp class]
diff --git a/Firestore/Protos/objc/google/firestore/v1beta1/Document.pbobjc.h b/Firestore/Protos/objc/google/firestore/v1beta1/Document.pbobjc.h
index 3c5bfb1..b960b00 100644
--- a/Firestore/Protos/objc/google/firestore/v1beta1/Document.pbobjc.h
+++ b/Firestore/Protos/objc/google/firestore/v1beta1/Document.pbobjc.h
@@ -95,7 +95,7 @@ typedef GPB_ENUM(GCFSDocument_FieldNumber) {
* The map keys represent field names.
*
* A simple field name contains only characters `a` to `z`, `A` to `Z`,
- * `0` to `9`, or `_`, and must not start with `0` to `9` or `_`. For example,
+ * `0` to `9`, or `_`, and must not start with `0` to `9`. For example,
* `foo_bar_17`.
*
* Field names matching the regular expression `__.*__` are reserved. Reserved
@@ -133,7 +133,7 @@ typedef GPB_ENUM(GCFSDocument_FieldNumber) {
/**
* Output only. The time at which the document was last changed.
*
- * This value is initally set to the `create_time` then increases
+ * This value is initially set to the `create_time` then increases
* monotonically with each change to the document. It can also be
* compared to values from other documents and the `read_time` of a query.
**/
diff --git a/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbobjc.h b/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbobjc.h
index 0acd8c0..11f55a9 100644
--- a/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbobjc.h
+++ b/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbobjc.h
@@ -642,10 +642,7 @@ typedef GPB_ENUM(GCFSCommitRequest_FieldNumber) {
/** The number of items in @c writesArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger writesArray_Count;
-/**
- * If non-empty, applies all writes in this transaction, and commits it.
- * Otherwise, applies the writes as if they were in their own transaction.
- **/
+/** If set, applies all writes in this transaction, and commits it. */
@property(nonatomic, readwrite, copy, null_resettable) NSData *transaction;
@end
diff --git a/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.h b/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.h
index d7f127b..991c3f0 100644
--- a/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.h
+++ b/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.h
@@ -14,29 +14,57 @@
* limitations under the License.
*/
-#import "Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbobjc.h"
+#if !GPB_GRPC_FORWARD_DECLARE_MESSAGE_PROTO
+#import "Firestore.pbobjc.h"
+#endif
#import <ProtoRPC/ProtoService.h>
#import <ProtoRPC/ProtoRPC.h>
#import <RxLibrary/GRXWriteable.h>
#import <RxLibrary/GRXWriter.h>
-#import "Firestore/Protos/objc/google/api/Annotations.pbobjc.h"
-#import "Firestore/Protos/objc/google/firestore/v1beta1/Common.pbobjc.h"
-#import "Firestore/Protos/objc/google/firestore/v1beta1/Document.pbobjc.h"
-#import "Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.h"
-#import "Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.h"
-#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS
- #import <Protobuf/Empty.pbobjc.h>
-#else
- #import "Empty.pbobjc.h"
-#endif
-#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS
- #import <Protobuf/Timestamp.pbobjc.h>
+#if GPB_GRPC_FORWARD_DECLARE_MESSAGE_PROTO
+ @class GCFSBatchGetDocumentsRequest;
+ @class GCFSBatchGetDocumentsResponse;
+ @class GCFSBeginTransactionRequest;
+ @class GCFSBeginTransactionResponse;
+ @class GCFSCommitRequest;
+ @class GCFSCommitResponse;
+ @class GCFSCreateDocumentRequest;
+ @class GCFSDeleteDocumentRequest;
+ @class GCFSDocument;
+ @class GCFSGetDocumentRequest;
+ @class GCFSListCollectionIdsRequest;
+ @class GCFSListCollectionIdsResponse;
+ @class GCFSListDocumentsRequest;
+ @class GCFSListDocumentsResponse;
+ @class GCFSListenRequest;
+ @class GCFSListenResponse;
+ @class GCFSRollbackRequest;
+ @class GCFSRunQueryRequest;
+ @class GCFSRunQueryResponse;
+ @class GCFSUpdateDocumentRequest;
+ @class GCFSWriteRequest;
+ @class GCFSWriteResponse;
+ @class GPBEmpty;
#else
- #import "Timestamp.pbobjc.h"
+ #import "Annotations.pbobjc.h"
+ #import "Common.pbobjc.h"
+ #import "Document.pbobjc.h"
+ #import "Query.pbobjc.h"
+ #import "Write.pbobjc.h"
+ #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS
+ #import <Protobuf/Empty.pbobjc.h>
+ #else
+ #import "Empty.pbobjc.h"
+ #endif
+ #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS
+ #import <Protobuf/Timestamp.pbobjc.h>
+ #else
+ #import "Timestamp.pbobjc.h"
+ #endif
+ #import "Status.pbobjc.h"
#endif
-#import "Firestore/Protos/objc/google/rpc/Status.pbobjc.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.m b/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.m
index eec4c9a..29359b6 100644
--- a/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.m
+++ b/Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.m
@@ -14,10 +14,27 @@
* limitations under the License.
*/
-#import "Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.h"
+#import "Firestore.pbrpc.h"
+#import "Firestore.pbobjc.h"
#import <ProtoRPC/ProtoRPC.h>
#import <RxLibrary/GRXWriter+Immediate.h>
+#import "Annotations.pbobjc.h"
+#import "Common.pbobjc.h"
+#import "Document.pbobjc.h"
+#import "Query.pbobjc.h"
+#import "Write.pbobjc.h"
+#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS
+ #import <Protobuf/Empty.pbobjc.h>
+#else
+ #import "Empty.pbobjc.h"
+#endif
+#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS
+ #import <Protobuf/Timestamp.pbobjc.h>
+#else
+ #import "Timestamp.pbobjc.h"
+#endif
+#import "Status.pbobjc.h"
@implementation GCFSFirestore
diff --git a/Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.h b/Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.h
index c2d80e7..7e32934 100644
--- a/Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.h
+++ b/Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.h
@@ -140,6 +140,9 @@ typedef GPB_ENUM(GCFSStructuredQuery_FieldFilter_Operator) {
/** Equal. */
GCFSStructuredQuery_FieldFilter_Operator_Equal = 5,
+
+ /** Contains. Requires that the field is an array. */
+ GCFSStructuredQuery_FieldFilter_Operator_ArrayContains = 7,
};
GPBEnumDescriptor *GCFSStructuredQuery_FieldFilter_Operator_EnumDescriptor(void);
diff --git a/Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.m b/Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.m
index 804a5d0..124930a 100644
--- a/Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.m
+++ b/Firestore/Protos/objc/google/firestore/v1beta1/Query.pbobjc.m
@@ -542,7 +542,7 @@ GPBEnumDescriptor *GCFSStructuredQuery_FieldFilter_Operator_EnumDescriptor(void)
static const char *valueNames =
"OperatorUnspecified\000LessThan\000LessThanOrE"
"qual\000GreaterThan\000GreaterThanOrEqual\000Equa"
- "l\000";
+ "l\000ArrayContains\000";
static const int32_t values[] = {
GCFSStructuredQuery_FieldFilter_Operator_OperatorUnspecified,
GCFSStructuredQuery_FieldFilter_Operator_LessThan,
@@ -550,6 +550,7 @@ GPBEnumDescriptor *GCFSStructuredQuery_FieldFilter_Operator_EnumDescriptor(void)
GCFSStructuredQuery_FieldFilter_Operator_GreaterThan,
GCFSStructuredQuery_FieldFilter_Operator_GreaterThanOrEqual,
GCFSStructuredQuery_FieldFilter_Operator_Equal,
+ GCFSStructuredQuery_FieldFilter_Operator_ArrayContains,
};
GPBEnumDescriptor *worker =
[GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GCFSStructuredQuery_FieldFilter_Operator)
@@ -572,6 +573,7 @@ BOOL GCFSStructuredQuery_FieldFilter_Operator_IsValidValue(int32_t value__) {
case GCFSStructuredQuery_FieldFilter_Operator_GreaterThan:
case GCFSStructuredQuery_FieldFilter_Operator_GreaterThanOrEqual:
case GCFSStructuredQuery_FieldFilter_Operator_Equal:
+ case GCFSStructuredQuery_FieldFilter_Operator_ArrayContains:
return YES;
default:
return NO;
diff --git a/Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.h b/Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.h
index c3c4498..539bfa3 100644
--- a/Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.h
+++ b/Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.h
@@ -43,6 +43,7 @@
CF_EXTERN_C_BEGIN
+@class GCFSArrayValue;
@class GCFSDocument;
@class GCFSDocumentMask;
@class GCFSDocumentTransform;
@@ -66,7 +67,10 @@ typedef GPB_ENUM(GCFSDocumentTransform_FieldTransform_ServerValue) {
/** Unspecified. This value must not be used. */
GCFSDocumentTransform_FieldTransform_ServerValue_ServerValueUnspecified = 0,
- /** The time at which the server processed the request. */
+ /**
+ * The time at which the server processed the request, with millisecond
+ * precision.
+ **/
GCFSDocumentTransform_FieldTransform_ServerValue_RequestTime = 1,
};
@@ -100,7 +104,6 @@ typedef GPB_ENUM(GCFSWrite_FieldNumber) {
GCFSWrite_FieldNumber_Delete_p = 2,
GCFSWrite_FieldNumber_UpdateMask = 3,
GCFSWrite_FieldNumber_CurrentDocument = 4,
- GCFSWrite_FieldNumber_Verify = 5,
GCFSWrite_FieldNumber_Transform = 6,
};
@@ -108,7 +111,6 @@ typedef GPB_ENUM(GCFSWrite_Operation_OneOfCase) {
GCFSWrite_Operation_OneOfCase_GPBUnsetOneOfCase = 0,
GCFSWrite_Operation_OneOfCase_Update = 1,
GCFSWrite_Operation_OneOfCase_Delete_p = 2,
- GCFSWrite_Operation_OneOfCase_Verify = 5,
GCFSWrite_Operation_OneOfCase_Transform = 6,
};
@@ -130,13 +132,6 @@ typedef GPB_ENUM(GCFSWrite_Operation_OneOfCase) {
@property(nonatomic, readwrite, copy, null_resettable) NSString *delete_p;
/**
- * The name of a document on which to verify the `current_document`
- * precondition.
- * This only requires read access to the document.
- **/
-@property(nonatomic, readwrite, copy, null_resettable) NSString *verify;
-
-/**
* Applies a tranformation to a document.
* At most one `transform` per document is allowed in a given request.
* An `update` cannot follow a `transform` on the same document in a given
@@ -148,9 +143,10 @@ typedef GPB_ENUM(GCFSWrite_Operation_OneOfCase) {
* The fields to update in this write.
*
* This field can be set only when the operation is `update`.
- * None of the field paths in the mask may contain a reserved name.
- * If the document exists on the server and has fields not referenced in the
- * mask, they are left unchanged.
+ * If the mask is not set for an `update` and the document exists, any
+ * existing data will be overwritten.
+ * If the mask is set and the document on the server has fields not covered by
+ * the mask, they are left unchanged.
* Fields referenced in the mask, but not present in the input document, are
* deleted from the document on the server.
* The field paths in this mask must not contain a reserved field name.
@@ -193,6 +189,7 @@ typedef GPB_ENUM(GCFSDocumentTransform_FieldNumber) {
/**
* The list of transformations to apply to the fields of the document, in
* order.
+ * This must not be empty.
**/
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GCFSDocumentTransform_FieldTransform*> *fieldTransformsArray;
/** The number of items in @c fieldTransformsArray without causing the array to be created. */
@@ -205,11 +202,15 @@ typedef GPB_ENUM(GCFSDocumentTransform_FieldNumber) {
typedef GPB_ENUM(GCFSDocumentTransform_FieldTransform_FieldNumber) {
GCFSDocumentTransform_FieldTransform_FieldNumber_FieldPath = 1,
GCFSDocumentTransform_FieldTransform_FieldNumber_SetToServerValue = 2,
+ GCFSDocumentTransform_FieldTransform_FieldNumber_AppendMissingElements = 6,
+ GCFSDocumentTransform_FieldTransform_FieldNumber_RemoveAllFromArray_p = 7,
};
typedef GPB_ENUM(GCFSDocumentTransform_FieldTransform_TransformType_OneOfCase) {
GCFSDocumentTransform_FieldTransform_TransformType_OneOfCase_GPBUnsetOneOfCase = 0,
GCFSDocumentTransform_FieldTransform_TransformType_OneOfCase_SetToServerValue = 2,
+ GCFSDocumentTransform_FieldTransform_TransformType_OneOfCase_AppendMissingElements = 6,
+ GCFSDocumentTransform_FieldTransform_TransformType_OneOfCase_RemoveAllFromArray_p = 7,
};
/**
@@ -229,6 +230,36 @@ typedef GPB_ENUM(GCFSDocumentTransform_FieldTransform_TransformType_OneOfCase) {
/** Sets the field to the given server value. */
@property(nonatomic, readwrite) GCFSDocumentTransform_FieldTransform_ServerValue setToServerValue;
+/**
+ * Append the given elements in order if they are not already present in
+ * the current field value.
+ * If the field is not an array, or if the field does not yet exist, it is
+ * first set to the empty array.
+ *
+ * Equivalent numbers of different types (e.g. 3L and 3.0) are
+ * considered equal when checking if a value is missing.
+ * NaN is equal to NaN, and Null is equal to Null.
+ * If the input contains multiple equivalent values, only the first will
+ * be considered.
+ *
+ * The corresponding transform_result will be the null value.
+ **/
+@property(nonatomic, readwrite, strong, null_resettable) GCFSArrayValue *appendMissingElements;
+
+/**
+ * Remove all of the given elements from the array in the field.
+ * If the field is not an array, or if the field does not yet exist, it is
+ * set to the empty array.
+ *
+ * Equivalent numbers of the different types (e.g. 3L and 3.0) are
+ * considered equal when deciding whether an element should be removed.
+ * NaN is equal to NaN, and Null is equal to Null.
+ * This will remove all equivalent values if there are duplicates.
+ *
+ * The corresponding transform_result will be the null value.
+ **/
+@property(nonatomic, readwrite, strong, null_resettable) GCFSArrayValue *removeAllFromArray_p;
+
@end
/**
diff --git a/Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.m b/Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.m
index e6fd0f4..591e634 100644
--- a/Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.m
+++ b/Firestore/Protos/objc/google/firestore/v1beta1/Write.pbobjc.m
@@ -74,7 +74,6 @@ static GPBFileDescriptor *GCFSWriteRoot_FileDescriptor(void) {
@dynamic operationOneOfCase;
@dynamic update;
@dynamic delete_p;
-@dynamic verify;
@dynamic transform;
@dynamic hasUpdateMask, updateMask;
@dynamic hasCurrentDocument, currentDocument;
@@ -85,7 +84,6 @@ typedef struct GCFSWrite__storage_ {
NSString *delete_p;
GCFSDocumentMask *updateMask;
GCFSPrecondition *currentDocument;
- NSString *verify;
GCFSDocumentTransform *transform;
} GCFSWrite__storage_;
@@ -132,15 +130,6 @@ typedef struct GCFSWrite__storage_ {
.dataType = GPBDataTypeMessage,
},
{
- .name = "verify",
- .dataTypeSpecific.className = NULL,
- .number = GCFSWrite_FieldNumber_Verify,
- .hasIndex = -1,
- .offset = (uint32_t)offsetof(GCFSWrite__storage_, verify),
- .flags = GPBFieldOptional,
- .dataType = GPBDataTypeString,
- },
- {
.name = "transform",
.dataTypeSpecific.className = GPBStringifySymbol(GCFSDocumentTransform),
.number = GCFSWrite_FieldNumber_Transform,
@@ -238,11 +227,15 @@ typedef struct GCFSDocumentTransform__storage_ {
@dynamic transformTypeOneOfCase;
@dynamic fieldPath;
@dynamic setToServerValue;
+@dynamic appendMissingElements;
+@dynamic removeAllFromArray_p;
typedef struct GCFSDocumentTransform_FieldTransform__storage_ {
uint32_t _has_storage_[2];
GCFSDocumentTransform_FieldTransform_ServerValue setToServerValue;
NSString *fieldPath;
+ GCFSArrayValue *appendMissingElements;
+ GCFSArrayValue *removeAllFromArray_p;
} GCFSDocumentTransform_FieldTransform__storage_;
// This method is threadsafe because it is initially called
@@ -269,6 +262,24 @@ typedef struct GCFSDocumentTransform_FieldTransform__storage_ {
.flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor),
.dataType = GPBDataTypeEnum,
},
+ {
+ .name = "appendMissingElements",
+ .dataTypeSpecific.className = GPBStringifySymbol(GCFSArrayValue),
+ .number = GCFSDocumentTransform_FieldTransform_FieldNumber_AppendMissingElements,
+ .hasIndex = -1,
+ .offset = (uint32_t)offsetof(GCFSDocumentTransform_FieldTransform__storage_, appendMissingElements),
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeMessage,
+ },
+ {
+ .name = "removeAllFromArray_p",
+ .dataTypeSpecific.className = GPBStringifySymbol(GCFSArrayValue),
+ .number = GCFSDocumentTransform_FieldTransform_FieldNumber_RemoveAllFromArray_p,
+ .hasIndex = -1,
+ .offset = (uint32_t)offsetof(GCFSDocumentTransform_FieldTransform__storage_, removeAllFromArray_p),
+ .flags = GPBFieldOptional,
+ .dataType = GPBDataTypeMessage,
+ },
};
GPBDescriptor *localDescriptor =
[GPBDescriptor allocDescriptorForClass:[GCFSDocumentTransform_FieldTransform class]
diff --git a/Firestore/Protos/protos/google/api/http.proto b/Firestore/Protos/protos/google/api/http.proto
index 5f8538a..78d515d 100644
--- a/Firestore/Protos/protos/google/api/http.proto
+++ b/Firestore/Protos/protos/google/api/http.proto
@@ -1,4 +1,4 @@
-// Copyright 2016 Google Inc.
+// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ option java_package = "com.google.api";
option objc_class_prefix = "GAPI";
-// Defines the HTTP configuration for a service. It contains a list of
+// Defines the HTTP configuration for an API service. It contains a list of
// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
// to one or more HTTP REST API methods.
message Http {
@@ -32,14 +32,22 @@ message Http {
//
// **NOTE:** All service configuration rules follow "last one wins" order.
repeated HttpRule rules = 1;
+
+ // When set to true, URL path parmeters will be fully URI-decoded except in
+ // cases of single segment matches in reserved expansion, where "%2F" will be
+ // left encoded.
+ //
+ // The default behavior is to not decode RFC 6570 reserved characters in multi
+ // segment matches.
+ bool fully_decode_reserved_expansion = 2;
}
// `HttpRule` defines the mapping of an RPC method to one or more HTTP
-// REST APIs. The mapping determines what portions of the request
-// message are populated from the path, query parameters, or body of
-// the HTTP request. The mapping is typically specified as an
-// `google.api.http` annotation, see "google/api/annotations.proto"
-// for details.
+// REST API methods. The mapping specifies how different portions of the RPC
+// request message are mapped to URL path, URL query parameters, and
+// HTTP request body. The mapping is typically specified as an
+// `google.api.http` annotation on the RPC method,
+// see "google/api/annotations.proto" for details.
//
// The mapping consists of a field specifying the path template and
// method kind. The path template can refer to fields in the request
@@ -87,6 +95,11 @@ message Http {
// parameters. Assume the following definition of the request message:
//
//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http).get = "/v1/messages/{message_id}";
+// }
+// }
// message GetMessageRequest {
// message SubMessage {
// string subfield = 1;
@@ -199,7 +212,7 @@ message Http {
// to the request message are as follows:
//
// 1. The `body` field specifies either `*` or a field path, or is
-// omitted. If omitted, it assumes there is no HTTP body.
+// omitted. If omitted, it indicates there is no HTTP request body.
// 2. Leaf fields (recursive expansion of nested messages in the
// request) can be classified into three types:
// (a) Matched in the URL template.
@@ -218,28 +231,34 @@ message Http {
// FieldPath = IDENT { "." IDENT } ;
// Verb = ":" LITERAL ;
//
-// The syntax `*` matches a single path segment. It follows the semantics of
-// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String
-// Expansion.
+// The syntax `*` matches a single path segment. The syntax `**` matches zero
+// or more path segments, which must be the last part of the path except the
+// `Verb`. The syntax `LITERAL` matches literal text in the path.
//
-// The syntax `**` matches zero or more path segments. It follows the semantics
-// of [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.3 Reserved
-// Expansion. NOTE: it must be the last segment in the path except the Verb.
-//
-// The syntax `LITERAL` matches literal text in the URL path.
-//
-// The syntax `Variable` matches the entire path as specified by its template;
-// this nested template must not contain further variables. If a variable
+// The syntax `Variable` matches part of the URL path as specified by its
+// template. A variable template must not contain other variables. If a variable
// matches a single path segment, its template may be omitted, e.g. `{var}`
// is equivalent to `{var=*}`.
//
+// If a variable contains exactly one path segment, such as `"{var}"` or
+// `"{var=*}"`, when such a variable is expanded into a URL path, all characters
+// except `[-_.~0-9a-zA-Z]` are percent-encoded. Such variables show up in the
+// Discovery Document as `{var}`.
+//
+// If a variable contains one or more path segments, such as `"{var=foo/*}"`
+// or `"{var=**}"`, when such a variable is expanded into a URL path, all
+// characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. Such variables
+// show up in the Discovery Document as `{+var}`.
+//
+// NOTE: While the single segment variable matches the semantics of
+// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2
+// Simple String Expansion, the multi segment variable **does not** match
+// RFC 6570 Reserved Expansion. The reason is that the Reserved Expansion
+// does not expand special characters like `?` and `#`, which would lead
+// to invalid URLs.
+//
// NOTE: the field paths in variables and in the `body` must not refer to
// repeated fields or map fields.
-//
-// Use CustomHttpPattern to specify any HTTP method that is not included in the
-// `pattern` field, such as HEAD, or "*" to leave the HTTP method unspecified for
-// a given URL path rule. The wild-card rule is useful for services that provide
-// content to Web (HTML) clients.
message HttpRule {
// Selects methods to which this rule applies.
//
@@ -265,7 +284,10 @@ message HttpRule {
// Used for updating a resource.
string patch = 6;
- // Custom pattern is used for defining custom verbs.
+ // The custom pattern is used for specifying an HTTP method that is not
+ // included in the `pattern` field, such as HEAD, or "*" to leave the
+ // HTTP method unspecified for this rule. The wild-card rule is useful
+ // for services that provide content to Web (HTML) clients.
CustomHttpPattern custom = 8;
}
diff --git a/Firestore/Protos/protos/google/firestore/v1beta1/common.proto b/Firestore/Protos/protos/google/firestore/v1beta1/common.proto
index e624323..5ceb7b9 100644
--- a/Firestore/Protos/protos/google/firestore/v1beta1/common.proto
+++ b/Firestore/Protos/protos/google/firestore/v1beta1/common.proto
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ option java_multiple_files = true;
option java_outer_classname = "CommonProto";
option java_package = "com.google.firestore.v1beta1";
option objc_class_prefix = "GCFS";
+option php_namespace = "Google\\Cloud\\Firestore\\V1beta1";
// A set of field paths on a document.
diff --git a/Firestore/Protos/protos/google/firestore/v1beta1/document.proto b/Firestore/Protos/protos/google/firestore/v1beta1/document.proto
index cf6001d..cd84c7a 100644
--- a/Firestore/Protos/protos/google/firestore/v1beta1/document.proto
+++ b/Firestore/Protos/protos/google/firestore/v1beta1/document.proto
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ option java_multiple_files = true;
option java_outer_classname = "DocumentProto";
option java_package = "com.google.firestore.v1beta1";
option objc_class_prefix = "GCFS";
+option php_namespace = "Google\\Cloud\\Firestore\\V1beta1";
// A Firestore document.
@@ -42,7 +43,7 @@ message Document {
// The map keys represent field names.
//
// A simple field name contains only characters `a` to `z`, `A` to `Z`,
- // `0` to `9`, or `_`, and must not start with `0` to `9` or `_`. For example,
+ // `0` to `9`, or `_`, and must not start with `0` to `9`. For example,
// `foo_bar_17`.
//
// Field names matching the regular expression `__.*__` are reserved. Reserved
@@ -72,7 +73,7 @@ message Document {
// Output only. The time at which the document was last changed.
//
- // This value is initally set to the `create_time` then increases
+ // This value is initially set to the `create_time` then increases
// monotonically with each change to the document. It can also be
// compared to values from other documents and the `read_time` of a query.
google.protobuf.Timestamp update_time = 4;
diff --git a/Firestore/Protos/protos/google/firestore/v1beta1/firestore.proto b/Firestore/Protos/protos/google/firestore/v1beta1/firestore.proto
index 3939caa..c7e8561 100644
--- a/Firestore/Protos/protos/google/firestore/v1beta1/firestore.proto
+++ b/Firestore/Protos/protos/google/firestore/v1beta1/firestore.proto
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ option java_multiple_files = true;
option java_outer_classname = "FirestoreProto";
option java_package = "com.google.firestore.v1beta1";
option objc_class_prefix = "GCFS";
+option php_namespace = "Google\\Cloud\\Firestore\\V1beta1";
// Specification of the Firestore API.
@@ -55,27 +56,39 @@ option objc_class_prefix = "GCFS";
service Firestore {
// Gets a single document.
rpc GetDocument(GetDocumentRequest) returns (Document) {
- option (google.api.http) = { get: "/v1beta1/{name=projects/*/databases/*/documents/*/**}" };
+ option (google.api.http) = {
+ get: "/v1beta1/{name=projects/*/databases/*/documents/*/**}"
+ };
}
// Lists documents.
rpc ListDocuments(ListDocumentsRequest) returns (ListDocumentsResponse) {
- option (google.api.http) = { get: "/v1beta1/{parent=projects/*/databases/*/documents/*/**}/{collection_id}" };
+ option (google.api.http) = {
+ get: "/v1beta1/{parent=projects/*/databases/*/documents/*/**}/{collection_id}"
+ };
}
// Creates a new document.
rpc CreateDocument(CreateDocumentRequest) returns (Document) {
- option (google.api.http) = { post: "/v1beta1/{parent=projects/*/databases/*/documents/**}/{collection_id}" body: "document" };
+ option (google.api.http) = {
+ post: "/v1beta1/{parent=projects/*/databases/*/documents/**}/{collection_id}"
+ body: "document"
+ };
}
// Updates or inserts a document.
rpc UpdateDocument(UpdateDocumentRequest) returns (Document) {
- option (google.api.http) = { patch: "/v1beta1/{document.name=projects/*/databases/*/documents/*/**}" body: "document" };
+ option (google.api.http) = {
+ patch: "/v1beta1/{document.name=projects/*/databases/*/documents/*/**}"
+ body: "document"
+ };
}
// Deletes a document.
rpc DeleteDocument(DeleteDocumentRequest) returns (google.protobuf.Empty) {
- option (google.api.http) = { delete: "/v1beta1/{name=projects/*/databases/*/documents/*/**}" };
+ option (google.api.http) = {
+ delete: "/v1beta1/{name=projects/*/databases/*/documents/*/**}"
+ };
}
// Gets multiple documents.
@@ -83,42 +96,74 @@ service Firestore {
// Documents returned by this method are not guaranteed to be returned in the
// same order that they were requested.
rpc BatchGetDocuments(BatchGetDocumentsRequest) returns (stream BatchGetDocumentsResponse) {
- option (google.api.http) = { post: "/v1beta1/{database=projects/*/databases/*}/documents:batchGet" body: "*" };
+ option (google.api.http) = {
+ post: "/v1beta1/{database=projects/*/databases/*}/documents:batchGet"
+ body: "*"
+ };
}
// Starts a new transaction.
rpc BeginTransaction(BeginTransactionRequest) returns (BeginTransactionResponse) {
- option (google.api.http) = { post: "/v1beta1/{database=projects/*/databases/*}/documents:beginTransaction" body: "*" };
+ option (google.api.http) = {
+ post: "/v1beta1/{database=projects/*/databases/*}/documents:beginTransaction"
+ body: "*"
+ };
}
// Commits a transaction, while optionally updating documents.
rpc Commit(CommitRequest) returns (CommitResponse) {
- option (google.api.http) = { post: "/v1beta1/{database=projects/*/databases/*}/documents:commit" body: "*" };
+ option (google.api.http) = {
+ post: "/v1beta1/{database=projects/*/databases/*}/documents:commit"
+ body: "*"
+ };
}
// Rolls back a transaction.
rpc Rollback(RollbackRequest) returns (google.protobuf.Empty) {
- option (google.api.http) = { post: "/v1beta1/{database=projects/*/databases/*}/documents:rollback" body: "*" };
+ option (google.api.http) = {
+ post: "/v1beta1/{database=projects/*/databases/*}/documents:rollback"
+ body: "*"
+ };
}
// Runs a query.
rpc RunQuery(RunQueryRequest) returns (stream RunQueryResponse) {
- option (google.api.http) = { post: "/v1beta1/{parent=projects/*/databases/*/documents}:runQuery" body: "*" };
+ option (google.api.http) = {
+ post: "/v1beta1/{parent=projects/*/databases/*/documents}:runQuery"
+ body: "*"
+ additional_bindings {
+ post: "/v1beta1/{parent=projects/*/databases/*/documents/*/**}:runQuery"
+ body: "*"
+ }
+ };
}
// Streams batches of document updates and deletes, in order.
rpc Write(stream WriteRequest) returns (stream WriteResponse) {
- option (google.api.http) = { post: "/v1beta1/{database=projects/*/databases/*}/documents:write" body: "*" };
+ option (google.api.http) = {
+ post: "/v1beta1/{database=projects/*/databases/*}/documents:write"
+ body: "*"
+ };
}
// Listens to changes.
rpc Listen(stream ListenRequest) returns (stream ListenResponse) {
- option (google.api.http) = { post: "/v1beta1/{database=projects/*/databases/*}/documents:listen" body: "*" };
+ option (google.api.http) = {
+ post: "/v1beta1/{database=projects/*/databases/*}/documents:listen"
+ body: "*"
+ };
}
// Lists all the collection IDs underneath a document.
rpc ListCollectionIds(ListCollectionIdsRequest) returns (ListCollectionIdsResponse) {
- option (google.api.http) = { post: "/v1beta1/{parent=projects/*/databases/*/documents}:listCollectionIds" body: "*" };
+ option (google.api.http) = {
+ post: "/v1beta1/{parent=projects/*/databases/*/documents}:listCollectionIds"
+ body: "*"
+ additional_bindings {
+ post: "/v1beta1/{parent=projects/*/databases/*/documents/*/**}:listCollectionIds"
+ body: "*"
+ }
+ };
}
}
@@ -356,8 +401,7 @@ message CommitRequest {
// Always executed atomically and in order.
repeated Write writes = 2;
- // If non-empty, applies all writes in this transaction, and commits it.
- // Otherwise, applies the writes as if they were in their own transaction.
+ // If set, applies all writes in this transaction, and commits it.
bytes transaction = 3;
}
diff --git a/Firestore/Protos/protos/google/firestore/v1beta1/query.proto b/Firestore/Protos/protos/google/firestore/v1beta1/query.proto
index d19b022..5f5b0cf 100644
--- a/Firestore/Protos/protos/google/firestore/v1beta1/query.proto
+++ b/Firestore/Protos/protos/google/firestore/v1beta1/query.proto
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ option java_multiple_files = true;
option java_outer_classname = "QueryProto";
option java_package = "com.google.firestore.v1beta1";
option objc_class_prefix = "GCFS";
+option php_namespace = "Google\\Cloud\\Firestore\\V1beta1";
// A Firestore query.
@@ -98,6 +99,9 @@ message StructuredQuery {
// Equal.
EQUAL = 5;
+
+ // Contains. Requires that the field is an array.
+ ARRAY_CONTAINS = 7;
}
// The field to filter by.
diff --git a/Firestore/Protos/protos/google/firestore/v1beta1/write.proto b/Firestore/Protos/protos/google/firestore/v1beta1/write.proto
index b6e9d5f..3f4732b 100644
--- a/Firestore/Protos/protos/google/firestore/v1beta1/write.proto
+++ b/Firestore/Protos/protos/google/firestore/v1beta1/write.proto
@@ -1,4 +1,4 @@
-// Copyright 2017 Google Inc.
+// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ option java_multiple_files = true;
option java_outer_classname = "WriteProto";
option java_package = "com.google.firestore.v1beta1";
option objc_class_prefix = "GCFS";
+option php_namespace = "Google\\Cloud\\Firestore\\V1beta1";
// A write on a document.
@@ -40,11 +41,6 @@ message Write {
// `projects/{project_id}/databases/{database_id}/documents/{document_path}`.
string delete = 2;
- // The name of a document on which to verify the `current_document`
- // precondition.
- // This only requires read access to the document.
- string verify = 5;
-
// Applies a tranformation to a document.
// At most one `transform` per document is allowed in a given request.
// An `update` cannot follow a `transform` on the same document in a given
@@ -55,9 +51,10 @@ message Write {
// The fields to update in this write.
//
// This field can be set only when the operation is `update`.
- // None of the field paths in the mask may contain a reserved name.
- // If the document exists on the server and has fields not referenced in the
- // mask, they are left unchanged.
+ // If the mask is not set for an `update` and the document exists, any
+ // existing data will be overwritten.
+ // If the mask is set and the document on the server has fields not covered by
+ // the mask, they are left unchanged.
// Fields referenced in the mask, but not present in the input document, are
// deleted from the document on the server.
// The field paths in this mask must not contain a reserved field name.
@@ -78,7 +75,8 @@ message DocumentTransform {
// Unspecified. This value must not be used.
SERVER_VALUE_UNSPECIFIED = 0;
- // The time at which the server processed the request.
+ // The time at which the server processed the request, with millisecond
+ // precision.
REQUEST_TIME = 1;
}
@@ -90,6 +88,32 @@ message DocumentTransform {
oneof transform_type {
// Sets the field to the given server value.
ServerValue set_to_server_value = 2;
+
+ // Append the given elements in order if they are not already present in
+ // the current field value.
+ // If the field is not an array, or if the field does not yet exist, it is
+ // first set to the empty array.
+ //
+ // Equivalent numbers of different types (e.g. 3L and 3.0) are
+ // considered equal when checking if a value is missing.
+ // NaN is equal to NaN, and Null is equal to Null.
+ // If the input contains multiple equivalent values, only the first will
+ // be considered.
+ //
+ // The corresponding transform_result will be the null value.
+ ArrayValue append_missing_elements = 6;
+
+ // Remove all of the given elements from the array in the field.
+ // If the field is not an array, or if the field does not yet exist, it is
+ // set to the empty array.
+ //
+ // Equivalent numbers of the different types (e.g. 3L and 3.0) are
+ // considered equal when deciding whether an element should be removed.
+ // NaN is equal to NaN, and Null is equal to Null.
+ // This will remove all equivalent values if there are duplicates.
+ //
+ // The corresponding transform_result will be the null value.
+ ArrayValue remove_all_from_array = 7;
}
}
@@ -98,6 +122,7 @@ message DocumentTransform {
// The list of transformations to apply to the fields of the document, in
// order.
+ // This must not be empty.
repeated FieldTransform field_transforms = 2;
}
diff --git a/Firestore/Protos/protos/google/protobuf/any.proto b/Firestore/Protos/protos/google/protobuf/any.proto
index c748667..4932942 100644
--- a/Firestore/Protos/protos/google/protobuf/any.proto
+++ b/Firestore/Protos/protos/google/protobuf/any.proto
@@ -120,17 +120,18 @@ option objc_class_prefix = "GPB";
// }
//
message Any {
- // A URL/resource name whose content describes the type of the
- // serialized protocol buffer message.
+ // A URL/resource name that uniquely identifies the type of the serialized
+ // protocol buffer message. The last segment of the URL's path must represent
+ // the fully qualified name of the type (as in
+ // `path/google.protobuf.Duration`). The name should be in a canonical form
+ // (e.g., leading "." is not accepted).
//
- // For URLs which use the scheme `http`, `https`, or no scheme, the
- // following restrictions and interpretations apply:
+ // In practice, teams usually precompile into the binary all types that they
+ // expect it to use in the context of Any. However, for URLs which use the
+ // scheme `http`, `https`, or no scheme, one can optionally set up a type
+ // server that maps type URLs to message definitions as follows:
//
// * If no scheme is provided, `https` is assumed.
- // * The last segment of the URL's path must represent the fully
- // qualified name of the type (as in `path/google.protobuf.Duration`).
- // The name should be in a canonical form (e.g., leading "." is
- // not accepted).
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
// value in binary format, or produce an error.
// * Applications are allowed to cache lookup results based on the
@@ -139,6 +140,10 @@ message Any {
// on changes to types. (Use versioned type names to manage
// breaking changes.)
//
+ // Note: this functionality is not currently available in the official
+ // protobuf release, and it is not used for type URLs beginning with
+ // type.googleapis.com.
+ //
// Schemes other than `http`, `https` (or the empty scheme) might be
// used with implementation specific semantics.
//
diff --git a/Firestore/Protos/protos/google/protobuf/timestamp.proto b/Firestore/Protos/protos/google/protobuf/timestamp.proto
index b7cbd17..eafb3fa 100644
--- a/Firestore/Protos/protos/google/protobuf/timestamp.proto
+++ b/Firestore/Protos/protos/google/protobuf/timestamp.proto
@@ -103,7 +103,9 @@ option objc_class_prefix = "GPB";
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
-// is required, though only UTC (as indicated by "Z") is presently supported.
+// is required. A proto3 JSON serializer should always use UTC (as indicated by
+// "Z") when printing the Timestamp type and a proto3 JSON parser should be
+// able to accept both UTC and other timezones (as indicated by an offset).
//
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
// 01:30 UTC on January 15, 2017.
@@ -114,8 +116,8 @@ option objc_class_prefix = "GPB";
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
-// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime())
-// to obtain a formatter capable of generating timestamps in this format.
+// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
+// ) to obtain a formatter capable of generating timestamps in this format.
//
//
message Timestamp {
diff --git a/Firestore/Source/API/FIRDocumentReference.mm b/Firestore/Source/API/FIRDocumentReference.mm
index cc52d45..9fb4541 100644
--- a/Firestore/Source/API/FIRDocumentReference.mm
+++ b/Firestore/Source/API/FIRDocumentReference.mm
@@ -16,11 +16,11 @@
#import "FIRDocumentReference.h"
+#import <GRPCClient/GRPCCall.h>
+
#include <memory>
#include <utility>
-#import <GRPCClient/GRPCCall.h>
-
#import "FIRFirestoreErrors.h"
#import "FIRSnapshotMetadata.h"
#import "Firestore/Source/API/FIRCollectionReference+Internal.h"
@@ -41,11 +41,13 @@
#import "Firestore/Source/Util/FSTUsageValidation.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.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::DocumentKey;
+using firebase::firestore::model::Precondition;
using firebase::firestore::model::ResourcePath;
NS_ASSUME_NONNULL_BEGIN
@@ -168,7 +170,7 @@ NS_ASSUME_NONNULL_BEGIN
? [self.firestore.dataConverter parsedMergeData:documentData]
: [self.firestore.dataConverter parsedSetData:documentData];
return [self.firestore.client
- writeMutations:[parsed mutationsWithKey:self.key precondition:[FSTPrecondition none]]
+ writeMutations:[parsed mutationsWithKey:self.key precondition:Precondition::None()]
completion:completion];
}
@@ -180,8 +182,7 @@ NS_ASSUME_NONNULL_BEGIN
completion:(nullable void (^)(NSError *_Nullable error))completion {
FSTParsedUpdateData *parsed = [self.firestore.dataConverter parsedUpdateData:fields];
return [self.firestore.client
- writeMutations:[parsed mutationsWithKey:self.key
- precondition:[FSTPrecondition preconditionWithExists:YES]]
+ writeMutations:[parsed mutationsWithKey:self.key precondition:Precondition::Exists(true)]
completion:completion];
}
@@ -191,7 +192,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)deleteDocumentWithCompletion:(nullable void (^)(NSError *_Nullable error))completion {
FSTDeleteMutation *mutation =
- [[FSTDeleteMutation alloc] initWithKey:self.key precondition:[FSTPrecondition none]];
+ [[FSTDeleteMutation alloc] initWithKey:self.key precondition:Precondition::None()];
return [self.firestore.client writeMutations:@[ mutation ] completion:completion];
}
diff --git a/Firestore/Source/API/FIRFieldPath.mm b/Firestore/Source/API/FIRFieldPath.mm
index c651160..d0d8714 100644
--- a/Firestore/Source/API/FIRFieldPath.mm
+++ b/Firestore/Source/API/FIRFieldPath.mm
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-#import "Firestore/Source/API/FIRFieldPath+Internal.h"
+#import "FIRFieldPath.h"
#include <functional>
#include <string>
#include <utility>
#include <vector>
+#import "Firestore/Source/API/FIRFieldPath+Internal.h"
#import "Firestore/Source/Util/FSTUsageValidation.h"
#include "Firestore/core/src/firebase/firestore/model/field_path.h"
diff --git a/Firestore/Source/API/FIRFieldValue+Internal.h b/Firestore/Source/API/FIRFieldValue+Internal.h
index 1b4a99c..1618cd4 100644
--- a/Firestore/Source/API/FIRFieldValue+Internal.h
+++ b/Firestore/Source/API/FIRFieldValue+Internal.h
@@ -18,6 +18,14 @@
NS_ASSUME_NONNULL_BEGIN
+@interface FIRFieldValue (Internal)
+/**
+ * The method name (e.g. "FieldValue.delete()") that was used to create this FIRFieldValue
+ * instance, for use in error messages, etc.
+ */
+@property(nonatomic, strong, readonly) NSString *methodName;
+@end
+
/**
* FIRFieldValue class for field deletes. Exposed internally so code can do isKindOfClass checks on
* it.
@@ -34,4 +42,16 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
@end
+/** FIRFieldValue class for array unions. */
+@interface FSTArrayUnionFieldValue : FIRFieldValue
+- (instancetype)init NS_UNAVAILABLE;
+@property(strong, nonatomic, readonly) NSArray<id> *elements;
+@end
+
+/** FIRFieldValue class for array removes. */
+@interface FSTArrayRemoveFieldValue : FIRFieldValue
+- (instancetype)init NS_UNAVAILABLE;
+@property(strong, nonatomic, readonly) NSArray<id> *elements;
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/Firestore/Source/API/FIRFieldValue.mm b/Firestore/Source/API/FIRFieldValue.mm
index 7ae4fb0..e0ed8c7 100644
--- a/Firestore/Source/API/FIRFieldValue.mm
+++ b/Firestore/Source/API/FIRFieldValue.mm
@@ -46,6 +46,10 @@ NS_ASSUME_NONNULL_BEGIN
return sharedInstance;
}
+- (NSString *)methodName {
+ return @"FieldValue.delete()";
+}
+
@end
#pragma mark - FSTServerTimestampFieldValue
@@ -72,6 +76,40 @@ NS_ASSUME_NONNULL_BEGIN
return sharedInstance;
}
+- (NSString *)methodName {
+ return @"FieldValue.serverTimestamp()";
+}
+
+@end
+
+#pragma mark - FSTArrayUnionFieldValue
+
+@interface FSTArrayUnionFieldValue ()
+- (instancetype)initWithElements:(NSArray<id> *)elements;
+@end
+
+@implementation FSTArrayUnionFieldValue
+- (instancetype)initWithElements:(NSArray<id> *)elements {
+ if (self = [super initPrivate]) {
+ _elements = elements;
+ }
+ return self;
+}
+@end
+
+#pragma mark - FSTArrayRemoveFieldValue
+
+@interface FSTArrayRemoveFieldValue ()
+- (instancetype)initWithElements:(NSArray<id> *)elements;
+@end
+
+@implementation FSTArrayRemoveFieldValue
+- (instancetype)initWithElements:(NSArray<id> *)elements {
+ if (self = [super initPrivate]) {
+ _elements = elements;
+ }
+ return self;
+}
@end
#pragma mark - FIRFieldValue
@@ -91,6 +129,14 @@ NS_ASSUME_NONNULL_BEGIN
return [FSTServerTimestampFieldValue serverTimestampFieldValue];
}
++ (instancetype)fieldValueForArrayUnion:(NSArray<id> *)elements {
+ return [[FSTArrayUnionFieldValue alloc] initWithElements:elements];
+}
+
++ (instancetype)fieldValueForArrayRemove:(NSArray<id> *)elements {
+ return [[FSTArrayRemoveFieldValue alloc] initWithElements:elements];
+}
+
@end
NS_ASSUME_NONNULL_END
diff --git a/Firestore/Source/API/FIRFirestore.mm b/Firestore/Source/API/FIRFirestore.mm
index 45d67cf..fe461d6 100644
--- a/Firestore/Source/API/FIRFirestore.mm
+++ b/Firestore/Source/API/FIRFirestore.mm
@@ -16,14 +16,14 @@
#import "FIRFirestore.h"
-#include <memory>
-#include <utility>
-
#import <FirebaseCore/FIRApp.h>
#import <FirebaseCore/FIRAppInternal.h>
#import <FirebaseCore/FIRLogger.h>
#import <FirebaseCore/FIROptions.h>
+#include <memory>
+#include <utility>
+
#import "FIRFirestoreSettings.h"
#import "Firestore/Source/API/FIRCollectionReference+Internal.h"
#import "Firestore/Source/API/FIRDocumentReference+Internal.h"
@@ -31,7 +31,6 @@
#import "Firestore/Source/API/FIRTransaction+Internal.h"
#import "Firestore/Source/API/FIRWriteBatch+Internal.h"
#import "Firestore/Source/API/FSTUserDataConverter.h"
-
#import "Firestore/Source/Core/FSTFirestoreClient.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTDispatchQueue.h"
diff --git a/Firestore/Source/API/FIRFirestoreVersion.mm b/Firestore/Source/API/FIRFirestoreVersion.mm
index b1fe480..8ebe814 100644
--- a/Firestore/Source/API/FIRFirestoreVersion.mm
+++ b/Firestore/Source/API/FIRFirestoreVersion.mm
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#import "Firestore/Source/API/FIRFirestoreVersion.h"
+
#ifndef FIRFirestore_VERSION
#error "FIRFirestore_VERSION is not defined: add -DFIRFirestore_VERSION=... to the build invocation"
#endif
diff --git a/Firestore/Source/API/FIRWriteBatch.mm b/Firestore/Source/API/FIRWriteBatch.mm
index b1cfa09..df6e5e0 100644
--- a/Firestore/Source/API/FIRWriteBatch.mm
+++ b/Firestore/Source/API/FIRWriteBatch.mm
@@ -24,6 +24,10 @@
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Util/FSTUsageValidation.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
+
+using firebase::firestore::model::Precondition;
+
NS_ASSUME_NONNULL_BEGIN
#pragma mark - FIRWriteBatch
@@ -69,8 +73,8 @@ NS_ASSUME_NONNULL_BEGIN
[self validateReference:document];
FSTParsedSetData *parsed = options.isMerge ? [self.firestore.dataConverter parsedMergeData:data]
: [self.firestore.dataConverter parsedSetData:data];
- [self.mutations addObjectsFromArray:[parsed mutationsWithKey:document.key
- precondition:[FSTPrecondition none]]];
+ [self.mutations
+ addObjectsFromArray:[parsed mutationsWithKey:document.key precondition:Precondition::None()]];
return self;
}
@@ -79,9 +83,8 @@ NS_ASSUME_NONNULL_BEGIN
[self verifyNotCommitted];
[self validateReference:document];
FSTParsedUpdateData *parsed = [self.firestore.dataConverter parsedUpdateData:fields];
- [self.mutations
- addObjectsFromArray:[parsed mutationsWithKey:document.key
- precondition:[FSTPrecondition preconditionWithExists:YES]]];
+ [self.mutations addObjectsFromArray:[parsed mutationsWithKey:document.key
+ precondition:Precondition::Exists(true)]];
return self;
}
@@ -89,7 +92,7 @@ NS_ASSUME_NONNULL_BEGIN
[self verifyNotCommitted];
[self validateReference:document];
[self.mutations addObject:[[FSTDeleteMutation alloc] initWithKey:document.key
- precondition:[FSTPrecondition none]]];
+ precondition:Precondition::None()]];
return self;
}
diff --git a/Firestore/Source/API/FSTUserDataConverter.h b/Firestore/Source/API/FSTUserDataConverter.h
index 3b178be..ea20b3e 100644
--- a/Firestore/Source/API/FSTUserDataConverter.h
+++ b/Firestore/Source/API/FSTUserDataConverter.h
@@ -16,16 +16,18 @@
#import <Foundation/Foundation.h>
+#include <vector>
+
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
+#include "Firestore/core/src/firebase/firestore/model/field_transform.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
@class FIRSetOptions;
@class FSTObjectValue;
-@class FSTFieldMask;
@class FSTFieldValue;
-@class FSTFieldTransform;
@class FSTMutation;
-@class FSTPrecondition;
@class FSTSnapshotVersion;
NS_ASSUME_NONNULL_BEGIN
@@ -36,20 +38,28 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithData:(FSTObjectValue *)data
- fieldMask:(nullable FSTFieldMask *)fieldMask
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms
+ fieldTransforms:
+ (std::vector<firebase::firestore::model::FieldTransform>)fieldTransforms
+ NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)initWithData:(FSTObjectValue *)data
+ fieldMask:(firebase::firestore::model::FieldMask)fieldMask
+ fieldTransforms:
+ (std::vector<firebase::firestore::model::FieldTransform>)fieldTransforms
NS_DESIGNATED_INITIALIZER;
+- (const std::vector<firebase::firestore::model::FieldTransform> &)fieldTransforms;
+
@property(nonatomic, strong, readonly) FSTObjectValue *data;
-@property(nonatomic, strong, readonly, nullable) FSTFieldMask *fieldMask;
-@property(nonatomic, strong, readonly) NSArray<FSTFieldTransform *> *fieldTransforms;
+@property(nonatomic, assign, readonly) BOOL isPatch;
/**
* Converts the parsed document data into 1 or 2 mutations (depending on whether there are any
* field transforms) using the specified document key and precondition.
*/
- (NSArray<FSTMutation *> *)mutationsWithKey:(const firebase::firestore::model::DocumentKey &)key
- precondition:(FSTPrecondition *)precondition;
+ precondition:
+ (const firebase::firestore::model::Precondition &)precondition;
@end
@@ -59,20 +69,23 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithData:(FSTObjectValue *)data
- fieldMask:(FSTFieldMask *)fieldMask
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms
+ fieldMask:(firebase::firestore::model::FieldMask)fieldMask
+ fieldTransforms:
+ (std::vector<firebase::firestore::model::FieldTransform>)fieldTransforms
NS_DESIGNATED_INITIALIZER;
+- (const firebase::firestore::model::FieldMask &)fieldMask;
+- (const std::vector<firebase::firestore::model::FieldTransform> &)fieldTransforms;
+
@property(nonatomic, strong, readonly) FSTObjectValue *data;
-@property(nonatomic, strong, readonly) FSTFieldMask *fieldMask;
-@property(nonatomic, strong, readonly) NSArray<FSTFieldTransform *> *fieldTransforms;
/**
* Converts the parsed update data into 1 or 2 mutations (depending on whether there are any
* field transforms) using the specified document key and precondition.
*/
- (NSArray<FSTMutation *> *)mutationsWithKey:(const firebase::firestore::model::DocumentKey &)key
- precondition:(FSTPrecondition *)precondition;
+ precondition:
+ (const firebase::firestore::model::Precondition &)precondition;
@end
diff --git a/Firestore/Source/API/FSTUserDataConverter.mm b/Firestore/Source/API/FSTUserDataConverter.mm
index 7ee16de..90d68d8 100644
--- a/Firestore/Source/API/FSTUserDataConverter.mm
+++ b/Firestore/Source/API/FSTUserDataConverter.mm
@@ -35,14 +35,24 @@
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/field_transform.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
+#include "Firestore/core/src/firebase/firestore/model/transform_operations.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::ArrayTransform;
using firebase::firestore::model::DatabaseId;
using firebase::firestore::model::DocumentKey;
+using firebase::firestore::model::FieldMask;
using firebase::firestore::model::FieldPath;
+using firebase::firestore::model::FieldTransform;
+using firebase::firestore::model::Precondition;
+using firebase::firestore::model::ServerTimestampTransform;
+using firebase::firestore::model::TransformOperation;
NS_ASSUME_NONNULL_BEGIN
@@ -50,25 +60,45 @@ static NSString *const RESERVED_FIELD_DESIGNATOR = @"__";
#pragma mark - FSTParsedSetData
-@implementation FSTParsedSetData
+@implementation FSTParsedSetData {
+ FieldMask _fieldMask;
+ std::vector<FieldTransform> _fieldTransforms;
+}
+
- (instancetype)initWithData:(FSTObjectValue *)data
- fieldMask:(nullable FSTFieldMask *)fieldMask
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms {
+ fieldTransforms:(std::vector<FieldTransform>)fieldTransforms {
self = [super init];
if (self) {
_data = data;
- _fieldMask = fieldMask;
- _fieldTransforms = fieldTransforms;
+ _fieldTransforms = std::move(fieldTransforms);
+ _isPatch = NO;
}
return self;
}
+- (instancetype)initWithData:(FSTObjectValue *)data
+ fieldMask:(FieldMask)fieldMask
+ fieldTransforms:(std::vector<FieldTransform>)fieldTransforms {
+ self = [super init];
+ if (self) {
+ _data = data;
+ _fieldMask = std::move(fieldMask);
+ _fieldTransforms = std::move(fieldTransforms);
+ _isPatch = YES;
+ }
+ return self;
+}
+
+- (const std::vector<FieldTransform> &)fieldTransforms {
+ return _fieldTransforms;
+}
+
- (NSArray<FSTMutation *> *)mutationsWithKey:(const DocumentKey &)key
- precondition:(FSTPrecondition *)precondition {
+ precondition:(const Precondition &)precondition {
NSMutableArray<FSTMutation *> *mutations = [NSMutableArray array];
- if (self.fieldMask) {
+ if (self.isPatch) {
[mutations addObject:[[FSTPatchMutation alloc] initWithKey:key
- fieldMask:self.fieldMask
+ fieldMask:_fieldMask
value:self.data
precondition:precondition]];
} else {
@@ -76,7 +106,7 @@ static NSString *const RESERVED_FIELD_DESIGNATOR = @"__";
value:self.data
precondition:precondition]];
}
- if (self.fieldTransforms.count > 0) {
+ if (!self.fieldTransforms.empty()) {
[mutations addObject:[[FSTTransformMutation alloc] initWithKey:key
fieldTransforms:self.fieldTransforms]];
}
@@ -87,33 +117,45 @@ static NSString *const RESERVED_FIELD_DESIGNATOR = @"__";
#pragma mark - FSTParsedUpdateData
-@implementation FSTParsedUpdateData
+@implementation FSTParsedUpdateData {
+ FieldMask _fieldMask;
+ std::vector<FieldTransform> _fieldTransforms;
+}
+
- (instancetype)initWithData:(FSTObjectValue *)data
- fieldMask:(FSTFieldMask *)fieldMask
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms {
+ fieldMask:(FieldMask)fieldMask
+ fieldTransforms:(std::vector<FieldTransform>)fieldTransforms {
self = [super init];
if (self) {
_data = data;
- _fieldMask = fieldMask;
- _fieldTransforms = fieldTransforms;
+ _fieldMask = std::move(fieldMask);
+ _fieldTransforms = std::move(fieldTransforms);
}
return self;
}
- (NSArray<FSTMutation *> *)mutationsWithKey:(const DocumentKey &)key
- precondition:(FSTPrecondition *)precondition {
+ precondition:(const Precondition &)precondition {
NSMutableArray<FSTMutation *> *mutations = [NSMutableArray array];
[mutations addObject:[[FSTPatchMutation alloc] initWithKey:key
fieldMask:self.fieldMask
value:self.data
precondition:precondition]];
- if (self.fieldTransforms.count > 0) {
+ if (!self.fieldTransforms.empty()) {
[mutations addObject:[[FSTTransformMutation alloc] initWithKey:key
fieldTransforms:self.fieldTransforms]];
}
return mutations;
}
+- (const firebase::firestore::model::FieldMask &)fieldMask {
+ return _fieldMask;
+}
+
+- (const std::vector<FieldTransform> &)fieldTransforms {
+ return _fieldTransforms;
+}
+
@end
/**
@@ -124,7 +166,11 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
FSTUserDataSourceSet,
FSTUserDataSourceMergeSet,
FSTUserDataSourceUpdate,
- FSTUserDataSourceQueryValue, // from a where clause or cursor bound.
+ /**
+ * Indicates the source is a where clause, cursor bound, arrayUnion() element, etc. In particular,
+ * this will result in [FSTParseContext isWrite] returning NO.
+ */
+ FSTUserDataSourceArgument,
};
#pragma mark - FSTParseContext
@@ -142,7 +188,6 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
* conditions apply during parsing and providing better error messages.
*/
@property(nonatomic, assign) FSTUserDataSource dataSource;
-@property(nonatomic, strong, readonly) NSMutableArray<FSTFieldTransform *> *fieldTransforms;
- (instancetype)init NS_UNAVAILABLE;
/**
@@ -160,7 +205,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
- (instancetype)initWithSource:(FSTUserDataSource)dataSource
path:(std::unique_ptr<FieldPath>)path
arrayElement:(BOOL)arrayElement
- fieldTransforms:(NSMutableArray<FSTFieldTransform *> *)fieldTransforms
+ fieldTransforms:(std::shared_ptr<std::vector<FieldTransform>>)fieldTransforms
fieldMask:(std::shared_ptr<std::vector<FieldPath>>)fieldMask
NS_DESIGNATED_INITIALIZER;
@@ -178,16 +223,22 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
- (void)appendToFieldMaskWithFieldPath:(FieldPath)fieldPath;
+- (const std::vector<FieldTransform> *)fieldTransforms;
+
+- (void)appendToFieldTransformsWithFieldPath:(FieldPath)fieldPath
+ transformOperation:
+ (std::unique_ptr<TransformOperation>)transformOperation;
@end
@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.
+ // _fieldMask and _fieldTransforms are 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 and _fieldTransforms.
std::shared_ptr<std::vector<FieldPath>> _fieldMask;
+ std::shared_ptr<std::vector<FieldTransform>> _fieldTransforms;
}
+ (instancetype)contextWithSource:(FSTUserDataSource)dataSource
@@ -196,7 +247,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
[[FSTParseContext alloc] initWithSource:dataSource
path:std::move(path)
arrayElement:NO
- fieldTransforms:[NSMutableArray array]
+ fieldTransforms:std::make_shared<std::vector<FieldTransform>>()
fieldMask:std::make_shared<std::vector<FieldPath>>()];
[context validatePath];
return context;
@@ -205,13 +256,13 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
- (instancetype)initWithSource:(FSTUserDataSource)dataSource
path:(std::unique_ptr<FieldPath>)path
arrayElement:(BOOL)arrayElement
- fieldTransforms:(NSMutableArray<FSTFieldTransform *> *)fieldTransforms
+ fieldTransforms:(std::shared_ptr<std::vector<FieldTransform>>)fieldTransforms
fieldMask:(std::shared_ptr<std::vector<FieldPath>>)fieldMask {
if (self = [super init]) {
_dataSource = dataSource;
_path = std::move(path);
_arrayElement = arrayElement;
- _fieldTransforms = fieldTransforms;
+ _fieldTransforms = std::move(fieldTransforms);
_fieldMask = std::move(fieldMask);
}
return self;
@@ -225,7 +276,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
FSTParseContext *context = [[FSTParseContext alloc] initWithSource:self.dataSource
path:std::move(path)
arrayElement:NO
- fieldTransforms:self.fieldTransforms
+ fieldTransforms:_fieldTransforms
fieldMask:_fieldMask];
[context validatePathSegment:fieldName];
return context;
@@ -239,7 +290,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
FSTParseContext *context = [[FSTParseContext alloc] initWithSource:self.dataSource
path:std::move(path)
arrayElement:NO
- fieldTransforms:self.fieldTransforms
+ fieldTransforms:_fieldTransforms
fieldMask:_fieldMask];
[context validatePath];
return context;
@@ -250,7 +301,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
return [[FSTParseContext alloc] initWithSource:self.dataSource
path:nil
arrayElement:YES
- fieldTransforms:self.fieldTransforms
+ fieldTransforms:_fieldTransforms
fieldMask:_fieldMask];
}
@@ -272,7 +323,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
case FSTUserDataSourceMergeSet: // Falls through.
case FSTUserDataSourceUpdate:
return YES;
- case FSTUserDataSourceQueryValue:
+ case FSTUserDataSourceArgument:
return NO;
default:
FSTThrowInvalidArgument(@"Unexpected case for FSTUserDataSource: %d", self.dataSource);
@@ -309,6 +360,16 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
_fieldMask->push_back(std::move(fieldPath));
}
+- (const std::vector<FieldTransform> *)fieldTransforms {
+ return _fieldTransforms.get();
+}
+
+- (void)appendToFieldTransformsWithFieldPath:(FieldPath)fieldPath
+ transformOperation:
+ (std::unique_ptr<TransformOperation>)transformOperation {
+ _fieldTransforms->emplace_back(std::move(fieldPath), std::move(transformOperation));
+}
+
@end
#pragma mark - FSTDocumentKeyReference
@@ -364,10 +425,9 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
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:FieldMask{*context.fieldMask}
+ fieldTransforms:*context.fieldTransforms];
}
- (FSTParsedSetData *)parsedSetData:(id)input {
@@ -382,9 +442,8 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
path:absl::make_unique<FieldPath>(FieldPath::EmptyPath())];
FSTObjectValue *updateData = (FSTObjectValue *)[self parseData:input context:context];
- return [[FSTParsedSetData alloc] initWithData:updateData
- fieldMask:nil
- fieldTransforms:context.fieldTransforms];
+ return
+ [[FSTParsedSetData alloc] initWithData:updateData fieldTransforms:*context.fieldTransforms];
}
- (FSTParsedUpdateData *)parsedUpdateData:(id)input {
@@ -428,19 +487,18 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
}
}];
- FSTFieldMask *mask = [[FSTFieldMask alloc] initWithFields:fieldMaskPaths];
return [[FSTParsedUpdateData alloc] initWithData:updateData
- fieldMask:mask
- fieldTransforms:context.fieldTransforms];
+ fieldMask:FieldMask{fieldMaskPaths}
+ fieldTransforms:*context.fieldTransforms];
}
- (FSTFieldValue *)parsedQueryValue:(id)input {
FSTParseContext *context =
- [FSTParseContext contextWithSource:FSTUserDataSourceQueryValue
+ [FSTParseContext contextWithSource:FSTUserDataSourceArgument
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.");
+ FSTAssert(context.fieldTransforms->empty(), @"Field transforms should have been disallowed.");
return parsed;
}
@@ -456,64 +514,128 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
*/
- (nullable FSTFieldValue *)parseData:(id)input context:(FSTParseContext *)context {
input = self.preConverter(input);
- if ([input isKindOfClass:[NSArray class]]) {
- // TODO(b/34871131): Include the path containing the array in the error message.
- if (context.isArrayElement) {
- FSTThrowInvalidArgument(@"Nested arrays are not supported");
- }
- NSArray *array = input;
- NSMutableArray<FSTFieldValue *> *result = [NSMutableArray arrayWithCapacity:array.count];
- [array enumerateObjectsUsingBlock:^(id entry, NSUInteger idx, BOOL *stop) {
- FSTFieldValue *_Nullable parsedEntry =
- [self parseData:entry context:[context contextForArrayIndex:idx]];
- if (!parsedEntry) {
- // Just include nulls in the array for fields being replaced with a sentinel.
- parsedEntry = [FSTNullValue nullValue];
- }
- [result addObject:parsedEntry];
- }];
+ if ([input isKindOfClass:[NSDictionary class]]) {
+ return [self parseDictionary:(NSDictionary *)input context:context];
+ } else {
// 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 appendToFieldMaskWithFieldPath:*context.path];
}
- return [[FSTArrayValue alloc] initWithValueNoCopy:result];
- } else if ([input isKindOfClass:[NSDictionary class]]) {
- NSDictionary *dict = input;
- NSMutableDictionary<NSString *, FSTFieldValue *> *result =
- [NSMutableDictionary dictionaryWithCapacity:dict.count];
- [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
- FSTFieldValue *_Nullable parsedValue =
- [self parseData:value context:[context contextForField:key]];
- if (parsedValue) {
- result[key] = parsedValue;
+ if ([input isKindOfClass:[NSArray class]]) {
+ // TODO(b/34871131): Include the path containing the array in the error message.
+ if (context.isArrayElement) {
+ FSTThrowInvalidArgument(@"Nested arrays are not supported");
}
- }];
- return [[FSTObjectValue alloc] initWithDictionary:result];
+ return [self parseArray:(NSArray *)input context:context];
+ } else if ([input isKindOfClass:[FIRFieldValue class]]) {
+ // parseSentinelFieldValue may add an FSTFieldTransform, but we return nil since nothing
+ // should be included in the actual parsed data.
+ [self parseSentinelFieldValue:(FIRFieldValue *)input context:context];
+ return nil;
+ } else {
+ return [self parseScalarValue:input context:context];
+ }
+ }
+}
- } else {
- // 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 appendToFieldMaskWithFieldPath:*context.path];
+- (FSTFieldValue *)parseDictionary:(NSDictionary *)dict context:(FSTParseContext *)context {
+ NSMutableDictionary<NSString *, FSTFieldValue *> *result =
+ [NSMutableDictionary dictionaryWithCapacity:dict.count];
+ [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
+ FSTFieldValue *_Nullable parsedValue =
+ [self parseData:value context:[context contextForField:key]];
+ if (parsedValue) {
+ result[key] = parsedValue;
}
- return [self parseScalarValue:input context:context];
+ }];
+ return [[FSTObjectValue alloc] initWithDictionary:result];
+}
+
+- (FSTFieldValue *)parseArray:(NSArray *)array context:(FSTParseContext *)context {
+ NSMutableArray<FSTFieldValue *> *result = [NSMutableArray arrayWithCapacity:array.count];
+ [array enumerateObjectsUsingBlock:^(id entry, NSUInteger idx, BOOL *stop) {
+ FSTFieldValue *_Nullable parsedEntry =
+ [self parseData:entry context:[context contextForArrayIndex:idx]];
+ if (!parsedEntry) {
+ // Just include nulls in the array for fields being replaced with a sentinel.
+ parsedEntry = [FSTNullValue nullValue];
+ }
+ [result addObject:parsedEntry];
+ }];
+ return [[FSTArrayValue alloc] initWithValueNoCopy:result];
+}
+
+/**
+ * "Parses" the provided FIRFieldValue, adding any necessary transforms to
+ * context.fieldTransforms.
+ */
+- (void)parseSentinelFieldValue:(FIRFieldValue *)fieldValue context:(FSTParseContext *)context {
+ // Sentinels are only supported with writes, and not within arrays.
+ if (![context isWrite]) {
+ FSTThrowInvalidArgument(@"%@ can only be used with updateData() and setData()%@",
+ fieldValue.methodName, [context fieldDescription]);
+ }
+ if (!context.path) {
+ FSTThrowInvalidArgument(@"%@ is not currently supported inside arrays", fieldValue.methodName);
+ }
+
+ if ([fieldValue isKindOfClass:[FSTDeleteFieldValue class]]) {
+ if (context.dataSource == FSTUserDataSourceMergeSet) {
+ // No transform to add for a delete, so we do nothing.
+ } else if (context.dataSource == FSTUserDataSourceUpdate) {
+ 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 "
+ "update data%@",
+ [context fieldDescription]);
+ } else {
+ // We shouldn't encounter delete sentinels for queries or non-merge setData calls.
+ FSTThrowInvalidArgument(
+ @"FieldValue.delete() can only be used with updateData() and setData() with "
+ @"SetOptions.merge()%@",
+ [context fieldDescription]);
+ }
+
+ } else if ([fieldValue isKindOfClass:[FSTServerTimestampFieldValue class]]) {
+ [context appendToFieldTransformsWithFieldPath:*context.path
+ transformOperation:absl::make_unique<ServerTimestampTransform>(
+ ServerTimestampTransform::Get())];
+
+ } else if ([fieldValue isKindOfClass:[FSTArrayUnionFieldValue class]]) {
+ std::vector<FSTFieldValue *> parsedElements =
+ [self parseArrayTransformElements:((FSTArrayUnionFieldValue *)fieldValue).elements];
+ auto array_union =
+ absl::make_unique<ArrayTransform>(TransformOperation::Type::ArrayUnion, parsedElements);
+ [context appendToFieldTransformsWithFieldPath:*context.path
+ transformOperation:std::move(array_union)];
+
+ } else if ([fieldValue isKindOfClass:[FSTArrayRemoveFieldValue class]]) {
+ std::vector<FSTFieldValue *> parsedElements =
+ [self parseArrayTransformElements:((FSTArrayRemoveFieldValue *)fieldValue).elements];
+ auto array_remove =
+ absl::make_unique<ArrayTransform>(TransformOperation::Type::ArrayRemove, parsedElements);
+ [context appendToFieldTransformsWithFieldPath:*context.path
+ transformOperation:std::move(array_remove)];
+
+ } else {
+ FSTFail(@"Unknown FIRFieldValue type: %@", NSStringFromClass([fieldValue class]));
}
}
/**
- * Helper to parse a scalar value (i.e. not an NSDictionary or NSArray).
+ * Helper to parse a scalar value (i.e. not an NSDictionary, NSArray, or FIRFieldValue).
*
* Note that it handles all NSNumber values that are encodable as int64_t or doubles
* (depending on the underlying type of the NSNumber). Unsigned integer values are handled though
* any value outside what is representable by int64_t (a signed 64-bit value) will throw an
* exception.
*
- * @return The parsed value, or nil if the value was a FieldValue sentinel that should not be
- * included in the resulting parsed data.
+ * @return The parsed value.
*/
-- (nullable FSTFieldValue *)parseScalarValue:(nullable id)input context:(FSTParseContext *)context {
+- (FSTFieldValue *)parseScalarValue:(nullable id)input context:(FSTParseContext *)context {
if (!input || [input isMemberOfClass:[NSNull class]]) {
return [FSTNullValue nullValue];
@@ -620,8 +742,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
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 "
- "update data%@",
+ @"FieldValue.delete() can only appear at the top level of your update data%@",
[context fieldDescription]);
} else {
// We shouldn't encounter delete sentinels for queries or non-merge setData calls.
@@ -639,10 +760,9 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
@"FieldValue.serverTimestamp() is not currently supported inside arrays%@",
[context fieldDescription]);
}
- [context.fieldTransforms
- addObject:[[FSTFieldTransform alloc]
- initWithPath:*context.path
- transform:[FSTServerTimestampTransform serverTimestampTransform]]];
+ [context appendToFieldTransformsWithFieldPath:*context.path
+ transformOperation:absl::make_unique<ServerTimestampTransform>(
+ ServerTimestampTransform::Get())];
// Return nil so this value is omitted from the parsed result.
return nil;
@@ -656,6 +776,22 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
}
}
+- (std::vector<FSTFieldValue *>)parseArrayTransformElements:(NSArray<id> *)elements {
+ std::vector<FSTFieldValue *> results;
+ for (id element in elements) {
+ // Although array transforms are used with writes, the actual elements being unioned or removed
+ // are not considered writes since they cannot contain any FieldValue sentinels, etc.
+ FSTParseContext *context =
+ [FSTParseContext contextWithSource:FSTUserDataSourceArgument
+ path:absl::make_unique<FieldPath>(FieldPath::EmptyPath())];
+ FSTFieldValue *parsedElement = [self parseData:element context:context];
+ FSTAssert(parsedElement && context.fieldTransforms->size() == 0,
+ @"Failed to properly parse array transform element: %@", element);
+ results.push_back(parsedElement);
+ }
+ return results;
+}
+
@end
NS_ASSUME_NONNULL_END
diff --git a/Firestore/Source/Core/FSTFirestoreClient.mm b/Firestore/Source/Core/FSTFirestoreClient.mm
index c0d38ca..33d1903 100644
--- a/Firestore/Source/Core/FSTFirestoreClient.mm
+++ b/Firestore/Source/Core/FSTFirestoreClient.mm
@@ -16,7 +16,8 @@
#import "Firestore/Source/Core/FSTFirestoreClient.h"
-#import <future>
+#include <future> // NOLINT(build/c++11)
+#include <memory>
#import "Firestore/Source/Core/FSTEventManager.h"
#import "Firestore/Source/Core/FSTSyncEngine.h"
diff --git a/Firestore/Source/Core/FSTListenSequence.mm b/Firestore/Source/Core/FSTListenSequence.mm
index 6f50d35..6a9f9ae 100644
--- a/Firestore/Source/Core/FSTListenSequence.mm
+++ b/Firestore/Source/Core/FSTListenSequence.mm
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#import "FSTListenSequence.h"
+#import "Firestore/Source/Core/FSTListenSequence.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Source/Core/FSTQuery.mm b/Firestore/Source/Core/FSTQuery.mm
index 811ad03..8f49c26 100644
--- a/Firestore/Source/Core/FSTQuery.mm
+++ b/Firestore/Source/Core/FSTQuery.mm
@@ -17,6 +17,7 @@
#import "Firestore/Source/Core/FSTQuery.h"
#include <memory>
+#include <string>
#include <utility>
#import "Firestore/Source/API/FIRFirestore+Internal.h"
diff --git a/Firestore/Source/Core/FSTSyncEngine.mm b/Firestore/Source/Core/FSTSyncEngine.mm
index 673991c..0a4fc94 100644
--- a/Firestore/Source/Core/FSTSyncEngine.mm
+++ b/Firestore/Source/Core/FSTSyncEngine.mm
@@ -16,11 +16,12 @@
#import "Firestore/Source/Core/FSTSyncEngine.h"
+#import <GRPCClient/GRPCCall.h>
+
#include <map>
+#include <set>
#include <unordered_map>
-#import <GRPCClient/GRPCCall.h>
-
#import "FIRFirestoreErrors.h"
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Core/FSTSnapshotVersion.h"
diff --git a/Firestore/Source/Core/FSTTransaction.h b/Firestore/Source/Core/FSTTransaction.h
index 676ada9..581a5fa 100644
--- a/Firestore/Source/Core/FSTTransaction.h
+++ b/Firestore/Source/Core/FSTTransaction.h
@@ -24,8 +24,6 @@
@class FIRSetOptions;
@class FSTDatastore;
-@class FSTFieldMask;
-@class FSTFieldTransform;
@class FSTMaybeDocument;
@class FSTObjectValue;
@class FSTParsedSetData;
diff --git a/Firestore/Source/Core/FSTTransaction.mm b/Firestore/Source/Core/FSTTransaction.mm
index 9e67ed4..681f9ca 100644
--- a/Firestore/Source/Core/FSTTransaction.mm
+++ b/Firestore/Source/Core/FSTTransaction.mm
@@ -16,11 +16,11 @@
#import "Firestore/Source/Core/FSTTransaction.h"
+#import <GRPCClient/GRPCCall.h>
+
#include <map>
#include <vector>
-#import <GRPCClient/GRPCCall.h>
-
#import "FIRFirestoreErrors.h"
#import "FIRSetOptions.h"
#import "Firestore/Source/API/FSTUserDataConverter.h"
@@ -33,8 +33,10 @@
#import "Firestore/Source/Util/FSTUsageValidation.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
using firebase::firestore::model::DocumentKey;
+using firebase::firestore::model::Precondition;
NS_ASSUME_NONNULL_BEGIN
@@ -136,25 +138,26 @@ NS_ASSUME_NONNULL_BEGIN
* Returns version of this doc when it was read in this transaction as a precondition, or no
* precondition if it was not read.
*/
-- (FSTPrecondition *)preconditionForDocumentKey:(const DocumentKey &)key {
+- (Precondition)preconditionForDocumentKey:(const DocumentKey &)key {
const auto iter = _readVersions.find(key);
if (iter == _readVersions.end()) {
- return [FSTPrecondition none];
+ return Precondition::None();
} else {
- return [FSTPrecondition preconditionWithUpdateTime:iter->second];
+ return Precondition::UpdateTime(iter->second);
}
}
/**
* Returns the precondition for a document if the operation is an update, based on the provided
- * UpdateOptions. Will return nil if an error occurred, in which case it sets the error parameter.
+ * UpdateOptions. Will return none precondition if an error occurred, in which case it sets the
+ * error parameter.
*/
-- (nullable FSTPrecondition *)preconditionForUpdateWithDocumentKey:(const DocumentKey &)key
- error:(NSError **)error {
+- (Precondition)preconditionForUpdateWithDocumentKey:(const DocumentKey &)key
+ error:(NSError **)error {
const auto iter = _readVersions.find(key);
if (iter == _readVersions.end()) {
// Document was not read, so we just use the preconditions for an update.
- return [FSTPrecondition preconditionWithExists:YES];
+ return Precondition::Exists(true);
}
FSTSnapshotVersion *version = iter->second;
@@ -169,10 +172,10 @@ NS_ASSUME_NONNULL_BEGIN
NSLocalizedDescriptionKey : @"Can't update a document that doesn't exist."
}];
}
- return nil;
+ return Precondition::None();
} else {
// Document exists, just base precondition on document update time.
- return [FSTPrecondition preconditionWithUpdateTime:version];
+ return Precondition::UpdateTime(version);
}
}
@@ -183,13 +186,12 @@ NS_ASSUME_NONNULL_BEGIN
- (void)updateData:(FSTParsedUpdateData *)data forDocument:(const DocumentKey &)key {
NSError *error = nil;
- FSTPrecondition *_Nullable precondition =
- [self preconditionForUpdateWithDocumentKey:key error:&error];
- if (precondition) {
- [self writeMutations:[data mutationsWithKey:key precondition:precondition]];
- } else {
+ const Precondition precondition = [self preconditionForUpdateWithDocumentKey:key error:&error];
+ if (precondition.IsNone()) {
FSTAssert(error, @"Got nil precondition, but error was not set");
self.lastWriteError = error;
+ } else {
+ [self writeMutations:[data mutationsWithKey:key precondition:precondition]];
}
}
@@ -198,7 +200,7 @@ NS_ASSUME_NONNULL_BEGIN
initWithKey:key
precondition:[self preconditionForDocumentKey:key]] ]];
// Since the delete will be applied before all following writes, we need to ensure that the
- // precondition for the next write will be exists: false.
+ // precondition for the next write will be exists without timestamp.
_readVersions[key] = [FSTSnapshotVersion noVersion];
}
diff --git a/Firestore/Source/Local/FSTLevelDB.mm b/Firestore/Source/Local/FSTLevelDB.mm
index 4812228..fae85e7 100644
--- a/Firestore/Source/Local/FSTLevelDB.mm
+++ b/Firestore/Source/Local/FSTLevelDB.mm
@@ -16,7 +16,7 @@
#import "Firestore/Source/Local/FSTLevelDB.h"
-#include <leveldb/db.h>
+#include <memory>
#import "FIRFirestoreErrors.h"
#import "Firestore/Source/Local/FSTLevelDBMigrations.h"
@@ -26,13 +26,14 @@
#import "Firestore/Source/Remote/FSTSerializerBeta.h"
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTLogger.h"
-#include "absl/memory/memory.h"
#include "Firestore/core/src/firebase/firestore/auth/user.h"
#include "Firestore/core/src/firebase/firestore/core/database_info.h"
#include "Firestore/core/src/firebase/firestore/local/leveldb_transaction.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+#include "absl/memory/memory.h"
+#include "leveldb/db.h"
namespace util = firebase::firestore::util;
using firebase::firestore::auth::User;
diff --git a/Firestore/Source/Local/FSTLevelDBKey.h b/Firestore/Source/Local/FSTLevelDBKey.h
index c7a64ee..5b234ec 100644
--- a/Firestore/Source/Local/FSTLevelDBKey.h
+++ b/Firestore/Source/Local/FSTLevelDBKey.h
@@ -16,6 +16,8 @@
#import <Foundation/Foundation.h>
+#include <string>
+
#import "Firestore/Source/Core/FSTTypes.h"
#import "Firestore/Source/Local/StringView.h"
diff --git a/Firestore/Source/Local/FSTLevelDBMigrations.mm b/Firestore/Source/Local/FSTLevelDBMigrations.mm
index cf06c9f..fefd0f7 100644
--- a/Firestore/Source/Local/FSTLevelDBMigrations.mm
+++ b/Firestore/Source/Local/FSTLevelDBMigrations.mm
@@ -14,16 +14,18 @@
* limitations under the License.
*/
-#include "Firestore/Source/Local/FSTLevelDBMigrations.h"
+#import "Firestore/Source/Local/FSTLevelDBMigrations.h"
-#include <absl/strings/match.h>
-#include "leveldb/write_batch.h"
+#include <string>
#import "Firestore/Protos/objc/firestore/local/Target.pbobjc.h"
#import "Firestore/Source/Local/FSTLevelDBKey.h"
#import "Firestore/Source/Local/FSTLevelDBQueryCache.h"
#import "Firestore/Source/Util/FSTAssert.h"
+#include "absl/strings/match.h"
+#include "leveldb/write_batch.h"
+
NS_ASSUME_NONNULL_BEGIN
// Current version of the schema defined in this file.
diff --git a/Firestore/Source/Local/FSTLevelDBMutationQueue.mm b/Firestore/Source/Local/FSTLevelDBMutationQueue.mm
index 29acead..75c3cf6 100644
--- a/Firestore/Source/Local/FSTLevelDBMutationQueue.mm
+++ b/Firestore/Source/Local/FSTLevelDBMutationQueue.mm
@@ -16,13 +16,10 @@
#import "Firestore/Source/Local/FSTLevelDBMutationQueue.h"
+#include <memory>
#include <set>
#include <string>
-#include <absl/strings/match.h>
-#include <leveldb/db.h>
-#include <leveldb/write_batch.h>
-
#import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h"
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Local/FSTLevelDB.h"
@@ -38,6 +35,9 @@
#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"
+#include "absl/strings/match.h"
+#include "leveldb/db.h"
+#include "leveldb/write_batch.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Source/Local/FSTLevelDBQueryCache.mm b/Firestore/Source/Local/FSTLevelDBQueryCache.mm
index aa1ab41..5fde7d7 100644
--- a/Firestore/Source/Local/FSTLevelDBQueryCache.mm
+++ b/Firestore/Source/Local/FSTLevelDBQueryCache.mm
@@ -16,6 +16,9 @@
#import "Firestore/Source/Local/FSTLevelDBQueryCache.h"
+#include <memory>
+#include <string>
+
#import "Firestore/Protos/objc/firestore/local/Target.pbobjc.h"
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Local/FSTLevelDB.h"
@@ -23,9 +26,9 @@
#import "Firestore/Source/Local/FSTLocalSerializer.h"
#import "Firestore/Source/Local/FSTQueryData.h"
#import "Firestore/Source/Util/FSTAssert.h"
-#include "absl/strings/match.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "absl/strings/match.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm b/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm
index 703fc69..f655e3a 100644
--- a/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm
+++ b/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm
@@ -16,8 +16,6 @@
#import "Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.h"
-#include <leveldb/db.h>
-#include <leveldb/write_batch.h>
#include <string>
#import "Firestore/Protos/objc/firestore/local/MaybeDocument.pbobjc.h"
@@ -29,8 +27,11 @@
#import "Firestore/Source/Model/FSTDocumentDictionary.h"
#import "Firestore/Source/Model/FSTDocumentSet.h"
#import "Firestore/Source/Util/FSTAssert.h"
+
#include "Firestore/core/src/firebase/firestore/local/leveldb_transaction.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "leveldb/db.h"
+#include "leveldb/write_batch.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Source/Local/FSTLocalSerializer.mm b/Firestore/Source/Local/FSTLocalSerializer.mm
index 1d9455d..61e173a 100644
--- a/Firestore/Source/Local/FSTLocalSerializer.mm
+++ b/Firestore/Source/Local/FSTLocalSerializer.mm
@@ -16,7 +16,7 @@
#import "Firestore/Source/Local/FSTLocalSerializer.h"
-#include <inttypes.h>
+#include <cinttypes>
#import "Firestore/Protos/objc/firestore/local/MaybeDocument.pbobjc.h"
#import "Firestore/Protos/objc/firestore/local/Mutation.pbobjc.h"
diff --git a/Firestore/Source/Local/FSTLocalStore.mm b/Firestore/Source/Local/FSTLocalStore.mm
index 990e332..b5dfeec 100644
--- a/Firestore/Source/Local/FSTLocalStore.mm
+++ b/Firestore/Source/Local/FSTLocalStore.mm
@@ -16,6 +16,8 @@
#import "Firestore/Source/Local/FSTLocalStore.h"
+#include <set>
+
#import "FIRTimestamp.h"
#import "Firestore/Source/Core/FSTListenSequence.h"
#import "Firestore/Source/Core/FSTQuery.h"
diff --git a/Firestore/Source/Local/FSTNoOpGarbageCollector.mm b/Firestore/Source/Local/FSTNoOpGarbageCollector.mm
index 451cde2..421d283 100644
--- a/Firestore/Source/Local/FSTNoOpGarbageCollector.mm
+++ b/Firestore/Source/Local/FSTNoOpGarbageCollector.mm
@@ -16,6 +16,8 @@
#import "Firestore/Source/Local/FSTNoOpGarbageCollector.h"
+#include <set>
+
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
using firebase::firestore::model::DocumentKey;
diff --git a/Firestore/Source/Local/StringView.h b/Firestore/Source/Local/StringView.h
index 4e36cff..85afcaa 100644
--- a/Firestore/Source/Local/StringView.h
+++ b/Firestore/Source/Local/StringView.h
@@ -19,9 +19,10 @@
#import <Foundation/Foundation.h>
-#include <leveldb/slice.h>
#include <string>
+
#include "absl/strings/string_view.h"
+#include "leveldb/slice.h"
namespace Firestore {
@@ -43,7 +44,7 @@ class StringView {
// Creates a StringView from an NSString. When StringView is an argument type
// into which an NSString* is passed, the caller should ensure that the
// NSString is retained.
- StringView(NSString *str)
+ StringView(NSString *str) // NOLINT(runtime/explicit)
: data_([str UTF8String]), size_([str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) {
}
@@ -54,20 +55,24 @@ class StringView {
// Creates a StringView from the given char* pointer but computes the size
// with strlen. This is really only suitable for passing C string literals.
- StringView(const char *data) : data_(data), size_(strlen(data)) {
+ StringView(const char *data) // NOLINT(runtime/explicit)
+ : data_(data), size_(strlen(data)) {
}
// Creates a StringView from the given slice.
- StringView(leveldb::Slice slice) : data_(slice.data()), size_(slice.size()) {
+ StringView(leveldb::Slice slice) // NOLINT(runtime/explicit)
+ : data_(slice.data()), size_(slice.size()) {
}
// Creates a StringView from the absl::string_view.
- StringView(absl::string_view s) : data_(s.data()), size_(s.size()) {
+ StringView(absl::string_view s) // NOLINT(runtime/explicit)
+ : data_(s.data()), size_(s.size()) {
}
// Creates a StringView from the given std::string. The string must be an
// lvalue for the lifetime requirements to be satisfied.
- StringView(const std::string &str) : data_(str.data()), size_(str.size()) {
+ StringView(const std::string &str) // NOLINT(runtime/explicit)
+ : data_(str.data()), size_(str.size()) {
}
// Converts this StringView to a Slice, which is an equivalent (and more
diff --git a/Firestore/Source/Model/FSTDocumentKey.h b/Firestore/Source/Model/FSTDocumentKey.h
index dbcff2c..a403117 100644
--- a/Firestore/Source/Model/FSTDocumentKey.h
+++ b/Firestore/Source/Model/FSTDocumentKey.h
@@ -17,6 +17,7 @@
#import <Foundation/Foundation.h>
#include <initializer_list>
+#include <string>
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
diff --git a/Firestore/Source/Model/FSTDocumentKey.mm b/Firestore/Source/Model/FSTDocumentKey.mm
index cbe9c89..679d7a6 100644
--- a/Firestore/Source/Model/FSTDocumentKey.mm
+++ b/Firestore/Source/Model/FSTDocumentKey.mm
@@ -16,6 +16,7 @@
#import "Firestore/Source/Model/FSTDocumentKey.h"
+#include <string>
#include <utility>
#import "Firestore/Source/Core/FSTFirestoreClient.h"
diff --git a/Firestore/Source/Model/FSTFieldValue.mm b/Firestore/Source/Model/FSTFieldValue.mm
index 80bd11f..0d7c649 100644
--- a/Firestore/Source/Model/FSTFieldValue.mm
+++ b/Firestore/Source/Model/FSTFieldValue.mm
@@ -18,9 +18,6 @@
#import "FIRTimestamp.h"
-#include "Firestore/core/src/firebase/firestore/util/comparison.h"
-#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
-
#import "Firestore/Source/API/FIRGeoPoint+Internal.h"
#import "Firestore/Source/API/FIRSnapshotOptions+Internal.h"
#import "Firestore/Source/Model/FSTDocumentKey.h"
@@ -29,6 +26,7 @@
#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/comparison.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
namespace util = firebase::firestore::util;
diff --git a/Firestore/Source/Model/FSTMutation.h b/Firestore/Source/Model/FSTMutation.h
index 4e4357d..7261f30 100644
--- a/Firestore/Source/Model/FSTMutation.h
+++ b/Firestore/Source/Model/FSTMutation.h
@@ -16,10 +16,15 @@
#import <Foundation/Foundation.h>
+#include <memory>
#include <vector>
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/field_transform.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
+#include "Firestore/core/src/firebase/firestore/model/transform_operations.h"
@class FSTDocument;
@class FSTFieldValue;
@@ -30,94 +35,6 @@
NS_ASSUME_NONNULL_BEGIN
-#pragma mark - FSTFieldMask
-
-/**
- * Provides a set of fields that can be used to partially patch a document. FieldMask is used in
- * conjunction with ObjectValue.
- *
- * Examples:
- * foo - Overwrites foo entirely with the provided value. If foo is not present in the companion
- * ObjectValue, the field is deleted.
- * foo.bar - Overwrites only the field bar of the object foo. If foo is not an object, foo is
- * replaced with an object containing bar.
- */
-@interface FSTFieldMask : NSObject
-- (id)init __attribute__((unavailable("Use initWithFields:")));
-
-/**
- * Initializes the field mask with the given field paths. Caller is expected to either copy or
- * or release the array of fields.
- */
-- (instancetype)initWithFields:(std::vector<firebase::firestore::model::FieldPath>)fields
- NS_DESIGNATED_INITIALIZER;
-
-- (const std::vector<firebase::firestore::model::FieldPath> &)fields;
-@end
-
-#pragma mark - FSTFieldTransform
-
-/** Represents a transform within a TransformMutation. */
-@protocol FSTTransformOperation <NSObject>
-@end
-
-/** Transforms a value into a server-generated timestamp. */
-@interface FSTServerTimestampTransform : NSObject <FSTTransformOperation>
-+ (instancetype)serverTimestampTransform;
-@end
-
-/** A field path and the FSTTransformOperation to perform upon it. */
-@interface FSTFieldTransform : NSObject
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithPath:(firebase::firestore::model::FieldPath)path
- transform:(id<FSTTransformOperation>)transform NS_DESIGNATED_INITIALIZER;
-- (const firebase::firestore::model::FieldPath &)path;
-@property(nonatomic, strong, readonly) id<FSTTransformOperation> transform;
-@end
-
-#pragma mark - FSTPrecondition
-
-typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
- FSTPreconditionExistsNotSet,
- FSTPreconditionExistsYes,
- FSTPreconditionExistsNo,
-};
-
-/**
- * Encodes a precondition for a mutation. This follows the model that the backend accepts with the
- * special case of an explicit "empty" precondition (meaning no precondition).
- */
-@interface FSTPrecondition : NSObject
-
-/** Creates a new FSTPrecondition with an exists flag. */
-+ (FSTPrecondition *)preconditionWithExists:(BOOL)exists;
-
-/** Creates a new FSTPrecondition based on a time the document exists at. */
-+ (FSTPrecondition *)preconditionWithUpdateTime:(FSTSnapshotVersion *)updateTime;
-
-/** Returns a precondition representing no precondition. */
-+ (FSTPrecondition *)none;
-
-/**
- * Returns true if the preconditions is valid for the given document (or null if no document is
- * available).
- */
-- (BOOL)isValidForDocument:(FSTMaybeDocument *_Nullable)maybeDoc;
-
-/** Returns whether this Precondition represents no precondition. */
-- (BOOL)isNone;
-
-/** If set, preconditions a mutation based on the last updateTime. */
-@property(nonatomic, strong, readonly, nullable) FSTSnapshotVersion *updateTime;
-
-/**
- * If set, preconditions a mutation based on whether the document exists.
- * Uses FSTPreconditionExistsNotSet to mark as unset.
- */
-@property(nonatomic, assign, readonly) FSTPreconditionExists exists;
-
-@end
-
#pragma mark - FSTMutationResult
@interface FSTMutationResult : NSObject
@@ -132,7 +49,7 @@ typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
/**
* The resulting fields returned from the backend after a FSTTransformMutation has been committed.
- * Contains one FieldValue for each FSTFieldTransform that was in the mutation.
+ * Contains one FieldValue for each FieldTransform that was in the mutation.
*
* Will be nil if the mutation was not a FSTTransformMutation.
*/
@@ -156,7 +73,8 @@ typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
- (id)init NS_UNAVAILABLE;
- (instancetype)initWithKey:(firebase::firestore::model::DocumentKey)key
- precondition:(FSTPrecondition *)precondition NS_DESIGNATED_INITIALIZER;
+ precondition:(firebase::firestore::model::Precondition)precondition
+ NS_DESIGNATED_INITIALIZER;
/**
* Applies this mutation to the given FSTDocument, FSTDeletedDocument or nil, if we don't have
@@ -217,8 +135,7 @@ typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
- (const firebase::firestore::model::DocumentKey &)key;
-/** The precondition for this mutation. */
-@property(nonatomic, strong, readonly) FSTPrecondition *precondition;
+- (const firebase::firestore::model::Precondition &)precondition;
@end
@@ -231,7 +148,7 @@ typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
@interface FSTSetMutation : FSTMutation
- (instancetype)initWithKey:(firebase::firestore::model::DocumentKey)key
- precondition:(FSTPrecondition *)precondition NS_UNAVAILABLE;
+ precondition:(firebase::firestore::model::Precondition)precondition NS_UNAVAILABLE;
/**
* Initializes the set mutation.
@@ -243,7 +160,8 @@ typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
*/
- (instancetype)initWithKey:(firebase::firestore::model::DocumentKey)key
value:(FSTObjectValue *)value
- precondition:(FSTPrecondition *)precondition NS_DESIGNATED_INITIALIZER;
+ precondition:(firebase::firestore::model::Precondition)precondition
+ NS_DESIGNATED_INITIALIZER;
/** The object value to use when setting the document. */
@property(nonatomic, strong, readonly) FSTObjectValue *value;
@@ -262,12 +180,12 @@ typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
*/
@interface FSTPatchMutation : FSTMutation
-/** Returns the precondition for the given FSTPrecondition. */
+/** Returns the precondition for the given Precondition. */
- (instancetype)initWithKey:(firebase::firestore::model::DocumentKey)key
- precondition:(FSTPrecondition *)precondition NS_UNAVAILABLE;
+ precondition:(firebase::firestore::model::Precondition)precondition NS_UNAVAILABLE;
/**
- * Initializes a new patch mutation with an explicit FSTFieldMask and FSTObjectValue representing
+ * Initializes a new patch mutation with an explicit FieldMask and FSTObjectValue representing
* the updates to perform
*
* @param key Identifies the location of the document to mutate.
@@ -278,18 +196,19 @@ typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
* @param precondition The precondition for this mutation.
*/
- (instancetype)initWithKey:(firebase::firestore::model::DocumentKey)key
- fieldMask:(FSTFieldMask *)fieldMask
+ fieldMask:(firebase::firestore::model::FieldMask)fieldMask
value:(FSTObjectValue *)value
- precondition:(FSTPrecondition *)precondition NS_DESIGNATED_INITIALIZER;
-
-/** The fields and associated values to use when patching the document. */
-@property(nonatomic, strong, readonly) FSTObjectValue *value;
+ precondition:(firebase::firestore::model::Precondition)precondition
+ NS_DESIGNATED_INITIALIZER;
/**
* A mask to apply to |value|, where only fields that are in both the fieldMask and the value
* will be updated.
*/
-@property(nonatomic, strong, readonly) FSTFieldMask *fieldMask;
+- (const firebase::firestore::model::FieldMask &)fieldMask;
+
+/** The fields and associated values to use when patching the document. */
+@property(nonatomic, strong, readonly) FSTObjectValue *value;
@end
@@ -307,20 +226,20 @@ typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
@interface FSTTransformMutation : FSTMutation
- (instancetype)initWithKey:(firebase::firestore::model::DocumentKey)key
- precondition:(FSTPrecondition *)precondition NS_UNAVAILABLE;
+ precondition:(firebase::firestore::model::Precondition)precondition NS_UNAVAILABLE;
/**
* Initializes a new transform mutation with the specified field transforms.
*
* @param key Identifies the location of the document to mutate.
- * @param fieldTransforms A list of FSTFieldTransform objects to perform to the document.
+ * @param fieldTransforms A list of FieldTransform objects to perform to the document.
*/
- (instancetype)initWithKey:(firebase::firestore::model::DocumentKey)key
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms
+ fieldTransforms:(std::vector<firebase::firestore::model::FieldTransform>)fieldTransforms
NS_DESIGNATED_INITIALIZER;
/** The field transforms to use when transforming the document. */
-@property(nonatomic, strong, readonly) NSArray<FSTFieldTransform *> *fieldTransforms;
+- (const std::vector<firebase::firestore::model::FieldTransform> &)fieldTransforms;
@end
diff --git a/Firestore/Source/Model/FSTMutation.mm b/Firestore/Source/Model/FSTMutation.mm
index 253a853..99d2e51 100644
--- a/Firestore/Source/Model/FSTMutation.mm
+++ b/Firestore/Source/Model/FSTMutation.mm
@@ -16,7 +16,10 @@
#import "Firestore/Source/Model/FSTMutation.h"
+#include <memory>
+#include <string>
#include <utility>
+#include <vector>
#import "FIRTimestamp.h"
@@ -27,211 +30,22 @@
#import "Firestore/Source/Util/FSTClasses.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/field_transform.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
+#include "Firestore/core/src/firebase/firestore/model/transform_operations.h"
using firebase::firestore::model::DocumentKey;
+using firebase::firestore::model::FieldMask;
using firebase::firestore::model::FieldPath;
+using firebase::firestore::model::FieldTransform;
+using firebase::firestore::model::Precondition;
+using firebase::firestore::model::ServerTimestampTransform;
+using firebase::firestore::model::TransformOperation;
NS_ASSUME_NONNULL_BEGIN
-#pragma mark - FSTFieldMask
-
-@implementation FSTFieldMask {
- std::vector<FieldPath> _fields;
-}
-
-- (instancetype)initWithFields:(std::vector<FieldPath>)fields {
- if (self = [super init]) {
- _fields = std::move(fields);
- }
- return self;
-}
-
-- (BOOL)isEqual:(id)other {
- if (other == self) {
- return YES;
- }
- if (![other isKindOfClass:[FSTFieldMask class]]) {
- return NO;
- }
-
- FSTFieldMask *otherMask = (FSTFieldMask *)other;
- return _fields == otherMask->_fields;
-}
-
-- (NSUInteger)hash {
- NSUInteger hashResult = 0;
- for (const FieldPath &field : _fields) {
- hashResult = hashResult * 31u + field.Hash();
- }
- return hashResult;
-}
-
-- (const std::vector<FieldPath> &)fields {
- return _fields;
-}
-@end
-
-#pragma mark - FSTServerTimestampTransform
-
-@implementation FSTServerTimestampTransform
-
-+ (instancetype)serverTimestampTransform {
- static FSTServerTimestampTransform *sharedInstance = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- sharedInstance = [[FSTServerTimestampTransform alloc] init];
- });
- return sharedInstance;
-}
-
-- (BOOL)isEqual:(id)other {
- if (other == self) {
- return YES;
- }
- return [other isKindOfClass:[FSTServerTimestampTransform class]];
-}
-
-- (NSUInteger)hash {
- // arbitrary number since all instances are equal.
- return 37;
-}
-
-@end
-
-#pragma mark - FSTFieldTransform
-
-@implementation FSTFieldTransform {
- FieldPath _path;
-}
-
-- (instancetype)initWithPath:(FieldPath)path transform:(id<FSTTransformOperation>)transform {
- self = [super init];
- if (self) {
- _path = std::move(path);
- _transform = transform;
- }
- return self;
-}
-
-- (BOOL)isEqual:(id)other {
- if (other == self) return YES;
- if (![[other class] isEqual:[self class]]) return NO;
- FSTFieldTransform *otherFieldTransform = other;
- return self.path == otherFieldTransform.path &&
- [self.transform isEqual:otherFieldTransform.transform];
-}
-
-- (NSUInteger)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
-
-@implementation FSTPrecondition
-
-+ (FSTPrecondition *)preconditionWithExists:(BOOL)exists {
- FSTPreconditionExists existsEnum = exists ? FSTPreconditionExistsYes : FSTPreconditionExistsNo;
- return [[FSTPrecondition alloc] initWithUpdateTime:nil exists:existsEnum];
-}
-
-+ (FSTPrecondition *)preconditionWithUpdateTime:(FSTSnapshotVersion *)updateTime {
- return [[FSTPrecondition alloc] initWithUpdateTime:updateTime exists:FSTPreconditionExistsNotSet];
-}
-
-+ (FSTPrecondition *)none {
- static dispatch_once_t onceToken;
- static FSTPrecondition *noPrecondition;
- dispatch_once(&onceToken, ^{
- noPrecondition =
- [[FSTPrecondition alloc] initWithUpdateTime:nil exists:FSTPreconditionExistsNotSet];
- });
- return noPrecondition;
-}
-
-- (instancetype)initWithUpdateTime:(FSTSnapshotVersion *_Nullable)updateTime
- exists:(FSTPreconditionExists)exists {
- if (self = [super init]) {
- _updateTime = updateTime;
- _exists = exists;
- }
- return self;
-}
-
-- (BOOL)isValidForDocument:(FSTMaybeDocument *_Nullable)maybeDoc {
- if (self.updateTime) {
- return
- [maybeDoc isKindOfClass:[FSTDocument class]] && [maybeDoc.version isEqual:self.updateTime];
- } else if (self.exists != FSTPreconditionExistsNotSet) {
- if (self.exists == FSTPreconditionExistsYes) {
- return [maybeDoc isKindOfClass:[FSTDocument class]];
- } else {
- FSTAssert(self.exists == FSTPreconditionExistsNo, @"Invalid precondition");
- return maybeDoc == nil || [maybeDoc isKindOfClass:[FSTDeletedDocument class]];
- }
- } else {
- FSTAssert(self.isNone, @"Precondition should be empty");
- return YES;
- }
-}
-
-- (BOOL)isNone {
- return self.updateTime == nil && self.exists == FSTPreconditionExistsNotSet;
-}
-
-- (BOOL)isEqual:(id)other {
- if (self == other) {
- return YES;
- }
-
- if (![other isKindOfClass:[FSTPrecondition class]]) {
- return NO;
- }
-
- FSTPrecondition *otherPrecondition = (FSTPrecondition *)other;
- // Compare references to cover nil equality
- return (self.updateTime == otherPrecondition.updateTime ||
- [self.updateTime isEqual:otherPrecondition.updateTime]) &&
- self.exists == otherPrecondition.exists;
-}
-
-- (NSUInteger)hash {
- NSUInteger hash = [self.updateTime hash];
- hash = hash * 31 + self.exists;
- return hash;
-}
-
-- (NSString *)description {
- if (self.isNone) {
- return @"<FSTPrecondition <none>>";
- } else {
- NSString *existsString;
- switch (self.exists) {
- case FSTPreconditionExistsYes:
- existsString = @"yes";
- break;
- case FSTPreconditionExistsNo:
- existsString = @"no";
- break;
- default:
- existsString = @"<not-set>";
- break;
- }
- return [NSString stringWithFormat:@"<FSTPrecondition updateTime=%@ exists=%@>", self.updateTime,
- existsString];
- }
-}
-
-@end
-
#pragma mark - FSTMutationResult
@implementation FSTMutationResult
@@ -251,12 +65,13 @@ NS_ASSUME_NONNULL_BEGIN
@implementation FSTMutation {
DocumentKey _key;
+ Precondition _precondition;
}
-- (instancetype)initWithKey:(DocumentKey)key precondition:(FSTPrecondition *)precondition {
+- (instancetype)initWithKey:(DocumentKey)key precondition:(Precondition)precondition {
if (self = [super init]) {
_key = std::move(key);
- _precondition = precondition;
+ _precondition = std::move(precondition);
}
return self;
}
@@ -279,6 +94,10 @@ NS_ASSUME_NONNULL_BEGIN
return _key;
}
+- (const firebase::firestore::model::Precondition &)precondition {
+ return _precondition;
+}
+
@end
#pragma mark - FSTSetMutation
@@ -287,8 +106,8 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithKey:(DocumentKey)key
value:(FSTObjectValue *)value
- precondition:(FSTPrecondition *)precondition {
- if (self = [super initWithKey:std::move(key) precondition:precondition]) {
+ precondition:(Precondition)precondition {
+ if (self = [super initWithKey:std::move(key) precondition:std::move(precondition)]) {
_value = value;
}
return self;
@@ -296,7 +115,8 @@ NS_ASSUME_NONNULL_BEGIN
- (NSString *)description {
return [NSString stringWithFormat:@"<FSTSetMutation key=%s value=%@ precondition=%@>",
- self.key.ToString().c_str(), self.value, self.precondition];
+ self.key.ToString().c_str(), self.value,
+ self.precondition.description()];
}
- (BOOL)isEqual:(id)other {
@@ -309,12 +129,12 @@ NS_ASSUME_NONNULL_BEGIN
FSTSetMutation *otherMutation = (FSTSetMutation *)other;
return [self.key isEqual:otherMutation.key] && [self.value isEqual:otherMutation.value] &&
- [self.precondition isEqual:otherMutation.precondition];
+ self.precondition == otherMutation.precondition;
}
- (NSUInteger)hash {
NSUInteger result = [self.key hash];
- result = 31 * result + [self.precondition hash];
+ result = 31 * result + self.precondition.Hash();
result = 31 * result + [self.value hash];
return result;
}
@@ -327,7 +147,7 @@ NS_ASSUME_NONNULL_BEGIN
FSTAssert(!mutationResult.transformResults, @"Transform results received by FSTSetMutation.");
}
- if (![self.precondition isValidForDocument:maybeDoc]) {
+ if (!self.precondition.IsValidFor(maybeDoc)) {
return maybeDoc;
}
@@ -354,20 +174,26 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - FSTPatchMutation
-@implementation FSTPatchMutation
+@implementation FSTPatchMutation {
+ FieldMask _fieldMask;
+}
- (instancetype)initWithKey:(DocumentKey)key
- fieldMask:(FSTFieldMask *)fieldMask
+ fieldMask:(FieldMask)fieldMask
value:(FSTObjectValue *)value
- precondition:(FSTPrecondition *)precondition {
- self = [super initWithKey:std::move(key) precondition:precondition];
+ precondition:(Precondition)precondition {
+ self = [super initWithKey:std::move(key) precondition:std::move(precondition)];
if (self) {
- _fieldMask = fieldMask;
+ _fieldMask = std::move(fieldMask);
_value = value;
}
return self;
}
+- (const firebase::firestore::model::FieldMask &)fieldMask {
+ return _fieldMask;
+}
+
- (BOOL)isEqual:(id)other {
if (other == self) {
return YES;
@@ -377,23 +203,23 @@ NS_ASSUME_NONNULL_BEGIN
}
FSTPatchMutation *otherMutation = (FSTPatchMutation *)other;
- return [self.key isEqual:otherMutation.key] && [self.fieldMask isEqual:otherMutation.fieldMask] &&
+ return [self.key isEqual:otherMutation.key] && self.fieldMask == otherMutation.fieldMask &&
[self.value isEqual:otherMutation.value] &&
- [self.precondition isEqual:otherMutation.precondition];
+ self.precondition == otherMutation.precondition;
}
- (NSUInteger)hash {
NSUInteger result = [self.key hash];
- result = 31 * result + [self.precondition hash];
- result = 31 * result + [self.fieldMask hash];
+ result = 31 * result + self.precondition.Hash();
+ result = 31 * result + self.fieldMask.Hash();
result = 31 * result + [self.value hash];
return result;
}
- (NSString *)description {
- return [NSString stringWithFormat:@"<FSTPatchMutation key=%s mask=%@ value=%@ precondition=%@>",
- self.key.ToString().c_str(), self.fieldMask, self.value,
- self.precondition];
+ return [NSString stringWithFormat:@"<FSTPatchMutation key=%s mask=%s value=%@ precondition=%@>",
+ self.key.ToString().c_str(), self.fieldMask.ToString().c_str(),
+ self.value, self.precondition.description()];
}
- (nullable FSTMaybeDocument *)applyTo:(nullable FSTMaybeDocument *)maybeDoc
@@ -404,7 +230,7 @@ NS_ASSUME_NONNULL_BEGIN
FSTAssert(!mutationResult.transformResults, @"Transform results received by FSTPatchMutation.");
}
- if (![self.precondition isValidForDocument:maybeDoc]) {
+ if (!self.precondition.IsValidFor(maybeDoc)) {
return maybeDoc;
}
@@ -434,7 +260,7 @@ NS_ASSUME_NONNULL_BEGIN
- (FSTObjectValue *)patchObjectValue:(FSTObjectValue *)objectValue {
FSTObjectValue *result = objectValue;
- for (const FieldPath &fieldPath : self.fieldMask.fields) {
+ for (const FieldPath &fieldPath : self.fieldMask) {
FSTFieldValue *newValue = [self.value valueForPath:fieldPath];
if (newValue) {
result = [result objectBySettingValue:newValue forPath:fieldPath];
@@ -447,20 +273,26 @@ NS_ASSUME_NONNULL_BEGIN
@end
-@implementation FSTTransformMutation
+@implementation FSTTransformMutation {
+ /** The field transforms to use when transforming the document. */
+ std::vector<FieldTransform> _fieldTransforms;
+}
- (instancetype)initWithKey:(DocumentKey)key
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms {
+ fieldTransforms:(std::vector<FieldTransform>)fieldTransforms {
// NOTE: We set a precondition of exists: true as a safety-check, since we always combine
// FSTTransformMutations with a FSTSetMutation or FSTPatchMutation which (if successful) should
// end up with an existing document.
- if (self = [super initWithKey:std::move(key)
- precondition:[FSTPrecondition preconditionWithExists:YES]]) {
- _fieldTransforms = fieldTransforms;
+ if (self = [super initWithKey:std::move(key) precondition:Precondition::Exists(true)]) {
+ _fieldTransforms = std::move(fieldTransforms);
}
return self;
}
+- (const std::vector<FieldTransform> &)fieldTransforms {
+ return _fieldTransforms;
+}
+
- (BOOL)isEqual:(id)other {
if (other == self) {
return YES;
@@ -471,21 +303,27 @@ NS_ASSUME_NONNULL_BEGIN
FSTTransformMutation *otherMutation = (FSTTransformMutation *)other;
return [self.key isEqual:otherMutation.key] &&
- [self.fieldTransforms isEqual:otherMutation.fieldTransforms] &&
- [self.precondition isEqual:otherMutation.precondition];
+ self.fieldTransforms == otherMutation.fieldTransforms &&
+ self.precondition == otherMutation.precondition;
}
- (NSUInteger)hash {
NSUInteger result = [self.key hash];
- result = 31 * result + [self.precondition hash];
- result = 31 * result + [self.fieldTransforms hash];
+ result = 31 * result + self.precondition.Hash();
+ for (const auto &transform : self.fieldTransforms) {
+ result = 31 * result + transform.Hash();
+ }
return result;
}
- (NSString *)description {
- return [NSString stringWithFormat:@"<FSTTransformMutation key=%s transforms=%@ precondition=%@>",
- self.key.ToString().c_str(), self.fieldTransforms,
- self.precondition];
+ std::string fieldTransforms;
+ for (const auto &transform : self.fieldTransforms) {
+ fieldTransforms += " " + transform.path().CanonicalString();
+ }
+ return [NSString stringWithFormat:@"<FSTTransformMutation key=%s transforms=%s precondition=%@>",
+ self.key.ToString().c_str(), fieldTransforms.c_str(),
+ self.precondition.description()];
}
- (nullable FSTMaybeDocument *)applyTo:(nullable FSTMaybeDocument *)maybeDoc
@@ -497,7 +335,7 @@ NS_ASSUME_NONNULL_BEGIN
@"Transform results missing for FSTTransformMutation.");
}
- if (![self.precondition isValidForDocument:maybeDoc]) {
+ if (!self.precondition.IsValidFor(maybeDoc)) {
return maybeDoc;
}
@@ -534,19 +372,19 @@ NS_ASSUME_NONNULL_BEGIN
(FSTMaybeDocument *_Nullable)baseDocument
writeTime:(FIRTimestamp *)localWriteTime {
NSMutableArray<FSTFieldValue *> *transformResults = [NSMutableArray array];
- for (FSTFieldTransform *fieldTransform in self.fieldTransforms) {
- if ([fieldTransform.transform isKindOfClass:[FSTServerTimestampTransform class]]) {
+ for (const FieldTransform &fieldTransform : self.fieldTransforms) {
+ if (fieldTransform.transformation().type() == TransformOperation::Type::ServerTimestamp) {
FSTFieldValue *previousValue = nil;
if ([baseDocument isMemberOfClass:[FSTDocument class]]) {
- previousValue = [((FSTDocument *)baseDocument) fieldForPath:fieldTransform.path];
+ previousValue = [((FSTDocument *)baseDocument) fieldForPath:fieldTransform.path()];
}
[transformResults
addObject:[FSTServerTimestampValue serverTimestampValueWithLocalWriteTime:localWriteTime
previousValue:previousValue]];
} else {
- FSTFail(@"Encountered unknown transform: %@", fieldTransform);
+ FSTFail(@"Encountered unknown transform: %d type", fieldTransform.transformation().type());
}
}
return transformResults;
@@ -554,17 +392,17 @@ NS_ASSUME_NONNULL_BEGIN
- (FSTObjectValue *)transformObject:(FSTObjectValue *)objectValue
transformResults:(NSArray<FSTFieldValue *> *)transformResults {
- FSTAssert(transformResults.count == self.fieldTransforms.count,
+ FSTAssert(transformResults.count == self.fieldTransforms.size(),
@"Transform results length mismatch.");
- for (NSUInteger i = 0; i < self.fieldTransforms.count; i++) {
- FSTFieldTransform *fieldTransform = self.fieldTransforms[i];
- id<FSTTransformOperation> transform = fieldTransform.transform;
- FieldPath fieldPath = fieldTransform.path;
- if ([transform isKindOfClass:[FSTServerTimestampTransform class]]) {
+ for (size_t i = 0; i < self.fieldTransforms.size(); i++) {
+ const FieldTransform &fieldTransform = self.fieldTransforms[i];
+ const TransformOperation &transform = fieldTransform.transformation();
+ const FieldPath &fieldPath = fieldTransform.path();
+ if (transform.type() == TransformOperation::Type::ServerTimestamp) {
objectValue = [objectValue objectBySettingValue:transformResults[i] forPath:fieldPath];
} else {
- FSTFail(@"Encountered unknown transform: %@", transform);
+ FSTFail(@"Encountered unknown transform: %d type", transform.type());
}
}
return objectValue;
@@ -585,19 +423,18 @@ NS_ASSUME_NONNULL_BEGIN
}
FSTDeleteMutation *otherMutation = (FSTDeleteMutation *)other;
- return [self.key isEqual:otherMutation.key] &&
- [self.precondition isEqual:otherMutation.precondition];
+ return [self.key isEqual:otherMutation.key] && self.precondition == otherMutation.precondition;
}
- (NSUInteger)hash {
NSUInteger result = [self.key hash];
- result = 31 * result + [self.precondition hash];
+ result = 31 * result + self.precondition.Hash();
return result;
}
- (NSString *)description {
return [NSString stringWithFormat:@"<FSTDeleteMutation key=%s precondition=%@>",
- self.key.ToString().c_str(), self.precondition];
+ self.key.ToString().c_str(), self.precondition.description()];
}
- (nullable FSTMaybeDocument *)applyTo:(nullable FSTMaybeDocument *)maybeDoc
@@ -609,7 +446,7 @@ NS_ASSUME_NONNULL_BEGIN
@"Transform results received by FSTDeleteMutation.");
}
- if (![self.precondition isValidForDocument:maybeDoc]) {
+ if (!self.precondition.IsValidFor(maybeDoc)) {
return maybeDoc;
}
diff --git a/Firestore/Source/Public/FIRFieldValue.h b/Firestore/Source/Public/FIRFieldValue.h
index 11a0da0..d896587 100644
--- a/Firestore/Source/Public/FIRFieldValue.h
+++ b/Firestore/Source/Public/FIRFieldValue.h
@@ -38,6 +38,29 @@ NS_SWIFT_NAME(FieldValue)
*/
+ (instancetype)fieldValueForServerTimestamp NS_SWIFT_NAME(serverTimestamp());
+/**
+ * Returns a special value that can be used with setData() or updateData() that tells the server to
+ * union the given elements with any array value that already exists on the server. Each
+ * specified element that doesn't already exist in the array will be added to the end. If the
+ * field being modified is not already an array it will be overwritten with an array containing
+ * exactly the specified elements.
+ *
+ * @param elements The elements to union into the array.
+ * @return The FieldValue sentinel for use in a call to setData() or updateData().
+ */
++ (instancetype)fieldValueForArrayUnion:(NSArray<id> *)elements NS_SWIFT_NAME(arrayUnion(_:));
+
+/**
+ * Returns a special value that can be used with setData() or updateData() that tells the server to
+ * remove the given elements from any array value that already exists on the server. All
+ * instances of each element specified will be removed from the array. If the field being
+ * modified is not already an array it will be overwritten with an empty array.
+ *
+ * @param elements The elements to remove from the array.
+ * @return The FieldValue sentinel for use in a call to setData() or updateData().
+ */
++ (instancetype)fieldValueForArrayRemove:(NSArray<id> *)elements NS_SWIFT_NAME(arrayRemove(_:));
+
@end
NS_ASSUME_NONNULL_END
diff --git a/Firestore/Source/Remote/FSTDatastore.mm b/Firestore/Source/Remote/FSTDatastore.mm
index 501237f..c7ee30f 100644
--- a/Firestore/Source/Remote/FSTDatastore.mm
+++ b/Firestore/Source/Remote/FSTDatastore.mm
@@ -16,12 +16,13 @@
#import "Firestore/Source/Remote/FSTDatastore.h"
-#include <memory>
-#include <vector>
-
#import <GRPCClient/GRPCCall+OAuth2.h>
#import <ProtoRPC/ProtoRPC.h>
+#include <map>
+#include <memory>
+#include <vector>
+
#import "FIRFirestoreErrors.h"
#import "Firestore/Source/API/FIRFirestore+Internal.h"
#import "Firestore/Source/API/FIRFirestoreVersion.h"
@@ -258,12 +259,10 @@ typedef GRPCProtoCall * (^RPCFactory)(void);
}
struct Closure {
- std::vector<DocumentKey> keys;
- FSTMaybeDocumentDictionary *results;
+ std::map<DocumentKey, FSTMaybeDocument *> results;
};
- __block std::shared_ptr<Closure> closure = std::make_shared<Closure>(
- Closure{keys, [FSTMaybeDocumentDictionary maybeDocumentDictionary]});
+ __block std::shared_ptr<Closure> closure = std::make_shared<Closure>(Closure{});
RPCFactory rpcFactory = ^GRPCProtoCall * {
__block GRPCProtoCall *rpc = [self.service
RPCToBatchGetDocumentsWithRequest:request
@@ -283,19 +282,17 @@ typedef GRPCProtoCall * (^RPCFactory)(void);
// Streaming response, accumulate result
FSTMaybeDocument *doc =
[self.serializer decodedMaybeDocumentFromBatch:response];
- closure->results =
- [closure->results dictionaryBySettingObject:doc
- forKey:doc.key];
+ closure->results.insert({doc.key, doc});
} else {
// Streaming response is done, call completion
FSTLog(@"RPC BatchGetDocuments completed successfully.");
[FSTDatastore logHeadersForRPC:rpc RPCName:@"BatchGetDocuments"];
FSTAssert(!response, @"Got response after done.");
NSMutableArray<FSTMaybeDocument *> *docs =
- [NSMutableArray arrayWithCapacity:closure->keys.size()];
- for (const DocumentKey &key : closure->keys) {
- [docs addObject:closure->results[static_cast<FSTDocumentKey *>(
- key)]];
+ [NSMutableArray arrayWithCapacity:closure->results.size()];
+ for (auto &&entry : closure->results) {
+ FSTMaybeDocument *doc = entry.second;
+ [docs addObject:doc];
}
completion(docs, nil);
}
diff --git a/Firestore/Source/Remote/FSTRemoteStore.mm b/Firestore/Source/Remote/FSTRemoteStore.mm
index 8892ffb..39d285a 100644
--- a/Firestore/Source/Remote/FSTRemoteStore.mm
+++ b/Firestore/Source/Remote/FSTRemoteStore.mm
@@ -16,7 +16,7 @@
#import "Firestore/Source/Remote/FSTRemoteStore.h"
-#include <inttypes.h>
+#include <cinttypes>
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Core/FSTSnapshotVersion.h"
diff --git a/Firestore/Source/Remote/FSTSerializerBeta.mm b/Firestore/Source/Remote/FSTSerializerBeta.mm
index 3a22a3f..c8b0fa4 100644
--- a/Firestore/Source/Remote/FSTSerializerBeta.mm
+++ b/Firestore/Source/Remote/FSTSerializerBeta.mm
@@ -16,10 +16,12 @@
#import "Firestore/Source/Remote/FSTSerializerBeta.h"
-#include <inttypes.h>
-
#import <GRPCClient/GRPCCall.h>
-#import "FIRTimestamp.h"
+
+#include <cinttypes>
+#include <string>
+#include <utility>
+#include <vector>
#import "Firestore/Protos/objc/google/firestore/v1beta1/Common.pbobjc.h"
#import "Firestore/Protos/objc/google/firestore/v1beta1/Document.pbobjc.h"
@@ -31,6 +33,7 @@
#import "FIRFirestoreErrors.h"
#import "FIRGeoPoint.h"
+#import "FIRTimestamp.h"
#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Core/FSTSnapshotVersion.h"
#import "Firestore/Source/Local/FSTQueryData.h"
@@ -44,15 +47,26 @@
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/field_transform.h"
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
+#include "Firestore/core/src/firebase/firestore/model/transform_operations.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::DocumentKey;
+using firebase::firestore::model::FieldMask;
using firebase::firestore::model::FieldPath;
+using firebase::firestore::model::FieldTransform;
+using firebase::firestore::model::Precondition;
using firebase::firestore::model::ResourcePath;
+using firebase::firestore::model::ServerTimestampTransform;
+using firebase::firestore::model::SnapshotVersion;
+using firebase::firestore::model::TransformOperation;
NS_ASSUME_NONNULL_BEGIN
@@ -464,7 +478,7 @@ NS_ASSUME_NONNULL_BEGIN
FSTFail(@"Unknown mutation type %@", NSStringFromClass(mutationClass));
}
- if (!mutation.precondition.isNone) {
+ if (!mutation.precondition.IsNone()) {
proto.currentDocument = [self encodedPrecondition:mutation.precondition];
}
@@ -472,9 +486,9 @@ NS_ASSUME_NONNULL_BEGIN
}
- (FSTMutation *)decodedMutation:(GCFSWrite *)mutation {
- FSTPrecondition *precondition = [mutation hasCurrentDocument]
- ? [self decodedPrecondition:mutation.currentDocument]
- : [FSTPrecondition none];
+ Precondition precondition = [mutation hasCurrentDocument]
+ ? [self decodedPrecondition:mutation.currentDocument]
+ : Precondition::None();
switch (mutation.operationOneOfCase) {
case GCFSWrite_Operation_OneOfCase_Update:
@@ -494,8 +508,7 @@ NS_ASSUME_NONNULL_BEGIN
precondition:precondition];
case GCFSWrite_Operation_OneOfCase_Transform: {
- FSTPreconditionExists exists = precondition.exists;
- FSTAssert(exists == FSTPreconditionExistsYes,
+ FSTAssert(precondition == Precondition::Exists(true),
@"Transforms must have precondition \"exists == true\"");
return [[FSTTransformMutation alloc]
@@ -509,79 +522,77 @@ NS_ASSUME_NONNULL_BEGIN
}
}
-- (GCFSPrecondition *)encodedPrecondition:(FSTPrecondition *)precondition {
- FSTAssert(!precondition.isNone, @"Can't serialize an empty precondition");
+- (GCFSPrecondition *)encodedPrecondition:(const Precondition &)precondition {
+ FSTAssert(!precondition.IsNone(), @"Can't serialize an empty precondition");
GCFSPrecondition *message = [GCFSPrecondition message];
- if (precondition.updateTime) {
- message.updateTime = [self encodedVersion:precondition.updateTime];
- } else if (precondition.exists != FSTPreconditionExistsNotSet) {
- message.exists = precondition.exists == FSTPreconditionExistsYes;
+ if (precondition.type() == Precondition::Type::UpdateTime) {
+ message.updateTime = [self encodedVersion:precondition.update_time()];
+ } else if (precondition.type() == Precondition::Type::Exists) {
+ message.exists = precondition == Precondition::Exists(true);
} else {
- FSTFail(@"Unknown precondition: %@", precondition);
+ FSTFail(@"Unknown precondition: %@", precondition.description());
}
return message;
}
-- (FSTPrecondition *)decodedPrecondition:(GCFSPrecondition *)precondition {
+- (Precondition)decodedPrecondition:(GCFSPrecondition *)precondition {
switch (precondition.conditionTypeOneOfCase) {
case GCFSPrecondition_ConditionType_OneOfCase_GPBUnsetOneOfCase:
- return [FSTPrecondition none];
+ return Precondition::None();
case GCFSPrecondition_ConditionType_OneOfCase_Exists:
- return [FSTPrecondition preconditionWithExists:precondition.exists];
+ return Precondition::Exists(precondition.exists);
case GCFSPrecondition_ConditionType_OneOfCase_UpdateTime:
- return [FSTPrecondition
- preconditionWithUpdateTime:[self decodedVersion:precondition.updateTime]];
+ return Precondition::UpdateTime([self decodedVersion:precondition.updateTime]);
default:
FSTFail(@"Unrecognized Precondition one-of case %@", precondition);
}
}
-- (GCFSDocumentMask *)encodedFieldMask:(FSTFieldMask *)fieldMask {
+- (GCFSDocumentMask *)encodedFieldMask:(const FieldMask &)fieldMask {
GCFSDocumentMask *mask = [GCFSDocumentMask message];
- for (const FieldPath &field : fieldMask.fields) {
+ for (const FieldPath &field : fieldMask) {
[mask.fieldPathsArray addObject:util::WrapNSString(field.CanonicalString())];
}
return mask;
}
-- (FSTFieldMask *)decodedFieldMask:(GCFSDocumentMask *)fieldMask {
- std::vector<FieldPath> fields{};
+- (FieldMask)decodedFieldMask:(GCFSDocumentMask *)fieldMask {
+ std::vector<FieldPath> fields;
fields.reserve(fieldMask.fieldPathsArray_Count);
for (NSString *path in fieldMask.fieldPathsArray) {
fields.push_back(FieldPath::FromServerFormat(util::MakeStringView(path)));
}
- return [[FSTFieldMask alloc] initWithFields:std::move(fields)];
+ return FieldMask(std::move(fields));
}
- (NSMutableArray<GCFSDocumentTransform_FieldTransform *> *)encodedFieldTransforms:
- (NSArray<FSTFieldTransform *> *)fieldTransforms {
+ (const std::vector<FieldTransform> &)fieldTransforms {
NSMutableArray *protos = [NSMutableArray array];
- for (FSTFieldTransform *fieldTransform in fieldTransforms) {
- FSTAssert([fieldTransform.transform isKindOfClass:[FSTServerTimestampTransform class]],
- @"Unknown transform: %@", fieldTransform.transform);
+ for (const FieldTransform &fieldTransform : fieldTransforms) {
+ FSTAssert(fieldTransform.transformation().type() == TransformOperation::Type::ServerTimestamp,
+ @"Unknown transform: %d type", fieldTransform.transformation().type());
GCFSDocumentTransform_FieldTransform *proto = [GCFSDocumentTransform_FieldTransform message];
- proto.fieldPath = util::WrapNSString(fieldTransform.path.CanonicalString());
+ proto.fieldPath = util::WrapNSString(fieldTransform.path().CanonicalString());
proto.setToServerValue = GCFSDocumentTransform_FieldTransform_ServerValue_RequestTime;
[protos addObject:proto];
}
return protos;
}
-- (NSArray<FSTFieldTransform *> *)decodedFieldTransforms:
+- (std::vector<FieldTransform>)decodedFieldTransforms:
(NSArray<GCFSDocumentTransform_FieldTransform *> *)protos {
- NSMutableArray<FSTFieldTransform *> *fieldTransforms = [NSMutableArray array];
+ std::vector<FieldTransform> fieldTransforms;
+ fieldTransforms.reserve(protos.count);
for (GCFSDocumentTransform_FieldTransform *proto in protos) {
FSTAssert(
proto.setToServerValue == GCFSDocumentTransform_FieldTransform_ServerValue_RequestTime,
@"Unknown transform setToServerValue: %d", proto.setToServerValue);
- [fieldTransforms
- addObject:[[FSTFieldTransform alloc]
- initWithPath:FieldPath::FromServerFormat(
- util::MakeStringView(proto.fieldPath))
- transform:[FSTServerTimestampTransform serverTimestampTransform]]];
+ fieldTransforms.emplace_back(
+ FieldPath::FromServerFormat(util::MakeStringView(proto.fieldPath)),
+ absl::make_unique<ServerTimestampTransform>(ServerTimestampTransform::Get()));
}
return fieldTransforms;
}
diff --git a/Firestore/Source/Remote/FSTStream.mm b/Firestore/Source/Remote/FSTStream.mm
index f65230b..a96feae 100644
--- a/Firestore/Source/Remote/FSTStream.mm
+++ b/Firestore/Source/Remote/FSTStream.mm
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#import "Firestore/Source/Remote/FSTDatastore.h"
-
#import <GRPCClient/GRPCCall+OAuth2.h>
#import <GRPCClient/GRPCCall.h>
@@ -24,6 +22,7 @@
#import "Firestore/Source/Local/FSTQueryData.h"
#import "Firestore/Source/Model/FSTMutation.h"
#import "Firestore/Source/Remote/FSTBufferedWriter.h"
+#import "Firestore/Source/Remote/FSTDatastore.h"
#import "Firestore/Source/Remote/FSTExponentialBackoff.h"
#import "Firestore/Source/Remote/FSTSerializerBeta.h"
#import "Firestore/Source/Remote/FSTStream.h"
diff --git a/Firestore/Source/Util/FSTAssert.h b/Firestore/Source/Util/FSTAssert.h
index 77bbb1d..610d306 100644
--- a/Firestore/Source/Util/FSTAssert.h
+++ b/Firestore/Source/Util/FSTAssert.h
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <Foundation/Foundation.h>
+#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Source/Util/FSTDispatchQueue.mm b/Firestore/Source/Util/FSTDispatchQueue.mm
index 15d6e7b..0974359 100644
--- a/Firestore/Source/Util/FSTDispatchQueue.mm
+++ b/Firestore/Source/Util/FSTDispatchQueue.mm
@@ -16,6 +16,8 @@
#import <Foundation/Foundation.h>
+#include <atomic>
+
#import "Firestore/Source/Util/FSTAssert.h"
#import "Firestore/Source/Util/FSTDispatchQueue.h"
@@ -146,24 +148,23 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - FSTDispatchQueue
@interface FSTDispatchQueue ()
-
/**
* Callbacks scheduled to be queued in the future. Callbacks are automatically removed after they
* are run or canceled.
*/
@property(nonatomic, strong, readonly) NSMutableArray<FSTDelayedCallback *> *delayedCallbacks;
-/**
- * Flag set while an FSTDispatchQueue operation is currently executing. Used for assertion
- * sanity-checks.
- */
-@property(nonatomic, assign) BOOL operationInProgress;
-
- (instancetype)initWithQueue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER;
@end
-@implementation FSTDispatchQueue
+@implementation FSTDispatchQueue {
+ /**
+ * Flag set while an FSTDispatchQueue operation is currently executing. Used for assertion
+ * sanity-checks.
+ */
+ std::atomic<bool> _operationInProgress;
+}
+ (instancetype)queueWith:(dispatch_queue_t)dispatchQueue {
return [[FSTDispatchQueue alloc] initWithQueue:dispatchQueue];
@@ -171,9 +172,9 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithQueue:(dispatch_queue_t)queue {
if (self = [super init]) {
+ _operationInProgress = false;
_queue = queue;
_delayedCallbacks = [NSMutableArray array];
- _operationInProgress = NO;
}
return self;
}
@@ -191,16 +192,16 @@ NS_ASSUME_NONNULL_BEGIN
FSTAssert(!_operationInProgress,
@"enterCheckedOperation may not be called when an operation is in progress");
@try {
- _operationInProgress = YES;
+ _operationInProgress = true;
[self verifyIsCurrentQueue];
block();
} @finally {
- _operationInProgress = NO;
+ _operationInProgress = false;
}
}
- (void)dispatchAsync:(void (^)(void))block {
- FSTAssert(!_operationInProgress || ![self onTargetQueue],
+ FSTAssert(![self onTargetQueue] || !_operationInProgress,
@"dispatchAsync called when we are already running on target dispatch queue '%@'",
[self targetQueueLabel]);
@@ -216,7 +217,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)dispatchSync:(void (^)(void))block {
- FSTAssert(!_operationInProgress || ![self onTargetQueue],
+ FSTAssert(![self onTargetQueue] || !_operationInProgress,
@"dispatchSync called when we are already running on target dispatch queue '%@'",
[self targetQueueLabel]);
diff --git a/Firestore/Source/Util/FSTUsageValidation.h b/Firestore/Source/Util/FSTUsageValidation.h
index a80dafa..05933ea 100644
--- a/Firestore/Source/Util/FSTUsageValidation.h
+++ b/Firestore/Source/Util/FSTUsageValidation.h
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <Foundation/Foundation.h>
+#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/Source/Util/FSTUsageValidation.mm b/Firestore/Source/Util/FSTUsageValidation.mm
index 82128f4..93abf87 100644
--- a/Firestore/Source/Util/FSTUsageValidation.mm
+++ b/Firestore/Source/Util/FSTUsageValidation.mm
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <Foundation/Foundation.h>
+#import "Firestore/Source/Util/FSTUsageValidation.h"
NS_ASSUME_NONNULL_BEGIN
diff --git a/Firestore/core/.clang-tidy b/Firestore/core/.clang-tidy
new file mode 100644
index 0000000..a071105
--- /dev/null
+++ b/Firestore/core/.clang-tidy
@@ -0,0 +1,34 @@
+---
+# cert-*
+# -cert-dcl50-cpp
+# We use variadic functions
+# -cert-err58-cpp
+# GoogleTest creates instances in static scope in a way that trips this
+# warning for every test.
+# readability-*
+# -readability-else-after-return
+# -readability-implicit-bool-conversion
+# These checks generate a bunch of noise that we're just not religious
+# about.
+# modernize-*
+# -modernize-use-equals-default
+# VS 2015 and Xcode <= 8.2 don't fully support this so we don't use
+# `= default`.
+# -modernize-use-equals-delete
+# GoogleTest generates test classes that use the old idiom of making
+# default constructors and operator= private.
+Checks: 'bugprone-*,cert-*,-cert-dcl50-cpp,-cert-err58-cpp,google-*,objc-*,readability-*,-readability-else-after-return,-readability-implicit-bool-conversion,misc-*,modernize-*,-modernize-use-equals-default,-modernize-use-equals-delete,clang-diagnostic-*,clang-analyzer-*'
+WarningsAsErrors: ''
+HeaderFilterRegex: ''
+CheckOptions:
+ - key: readability-braces-around-statements.ShortStatementLines
+ value: '1'
+ - key: google-readability-braces-around-statements.ShortStatementLines
+ value: '1'
+ - key: google-readability-function-size.StatementThreshold
+ value: '800'
+ - key: google-readability-namespace-comments.ShortNamespaceLines
+ value: '10'
+ - key: google-readability-namespace-comments.SpacesBeforeComments
+ value: '2'
+...
diff --git a/Firestore/core/include/firebase/firestore/document_reference.h b/Firestore/core/include/firebase/firestore/document_reference.h
index 58310b5..d295188 100644
--- a/Firestore/core/include/firebase/firestore/document_reference.h
+++ b/Firestore/core/include/firebase/firestore/document_reference.h
@@ -16,7 +16,7 @@
// TODO(rsgowman): This file isn't intended to be used just yet. It's just an
// outline of what the API might eventually look like. Most of this was
-// shamelessly stolen and modified from rtdb's header file, melded with the
+// shamelessly stolen and modified from RTDB's header file, melded with the
// (java) firestore api.
#ifndef FIRESTORE_CORE_INCLUDE_FIREBASE_FIRESTORE_DOCUMENT_REFERENCE_H_
@@ -36,7 +36,7 @@
// here so we don't forget to mention this during the API review, and should be
// removed once this note has migrated to the API review doc.
-// TODO(rsgowman): replace these forward decl's with appropriate includes (once
+// TODO(rsgowman): replace these forward decls with appropriate includes (once
// they exist)
namespace firebase {
class App;
@@ -47,7 +47,7 @@ class Future;
namespace firebase {
namespace firestore {
-// TODO(rsgowman): replace these forward decl's with appropriate includes (once
+// TODO(rsgowman): replace these forward decls with appropriate includes (once
// they exist)
class FieldValue;
class DocumentSnapshot;
@@ -361,7 +361,7 @@ namespace std {
// C++ style guide. But we think this is probably ok in this case since:
// a) It's the standard way of doing this outside of Google (as the style guide
// itself points out), and
-// b) This has a straightfoward hash function anyway (just hash the path) so I
+// b) This has a straightforward hash function anyway (just hash the path) so I
// don't think the concerns in the style guide are going to bite us.
//
// Raise this concern during the API review.
diff --git a/Firestore/core/include/firebase/firestore/timestamp.h b/Firestore/core/include/firebase/firestore/timestamp.h
index 2ee1c46..1736981 100644
--- a/Firestore/core/include/firebase/firestore/timestamp.h
+++ b/Firestore/core/include/firebase/firestore/timestamp.h
@@ -17,12 +17,13 @@
#ifndef FIRESTORE_CORE_INCLUDE_FIREBASE_FIRESTORE_TIMESTAMP_H_
#define FIRESTORE_CORE_INCLUDE_FIREBASE_FIRESTORE_TIMESTAMP_H_
-#include <stdint.h>
-#include <time.h>
+#include <cstdint>
+#include <ctime>
+#include <string>
+
#if !defined(_STLPORT_VERSION)
#include <chrono> // NOLINT(build/c++11)
#endif // !defined(_STLPORT_VERSION)
-#include <string>
namespace firebase {
diff --git a/Firestore/core/src/firebase/firestore/auth/credentials_provider.h b/Firestore/core/src/firebase/firestore/auth/credentials_provider.h
index 1aa76df..0a1930a 100644
--- a/Firestore/core/src/firebase/firestore/auth/credentials_provider.h
+++ b/Firestore/core/src/firebase/firestore/auth/credentials_provider.h
@@ -31,10 +31,10 @@ namespace firestore {
namespace auth {
// `TokenErrorListener` is a listener that gets a token or an error.
-typedef std::function<void(util::StatusOr<Token>)> TokenListener;
+using TokenListener = std::function<void(util::StatusOr<Token>)>;
// Listener notified with a User change.
-typedef std::function<void(User user)> UserChangeListener;
+using UserChangeListener = std::function<void(User user)>;
/**
* Provides methods for getting the uid and token for the current user and
diff --git a/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h b/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h
index 66c3c87..0e1da31 100644
--- a/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h
+++ b/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h
@@ -78,7 +78,7 @@ class FirebaseCredentialsProvider : public CredentialsProvider {
*/
struct Contents {
Contents(FIRApp* app, User&& user)
- : app(app), current_user(std::move(user)), mutex() {
+ : app(app), current_user(std::move(user)) {
}
const FIRApp* app;
diff --git a/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.mm b/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.mm
index 2bd3acc..ff2d5f7 100644
--- a/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.mm
+++ b/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.mm
@@ -24,6 +24,7 @@
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
// NB: This is also defined in Firestore/Source/Public/FIRFirestoreErrors.h
+// NOLINTNEXTLINE: public constant
NSString* const FIRFirestoreErrorDomain = @"FIRFirestoreErrorDomain";
namespace firebase {
@@ -47,7 +48,7 @@ FirebaseCredentialsProvider::FirebaseCredentialsProvider(FIRApp* app)
std::unique_lock<std::mutex> lock(contents->mutex);
NSDictionary<NSString*, id>* user_info = notification.userInfo;
- // ensure we're only notifiying for the current app.
+ // ensure we're only notifying for the current app.
FIRApp* notified_app =
user_info[FIRAuthStateDidChangeInternalNotificationAppKey];
if (![contents->app isEqual:notified_app]) {
diff --git a/Firestore/core/src/firebase/firestore/auth/token.h b/Firestore/core/src/firebase/firestore/auth/token.h
index 4b2f3aa..56084f8 100644
--- a/Firestore/core/src/firebase/firestore/auth/token.h
+++ b/Firestore/core/src/firebase/firestore/auth/token.h
@@ -42,7 +42,7 @@ namespace auth {
// TODO(zxu123): Make this support token-type for desktop workflow.
class Token {
public:
- Token(const absl::string_view token, const User& user);
+ Token(absl::string_view token, const User& user);
/** The actual raw token. */
const std::string& token() const {
diff --git a/Firestore/core/src/firebase/firestore/auth/user.cc b/Firestore/core/src/firebase/firestore/auth/user.cc
index f442d7b..4793fed 100644
--- a/Firestore/core/src/firebase/firestore/auth/user.cc
+++ b/Firestore/core/src/firebase/firestore/auth/user.cc
@@ -22,7 +22,7 @@ namespace firebase {
namespace firestore {
namespace auth {
-User::User() : uid_(), is_authenticated_(false) {
+User::User() : is_authenticated_(false) {
}
User::User(const absl::string_view uid) : uid_(uid), is_authenticated_(true) {
diff --git a/Firestore/core/src/firebase/firestore/auth/user.h b/Firestore/core/src/firebase/firestore/auth/user.h
index 3918c61..cc030cc 100644
--- a/Firestore/core/src/firebase/firestore/auth/user.h
+++ b/Firestore/core/src/firebase/firestore/auth/user.h
@@ -41,7 +41,7 @@ class User {
User();
/** Construct an authenticated user with the given UID. */
- explicit User(const absl::string_view uid);
+ explicit User(absl::string_view uid);
const std::string& uid() const {
return uid_;
diff --git a/Firestore/core/src/firebase/firestore/core/database_info.h b/Firestore/core/src/firebase/firestore/core/database_info.h
index 2e1303e..0f97b1f 100644
--- a/Firestore/core/src/firebase/firestore/core/database_info.h
+++ b/Firestore/core/src/firebase/firestore/core/database_info.h
@@ -41,12 +41,12 @@ class DatabaseInfo {
* @param database_id The project/database to use.
* @param persistence_key A unique identifier for this Firestore's local
* storage. Usually derived from -[FIRApp appName].
- * @param host The hostname of the datastore backend.
+ * @param host The hostname of the Firestore backend.
* @param ssl_enabled Whether to use SSL when connecting.
*/
DatabaseInfo(const firebase::firestore::model::DatabaseId& database_id,
- const absl::string_view persistence_key,
- const absl::string_view host,
+ absl::string_view persistence_key,
+ absl::string_view host,
bool ssl_enabled);
const firebase::firestore::model::DatabaseId& database_id() const {
diff --git a/Firestore/core/src/firebase/firestore/geo_point.cc b/Firestore/core/src/firebase/firestore/geo_point.cc
index fb01023..1ed5126 100644
--- a/Firestore/core/src/firebase/firestore/geo_point.cc
+++ b/Firestore/core/src/firebase/firestore/geo_point.cc
@@ -16,10 +16,12 @@
#include "Firestore/core/include/firebase/firestore/geo_point.h"
-#include <math.h>
+#include <cmath>
#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
+using std::isnan;
+
namespace firebase {
namespace firestore {
diff --git a/Firestore/core/src/firebase/firestore/immutable/array_sorted_map.h b/Firestore/core/src/firebase/firestore/immutable/array_sorted_map.h
index 56da9e9..92fd823 100644
--- a/Firestore/core/src/firebase/firestore/immutable/array_sorted_map.h
+++ b/Firestore/core/src/firebase/firestore/immutable/array_sorted_map.h
@@ -70,8 +70,8 @@ class FixedArray {
*/
template <typename SourceIterator>
void append(SourceIterator src_begin, SourceIterator src_end) {
- size_type appending = static_cast<size_type>(src_end - src_begin);
- size_type new_size = size_ + appending;
+ auto appending = static_cast<size_type>(src_end - src_begin);
+ auto new_size = size_ + appending;
FIREBASE_ASSERT(new_size <= fixed_size);
std::copy(src_begin, src_end, end());
@@ -229,8 +229,6 @@ class ArraySortedMap : public SortedMapBase {
}
}
- // TODO(wilhuff): indexof
-
/** Returns true if the map contains no elements. */
bool empty() const {
return size() == 0;
diff --git a/Firestore/core/src/firebase/firestore/immutable/map_entry.h b/Firestore/core/src/firebase/firestore/immutable/map_entry.h
index 2130b5b..1022b06 100644
--- a/Firestore/core/src/firebase/firestore/immutable/map_entry.h
+++ b/Firestore/core/src/firebase/firestore/immutable/map_entry.h
@@ -33,7 +33,7 @@ namespace immutable {
*/
template <typename K, typename V, typename C = std::less<K>>
struct KeyComparator {
- typedef std::pair<K, V> pair_type;
+ using pair_type = std::pair<K, V>;
explicit KeyComparator(const C& comparator = C())
: key_comparator_(comparator) {
diff --git a/Firestore/core/src/firebase/firestore/immutable/sorted_map.h b/Firestore/core/src/firebase/firestore/immutable/sorted_map.h
index 5ed16b3..ef6f54e 100644
--- a/Firestore/core/src/firebase/firestore/immutable/sorted_map.h
+++ b/Firestore/core/src/firebase/firestore/immutable/sorted_map.h
@@ -144,6 +144,7 @@ class SortedMap : public impl::SortedMapBase {
case Tag::Tree:
return SortedMap{tree_.insert(key, value)};
}
+ FIREBASE_UNREACHABLE();
}
/**
@@ -159,6 +160,7 @@ class SortedMap : public impl::SortedMapBase {
case Tag::Tree:
return SortedMap{tree_.erase(key)};
}
+ FIREBASE_UNREACHABLE();
}
/** Returns true if the map contains no elements. */
@@ -169,6 +171,7 @@ class SortedMap : public impl::SortedMapBase {
case Tag::Tree:
return tree_.empty();
}
+ FIREBASE_UNREACHABLE();
}
/** Returns the number of items in this map. */
@@ -179,6 +182,7 @@ class SortedMap : public impl::SortedMapBase {
case Tag::Tree:
return tree_.size();
}
+ FIREBASE_UNREACHABLE();
}
private:
diff --git a/Firestore/core/src/firebase/firestore/immutable/sorted_map_base.h b/Firestore/core/src/firebase/firestore/immutable/sorted_map_base.h
index accb5ef..cfb19c1 100644
--- a/Firestore/core/src/firebase/firestore/immutable/sorted_map_base.h
+++ b/Firestore/core/src/firebase/firestore/immutable/sorted_map_base.h
@@ -17,7 +17,7 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_IMMUTABLE_SORTED_MAP_BASE_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_IMMUTABLE_SORTED_MAP_BASE_H_
-#include <stdint.h>
+#include <cstdint>
namespace firebase {
namespace firestore {
diff --git a/Firestore/core/src/firebase/firestore/immutable/tree_sorted_map.h b/Firestore/core/src/firebase/firestore/immutable/tree_sorted_map.h
index e3102e7..dfe270d 100644
--- a/Firestore/core/src/firebase/firestore/immutable/tree_sorted_map.h
+++ b/Firestore/core/src/firebase/firestore/immutable/tree_sorted_map.h
@@ -17,9 +17,8 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_IMMUTABLE_TREE_SORTED_MAP_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_IMMUTABLE_TREE_SORTED_MAP_H_
-#include <assert.h>
-
#include <algorithm>
+#include <cassert>
#include <functional>
#include <memory>
#include <utility>
diff --git a/Firestore/core/src/firebase/firestore/local/leveldb_key.cc b/Firestore/core/src/firebase/firestore/local/leveldb_key.cc
index 03dbeae..7febe71 100644
--- a/Firestore/core/src/firebase/firestore/local/leveldb_key.cc
+++ b/Firestore/core/src/firebase/firestore/local/leveldb_key.cc
@@ -373,7 +373,7 @@ DocumentKey Reader::ReadDocumentKey() {
}
ResourcePath path{std::move(path_segments)};
- if (ok_ && path.size() > 0 && DocumentKey::IsDocumentKey(path)) {
+ if (ok_ && !path.empty() && DocumentKey::IsDocumentKey(path)) {
return DocumentKey{std::move(path)};
}
diff --git a/Firestore/core/src/firebase/firestore/local/leveldb_transaction.cc b/Firestore/core/src/firebase/firestore/local/leveldb_transaction.cc
index d84d441..f998550 100644
--- a/Firestore/core/src/firebase/firestore/local/leveldb_transaction.cc
+++ b/Firestore/core/src/firebase/firestore/local/leveldb_transaction.cc
@@ -16,12 +16,11 @@
#include "Firestore/core/src/firebase/firestore/local/leveldb_transaction.h"
-#include <leveldb/write_batch.h>
-
#include "Firestore/core/src/firebase/firestore/local/leveldb_key.h"
#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
#include "Firestore/core/src/firebase/firestore/util/log.h"
#include "absl/memory/memory.h"
+#include "leveldb/write_batch.h"
using leveldb::DB;
using leveldb::ReadOptions;
diff --git a/Firestore/core/src/firebase/firestore/local/leveldb_transaction.h b/Firestore/core/src/firebase/firestore/local/leveldb_transaction.h
index 56a9a77..a6ddce2 100644
--- a/Firestore/core/src/firebase/firestore/local/leveldb_transaction.h
+++ b/Firestore/core/src/firebase/firestore/local/leveldb_transaction.h
@@ -17,16 +17,16 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_LOCAL_LEVELDB_TRANSACTION_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_LOCAL_LEVELDB_TRANSACTION_H_
-#include <absl/strings/string_view.h>
-#include <leveldb/db.h>
-
-#include <stdint.h>
+#include <cstdint>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
+#include "absl/strings/string_view.h"
+#include "leveldb/db.h"
+
#if __OBJC__
#import <Protobuf/GPBProtocolBuffers.h>
#endif
diff --git a/Firestore/core/src/firebase/firestore/model/CMakeLists.txt b/Firestore/core/src/firebase/firestore/model/CMakeLists.txt
index 78f5cd6..02affdb 100644
--- a/Firestore/core/src/firebase/firestore/model/CMakeLists.txt
+++ b/Firestore/core/src/firebase/firestore/model/CMakeLists.txt
@@ -22,18 +22,23 @@ cc_library(
document.h
document_key.cc
document_key.h
+ field_mask.h
field_path.cc
field_path.h
+ field_transform.h
field_value.cc
field_value.h
maybe_document.cc
maybe_document.h
no_document.cc
no_document.h
+ precondition.cc
+ precondition.h
resource_path.cc
resource_path.h
snapshot_version.cc
snapshot_version.h
+ transform_operations.h
types.h
DEPENDS
absl_strings
diff --git a/Firestore/core/src/firebase/firestore/model/database_id.h b/Firestore/core/src/firebase/firestore/model/database_id.h
index 2ad1332..0c0e0ec 100644
--- a/Firestore/core/src/firebase/firestore/model/database_id.h
+++ b/Firestore/core/src/firebase/firestore/model/database_id.h
@@ -17,8 +17,7 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_DATABASE_ID_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_DATABASE_ID_H_
-#include <stdint.h>
-
+#include <cstdint>
#include <string>
#include "absl/strings/string_view.h"
@@ -45,8 +44,7 @@ class DatabaseId {
* @param project_id The project for the database.
* @param database_id The database in the project to use.
*/
- DatabaseId(const absl::string_view project_id,
- const absl::string_view database_id);
+ DatabaseId(absl::string_view project_id, absl::string_view database_id);
const std::string& project_id() const {
return project_id_;
diff --git a/Firestore/core/src/firebase/firestore/model/document.cc b/Firestore/core/src/firebase/firestore/model/document.cc
index 16548cd..ae59d15 100644
--- a/Firestore/core/src/firebase/firestore/model/document.cc
+++ b/Firestore/core/src/firebase/firestore/model/document.cc
@@ -39,7 +39,7 @@ bool Document::Equals(const MaybeDocument& other) const {
if (other.type() != Type::Document) {
return false;
}
- const Document& other_doc = static_cast<const Document&>(other);
+ auto& other_doc = static_cast<const Document&>(other);
return MaybeDocument::Equals(other) &&
has_local_mutations_ == other_doc.has_local_mutations_ &&
data_ == other_doc.data_;
diff --git a/Firestore/core/src/firebase/firestore/model/field_mask.h b/Firestore/core/src/firebase/firestore/model/field_mask.h
new file mode 100644
index 0000000..b895ab3
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/model/field_mask.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_MASK_H_
+#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_MASK_H_
+
+#include <initializer_list>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+/**
+ * Provides a set of fields that can be used to partially patch a document.
+ * FieldMask is used in conjunction with FieldValue of Object type.
+ *
+ * Examples:
+ * foo - Overwrites foo entirely with the provided value. If foo is not
+ * present in the companion FieldValue, the field is deleted.
+ * foo.bar - Overwrites only the field bar of the object foo. If foo is not an
+ * object, foo is replaced with an object containing bar.
+ */
+class FieldMask {
+ public:
+ using const_iterator = std::vector<FieldPath>::const_iterator;
+
+ FieldMask(std::initializer_list<FieldPath> list) : fields_{list} {
+ }
+ explicit FieldMask(std::vector<FieldPath> fields)
+ : fields_{std::move(fields)} {
+ }
+
+ const_iterator begin() const {
+ return fields_.begin();
+ }
+ const_iterator end() const {
+ return fields_.end();
+ }
+
+ std::string ToString() const {
+ // Ideally, one should use a string builder. Since this is only non-critical
+ // code for logging and debugging, the logic is kept simple here.
+ std::string result("{ ");
+ for (const FieldPath& field : fields_) {
+ result += field.CanonicalString() + " ";
+ }
+ return result + "}";
+ }
+
+#if defined(__OBJC__)
+ FieldMask() {
+ }
+
+ NSUInteger Hash() const {
+ NSUInteger hashResult = 0;
+ for (const FieldPath& field : fields_) {
+ hashResult = hashResult * 31u + field.Hash();
+ }
+ return hashResult;
+ }
+#endif
+
+ friend bool operator==(const FieldMask& lhs, const FieldMask& rhs);
+
+ private:
+ std::vector<FieldPath> fields_;
+};
+
+inline bool operator==(const FieldMask& lhs, const FieldMask& rhs) {
+ return lhs.fields_ == rhs.fields_;
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
+
+#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_MASK_H_
diff --git a/Firestore/core/src/firebase/firestore/model/field_transform.h b/Firestore/core/src/firebase/firestore/model/field_transform.h
new file mode 100644
index 0000000..a1dd96c
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/model/field_transform.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_TRANSFORM_H_
+#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_TRANSFORM_H_
+
+#include <memory>
+#include <utility>
+
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/transform_operations.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+/** A field path and the TransformOperation to perform upon it. */
+class FieldTransform {
+ public:
+ FieldTransform(FieldPath path,
+ std::unique_ptr<TransformOperation> transformation) noexcept
+ : path_{std::move(path)}, transformation_{std::move(transformation)} {
+ }
+
+ const FieldPath& path() const {
+ return path_;
+ }
+
+ const TransformOperation& transformation() const {
+ return *transformation_.get();
+ }
+
+ bool operator==(const FieldTransform& other) const {
+ return path_ == other.path_ && *transformation_ == *other.transformation_;
+ }
+
+#if defined(__OBJC__)
+ // For Objective-C++ hash; to be removed after migration.
+ // Do NOT use in C++ code.
+ NSUInteger Hash() const {
+ NSUInteger hash = path_.Hash();
+ hash = hash * 31 + transformation_->Hash();
+ return hash;
+ }
+#endif // defined(__OBJC__)
+
+ private:
+ FieldPath path_;
+ // Shared by copies of the same FieldTransform.
+ std::shared_ptr<const TransformOperation> transformation_;
+};
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
+
+#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_TRANSFORM_H_
diff --git a/Firestore/core/src/firebase/firestore/model/field_value.cc b/Firestore/core/src/firebase/firestore/model/field_value.cc
index 2c1af53..b0519f7 100644
--- a/Firestore/core/src/firebase/firestore/model/field_value.cc
+++ b/Firestore/core/src/firebase/firestore/model/field_value.cc
@@ -16,9 +16,8 @@
#include "Firestore/core/src/firebase/firestore/model/field_value.h"
-#include <math.h>
-
#include <algorithm>
+#include <cmath>
#include <memory>
#include <utility>
#include <vector>
@@ -39,7 +38,7 @@ namespace {
/**
* This deviates from the other platforms that define TypeOrder. Since
* we already define Type for union types, we use it together with this
- * function to achive the equivalent order of types i.e.
+ * function to achieve the equivalent order of types i.e.
* i) if two types are comparable, then they are of equal order;
* ii) otherwise, their order is the same as the order of their Type.
*/
@@ -149,7 +148,8 @@ FieldValue& FieldValue::operator=(FieldValue&& value) {
return *this;
default:
// We just copy over POD union types.
- return *this = value;
+ *this = value;
+ return *this;
}
}
diff --git a/Firestore/core/src/firebase/firestore/model/field_value.h b/Firestore/core/src/firebase/firestore/model/field_value.h
index c42d533..3c5af9c 100644
--- a/Firestore/core/src/firebase/firestore/model/field_value.h
+++ b/Firestore/core/src/firebase/firestore/model/field_value.h
@@ -17,8 +17,7 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_VALUE_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_FIELD_VALUE_H_
-#include <stdint.h>
-
+#include <cstdint>
#include <map>
#include <memory>
#include <string>
@@ -164,7 +163,7 @@ class FieldValue {
/**
* Switch to the specified type, if different from the current type.
*/
- void SwitchTo(const Type type);
+ void SwitchTo(Type type);
Type tag_ = Type::Null;
union {
diff --git a/Firestore/core/src/firebase/firestore/model/precondition.cc b/Firestore/core/src/firebase/firestore/model/precondition.cc
new file mode 100644
index 0000000..423d5a2
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/model/precondition.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
+
+#include "Firestore/core/src/firebase/firestore/model/maybe_document.h"
+#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
+#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+Precondition::Precondition(Type type, SnapshotVersion update_time, bool exists)
+ : type_(type), update_time_(std::move(update_time)), exists_(exists) {
+}
+
+/* static */
+Precondition Precondition::Exists(bool exists) {
+ return Precondition{Type::Exists, SnapshotVersion::None(), exists};
+}
+
+/* static */
+Precondition Precondition::UpdateTime(SnapshotVersion update_time) {
+ // update_time could be SnapshotVersion::None() in particular for locally
+ // deleted documents.
+ return Precondition{Type::UpdateTime, std::move(update_time), false};
+}
+
+/* static */
+Precondition Precondition::None() {
+ return Precondition{Type::None, SnapshotVersion::None(), false};
+}
+
+bool Precondition::IsValidFor(const MaybeDocument& maybe_doc) const {
+ switch (type_) {
+ case Type::UpdateTime:
+ return maybe_doc.type() == MaybeDocument::Type::Document &&
+ maybe_doc.version() == update_time_;
+ case Type::Exists:
+ if (exists_) {
+ return maybe_doc.type() == MaybeDocument::Type::Document;
+ } else {
+ return maybe_doc.type() == MaybeDocument::Type::NoDocument;
+ }
+ case Type::None:
+ return true;
+ }
+ FIREBASE_UNREACHABLE();
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/src/firebase/firestore/model/precondition.h b/Firestore/core/src/firebase/firestore/model/precondition.h
new file mode 100644
index 0000000..4ab03c2
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/model/precondition.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_PRECONDITION_H_
+#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_PRECONDITION_H_
+
+#include <utility>
+
+#if defined(__OBJC__)
+#import "FIRTimestamp.h"
+#import "Firestore/Source/Core/FSTSnapshotVersion.h"
+#import "Firestore/Source/Model/FSTDocument.h"
+#include "Firestore/core/include/firebase/firestore/timestamp.h"
+#endif // defined(__OBJC__)
+
+#include "Firestore/core/src/firebase/firestore/model/maybe_document.h"
+#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
+#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+/**
+ * Encodes a precondition for a mutation. This follows the model that the
+ * backend accepts with the special case of an explicit "empty" precondition
+ * (meaning no precondition).
+ */
+class Precondition {
+ public:
+ enum class Type {
+ None,
+ Exists,
+ UpdateTime,
+ };
+
+ /** Creates a new Precondition with an exists flag. */
+ static Precondition Exists(bool exists);
+
+ /** Creates a new Precondition based on a time the document exists at. */
+ static Precondition UpdateTime(SnapshotVersion update_time);
+
+ /** Returns a precondition representing no precondition. */
+ static Precondition None();
+
+ /**
+ * Returns true if the precondition is valid for the given document (and the
+ * document is available).
+ */
+ bool IsValidFor(const MaybeDocument& maybe_doc) const;
+
+ /** Returns whether this Precondition represents no precondition. */
+ bool IsNone() const {
+ return type_ == Type::None;
+ }
+
+ Type type() const {
+ return type_;
+ }
+
+ const SnapshotVersion& update_time() const {
+ return update_time_;
+ }
+
+ bool operator==(const Precondition& other) const {
+ return type_ == other.type_ && update_time_ == other.update_time_ &&
+ exists_ == other.exists_;
+ }
+
+#if defined(__OBJC__)
+ // Objective-C requires a default constructor.
+ Precondition()
+ : type_(Type::None),
+ update_time_(SnapshotVersion::None()),
+ exists_(false) {
+ }
+
+ // MaybeDocument is not fully ported yet. So we suppose this addition helper.
+ bool IsValidFor(FSTMaybeDocument* maybe_doc) const {
+ switch (type_) {
+ case Type::UpdateTime:
+ return [maybe_doc isKindOfClass:[FSTDocument class]] &&
+ firebase::firestore::model::SnapshotVersion(maybe_doc.version) ==
+ update_time_;
+ case Type::Exists:
+ if (exists_) {
+ return [maybe_doc isKindOfClass:[FSTDocument class]];
+ } else {
+ return maybe_doc == nil ||
+ [maybe_doc isKindOfClass:[FSTDeletedDocument class]];
+ }
+ case Type::None:
+ return true;
+ }
+ FIREBASE_UNREACHABLE();
+ }
+
+ // For Objective-C++ hash; to be removed after migration.
+ // Do NOT use in C++ code.
+ NSUInteger Hash() const {
+ NSUInteger hash = std::hash<Timestamp>()(update_time_.timestamp());
+ hash = hash * 31 + exists_;
+ hash = hash * 31 + static_cast<NSUInteger>(type_);
+ return hash;
+ }
+
+ NSString* description() const {
+ switch (type_) {
+ case Type::None:
+ return @"<Precondition <none>>";
+ case Type::Exists:
+ if (exists_) {
+ return @"<Precondition exists=yes>";
+ } else {
+ return @"<Precondition exists=no>";
+ }
+ case Type::UpdateTime:
+ return [NSString
+ stringWithFormat:@"<Precondition update_time=%s>",
+ update_time_.timestamp().ToString().c_str()];
+ }
+ // We only raise dev assertion here. This function is mainly used in
+ // logging.
+ FIREBASE_DEV_ASSERT_MESSAGE(false, "precondition invalid");
+ return @"<Precondition invalid>";
+ }
+#endif // defined(__OBJC__)
+
+ private:
+ Precondition(Type type, SnapshotVersion update_time, bool exists);
+
+ // The actual time of this precondition.
+ Type type_ = Type::None;
+
+ // For UpdateTime type, preconditions a mutation based on the last updateTime.
+ SnapshotVersion update_time_;
+
+ // For Exists type, preconditions a mutation based on whether the document
+ // exists.
+ bool exists_;
+};
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
+
+#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_PRECONDITION_H_
diff --git a/Firestore/core/src/firebase/firestore/model/snapshot_version.h b/Firestore/core/src/firebase/firestore/model/snapshot_version.h
index 56e8c50..1fbba1c 100644
--- a/Firestore/core/src/firebase/firestore/model/snapshot_version.h
+++ b/Firestore/core/src/firebase/firestore/model/snapshot_version.h
@@ -19,6 +19,11 @@
#include "Firestore/core/include/firebase/firestore/timestamp.h"
+#if defined(__OBJC__)
+#import "FIRTimestamp.h"
+#import "Firestore/Source/Core/FSTSnapshotVersion.h"
+#endif // defined(__OBJC__)
+
namespace firebase {
namespace firestore {
namespace model {
@@ -38,6 +43,24 @@ class SnapshotVersion {
/** Creates a new version that is smaller than all other versions. */
static const SnapshotVersion& None();
+#if defined(__OBJC__)
+ SnapshotVersion(FSTSnapshotVersion* version) // NOLINT(runtime/explicit)
+ : timestamp_{version.timestamp.seconds, version.timestamp.nanoseconds} {
+ }
+
+ operator FSTSnapshotVersion*() const {
+ if (timestamp_ == Timestamp{}) {
+ return [FSTSnapshotVersion noVersion];
+ } else {
+ return [FSTSnapshotVersion
+ versionWithTimestamp:[FIRTimestamp
+ timestampWithSeconds:timestamp_.seconds()
+ nanoseconds:timestamp_
+ .nanoseconds()]];
+ }
+ }
+#endif // defined(__OBJC__)
+
private:
Timestamp timestamp_;
};
diff --git a/Firestore/core/src/firebase/firestore/model/transform_operations.h b/Firestore/core/src/firebase/firestore/model/transform_operations.h
new file mode 100644
index 0000000..aad5a9b
--- /dev/null
+++ b/Firestore/core/src/firebase/firestore/model/transform_operations.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_TRANSFORM_OPERATIONS_H_
+#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_TRANSFORM_OPERATIONS_H_
+
+#include <vector>
+
+#if defined(__OBJC__)
+#import "Firestore/Source/Model/FSTFieldValue.h"
+#endif
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+// TODO(zxu123): We might want to refactor transform_operations.h into several
+// files when the number of different types of operations grows gigantically.
+// For now, put the interface and the only operation here.
+
+/** Represents a transform within a TransformMutation. */
+class TransformOperation {
+ public:
+ /** All the different kinds to TransformOperation. */
+ enum class Type {
+ ServerTimestamp,
+ ArrayUnion,
+ ArrayRemove,
+ Test, // Purely for test purpose.
+ };
+
+ virtual ~TransformOperation() {
+ }
+
+ /** Returns the actual type. */
+ virtual Type type() const = 0;
+
+ /** Returns whether the two are equal. */
+ virtual bool operator==(const TransformOperation& other) const = 0;
+
+ /** Returns whether the two are not equal. */
+ bool operator!=(const TransformOperation& other) const {
+ return !operator==(other);
+ }
+
+#if defined(__OBJC__)
+ // For Objective-C++ hash; to be removed after migration.
+ // Do NOT use in C++ code.
+ virtual NSUInteger Hash() const = 0;
+#endif // defined(__OBJC__)
+};
+
+/** Transforms a value into a server-generated timestamp. */
+class ServerTimestampTransform : public TransformOperation {
+ public:
+ ~ServerTimestampTransform() override {
+ }
+
+ Type type() const override {
+ return Type::ServerTimestamp;
+ }
+
+ bool operator==(const TransformOperation& other) const override {
+ // All ServerTimestampTransform objects are equal.
+ return other.type() == Type::ServerTimestamp;
+ }
+
+ static const ServerTimestampTransform& Get() {
+ static ServerTimestampTransform shared_instance;
+ return shared_instance;
+ }
+
+#if defined(__OBJC__)
+ // For Objective-C++ hash; to be removed after migration.
+ // Do NOT use in C++ code.
+ NSUInteger Hash() const override {
+ // arbitrary number, the same as used in ObjC implementation, since all
+ // instances are equal.
+ return 37;
+ }
+#endif // defined(__OBJC__)
+
+ private:
+ ServerTimestampTransform() {
+ }
+};
+
+// TODO(mikelehen): ArrayTransform can only be used from Obj-C until we switch
+// to using FieldValue instead of FSTFieldValue.
+#if defined(__OBJC__)
+/**
+ * Transforms an array via a union or remove operation (for convenience, we use
+ * this class for both Type::ArrayUnion and Type::ArrayRemove).
+ */
+class ArrayTransform : public TransformOperation {
+ public:
+ ArrayTransform(const Type& type, const std::vector<FSTFieldValue*> elements)
+ : type_(type), elements_(elements) {
+ }
+
+ ~ArrayTransform() override {
+ }
+
+ Type type() const override {
+ return type_;
+ }
+
+ const std::vector<FSTFieldValue*>& elements() const {
+ return elements_;
+ }
+
+ bool operator==(const TransformOperation& other) const override {
+ if (other.type() != type()) {
+ return false;
+ }
+ auto array_transform = static_cast<const ArrayTransform&>(other);
+ if (array_transform.elements_.size() != elements_.size()) {
+ return false;
+ }
+ for (int i = 0; i < elements_.size(); i++) {
+ if (![array_transform.elements_[i] isEqual:elements_[i]]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+#if defined(__OBJC__)
+ // For Objective-C++ hash; to be removed after migration.
+ // Do NOT use in C++ code.
+ NSUInteger Hash() const override {
+ NSUInteger result = 37;
+ result = 31 * result + (type() == Type::ArrayUnion ? 1231 : 1237);
+ for (FSTFieldValue* element : elements_) {
+ result = 31 * result + [element hash];
+ }
+ return result;
+ }
+#endif // defined(__OBJC__)
+
+ private:
+ Type type_;
+ std::vector<FSTFieldValue*> elements_;
+};
+#endif
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
+
+#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_TRANSFORM_OPERATIONS_H_
diff --git a/Firestore/core/src/firebase/firestore/model/types.h b/Firestore/core/src/firebase/firestore/model/types.h
index fc1b196..3f813be 100644
--- a/Firestore/core/src/firebase/firestore/model/types.h
+++ b/Firestore/core/src/firebase/firestore/model/types.h
@@ -17,7 +17,7 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_TYPES_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_TYPES_H_
-#include <stdint.h>
+#include <cstdint>
namespace firebase {
namespace firestore {
diff --git a/Firestore/core/src/firebase/firestore/remote/serializer.cc b/Firestore/core/src/firebase/firestore/remote/serializer.cc
index 5483e1f..befe032 100644
--- a/Firestore/core/src/firebase/firestore/remote/serializer.cc
+++ b/Firestore/core/src/firebase/firestore/remote/serializer.cc
@@ -32,18 +32,34 @@ namespace remote {
using firebase::firestore::model::FieldValue;
using firebase::firestore::model::ObjectValue;
+using firebase::firestore::util::Status;
namespace {
class Writer;
+class Reader;
+
void EncodeObject(Writer* writer, const ObjectValue& object_value);
-ObjectValue DecodeObject(pb_istream_t* stream);
+ObjectValue DecodeObject(Reader* reader);
+
+/**
+ * Represents a nanopb tag.
+ *
+ * field_number is one of the field tags that nanopb generates based off of
+ * the proto messages. They're typically named in the format:
+ * <parentNameSpace>_<childNameSpace>_<message>_<field>_tag, e.g.
+ * google_firestore_v1beta1_Document_name_tag.
+ */
+struct Tag {
+ pb_wire_type_t wire_type;
+ uint32_t field_number;
+};
/**
* Docs TODO(rsgowman). But currently, this just wraps the underlying nanopb
- * pb_ostream_t.
+ * pb_ostream_t. Also doc how to check status.
*/
class Writer {
public:
@@ -70,13 +86,8 @@ class Writer {
* Writes a message type to the output stream.
*
* This essentially wraps calls to nanopb's pb_encode_tag() method.
- *
- * @param field_number is one of the field tags that nanopb generates based
- * off of the proto messages. They're typically named in the format:
- * <parentNameSpace>_<childNameSpace>_<message>_<field>_tag, e.g.
- * google_firestore_v1beta1_Document_name_tag.
*/
- void WriteTag(pb_wire_type_t wiretype, uint32_t field_number);
+ void WriteTag(Tag tag);
void WriteSize(size_t size);
void WriteNull();
@@ -105,7 +116,13 @@ class Writer {
return stream_.bytes_written;
}
+ Status status() const {
+ return status_;
+ }
+
private:
+ Status status_ = Status::OK();
+
/**
* Creates a new Writer, based on the given nanopb pb_ostream_t. Note that
* a shallow copy will be taken. (Non-null pointers within this struct must
@@ -132,6 +149,79 @@ class Writer {
pb_ostream_t stream_;
};
+/**
+ * Docs TODO(rsgowman). But currently, this just wraps the underlying nanopb
+ * pb_istream_t.
+ */
+class Reader {
+ public:
+ /**
+ * Creates an input stream that reads from the specified bytes. Note that
+ * this reference must remain valid for the lifetime of this Reader.
+ *
+ * (This is roughly equivalent to the nanopb function
+ * pb_istream_from_buffer())
+ *
+ * @param bytes where the input should be deserialized from.
+ */
+ static Reader Wrap(const uint8_t* bytes, size_t length);
+
+ /**
+ * Reads a message type from the input stream.
+ *
+ * This essentially wraps calls to nanopb's pb_decode_tag() method.
+ */
+ Tag ReadTag();
+
+ void ReadNull();
+ bool ReadBool();
+ int64_t ReadInteger();
+
+ std::string ReadString();
+
+ /**
+ * Reads a message and its length.
+ *
+ * Analog to Writer::WriteNestedMessage(). See that methods docs for further
+ * details.
+ *
+ * Call this method when reading a nested message. Provide a function to read
+ * the message itself.
+ */
+ template <typename T>
+ T ReadNestedMessage(const std::function<T(Reader*)>& read_message_fn);
+
+ size_t bytes_left() const {
+ return stream_.bytes_left;
+ }
+
+ private:
+ /**
+ * Creates a new Reader, based on the given nanopb pb_istream_t. Note that
+ * a shallow copy will be taken. (Non-null pointers within this struct must
+ * remain valid for the lifetime of this Reader.)
+ */
+ explicit Reader(pb_istream_t stream) : stream_(stream) {
+ }
+
+ /**
+ * Reads a "varint" from the input stream.
+ *
+ * This essentially wraps calls to nanopb's pb_decode_varint() method.
+ *
+ * Note that (despite the return type) this works for bool, enum, int32,
+ * int64, uint32 and uint64 proto field types.
+ *
+ * Note: This is not expected to be called direclty, but rather only via the
+ * other Decode* methods (i.e. DecodeBool, DecodeLong, etc)
+ *
+ * @return The decoded varint as a uint64_t.
+ */
+ uint64_t ReadVarint();
+
+ pb_istream_t stream_;
+};
+
Writer Writer::Wrap(std::vector<uint8_t>* out_bytes) {
// TODO(rsgowman): find a better home for this constant.
// A document is defined to have a max size of 1MiB - 4 bytes.
@@ -159,18 +249,33 @@ Writer Writer::Wrap(std::vector<uint8_t>* out_bytes) {
return Writer(raw_stream);
}
+Reader Reader::Wrap(const uint8_t* bytes, size_t length) {
+ return Reader{pb_istream_from_buffer(bytes, length)};
+}
+
// TODO(rsgowman): I've left the methods as near as possible to where they were
// before, which implies that the Writer methods are interspersed with the
-// PbIstream methods (or what will become the PbIstream methods). This should
-// make it a bit easier to review. Refactor these to group the related methods
-// together (probably within their own file rather than here).
+// Reader methods. This should make it a bit easier to review. Refactor these to
+// group the related methods together (probably within their own file rather
+// than here).
+
+void Writer::WriteTag(Tag tag) {
+ if (!status_.ok()) return;
-void Writer::WriteTag(pb_wire_type_t wiretype, uint32_t field_number) {
- bool status = pb_encode_tag(&stream_, wiretype, field_number);
- if (!status) {
+ if (!pb_encode_tag(&stream_, tag.wire_type, tag.field_number)) {
+ FIREBASE_ASSERT_MESSAGE(false, PB_GET_ERROR(&stream_));
+ }
+}
+
+Tag Reader::ReadTag() {
+ Tag tag;
+ bool eof;
+ bool ok = pb_decode_tag(&stream_, &tag.wire_type, &tag.field_number, &eof);
+ if (!ok || eof) {
// TODO(rsgowman): figure out error handling
abort();
}
+ return tag;
}
void Writer::WriteSize(size_t size) {
@@ -178,10 +283,10 @@ void Writer::WriteSize(size_t size) {
}
void Writer::WriteVarint(uint64_t value) {
- bool status = pb_encode_varint(&stream_, value);
- if (!status) {
- // TODO(rsgowman): figure out error handling
- abort();
+ if (!status_.ok()) return;
+
+ if (!pb_encode_varint(&stream_, value)) {
+ FIREBASE_ASSERT_MESSAGE(false, PB_GET_ERROR(&stream_));
}
}
@@ -189,15 +294,14 @@ void Writer::WriteVarint(uint64_t value) {
* Note that (despite the return type) this works for bool, enum, int32, int64,
* uint32 and uint64 proto field types.
*
- * Note: This is not expected to be called direclty, but rather only via the
+ * Note: This is not expected to be called directly, but rather only via the
* other Decode* methods (i.e. DecodeBool, DecodeLong, etc)
*
* @return The decoded varint as a uint64_t.
*/
-uint64_t DecodeVarint(pb_istream_t* stream) {
+uint64_t Reader::ReadVarint() {
uint64_t varint_value;
- bool status = pb_decode_varint(stream, &varint_value);
- if (!status) {
+ if (!pb_decode_varint(&stream_, &varint_value)) {
// TODO(rsgowman): figure out error handling
abort();
}
@@ -208,8 +312,8 @@ void Writer::WriteNull() {
return WriteVarint(google_protobuf_NullValue_NULL_VALUE);
}
-void DecodeNull(pb_istream_t* stream) {
- uint64_t varint = DecodeVarint(stream);
+void Reader::ReadNull() {
+ uint64_t varint = ReadVarint();
if (varint != google_protobuf_NullValue_NULL_VALUE) {
// TODO(rsgowman): figure out error handling
abort();
@@ -220,8 +324,8 @@ void Writer::WriteBool(bool bool_value) {
return WriteVarint(bool_value);
}
-bool DecodeBool(pb_istream_t* stream) {
- uint64_t varint = DecodeVarint(stream);
+bool Reader::ReadBool() {
+ uint64_t varint = ReadVarint();
switch (varint) {
case 0:
return false;
@@ -237,32 +341,30 @@ void Writer::WriteInteger(int64_t integer_value) {
return WriteVarint(integer_value);
}
-int64_t DecodeInteger(pb_istream_t* stream) {
- return DecodeVarint(stream);
+int64_t Reader::ReadInteger() {
+ return ReadVarint();
}
void Writer::WriteString(const std::string& string_value) {
- bool status = pb_encode_string(
- &stream_, reinterpret_cast<const pb_byte_t*>(string_value.c_str()),
- string_value.length());
- if (!status) {
- // TODO(rsgowman): figure out error handling
- abort();
+ if (!status_.ok()) return;
+
+ if (!pb_encode_string(
+ &stream_, reinterpret_cast<const pb_byte_t*>(string_value.c_str()),
+ string_value.length())) {
+ FIREBASE_ASSERT_MESSAGE(false, PB_GET_ERROR(&stream_));
}
}
-std::string DecodeString(pb_istream_t* stream) {
+std::string Reader::ReadString() {
pb_istream_t substream;
- bool status = pb_make_string_substream(stream, &substream);
- if (!status) {
+ if (!pb_make_string_substream(&stream_, &substream)) {
// TODO(rsgowman): figure out error handling
abort();
}
std::string result(substream.bytes_left, '\0');
- status = pb_read(&substream, reinterpret_cast<pb_byte_t*>(&result[0]),
- substream.bytes_left);
- if (!status) {
+ if (!pb_read(&substream, reinterpret_cast<pb_byte_t*>(&result[0]),
+ substream.bytes_left)) {
// TODO(rsgowman): figure out error handling
abort();
}
@@ -277,7 +379,7 @@ std::string DecodeString(pb_istream_t* stream) {
abort();
}
- pb_close_string_substream(stream, &substream);
+ pb_close_string_substream(&stream_, &substream);
return result;
}
@@ -291,32 +393,32 @@ void EncodeFieldValueImpl(Writer* writer, const FieldValue& field_value) {
// non-varint, non-fixed-size (i.e. string) type is present before doing so.
switch (field_value.type()) {
case FieldValue::Type::Null:
- writer->WriteTag(PB_WT_VARINT,
- google_firestore_v1beta1_Value_null_value_tag);
+ writer->WriteTag(
+ {PB_WT_VARINT, google_firestore_v1beta1_Value_null_value_tag});
writer->WriteNull();
break;
case FieldValue::Type::Boolean:
- writer->WriteTag(PB_WT_VARINT,
- google_firestore_v1beta1_Value_boolean_value_tag);
+ writer->WriteTag(
+ {PB_WT_VARINT, google_firestore_v1beta1_Value_boolean_value_tag});
writer->WriteBool(field_value.boolean_value());
break;
case FieldValue::Type::Integer:
- writer->WriteTag(PB_WT_VARINT,
- google_firestore_v1beta1_Value_integer_value_tag);
+ writer->WriteTag(
+ {PB_WT_VARINT, google_firestore_v1beta1_Value_integer_value_tag});
writer->WriteInteger(field_value.integer_value());
break;
case FieldValue::Type::String:
- writer->WriteTag(PB_WT_STRING,
- google_firestore_v1beta1_Value_string_value_tag);
+ writer->WriteTag(
+ {PB_WT_STRING, google_firestore_v1beta1_Value_string_value_tag});
writer->WriteString(field_value.string_value());
break;
case FieldValue::Type::Object:
- writer->WriteTag(PB_WT_STRING,
- google_firestore_v1beta1_Value_map_value_tag);
+ writer->WriteTag(
+ {PB_WT_STRING, google_firestore_v1beta1_Value_map_value_tag});
EncodeObject(writer, field_value.object_value());
break;
@@ -326,30 +428,23 @@ void EncodeFieldValueImpl(Writer* writer, const FieldValue& field_value) {
}
}
-FieldValue DecodeFieldValueImpl(pb_istream_t* stream) {
- pb_wire_type_t wire_type;
- uint32_t tag;
- bool eof;
- bool status = pb_decode_tag(stream, &wire_type, &tag, &eof);
- if (!status) {
- // TODO(rsgowman): figure out error handling
- abort();
- }
+FieldValue DecodeFieldValueImpl(Reader* reader) {
+ Tag tag = reader->ReadTag();
// Ensure the tag matches the wire type
// TODO(rsgowman): figure out error handling
- switch (tag) {
+ switch (tag.field_number) {
case google_firestore_v1beta1_Value_null_value_tag:
case google_firestore_v1beta1_Value_boolean_value_tag:
case google_firestore_v1beta1_Value_integer_value_tag:
- if (wire_type != PB_WT_VARINT) {
+ if (tag.wire_type != PB_WT_VARINT) {
abort();
}
break;
case google_firestore_v1beta1_Value_string_value_tag:
case google_firestore_v1beta1_Value_map_value_tag:
- if (wire_type != PB_WT_STRING) {
+ if (tag.wire_type != PB_WT_STRING) {
abort();
}
break;
@@ -358,19 +453,19 @@ FieldValue DecodeFieldValueImpl(pb_istream_t* stream) {
abort();
}
- switch (tag) {
+ switch (tag.field_number) {
case google_firestore_v1beta1_Value_null_value_tag:
- DecodeNull(stream);
+ reader->ReadNull();
return FieldValue::NullValue();
case google_firestore_v1beta1_Value_boolean_value_tag:
- return FieldValue::BooleanValue(DecodeBool(stream));
+ return FieldValue::BooleanValue(reader->ReadBool());
case google_firestore_v1beta1_Value_integer_value_tag:
- return FieldValue::IntegerValue(DecodeInteger(stream));
+ return FieldValue::IntegerValue(reader->ReadInteger());
case google_firestore_v1beta1_Value_string_value_tag:
- return FieldValue::StringValue(DecodeString(stream));
+ return FieldValue::StringValue(reader->ReadString());
case google_firestore_v1beta1_Value_map_value_tag:
return FieldValue::ObjectValueFromMap(
- DecodeObject(stream).internal_value);
+ DecodeObject(reader).internal_value);
default:
// TODO(rsgowman): figure out error handling
@@ -380,31 +475,35 @@ FieldValue DecodeFieldValueImpl(pb_istream_t* stream) {
void Writer::WriteNestedMessage(
const std::function<void(Writer*)>& write_message_fn) {
+ if (!status_.ok()) return;
+
// First calculate the message size using a non-writing substream.
Writer sizer = Writer::Sizing();
write_message_fn(&sizer);
+ status_ = sizer.status();
+ if (!status_.ok()) return;
size_t size = sizer.bytes_written();
// Write out the size to the output writer.
WriteSize(size);
+ if (!status_.ok()) return;
// If this stream is itself a sizing stream, then we don't need to actually
// parse field_value a second time; just update the bytes_written via a call
// to pb_write. (If we try to write the contents into a sizing stream, it'll
// fail since sizing streams don't actually have any buffer space.)
if (stream_.callback == nullptr) {
- bool status = pb_write(&stream_, nullptr, size);
- if (!status) {
- // TODO(rsgowman): figure out error handling
- abort();
+ if (!pb_write(&stream_, nullptr, size)) {
+ FIREBASE_ASSERT_MESSAGE(false, PB_GET_ERROR(&stream_));
}
return;
}
// Ensure the output stream has enough space
if (stream_.bytes_written + size > stream_.max_size) {
- // TODO(rsgowman): figure out error handling
- abort();
+ FIREBASE_ASSERT_MESSAGE(
+ false,
+ "Insufficient space in the output stream to write the given message");
}
// Use a substream to verify that a callback doesn't write more than what it
@@ -415,6 +514,8 @@ void Writer::WriteNestedMessage(
/*max_size=*/size, /*bytes_written=*/0,
/*errmsg=*/nullptr});
write_message_fn(&writer);
+ status_ = writer.status();
+ if (!status_.ok()) return;
stream_.bytes_written += writer.stream_.bytes_written;
stream_.state = writer.stream_.state;
@@ -422,35 +523,36 @@ void Writer::WriteNestedMessage(
if (writer.bytes_written() != size) {
// submsg size changed
- // TODO(rsgowman): figure out error handling
- abort();
+ FIREBASE_ASSERT_MESSAGE(
+ false, "Parsing the nested message twice yielded different sizes");
}
}
-FieldValue DecodeNestedFieldValue(pb_istream_t* stream) {
+template <typename T>
+T Reader::ReadNestedMessage(const std::function<T(Reader*)>& read_message_fn) {
// Implementation note: This is roughly modeled on pb_decode_delimited,
// adjusted to account for the oneof in FieldValue.
- pb_istream_t substream;
- bool status = pb_make_string_substream(stream, &substream);
- if (!status) {
+ pb_istream_t raw_substream;
+ if (!pb_make_string_substream(&stream_, &raw_substream)) {
// TODO(rsgowman): figure out error handling
abort();
}
+ Reader substream(raw_substream);
- FieldValue fv = DecodeFieldValueImpl(&substream);
+ T message = read_message_fn(&substream);
// NB: future versions of nanopb read the remaining characters out of the
// substream (and return false if that fails) as an additional safety
// check within pb_close_string_substream. Unfortunately, that's not present
// in the current version (0.38). We'll make a stronger assertion and check
// to make sure there *are* no remaining characters in the substream.
- if (substream.bytes_left != 0) {
+ if (substream.bytes_left() != 0) {
// TODO(rsgowman): figure out error handling
abort();
}
- pb_close_string_substream(stream, &substream);
+ pb_close_string_substream(&stream_, &substream.stream_);
- return fv;
+ return message;
}
/**
@@ -475,102 +577,90 @@ FieldValue DecodeNestedFieldValue(pb_istream_t* stream) {
*/
void EncodeFieldsEntry(Writer* writer, const ObjectValue::Map::value_type& kv) {
// Write the key (string)
- writer->WriteTag(PB_WT_STRING,
- google_firestore_v1beta1_MapValue_FieldsEntry_key_tag);
+ writer->WriteTag(
+ {PB_WT_STRING, google_firestore_v1beta1_MapValue_FieldsEntry_key_tag});
writer->WriteString(kv.first);
// Write the value (FieldValue)
- writer->WriteTag(PB_WT_STRING,
- google_firestore_v1beta1_MapValue_FieldsEntry_value_tag);
+ writer->WriteTag(
+ {PB_WT_STRING, google_firestore_v1beta1_MapValue_FieldsEntry_value_tag});
writer->WriteNestedMessage(
[&kv](Writer* writer) { EncodeFieldValueImpl(writer, kv.second); });
}
-ObjectValue::Map::value_type DecodeFieldsEntry(pb_istream_t* stream) {
- pb_wire_type_t wire_type;
- uint32_t tag;
- bool eof;
- bool status = pb_decode_tag(stream, &wire_type, &tag, &eof);
+ObjectValue::Map::value_type DecodeFieldsEntry(Reader* reader) {
+ Tag tag = reader->ReadTag();
+
// TODO(rsgowman): figure out error handling: We can do better than a failed
// assertion.
- FIREBASE_ASSERT(tag == google_firestore_v1beta1_MapValue_FieldsEntry_key_tag);
- FIREBASE_ASSERT(wire_type == PB_WT_STRING);
- FIREBASE_ASSERT(!eof);
- FIREBASE_ASSERT(status);
- std::string key = DecodeString(stream);
-
- status = pb_decode_tag(stream, &wire_type, &tag, &eof);
- FIREBASE_ASSERT(tag ==
+ FIREBASE_ASSERT(tag.field_number ==
+ google_firestore_v1beta1_MapValue_FieldsEntry_key_tag);
+ FIREBASE_ASSERT(tag.wire_type == PB_WT_STRING);
+ std::string key = reader->ReadString();
+
+ tag = reader->ReadTag();
+ FIREBASE_ASSERT(tag.field_number ==
google_firestore_v1beta1_MapValue_FieldsEntry_value_tag);
- FIREBASE_ASSERT(wire_type == PB_WT_STRING);
- FIREBASE_ASSERT(!eof);
- FIREBASE_ASSERT(status);
+ FIREBASE_ASSERT(tag.wire_type == PB_WT_STRING);
- FieldValue value = DecodeNestedFieldValue(stream);
+ FieldValue value =
+ reader->ReadNestedMessage<FieldValue>(DecodeFieldValueImpl);
return {key, value};
}
void EncodeObject(Writer* writer, const ObjectValue& object_value) {
- writer->WriteNestedMessage([&object_value](Writer* writer) {
+ return writer->WriteNestedMessage([&object_value](Writer* writer) {
// Write each FieldsEntry (i.e. key-value pair.)
for (const auto& kv : object_value.internal_value) {
- writer->WriteTag(PB_WT_STRING,
- google_firestore_v1beta1_MapValue_FieldsEntry_key_tag);
+ writer->WriteTag({PB_WT_STRING,
+ google_firestore_v1beta1_MapValue_FieldsEntry_key_tag});
writer->WriteNestedMessage(
- [&kv](Writer* writer) { EncodeFieldsEntry(writer, kv); });
+ [&kv](Writer* writer) { return EncodeFieldsEntry(writer, kv); });
}
-
- return true;
});
}
-ObjectValue DecodeObject(pb_istream_t* stream) {
- google_firestore_v1beta1_MapValue map_value =
- google_firestore_v1beta1_MapValue_init_zero;
- ObjectValue::Map result;
- // NB: c-style callbacks can't use *capturing* lambdas, so we'll pass in the
- // object_value via the arg field (and therefore need to do a bunch of
- // casting).
- map_value.fields.funcs.decode = [](pb_istream_t* stream, const pb_field_t*,
- void** arg) -> bool {
- auto& result = *static_cast<ObjectValue::Map*>(*arg);
-
- ObjectValue::Map::value_type fv = DecodeFieldsEntry(stream);
-
- // Sanity check: ensure that this key doesn't already exist in the map.
- // TODO(rsgowman): figure out error handling: We can do better than a failed
- // assertion.
- FIREBASE_ASSERT(result.find(fv.first) == result.end());
-
- // Add this key,fieldvalue to the results map.
- result.emplace(std::move(fv));
-
- return true;
- };
- map_value.fields.arg = &result;
-
- bool status = pb_decode_delimited(
- stream, google_firestore_v1beta1_MapValue_fields, &map_value);
- if (!status) {
- // TODO(rsgowman): figure out error handling
- abort();
- }
-
- return ObjectValue{result};
+ObjectValue DecodeObject(Reader* reader) {
+ ObjectValue::Map internal_value = reader->ReadNestedMessage<ObjectValue::Map>(
+ [](Reader* reader) -> ObjectValue::Map {
+ ObjectValue::Map result;
+ while (reader->bytes_left()) {
+ Tag tag = reader->ReadTag();
+ FIREBASE_ASSERT(tag.field_number ==
+ google_firestore_v1beta1_MapValue_fields_tag);
+ FIREBASE_ASSERT(tag.wire_type == PB_WT_STRING);
+
+ ObjectValue::Map::value_type fv =
+ reader->ReadNestedMessage<ObjectValue::Map::value_type>(
+ DecodeFieldsEntry);
+
+ // Sanity check: ensure that this key doesn't already exist in the
+ // map.
+ // TODO(rsgowman): figure out error handling: We can do better than a
+ // failed assertion.
+ FIREBASE_ASSERT(result.find(fv.first) == result.end());
+
+ // Add this key,fieldvalue to the results map.
+ result.emplace(std::move(fv));
+ }
+ return result;
+ });
+ return ObjectValue{internal_value};
}
} // namespace
-void Serializer::EncodeFieldValue(const FieldValue& field_value,
- std::vector<uint8_t>* out_bytes) {
+Status Serializer::EncodeFieldValue(const FieldValue& field_value,
+ std::vector<uint8_t>* out_bytes) {
Writer writer = Writer::Wrap(out_bytes);
EncodeFieldValueImpl(&writer, field_value);
+ return writer.status();
}
FieldValue Serializer::DecodeFieldValue(const uint8_t* bytes, size_t length) {
- pb_istream_t stream = pb_istream_from_buffer(bytes, length);
- return DecodeFieldValueImpl(&stream);
+ Reader reader = Reader::Wrap(bytes, length);
+ return DecodeFieldValueImpl(&reader);
}
} // namespace remote
diff --git a/Firestore/core/src/firebase/firestore/remote/serializer.h b/Firestore/core/src/firebase/firestore/remote/serializer.h
index 10cacbc..7541ef5 100644
--- a/Firestore/core/src/firebase/firestore/remote/serializer.h
+++ b/Firestore/core/src/firebase/firestore/remote/serializer.h
@@ -17,13 +17,15 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_REMOTE_SERIALIZER_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_REMOTE_SERIALIZER_H_
-#include <stdint.h>
-#include <stdlib.h>
+#include <cstdint>
+#include <cstdlib>
#include <vector>
#include "Firestore/Protos/nanopb/google/firestore/v1beta1/document.pb.h"
#include "Firestore/core/src/firebase/firestore/model/field_value.h"
#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
+#include "Firestore/core/src/firebase/firestore/util/status.h"
+#include "absl/base/attributes.h"
namespace firebase {
namespace firestore {
@@ -70,7 +72,7 @@ class Serializer {
// TODO(rsgowman): If we never support any output except to a vector, it may
// make sense to have Serializer own the vector and provide an accessor rather
// than asking the user to create it first.
- static void EncodeFieldValue(
+ util::Status EncodeFieldValue(
const firebase::firestore::model::FieldValue& field_value,
std::vector<uint8_t>* out_bytes);
@@ -82,8 +84,7 @@ class Serializer {
* @return The model equivalent of the bytes.
*/
// TODO(rsgowman): error handling.
- static firebase::firestore::model::FieldValue DecodeFieldValue(
- const uint8_t* bytes, size_t length);
+ model::FieldValue DecodeFieldValue(const uint8_t* bytes, size_t length);
/**
* @brief Converts from bytes to the model FieldValue format.
@@ -93,14 +94,13 @@ class Serializer {
* @return The model equivalent of the bytes.
*/
// TODO(rsgowman): error handling.
- static firebase::firestore::model::FieldValue DecodeFieldValue(
- const std::vector<uint8_t>& bytes) {
+ model::FieldValue DecodeFieldValue(const std::vector<uint8_t>& bytes) {
return DecodeFieldValue(bytes.data(), bytes.size());
}
private:
// TODO(rsgowman): We don't need the database_id_ yet (but will eventually).
- // const firebase::firestore::model::DatabaseId& database_id_;
+ // model::DatabaseId* database_id_;
};
} // namespace remote
diff --git a/Firestore/core/src/firebase/firestore/timestamp.cc b/Firestore/core/src/firebase/firestore/timestamp.cc
index 7d947c5..a5f0121 100644
--- a/Firestore/core/src/firebase/firestore/timestamp.cc
+++ b/Firestore/core/src/firebase/firestore/timestamp.cc
@@ -48,7 +48,7 @@ Timestamp Timestamp::Now() {
}
Timestamp Timestamp::FromTimeT(const time_t seconds_since_unix_epoch) {
- return Timestamp(seconds_since_unix_epoch, 0);
+ return {seconds_since_unix_epoch, 0};
}
#if !defined(_STLPORT_VERSION)
diff --git a/Firestore/core/src/firebase/firestore/util/CMakeLists.txt b/Firestore/core/src/firebase/firestore/util/CMakeLists.txt
index eac7053..701d288 100644
--- a/Firestore/core/src/firebase/firestore/util/CMakeLists.txt
+++ b/Firestore/core/src/firebase/firestore/util/CMakeLists.txt
@@ -31,9 +31,11 @@ cc_library(
## assert and log
cc_library(
- firebase_firestore_util_stdio
+ firebase_firestore_util_log_stdio
SOURCES
+ firebase_assert.h
assert_stdio.cc
+ log.h
log_stdio.cc
DEPENDS
firebase_firestore_util_base
@@ -42,9 +44,11 @@ cc_library(
)
cc_library(
- firebase_firestore_util_apple
+ firebase_firestore_util_log_apple
SOURCES
+ firebase_assert.h
assert_apple.mm
+ log.h
log_apple.mm
string_apple.h
DEPENDS
@@ -53,12 +57,16 @@ cc_library(
EXCLUDE_FROM_ALL
)
-# Export a dependency on the correct logging library for this platform. All
-# buildable libraries are built and tested but only the best fit is exported.
if(APPLE)
- list(APPEND UTIL_DEPENDS firebase_firestore_util_apple)
+ set(
+ FIREBASE_FIRESTORE_UTIL_LOG
+ firebase_firestore_util_log_apple
+ )
else()
- list(APPEND UTIL_DEPENDS firebase_firestore_util_stdio)
+ set(
+ FIREBASE_FIRESTORE_UTIL_LOG
+ firebase_firestore_util_log_stdio
+ )
endif()
@@ -66,7 +74,7 @@ endif()
check_symbol_exists(arc4random stdlib.h HAVE_ARC4RANDOM)
cc_library(
- firebase_firestore_util_arc4random
+ firebase_firestore_util_random_arc4random
SOURCES
secure_random_arc4random.cc
)
@@ -77,7 +85,7 @@ get_target_property(
)
check_include_files(openssl/rand.h HAVE_OPENSSL_RAND_H)
cc_library(
- firebase_firestore_util_openssl
+ firebase_firestore_util_random_openssl
SOURCES
secure_random_openssl.cc
DEPENDS
@@ -85,10 +93,16 @@ cc_library(
)
if(HAVE_ARC4RANDOM)
- list(APPEND UTIL_DEPENDS firebase_firestore_util_arc4random)
+ set(
+ FIREBASE_FIRESTORE_UTIL_RANDOM
+ firebase_firestore_util_random_arc4random
+ )
elseif(HAVE_OPENSSL_RAND_H)
- list(APPEND UTIL_DEPENDS firebase_firestore_util_openssl)
+ set(
+ FIREBASE_FIRESTORE_UTIL_RANDOM
+ firebase_firestore_util_random_openssl
+ )
else()
message(FATAL_ERROR "No implementation for SecureRandom available.")
@@ -97,6 +111,7 @@ endif()
## main library
+
configure_file(
config.h.in
config.h
@@ -113,9 +128,7 @@ cc_library(
comparison.cc
comparison.h
config.h
- firebase_assert.h
iterator_adaptors.h
- log.h
ordered_code.cc
ordered_code.h
secure_random.h
@@ -127,7 +140,8 @@ cc_library(
string_util.cc
string_util.h
DEPENDS
- ${UTIL_DEPENDS}
- firebase_firestore_util_base
absl_base
+ firebase_firestore_util_base
+ ${FIREBASE_FIRESTORE_UTIL_LOG}
+ ${FIREBASE_FIRESTORE_UTIL_RANDOM}
)
diff --git a/Firestore/core/src/firebase/firestore/util/assert_apple.mm b/Firestore/core/src/firebase/firestore/util/assert_apple.mm
index 83b76e1..9b6a651 100644
--- a/Firestore/core/src/firebase/firestore/util/assert_apple.mm
+++ b/Firestore/core/src/firebase/firestore/util/assert_apple.mm
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
-
#import <Foundation/Foundation.h>
-#include <string.h>
-
+// TODO(wilhuff): match basenames so this can move up top
+#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
namespace firebase {
diff --git a/Firestore/core/src/firebase/firestore/util/assert_stdio.cc b/Firestore/core/src/firebase/firestore/util/assert_stdio.cc
index 1d2e333..e01e564 100644
--- a/Firestore/core/src/firebase/firestore/util/assert_stdio.cc
+++ b/Firestore/core/src/firebase/firestore/util/assert_stdio.cc
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#include <stdarg.h>
-
+#include <cstdarg>
#include <stdexcept>
#include <string>
diff --git a/Firestore/core/src/firebase/firestore/util/bits.h b/Firestore/core/src/firebase/firestore/util/bits.h
index 185273f..94a018f 100644
--- a/Firestore/core/src/firebase/firestore/util/bits.h
+++ b/Firestore/core/src/firebase/firestore/util/bits.h
@@ -22,7 +22,7 @@
// Munging bits in _signed_ integers is fraught with peril! For example,
// -5 << n has undefined behavior (for some values of n).
-#include <stdint.h>
+#include <cstdint>
class Bits_Port32_Test;
class Bits_Port64_Test;
@@ -139,23 +139,23 @@ inline int Bits::Log2FloorNonZero_Portable(uint32_t n) {
// Log2Floor64() is defined in terms of Log2Floor32(), Log2FloorNonZero32()
inline int Bits::Log2Floor64_Portable(uint64_t n) {
- const uint32_t topbits = static_cast<uint32_t>(n >> 32);
- if (topbits == 0) {
+ const auto top_bits = static_cast<uint32_t>(n >> 32);
+ if (top_bits == 0) {
// Top bits are zero, so scan in bottom bits
return Log2Floor(static_cast<uint32_t>(n));
} else {
- return 32 + Log2FloorNonZero(topbits);
+ return 32 + Log2FloorNonZero(top_bits);
}
}
// Log2FloorNonZero64() is defined in terms of Log2FloorNonZero32()
inline int Bits::Log2FloorNonZero64_Portable(uint64_t n) {
- const uint32_t topbits = static_cast<uint32_t>(n >> 32);
- if (topbits == 0) {
+ const auto top_bits = static_cast<uint32_t>(n >> 32);
+ if (top_bits == 0) {
// Top bits are zero, so scan in bottom bits
return Log2FloorNonZero(static_cast<uint32_t>(n));
} else {
- return 32 + Log2FloorNonZero(topbits);
+ return 32 + Log2FloorNonZero(top_bits);
}
}
diff --git a/Firestore/core/src/firebase/firestore/util/comparator_holder.h b/Firestore/core/src/firebase/firestore/util/comparator_holder.h
index 8641b0f..c7f6144 100644
--- a/Firestore/core/src/firebase/firestore/util/comparator_holder.h
+++ b/Firestore/core/src/firebase/firestore/util/comparator_holder.h
@@ -47,7 +47,7 @@ class ComparatorHolder {
template <typename C>
class ComparatorHolder<C, true> : private C {
protected:
- explicit ComparatorHolder(const C&) noexcept {
+ explicit ComparatorHolder(const C& /* comparator */) noexcept {
}
const C& comparator() const noexcept {
diff --git a/Firestore/core/src/firebase/firestore/util/comparison.cc b/Firestore/core/src/firebase/firestore/util/comparison.cc
index 4bef843..5ac4c27 100644
--- a/Firestore/core/src/firebase/firestore/util/comparison.cc
+++ b/Firestore/core/src/firebase/firestore/util/comparison.cc
@@ -16,10 +16,11 @@
#include "Firestore/core/src/firebase/firestore/util/comparison.h"
-#include <math.h>
-
+#include <cmath>
#include <limits>
+using std::isnan;
+
namespace firebase {
namespace firestore {
namespace util {
@@ -77,7 +78,7 @@ ComparisonResult CompareMixedNumber(double double_value, int64_t int64_value) {
// At this point the long representations are equal but this could be due to
// rounding.
- double int64_as_double = static_cast<double>(int64_value);
+ auto int64_as_double = static_cast<double>(int64_value);
return Compare<double>(double_value, int64_as_double);
}
diff --git a/Firestore/core/src/firebase/firestore/util/comparison.h b/Firestore/core/src/firebase/firestore/util/comparison.h
index 6fd1e2b..23207f5 100644
--- a/Firestore/core/src/firebase/firestore/util/comparison.h
+++ b/Firestore/core/src/firebase/firestore/util/comparison.h
@@ -21,9 +21,9 @@
#import <Foundation/Foundation.h>
#endif
-#include <stdint.h>
#include <sys/types.h>
+#include <cstdint>
#include <functional>
#include <string>
#include <vector>
diff --git a/Firestore/core/src/firebase/firestore/util/firebase_assert.h b/Firestore/core/src/firebase/firestore/util/firebase_assert.h
index 20c8429..6a9c2eb 100644
--- a/Firestore/core/src/firebase/firestore/util/firebase_assert.h
+++ b/Firestore/core/src/firebase/firestore/util/firebase_assert.h
@@ -20,7 +20,7 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_FIREBASE_ASSERT_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_FIREBASE_ASSERT_H_
-#include <stdlib.h>
+#include <cstdlib>
#include "Firestore/core/src/firebase/firestore/util/log.h"
#include "absl/base/attributes.h"
@@ -76,10 +76,6 @@
} \
} while (0)
-// Assert with custom message that is not compiled out in release builds.
-#define FIREBASE_ASSERT_MESSAGE(expression, ...) \
- FIREBASE_ASSERT_MESSAGE_WITH_EXPRESSION(expression, expression, __VA_ARGS__)
-
// Assert condition is true otherwise display the specified expression,
// message and abort. Compiled out of release builds.
#if defined(NDEBUG)
@@ -103,16 +99,18 @@
FIREBASE_DEV_ASSERT_MESSAGE_WITH_EXPRESSION(expression, expression, \
__VA_ARGS__)
+// Indicates an area of the code that cannot be reached (except possibly due to
+// undefined behaviour or other similar badness). The only reasonable thing to
+// do in these cases is to immediately abort.
+#define FIREBASE_UNREACHABLE() abort()
+
namespace firebase {
namespace firestore {
namespace util {
// A no-return helper function. To raise an assertion, use Macro instead.
-ABSL_ATTRIBUTE_NORETURN void FailAssert(const char* file,
- const char* func,
- const int line,
- const char* format,
- ...);
+ABSL_ATTRIBUTE_NORETURN void FailAssert(
+ const char* file, const char* func, int line, const char* format, ...);
} // namespace util
} // namespace firestore
diff --git a/Firestore/core/src/firebase/firestore/util/log.h b/Firestore/core/src/firebase/firestore/util/log.h
index d0cff4d..1944596 100644
--- a/Firestore/core/src/firebase/firestore/util/log.h
+++ b/Firestore/core/src/firebase/firestore/util/log.h
@@ -17,7 +17,7 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_LOG_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_LOG_H_
-#include <stdarg.h>
+#include <cstdarg>
namespace firebase {
namespace firestore {
diff --git a/Firestore/core/src/firebase/firestore/util/log_stdio.cc b/Firestore/core/src/firebase/firestore/util/log_stdio.cc
index bca2dc9..b277406 100644
--- a/Firestore/core/src/firebase/firestore/util/log_stdio.cc
+++ b/Firestore/core/src/firebase/firestore/util/log_stdio.cc
@@ -16,7 +16,7 @@
#include "Firestore/core/src/firebase/firestore/util/log.h"
-#include <stdio.h>
+#include <cstdio>
#include <string>
namespace firebase {
diff --git a/Firestore/core/src/firebase/firestore/util/ordered_code.cc b/Firestore/core/src/firebase/firestore/util/ordered_code.cc
index 0eadf18..cb53b09 100644
--- a/Firestore/core/src/firebase/firestore/util/ordered_code.cc
+++ b/Firestore/core/src/firebase/firestore/util/ordered_code.cc
@@ -16,12 +16,11 @@
#include "Firestore/core/src/firebase/firestore/util/ordered_code.h"
-#include <absl/base/internal/endian.h>
-#include <absl/base/internal/unaligned_access.h>
-#include <absl/base/port.h>
-
#include "Firestore/core/src/firebase/firestore/util/bits.h"
#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/unaligned_access.h"
+#include "absl/base/port.h"
#define UNALIGNED_LOAD32 ABSL_INTERNAL_UNALIGNED_LOAD32
#define UNALIGNED_LOAD64 ABSL_INTERNAL_UNALIGNED_LOAD64
diff --git a/Firestore/core/src/firebase/firestore/util/secure_random.h b/Firestore/core/src/firebase/firestore/util/secure_random.h
index 95b41e1..f030b5e 100644
--- a/Firestore/core/src/firebase/firestore/util/secure_random.h
+++ b/Firestore/core/src/firebase/firestore/util/secure_random.h
@@ -17,7 +17,7 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_SECURE_RANDOM_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_SECURE_RANDOM_H_
-#include <stdint.h>
+#include <cstdint>
#include <limits>
diff --git a/Firestore/core/src/firebase/firestore/util/secure_random_arc4random.cc b/Firestore/core/src/firebase/firestore/util/secure_random_arc4random.cc
index 83f72b5..d7e9be3 100644
--- a/Firestore/core/src/firebase/firestore/util/secure_random_arc4random.cc
+++ b/Firestore/core/src/firebase/firestore/util/secure_random_arc4random.cc
@@ -20,7 +20,7 @@
#if HAVE_ARC4RANDOM
-#include <stdlib.h>
+#include <cstdlib>
namespace firebase {
namespace firestore {
diff --git a/Firestore/core/src/firebase/firestore/util/secure_random_openssl.cc b/Firestore/core/src/firebase/firestore/util/secure_random_openssl.cc
index d3f6e63..e024846 100644
--- a/Firestore/core/src/firebase/firestore/util/secure_random_openssl.cc
+++ b/Firestore/core/src/firebase/firestore/util/secure_random_openssl.cc
@@ -20,8 +20,8 @@
#if HAVE_OPENSSL_RAND_H
-#include <openssl/err.h>
-#include <openssl/rand.h>
+#include "openssl/err.h"
+#include "openssl/rand.h"
namespace firebase {
namespace firestore {
diff --git a/Firestore/core/src/firebase/firestore/util/string_printf.cc b/Firestore/core/src/firebase/firestore/util/string_printf.cc
index 9c4e31c..c5483f4 100644
--- a/Firestore/core/src/firebase/firestore/util/string_printf.cc
+++ b/Firestore/core/src/firebase/firestore/util/string_printf.cc
@@ -16,7 +16,7 @@
#include "Firestore/core/src/firebase/firestore/util/string_printf.h"
-#include <stdio.h>
+#include <cstdio>
namespace firebase {
namespace firestore {
diff --git a/Firestore/core/src/firebase/firestore/util/string_printf.h b/Firestore/core/src/firebase/firestore/util/string_printf.h
index 10dfae9..553af66 100644
--- a/Firestore/core/src/firebase/firestore/util/string_printf.h
+++ b/Firestore/core/src/firebase/firestore/util/string_printf.h
@@ -17,8 +17,7 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_PRINTF_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_PRINTF_H_
-#include <stdarg.h>
-
+#include <cstdarg>
#include <string>
#include "absl/base/attributes.h"
diff --git a/Firestore/core/test/firebase/firestore/immutable/array_sorted_map_test.cc b/Firestore/core/test/firebase/firestore/immutable/array_sorted_map_test.cc
index fceab7d..6758dd5 100644
--- a/Firestore/core/test/firebase/firestore/immutable/array_sorted_map_test.cc
+++ b/Firestore/core/test/firebase/firestore/immutable/array_sorted_map_test.cc
@@ -29,7 +29,7 @@ namespace firestore {
namespace immutable {
namespace impl {
-typedef ArraySortedMap<int, int> IntMap;
+using IntMap = ArraySortedMap<int, int>;
constexpr IntMap::size_type kFixedSize = IntMap::kFixedSize;
// TODO(wilhuff): ReverseTraversal
@@ -153,7 +153,7 @@ TEST(ArraySortedMap, EmptyRemoval) {
TEST(ArraySortedMap, InsertionAndRemovalOfMaxItems) {
auto expected_size = kFixedSize;
- int n = static_cast<int>(expected_size);
+ auto n = static_cast<int>(expected_size);
std::vector<int> to_insert = Shuffled(Sequence(n));
std::vector<int> to_remove = Shuffled(to_insert);
diff --git a/Firestore/core/test/firebase/firestore/immutable/sorted_map_test.cc b/Firestore/core/test/firebase/firestore/immutable/sorted_map_test.cc
index 44dca50..747c66b 100644
--- a/Firestore/core/test/firebase/firestore/immutable/sorted_map_test.cc
+++ b/Firestore/core/test/firebase/firestore/immutable/sorted_map_test.cc
@@ -49,6 +49,7 @@ class SortedMapTest : public ::testing::Test {
}
};
+// NOLINTNEXTLINE: must be a typedef for the gtest macros
typedef ::testing::Types<SortedMap<int, int>,
impl::ArraySortedMap<int, int>,
impl::TreeSortedMap<int, int>>
diff --git a/Firestore/core/test/firebase/firestore/immutable/tree_sorted_map_test.cc b/Firestore/core/test/firebase/firestore/immutable/tree_sorted_map_test.cc
index 7a96b67..c03dc6c 100644
--- a/Firestore/core/test/firebase/firestore/immutable/tree_sorted_map_test.cc
+++ b/Firestore/core/test/firebase/firestore/immutable/tree_sorted_map_test.cc
@@ -25,7 +25,7 @@ namespace firestore {
namespace immutable {
namespace impl {
-typedef TreeSortedMap<int, int> IntMap;
+using IntMap = TreeSortedMap<int, int>;
TEST(TreeSortedMap, EmptySize) {
IntMap map;
diff --git a/Firestore/core/test/firebase/firestore/model/CMakeLists.txt b/Firestore/core/test/firebase/firestore/model/CMakeLists.txt
index 2c2281f..9c94677 100644
--- a/Firestore/core/test/firebase/firestore/model/CMakeLists.txt
+++ b/Firestore/core/test/firebase/firestore/model/CMakeLists.txt
@@ -18,12 +18,16 @@ cc_test(
database_id_test.cc
document_key_test.cc
document_test.cc
+ field_mask_test.cc
field_path_test.cc
+ field_transform_test.cc
field_value_test.cc
maybe_document_test.cc
no_document_test.cc
+ precondition_test.cc
resource_path_test.cc
snapshot_version_test.cc
+ transform_operations_test.cc
DEPENDS
firebase_firestore_model
)
diff --git a/Firestore/core/test/firebase/firestore/model/document_key_test.cc b/Firestore/core/test/firebase/firestore/model/document_key_test.cc
index 0e0df2d..619ee7f 100644
--- a/Firestore/core/test/firebase/firestore/model/document_key_test.cc
+++ b/Firestore/core/test/firebase/firestore/model/document_key_test.cc
@@ -46,7 +46,7 @@ TEST(DocumentKey, Constructor_FromPath) {
EXPECT_EQ(key_from_path_copy.path(), path);
const DocumentKey key_from_moved_path{std::move(path)};
- EXPECT_TRUE(path.empty());
+ EXPECT_TRUE(path.empty()); // NOLINT: use after move intended
EXPECT_FALSE(key_from_moved_path.path().empty());
EXPECT_EQ(key_from_path_copy.path(), key_from_moved_path.path());
}
@@ -62,7 +62,7 @@ TEST(DocumentKey, CopyAndMove) {
const DocumentKey moved = std::move(key);
EXPECT_EQ(path_string, moved.path().CanonicalString());
- EXPECT_NE(key, moved);
+ EXPECT_NE(key, moved); // NOLINT: use after move intended
EXPECT_TRUE(key.path().empty());
// Reassignment.
@@ -74,7 +74,7 @@ TEST(DocumentKey, CopyAndMove) {
key = {};
EXPECT_TRUE(key.path().empty());
key = std::move(copied);
- EXPECT_NE(copied, key);
+ EXPECT_NE(copied, key); // NOLINT: use after move intended
EXPECT_TRUE(copied.path().empty());
EXPECT_EQ(path_string, key.path().CanonicalString());
}
diff --git a/Firestore/core/test/firebase/firestore/model/field_mask_test.cc b/Firestore/core/test/firebase/firestore/model/field_mask_test.cc
new file mode 100644
index 0000000..52d5951
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/model/field_mask_test.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/field_mask.h"
+
+#include <vector>
+
+#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+TEST(FieldMask, ConstructorAndEqual) {
+ FieldMask mask_a{FieldPath::FromServerFormat("foo"),
+ FieldPath::FromServerFormat("bar")};
+ std::vector<FieldPath> field_path_vector{FieldPath::FromServerFormat("foo"),
+ FieldPath::FromServerFormat("bar")};
+ FieldMask mask_b{field_path_vector};
+ FieldMask mask_c{std::vector<FieldPath>{FieldPath::FromServerFormat("foo"),
+ FieldPath::FromServerFormat("bar")}};
+ EXPECT_EQ(mask_a, mask_b);
+ EXPECT_EQ(mask_b, mask_c);
+}
+
+TEST(FieldMask, Getter) {
+ FieldMask mask{FieldPath::FromServerFormat("foo"),
+ FieldPath::FromServerFormat("bar")};
+ EXPECT_EQ(std::vector<FieldPath>({FieldPath::FromServerFormat("foo"),
+ FieldPath::FromServerFormat("bar")}),
+ std::vector<FieldPath>(mask.begin(), mask.end()));
+}
+
+TEST(FieldMask, ToString) {
+ FieldMask mask{FieldPath::FromServerFormat("foo"),
+ FieldPath::FromServerFormat("bar")};
+ EXPECT_EQ("{ foo bar }", mask.ToString());
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/model/field_path_test.cc b/Firestore/core/test/firebase/firestore/model/field_path_test.cc
index a5ae3b2..a215a96 100644
--- a/Firestore/core/test/firebase/firestore/model/field_path_test.cc
+++ b/Firestore/core/test/firebase/firestore/model/field_path_test.cc
@@ -47,7 +47,7 @@ TEST(FieldPath, Constructors) {
EXPECT_EQ(path_from_list, copied);
const FieldPath moved = std::move(copied);
EXPECT_EQ(path_from_list, moved);
- EXPECT_NE(copied, moved);
+ EXPECT_NE(copied, moved); // NOLINT: use after move intended
EXPECT_EQ(empty_path, copied);
}
@@ -68,7 +68,7 @@ TEST(FieldPath, PopFirst) {
const FieldPath bc{"Eros", "messages"};
const FieldPath c{"messages"};
const FieldPath empty;
- const FieldPath abc_dupl{"rooms", "Eros", "messages"};
+ const FieldPath abc_dup{"rooms", "Eros", "messages"};
EXPECT_NE(empty, c);
EXPECT_NE(c, bc);
@@ -77,7 +77,7 @@ TEST(FieldPath, PopFirst) {
EXPECT_EQ(bc, abc.PopFirst());
EXPECT_EQ(c, abc.PopFirst(2));
EXPECT_EQ(empty, abc.PopFirst(3));
- EXPECT_EQ(abc_dupl, abc);
+ EXPECT_EQ(abc_dup, abc);
}
TEST(FieldPath, PopLast) {
@@ -85,7 +85,7 @@ TEST(FieldPath, PopLast) {
const FieldPath ab{"rooms", "Eros"};
const FieldPath a{"rooms"};
const FieldPath empty;
- const FieldPath abc_dupl{"rooms", "Eros", "messages"};
+ const FieldPath abc_dup{"rooms", "Eros", "messages"};
EXPECT_EQ(ab, abc.PopLast());
EXPECT_EQ(a, abc.PopLast().PopLast());
diff --git a/Firestore/core/test/firebase/firestore/model/field_transform_test.cc b/Firestore/core/test/firebase/firestore/model/field_transform_test.cc
new file mode 100644
index 0000000..b66aeef
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/model/field_transform_test.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/field_transform.h"
+#include "Firestore/core/src/firebase/firestore/model/transform_operations.h"
+#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+
+#include "absl/memory/memory.h"
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+TEST(FieldTransform, Getter) {
+ FieldTransform transform(testutil::Field("foo"),
+ absl::make_unique<ServerTimestampTransform>(
+ ServerTimestampTransform::Get()));
+
+ EXPECT_EQ(testutil::Field("foo"), transform.path());
+ EXPECT_EQ(ServerTimestampTransform::Get(), transform.transformation());
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/model/field_value_test.cc b/Firestore/core/test/firebase/firestore/model/field_value_test.cc
index 40be2d5..c5645a4 100644
--- a/Firestore/core/test/firebase/firestore/model/field_value_test.cc
+++ b/Firestore/core/test/firebase/firestore/model/field_value_test.cc
@@ -16,8 +16,7 @@
#include "Firestore/core/src/firebase/firestore/model/field_value.h"
-#include <limits.h>
-
+#include <climits>
#include <vector>
#include "gtest/gtest.h"
@@ -412,7 +411,7 @@ TEST(FieldValue, Move) {
EXPECT_EQ(FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"),
&database_id),
clone);
- clone = null_value;
+ clone = null_value; // NOLINT: use after move intended
EXPECT_EQ(FieldValue::NullValue(), clone);
FieldValue geo_point_value = FieldValue::GeoPointValue({1, 2});
diff --git a/Firestore/core/test/firebase/firestore/model/precondition_test.cc b/Firestore/core/test/firebase/firestore/model/precondition_test.cc
new file mode 100644
index 0000000..3ddb2ba
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/model/precondition_test.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/precondition.h"
+
+#include "Firestore/core/src/firebase/firestore/model/document.h"
+#include "Firestore/core/src/firebase/firestore/model/no_document.h"
+#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
+#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
+
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+TEST(Precondition, None) {
+ const Precondition none = Precondition::None();
+ EXPECT_EQ(Precondition::Type::None, none.type());
+ EXPECT_TRUE(none.IsNone());
+ EXPECT_EQ(SnapshotVersion::None(), none.update_time());
+
+ const NoDocument deleted_doc = testutil::DeletedDoc("foo/doc", 1234567);
+ const Document doc = testutil::Doc("bar/doc", 7654321);
+ EXPECT_TRUE(none.IsValidFor(deleted_doc));
+ EXPECT_TRUE(none.IsValidFor(doc));
+}
+
+TEST(Precondition, Exists) {
+ const Precondition exists = Precondition::Exists(true);
+ const Precondition no_exists = Precondition::Exists(false);
+ EXPECT_EQ(Precondition::Type::Exists, exists.type());
+ EXPECT_EQ(Precondition::Type::Exists, no_exists.type());
+ EXPECT_FALSE(exists.IsNone());
+ EXPECT_FALSE(no_exists.IsNone());
+ EXPECT_EQ(SnapshotVersion::None(), exists.update_time());
+ EXPECT_EQ(SnapshotVersion::None(), no_exists.update_time());
+
+ const NoDocument deleted_doc = testutil::DeletedDoc("foo/doc", 1234567);
+ const Document doc = testutil::Doc("bar/doc", 7654321);
+ EXPECT_FALSE(exists.IsValidFor(deleted_doc));
+ EXPECT_TRUE(exists.IsValidFor(doc));
+ EXPECT_TRUE(no_exists.IsValidFor(deleted_doc));
+ EXPECT_FALSE(no_exists.IsValidFor(doc));
+}
+
+TEST(Precondition, UpdateTime) {
+ const Precondition update_time =
+ Precondition::UpdateTime(testutil::Version(1234567));
+ EXPECT_EQ(Precondition::Type::UpdateTime, update_time.type());
+ EXPECT_FALSE(update_time.IsNone());
+ EXPECT_EQ(testutil::Version(1234567), update_time.update_time());
+
+ const NoDocument deleted_doc = testutil::DeletedDoc("foo/doc", 1234567);
+ const Document not_match = testutil::Doc("bar/doc", 7654321);
+ const Document match = testutil::Doc("baz/doc", 1234567);
+ EXPECT_FALSE(update_time.IsValidFor(deleted_doc));
+ EXPECT_FALSE(update_time.IsValidFor(not_match));
+ EXPECT_TRUE(update_time.IsValidFor(match));
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/model/resource_path_test.cc b/Firestore/core/test/firebase/firestore/model/resource_path_test.cc
index 637e78e..8545884 100644
--- a/Firestore/core/test/firebase/firestore/model/resource_path_test.cc
+++ b/Firestore/core/test/firebase/firestore/model/resource_path_test.cc
@@ -47,7 +47,7 @@ TEST(ResourcePath, Constructor) {
EXPECT_EQ(path_from_list, copied);
const ResourcePath moved = std::move(copied);
EXPECT_EQ(path_from_list, moved);
- EXPECT_NE(copied, moved);
+ EXPECT_NE(copied, moved); // NOLINT: use after move intended
EXPECT_EQ(empty_path, copied);
}
diff --git a/Firestore/core/test/firebase/firestore/model/transform_operations_test.cc b/Firestore/core/test/firebase/firestore/model/transform_operations_test.cc
new file mode 100644
index 0000000..ec0882a
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/model/transform_operations_test.cc
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/transform_operations.h"
+
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+class DummyOperation : public TransformOperation {
+ public:
+ DummyOperation() {
+ }
+
+ Type type() const override {
+ return Type::Test;
+ }
+
+ bool operator==(const TransformOperation& other) const override {
+ return this == &other;
+ }
+};
+
+TEST(TransformOperations, ServerTimestamp) {
+ ServerTimestampTransform transform = ServerTimestampTransform::Get();
+ EXPECT_EQ(TransformOperation::Type::ServerTimestamp, transform.type());
+
+ ServerTimestampTransform another = ServerTimestampTransform::Get();
+ DummyOperation dummy;
+ EXPECT_EQ(transform, another);
+ EXPECT_NE(transform, dummy);
+}
+
+// TODO(mikelehen): Add ArrayTransform test once it no longer depends on
+// FSTFieldValue and can be exposed to C++ code.
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/remote/datastore_test.cc b/Firestore/core/test/firebase/firestore/remote/datastore_test.cc
index 42a9a8c..53e95a9 100644
--- a/Firestore/core/test/firebase/firestore/remote/datastore_test.cc
+++ b/Firestore/core/test/firebase/firestore/remote/datastore_test.cc
@@ -16,8 +16,9 @@
#include "Firestore/core/src/firebase/firestore/remote/datastore.h"
-#include <grpc/grpc.h>
-#include <gtest/gtest.h>
+#include "grpc/grpc.h"
+
+#include "gtest/gtest.h"
TEST(Datastore, CanLinkToGrpc) {
// This test doesn't actually do anything interesting as far as actually
diff --git a/Firestore/core/test/firebase/firestore/remote/serializer_test.cc b/Firestore/core/test/firebase/firestore/remote/serializer_test.cc
index 862ac97..addc830 100644
--- a/Firestore/core/test/firebase/firestore/remote/serializer_test.cc
+++ b/Firestore/core/test/firebase/firestore/remote/serializer_test.cc
@@ -42,17 +42,19 @@
#include <vector>
#include "Firestore/core/src/firebase/firestore/model/field_value.h"
+#include "Firestore/core/src/firebase/firestore/util/status.h"
#include "gtest/gtest.h"
using firebase::firestore::model::FieldValue;
using firebase::firestore::remote::Serializer;
+using firebase::firestore::util::Status;
TEST(Serializer, CanLinkToNanopb) {
// This test doesn't actually do anything interesting as far as actually using
// nanopb is concerned but that it can run at all is proof that all the
// libraries required for nanopb to work are actually linked correctly into
// the test.
- pb_ostream_from_buffer(NULL, 0);
+ pb_ostream_from_buffer(nullptr, 0);
}
// Fixture for running serializer tests.
@@ -67,7 +69,8 @@ class SerializerTest : public ::testing::Test {
FieldValue::Type type) {
EXPECT_EQ(type, model.type());
std::vector<uint8_t> actual_bytes;
- serializer.EncodeFieldValue(model, &actual_bytes);
+ Status status = serializer.EncodeFieldValue(model, &actual_bytes);
+ EXPECT_TRUE(status.ok());
EXPECT_EQ(bytes, actual_bytes);
FieldValue actual_model = serializer.DecodeFieldValue(bytes);
EXPECT_EQ(type, actual_model.type());
diff --git a/Firestore/core/test/firebase/firestore/testutil/testutil.h b/Firestore/core/test/firebase/firestore/testutil/testutil.h
index 9c69784..9a875f4 100644
--- a/Firestore/core/test/firebase/firestore/testutil/testutil.h
+++ b/Firestore/core/test/firebase/firestore/testutil/testutil.h
@@ -17,9 +17,16 @@
#ifndef FIRESTORE_CORE_TEST_FIREBASE_FIRESTORE_TESTUTIL_TESTUTIL_H_
#define FIRESTORE_CORE_TEST_FIREBASE_FIRESTORE_TESTUTIL_TESTUTIL_H_
+#include <chrono> // NOLINT(build/c++11)
+#include <cstdint>
+
+#include "Firestore/core/include/firebase/firestore/timestamp.h"
+#include "Firestore/core/src/firebase/firestore/model/document.h"
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
#include "Firestore/core/src/firebase/firestore/model/field_path.h"
+#include "Firestore/core/src/firebase/firestore/model/no_document.h"
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
+#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
#include "absl/strings/string_view.h"
namespace firebase {
@@ -40,6 +47,28 @@ inline model::ResourcePath Resource(absl::string_view field) {
return model::ResourcePath::FromString(field);
}
+/**
+ * Creates a snapshot version from the given version timestamp.
+ *
+ * @param version a timestamp in microseconds since the epoch.
+ */
+inline model::SnapshotVersion Version(int64_t version) {
+ namespace chr = std::chrono;
+ auto timepoint =
+ chr::time_point<chr::system_clock>(chr::microseconds(version));
+ return model::SnapshotVersion{Timestamp::FromTimePoint(timepoint)};
+}
+
+inline model::Document Doc(absl::string_view key, int64_t version) {
+ return model::Document{model::FieldValue::ObjectValueFromMap({}), Key(key),
+ Version(version),
+ /* has_local_mutations= */ false};
+}
+
+inline model::NoDocument DeletedDoc(absl::string_view key, int64_t version) {
+ return model::NoDocument{Key(key), Version(version)};
+}
+
// Add a non-inline function to make this library buildable.
// TODO(zxu123): remove once there is non-inline function.
void dummy();
diff --git a/Firestore/core/test/firebase/firestore/util/CMakeLists.txt b/Firestore/core/test/firebase/firestore/util/CMakeLists.txt
index 13482b0..e5dbec5 100644
--- a/Firestore/core/test/firebase/firestore/util/CMakeLists.txt
+++ b/Firestore/core/test/firebase/firestore/util/CMakeLists.txt
@@ -17,26 +17,52 @@ set(CMAKE_CXX_EXTENSIONS ON)
# Required to allow 0 length printf style strings for testing purposes.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-format-zero-length")
+## assert and log
+
+if(APPLE)
+ cc_test(
+ firebase_firestore_util_log_apple_test
+ SOURCES
+ assert_test.cc
+ log_test.cc
+ DEPENDS
+ firebase_firestore_util_log_apple
+ )
+endif(APPLE)
+
+cc_test(
+ firebase_firestore_util_log_stdio_test
+ SOURCES
+ assert_test.cc
+ log_test.cc
+ DEPENDS
+ firebase_firestore_util_log_stdio
+)
+
+## secure random
+
if(HAVE_ARC4RANDOM)
cc_test(
- firebase_firestore_util_arc4random_test
+ firebase_firestore_util_random_arc4random_test
SOURCES
secure_random_test.cc
DEPENDS
- firebase_firestore_util_arc4random
+ firebase_firestore_util_random_arc4random
)
endif()
if(HAVE_OPENSSL_RAND_H)
cc_test(
- firebase_firestore_util_openssl_test
+ firebase_firestore_util_random_openssl_test
SOURCES
secure_random_test.cc
DEPENDS
- firebase_firestore_util_openssl
+ firebase_firestore_util_random_openssl
)
endif()
+## main library
+
cc_test(
firebase_firestore_util_test
SOURCES
@@ -56,23 +82,3 @@ cc_test(
firebase_firestore_util
gmock
)
-
-if(APPLE)
- cc_test(
- firebase_firestore_util_apple_test
- SOURCES
- assert_test.cc
- log_test.cc
- DEPENDS
- firebase_firestore_util_apple
- )
-endif(APPLE)
-
-cc_test(
- firebase_firestore_util_stdio_test
- SOURCES
- assert_test.cc
- log_test.cc
- DEPENDS
- firebase_firestore_util_stdio
-)
diff --git a/Firestore/core/test/firebase/firestore/util/autoid_test.cc b/Firestore/core/test/firebase/firestore/util/autoid_test.cc
index 079b990..808850b 100644
--- a/Firestore/core/test/firebase/firestore/util/autoid_test.cc
+++ b/Firestore/core/test/firebase/firestore/util/autoid_test.cc
@@ -16,9 +16,9 @@
#include "Firestore/core/src/firebase/firestore/util/autoid.h"
-#include <ctype.h>
+#include <cctype>
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
using firebase::firestore::util::CreateAutoId;
diff --git a/Firestore/core/test/firebase/firestore/util/bits_test.cc b/Firestore/core/test/firebase/firestore/util/bits_test.cc
index cb0976b..572721f 100644
--- a/Firestore/core/test/firebase/firestore/util/bits_test.cc
+++ b/Firestore/core/test/firebase/firestore/util/bits_test.cc
@@ -69,16 +69,16 @@ TEST_F(BitsTest, Log2Random) {
std::cout << "TestLog2Random" << std::endl;
for (int i = 0; i < kNumIterations; i++) {
- int maxbit = -1;
+ int max_bit = -1;
uint32_t n = 0;
while (!random_.OneIn(32u)) {
int bit = static_cast<int>(random_.Uniform(32u));
n |= (1U << bit);
- maxbit = std::max(bit, maxbit);
+ max_bit = std::max(bit, max_bit);
}
- EXPECT_EQ(maxbit, Bits::Log2Floor(n));
+ EXPECT_EQ(max_bit, Bits::Log2Floor(n));
if (n != 0) {
- EXPECT_EQ(maxbit, Bits::Log2FloorNonZero(n));
+ EXPECT_EQ(max_bit, Bits::Log2FloorNonZero(n));
}
}
}
@@ -87,16 +87,16 @@ TEST_F(BitsTest, Log2Random64) {
std::cout << "TestLog2Random64" << std::endl;
for (int i = 0; i < kNumIterations; i++) {
- int maxbit = -1;
+ int max_bit = -1;
uint64_t n = 0;
while (!random_.OneIn(64u)) {
int bit = static_cast<int>(random_.Uniform(64u));
n |= (1ULL << bit);
- maxbit = std::max(bit, maxbit);
+ max_bit = std::max(bit, max_bit);
}
- EXPECT_EQ(maxbit, Bits::Log2Floor64(n));
+ EXPECT_EQ(max_bit, Bits::Log2Floor64(n));
if (n != 0) {
- EXPECT_EQ(maxbit, Bits::Log2FloorNonZero64(n));
+ EXPECT_EQ(max_bit, Bits::Log2FloorNonZero64(n));
}
}
}
diff --git a/Firestore/core/test/firebase/firestore/util/comparison_test.cc b/Firestore/core/test/firebase/firestore/util/comparison_test.cc
index ccb3011..a03aec8 100644
--- a/Firestore/core/test/firebase/firestore/util/comparison_test.cc
+++ b/Firestore/core/test/firebase/firestore/util/comparison_test.cc
@@ -16,9 +16,8 @@
#include "Firestore/core/src/firebase/firestore/util/comparison.h"
-#include <inttypes.h>
-#include <math.h>
-
+#include <cinttypes>
+#include <cmath>
#include <limits>
#include "Firestore/core/src/firebase/firestore/util/string_printf.h"
diff --git a/Firestore/core/test/firebase/firestore/util/secure_random_test.cc b/Firestore/core/test/firebase/firestore/util/secure_random_test.cc
index 0b7a51b..b0dfdd6 100644
--- a/Firestore/core/test/firebase/firestore/util/secure_random_test.cc
+++ b/Firestore/core/test/firebase/firestore/util/secure_random_test.cc
@@ -16,7 +16,7 @@
#include "Firestore/core/src/firebase/firestore/util/secure_random.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
using firebase::firestore::util::SecureRandom;
diff --git a/Firestore/core/test/firebase/firestore/util/string_printf_test.cc b/Firestore/core/test/firebase/firestore/util/string_printf_test.cc
index 085be84..14cc9c8 100644
--- a/Firestore/core/test/firebase/firestore/util/string_printf_test.cc
+++ b/Firestore/core/test/firebase/firestore/util/string_printf_test.cc
@@ -16,7 +16,7 @@
#include "Firestore/core/src/firebase/firestore/util/string_printf.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
namespace firebase {
namespace firestore {
diff --git a/Firestore/core/test/firebase/firestore/util/string_util_test.cc b/Firestore/core/test/firebase/firestore/util/string_util_test.cc
index f94596f..a85c849 100644
--- a/Firestore/core/test/firebase/firestore/util/string_util_test.cc
+++ b/Firestore/core/test/firebase/firestore/util/string_util_test.cc
@@ -16,7 +16,7 @@
#include "Firestore/core/src/firebase/firestore/util/string_util.h"
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
namespace firebase {
namespace firestore {
diff --git a/Functions/FirebaseFunctions/Public/FIRError.h b/Functions/FirebaseFunctions/Public/FIRError.h
index 3048dee..5037f7b 100644
--- a/Functions/FirebaseFunctions/Public/FIRError.h
+++ b/Functions/FirebaseFunctions/Public/FIRError.h
@@ -86,6 +86,6 @@ typedef NS_ENUM(NSInteger, FIRFunctionsErrorCode) {
FIRFunctionsErrorCodeDataLoss = 15,
/** The request does not have valid authentication credentials for the operation. */
FIRFunctionsErrorCodeUnauthenticated = 16,
-};
+} NS_SWIFT_NAME(FunctionsErrorCode);
NS_ASSUME_NONNULL_END
diff --git a/scripts/build.sh b/scripts/build.sh
index 8841dc9..827fc14 100755
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -119,6 +119,33 @@ case "$product-$method-$platform" in
"${xcb_flags[@]}" \
build \
test
+
+ # Test iOS Objective-C static library build
+ cd Example
+ sed -i -e 's/use_frameworks/\#use_frameworks/' Podfile
+ pod update --no-repo-update
+ # Workarounds for https://github.com/CocoaPods/CocoaPods/issues/7592.
+ # Remove when updating to CocoaPods 1.5.1
+ sed -i -e 's/-l"FirebaseMessaging"//' "Pods/Target Support Files/Pods-Messaging_Tests_iOS/Pods-Messaging_Tests_iOS.debug.xcconfig"
+ sed -i -e 's/-l"FirebaseAuth-iOS" -l"FirebaseCore-iOS"//' "Pods/Target Support Files/Pods-Auth_Tests_iOS/Pods-Auth_Tests_iOS.debug.xcconfig"
+ cd ..
+ RunXcodebuild \
+ -workspace 'Example/Firebase.xcworkspace' \
+ -scheme "AllUnitTests_$platform" \
+ "${xcb_flags[@]}" \
+ build \
+ test
+
+ cd Functions/Example
+ sed -i -e 's/use_frameworks/\#use_frameworks/' Podfile
+ pod update --no-repo-update
+ cd ../..
+ RunXcodebuild \
+ -workspace 'Functions/Example/FirebaseFunctions.xcworkspace' \
+ -scheme "FirebaseFunctions_Tests" \
+ "${xcb_flags[@]}" \
+ build \
+ test
fi
;;
diff --git a/scripts/cpplint.py b/scripts/cpplint.py
index d1c80b3..f09695c 100644
--- a/scripts/cpplint.py
+++ b/scripts/cpplint.py
@@ -428,6 +428,11 @@ _CPP_HEADERS = frozenset([
'cwctype',
])
+_C_SYSTEM_DIRECTORIES = frozenset([
+ 'libkern',
+ 'sys',
+])
+
# Type names
_TYPES = re.compile(
r'^(?:'
@@ -685,7 +690,7 @@ def Search(pattern, s):
def _IsSourceExtension(s):
"""File extension (excluding dot) matches a source file extension."""
- return s in ('c', 'cc', 'cpp', 'cxx')
+ return s in ('c', 'cc', 'cpp', 'cxx', 'm', 'mm')
class _IncludeState(object):
@@ -4411,7 +4416,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
-_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
+_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*(?:include|import)\s*([<"])([^>"]*)[>"].*$')
# Matches the first component of a filename delimited by -s and _s. That is:
# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
@@ -4444,6 +4449,11 @@ def _DropCommonSuffixes(filename):
if (filename.endswith(suffix) and len(filename) > len(suffix) and
filename[-len(suffix) - 1] in ('-', '_')):
return filename[:-len(suffix) - 1]
+
+ for suffix in ['Tests.h', 'Test.m', 'Test.mm', 'Tests.m', 'Tests.mm']:
+ if (filename.endswith(suffix) and len(filename) > len(suffix)):
+ return filename[:-len(suffix)]
+
return os.path.splitext(filename)[0]
@@ -4524,6 +4534,30 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
fileinfo = FileInfo(filename)
line = clean_lines.lines[linenum]
+ # system-style includes should not be used for project includes
+ match = Match(r'#include\s*<(([^/>]+)/[^>]+)', line)
+ if match:
+ if match.group(2) not in _C_SYSTEM_DIRECTORIES:
+ error(filename, linenum, 'build/include', 4,
+ '<%s> should be #include "%s" or #import <%s>' %
+ (match.group(1), match.group(1), match.group(1)))
+
+ # C++ system files should not be #imported
+ match = Match(r'#import\s*<([^/>.]+)>', line)
+ if match:
+ error(filename, linenum, 'build/include', 4,
+ 'C++ header <%s> was #imported. Should be #include <%s>' %
+ (match.group(1), match.group(1)))
+
+ # Prefer C++ wrappers for C headers
+ match = Match(r'#include\s*<(([^>]+).h)>', line)
+ if match:
+ wrapper = 'c' + match.group(2)
+ if wrapper in _CPP_HEADERS:
+ error(filename, linenum, 'build/include', 4,
+ 'Prefer C++ header <%s> for C system header %s' %
+ (wrapper, match.group(1)))
+
# "include" should use the new style "foo/bar.h" instead of just "bar.h"
# Only do this check if the included header follows google naming
# conventions. If not, assume that it's a 3rd party API that
diff --git a/scripts/lint.sh b/scripts/lint.sh
index d0f82b1..9e33c87 100755
--- a/scripts/lint.sh
+++ b/scripts/lint.sh
@@ -14,21 +14,74 @@
# Lints C++ files for conformance with the Google C++ style guide
-options=(
+# Joins the given arguments with the separator given as the first argument.
+function join() {
+ local IFS="$1"
+ shift
+ echo "$*"
+}
+
+git_options=(
-z # \0 terminate output
)
+objc_lint_filters=(
+ # Objective-C uses #import and does not use header guards
+ -build/header_guard
+
+ # Inline definitions of Objective-C blocks confuse
+ -readability/braces
+
+ # C-style casts are acceptable in Objective-C++
+ -readability/casting
+
+ # Objective-C needs use type 'long' for interop between types like NSInteger
+ # and printf-style functions.
+ -runtime/int
+
+ # cpplint is generally confused by Objective-C mixing with C++.
+ # * Objective-C method invocations in a for loop make it think its a
+ # range-for
+ # * Objective-C dictionary literals confuse brace spacing
+ # * Empty category declarations ("@interface Foo ()") look like function
+ # invocations
+ -whitespace
+)
+
+objc_lint_options=(
+ # cpplint normally excludes Objective-C++
+ --extensions=h,m,mm
+
+ # Objective-C style allows longer lines
+ --linelength=100
+
+ --filter=$(join , "${objc_lint_filters[@]}")
+)
+
if [[ $# -gt 0 ]]; then
# Interpret any command-line argument as a revision range
command=(git diff --name-only)
- options+=("$@")
+ git_options+=("$@")
else
# Default to operating on all files that match the pattern
command=(git ls-files)
fi
-
-"${command[@]}" "${options[@]}" \
+# Straight C++ files get regular cpplint
+"${command[@]}" "${git_options[@]}" \
-- 'Firestore/core/**/*.'{h,cc} \
- | xargs -0 python scripts/cpplint.py --quiet
+ | xargs -0 python scripts/cpplint.py --quiet 2>&1
+CPP_STATUS=$?
+
+# Objective-C++ files get a looser cpplint
+"${command[@]}" "${git_options[@]}" \
+ -- 'Firestore/Source/**/*.'{h,m,mm} \
+ 'Firestore/Example/Tests/**/*.'{h,m,mm} \
+ 'Firestore/core/**/*.mm' \
+ | xargs -0 python scripts/cpplint.py "${objc_lint_options[@]}" --quiet 2>&1
+OBJC_STATUS=$?
+
+if [[ $CPP_STATUS != 0 || $OBJC_STATUS != 0 ]]; then
+ exit 1
+fi