aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar zxu <zxu@google.com>2018-04-10 16:28:22 -0400
committerGravatar GitHub <noreply@github.com>2018-04-10 16:28:22 -0400
commit2ac778f312301a8dd10c3c6498a59ce536abd738 (patch)
tree68ac918167ec2e474c552f821297ade071e33a20
parent59f9dcb72f46258ffefea3aaf93f51e927c1cc10 (diff)
Port FieldTransform to C++ (#1033)
* port FieldMask to C++ * address changes * address changes * fix test * address change * Port transform operations (FSTTransformOperation, FSTServerTimestampTransform) to C++ * address changes * address changes * address changes * implement `FieldTransform` in C++ * port `FieldTransform` * make `fieldTransforms` shared inside `context` * address changes * fix lint * address changes
-rw-r--r--Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm6
-rw-r--r--Firestore/Example/Tests/Util/FSTHelpers.mm12
-rw-r--r--Firestore/Source/API/FSTUserDataConverter.h18
-rw-r--r--Firestore/Source/API/FSTUserDataConverter.mm83
-rw-r--r--Firestore/Source/Core/FSTTransaction.h1
-rw-r--r--Firestore/Source/Model/FSTMutation.h22
-rw-r--r--Firestore/Source/Model/FSTMutation.mm93
-rw-r--r--Firestore/Source/Remote/FSTSerializerBeta.mm27
-rw-r--r--Firestore/core/src/firebase/firestore/model/CMakeLists.txt1
-rw-r--r--Firestore/core/src/firebase/firestore/model/field_transform.h70
-rw-r--r--Firestore/core/test/firebase/firestore/model/CMakeLists.txt1
-rw-r--r--Firestore/core/test/firebase/firestore/model/field_transform_test.cc39
12 files changed, 243 insertions, 130 deletions
diff --git a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
index 17191f8..c0e9cad 100644
--- a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
+++ b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
@@ -23,6 +23,8 @@
#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"
@@ -47,6 +49,7 @@
#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/util/string_apple.h"
#include "Firestore/core/test/firebase/firestore/testutil/testutil.h"
@@ -54,6 +57,7 @@ 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;
NS_ASSUME_NONNULL_BEGIN
@@ -67,7 +71,7 @@ NS_ASSUME_NONNULL_BEGIN
- (GCFSDocumentMask *)encodedFieldMask:(const FieldMask &)fieldMask;
- (NSMutableArray<GCFSDocumentTransform_FieldTransform *> *)encodedFieldTransforms:
- (NSArray<FSTFieldTransform *> *)fieldTransforms;
+ (const std::vector<FieldTransform> &)fieldTransforms;
- (GCFSStructuredQuery_Filter *)encodedRelationFilter:(FSTRelationFilter *)filter;
@end
diff --git a/Firestore/Example/Tests/Util/FSTHelpers.mm b/Firestore/Example/Tests/Util/FSTHelpers.mm
index 8f170e6..2e1082e 100644
--- a/Firestore/Example/Tests/Util/FSTHelpers.mm
+++ b/Firestore/Example/Tests/Util/FSTHelpers.mm
@@ -46,6 +46,7 @@
#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/resource_path.h"
#include "Firestore/core/src/firebase/firestore/model/transform_operations.h"
@@ -59,6 +60,7 @@ 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::ResourcePath;
using firebase::firestore::model::ServerTimestampTransform;
@@ -279,15 +281,13 @@ FSTPatchMutation *FSTTestPatchMutation(const absl::string_view path,
FSTTransformMutation *FSTTestTransformMutation(NSString *path,
NSArray<NSString *> *serverTimestampFields) {
FSTDocumentKey *key = [FSTDocumentKey keyWithPath:testutil::Resource(util::MakeStringView(path))];
- NSMutableArray<FSTFieldTransform *> *fieldTransforms = [NSMutableArray array];
+ std::vector<FieldTransform> fieldTransforms;
for (NSString *field in serverTimestampFields) {
- const FieldPath fieldPath = testutil::Field(util::MakeStringView(field));
+ FieldPath fieldPath = testutil::Field(util::MakeStringView(field));
auto transformOp = absl::make_unique<ServerTimestampTransform>(ServerTimestampTransform::Get());
- FSTFieldTransform *transform =
- [[FSTFieldTransform alloc] initWithPath:fieldPath transform:std::move(transformOp)];
- [fieldTransforms addObject:transform];
+ fieldTransforms.emplace_back(std::move(fieldPath), std::move(transformOp));
}
- return [[FSTTransformMutation alloc] initWithKey:key fieldTransforms:fieldTransforms];
+ return [[FSTTransformMutation alloc] initWithKey:key fieldTransforms:std::move(fieldTransforms)];
}
FSTDeleteMutation *FSTTestDeleteMutation(NSString *path) {
diff --git a/Firestore/Source/API/FSTUserDataConverter.h b/Firestore/Source/API/FSTUserDataConverter.h
index 2b4b340..a2f947a 100644
--- a/Firestore/Source/API/FSTUserDataConverter.h
+++ b/Firestore/Source/API/FSTUserDataConverter.h
@@ -16,14 +16,16 @@
#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"
@class FIRSetOptions;
@class FSTObjectValue;
@class FSTFieldValue;
-@class FSTFieldTransform;
@class FSTMutation;
@class FSTPrecondition;
@class FSTSnapshotVersion;
@@ -36,16 +38,19 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithData:(FSTObjectValue *)data
- 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:(NSArray<FSTFieldTransform *> *)fieldTransforms
+ 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) NSArray<FSTFieldTransform *> *fieldTransforms;
@property(nonatomic, assign, readonly) BOOL isPatch;
/**
@@ -64,13 +69,14 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithData:(FSTObjectValue *)data
fieldMask:(firebase::firestore::model::FieldMask)fieldMask
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms
+ 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) NSArray<FSTFieldTransform *> *fieldTransforms;
/**
* Converts the parsed update data into 1 or 2 mutations (depending on whether there are any
diff --git a/Firestore/Source/API/FSTUserDataConverter.mm b/Firestore/Source/API/FSTUserDataConverter.mm
index c6a6e34..2eee878 100644
--- a/Firestore/Source/API/FSTUserDataConverter.mm
+++ b/Firestore/Source/API/FSTUserDataConverter.mm
@@ -37,6 +37,7 @@
#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/transform_operations.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
#include "absl/memory/memory.h"
@@ -46,7 +47,9 @@ 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::ServerTimestampTransform;
+using firebase::firestore::model::TransformOperation;
NS_ASSUME_NONNULL_BEGIN
@@ -56,14 +59,15 @@ static NSString *const RESERVED_FIELD_DESIGNATOR = @"__";
@implementation FSTParsedSetData {
FieldMask _fieldMask;
+ std::vector<FieldTransform> _fieldTransforms;
}
- (instancetype)initWithData:(FSTObjectValue *)data
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms {
+ fieldTransforms:(std::vector<FieldTransform>)fieldTransforms {
self = [super init];
if (self) {
_data = data;
- _fieldTransforms = fieldTransforms;
+ _fieldTransforms = std::move(fieldTransforms);
_isPatch = NO;
}
return self;
@@ -71,17 +75,21 @@ static NSString *const RESERVED_FIELD_DESIGNATOR = @"__";
- (instancetype)initWithData:(FSTObjectValue *)data
fieldMask:(FieldMask)fieldMask
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms {
+ fieldTransforms:(std::vector<FieldTransform>)fieldTransforms {
self = [super init];
if (self) {
_data = data;
_fieldMask = std::move(fieldMask);
- _fieldTransforms = fieldTransforms;
+ _fieldTransforms = std::move(fieldTransforms);
_isPatch = YES;
}
return self;
}
+- (const std::vector<FieldTransform> &)fieldTransforms {
+ return _fieldTransforms;
+}
+
- (NSArray<FSTMutation *> *)mutationsWithKey:(const DocumentKey &)key
precondition:(FSTPrecondition *)precondition {
NSMutableArray<FSTMutation *> *mutations = [NSMutableArray array];
@@ -95,7 +103,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]];
}
@@ -108,16 +116,17 @@ static NSString *const RESERVED_FIELD_DESIGNATOR = @"__";
@implementation FSTParsedUpdateData {
FieldMask _fieldMask;
+ std::vector<FieldTransform> _fieldTransforms;
}
- (instancetype)initWithData:(FSTObjectValue *)data
fieldMask:(FieldMask)fieldMask
- fieldTransforms:(NSArray<FSTFieldTransform *> *)fieldTransforms {
+ fieldTransforms:(std::vector<FieldTransform>)fieldTransforms {
self = [super init];
if (self) {
_data = data;
_fieldMask = std::move(fieldMask);
- _fieldTransforms = fieldTransforms;
+ _fieldTransforms = std::move(fieldTransforms);
}
return self;
}
@@ -129,7 +138,7 @@ static NSString *const RESERVED_FIELD_DESIGNATOR = @"__";
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]];
}
@@ -140,6 +149,10 @@ static NSString *const RESERVED_FIELD_DESIGNATOR = @"__";
return _fieldMask;
}
+- (const std::vector<FieldTransform> &)fieldTransforms {
+ return _fieldTransforms;
+}
+
@end
/**
@@ -168,7 +181,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;
/**
@@ -186,7 +198,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;
@@ -204,16 +216,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
@@ -222,7 +240,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;
@@ -231,13 +249,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;
@@ -251,7 +269,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;
@@ -265,7 +283,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;
@@ -276,7 +294,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
return [[FSTParseContext alloc] initWithSource:self.dataSource
path:nil
arrayElement:YES
- fieldTransforms:self.fieldTransforms
+ fieldTransforms:_fieldTransforms
fieldMask:_fieldMask];
}
@@ -335,6 +353,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
@@ -392,7 +420,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
return [[FSTParsedSetData alloc] initWithData:updateData
fieldMask:FieldMask{*context.fieldMask}
- fieldTransforms:context.fieldTransforms];
+ fieldTransforms:*context.fieldTransforms];
}
- (FSTParsedSetData *)parsedSetData:(id)input {
@@ -407,7 +435,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 fieldTransforms:context.fieldTransforms];
+ return
+ [[FSTParsedSetData alloc] initWithData:updateData fieldTransforms:*context.fieldTransforms];
}
- (FSTParsedUpdateData *)parsedUpdateData:(id)input {
@@ -453,7 +482,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
return [[FSTParsedUpdateData alloc] initWithData:updateData
fieldMask:FieldMask{fieldMaskPaths}
- fieldTransforms:context.fieldTransforms];
+ fieldTransforms:*context.fieldTransforms];
}
- (FSTFieldValue *)parsedQueryValue:(id)input {
@@ -462,7 +491,7 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
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;
}
@@ -661,11 +690,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:absl::make_unique<ServerTimestampTransform>(
- ServerTimestampTransform::Get())]];
+ [context appendToFieldTransformsWithFieldPath:*context.path
+ transformOperation:absl::make_unique<ServerTimestampTransform>(
+ ServerTimestampTransform::Get())];
// Return nil so this value is omitted from the parsed result.
return nil;
diff --git a/Firestore/Source/Core/FSTTransaction.h b/Firestore/Source/Core/FSTTransaction.h
index 01c2e20..581a5fa 100644
--- a/Firestore/Source/Core/FSTTransaction.h
+++ b/Firestore/Source/Core/FSTTransaction.h
@@ -24,7 +24,6 @@
@class FIRSetOptions;
@class FSTDatastore;
-@class FSTFieldTransform;
@class FSTMaybeDocument;
@class FSTObjectValue;
@class FSTParsedSetData;
diff --git a/Firestore/Source/Model/FSTMutation.h b/Firestore/Source/Model/FSTMutation.h
index 2fa8806..38c35bf 100644
--- a/Firestore/Source/Model/FSTMutation.h
+++ b/Firestore/Source/Model/FSTMutation.h
@@ -22,6 +22,7 @@
#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/transform_operations.h"
@class FSTDocument;
@@ -33,19 +34,6 @@
NS_ASSUME_NONNULL_BEGIN
-#pragma mark - FSTFieldTransform
-
-/** A field path and the TransformOperation to perform upon it. */
-@interface FSTFieldTransform : NSObject
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithPath:(firebase::firestore::model::FieldPath)path
- transform:
- (std::unique_ptr<firebase::firestore::model::TransformOperation>)transform
- NS_DESIGNATED_INITIALIZER;
-- (const firebase::firestore::model::FieldPath &)path;
-- (const firebase::firestore::model::TransformOperation *)transform;
-@end
-
#pragma mark - FSTPrecondition
typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
@@ -103,7 +91,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.
*/
@@ -284,14 +272,14 @@ typedef NS_ENUM(NSUInteger, FSTPreconditionExists) {
* 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 a18053c..dd649a0 100644
--- a/Firestore/Source/Model/FSTMutation.mm
+++ b/Firestore/Source/Model/FSTMutation.mm
@@ -17,7 +17,9 @@
#import "Firestore/Source/Model/FSTMutation.h"
#include <memory>
+#include <string>
#include <utility>
+#include <vector>
#import "FIRTimestamp.h"
@@ -30,56 +32,18 @@
#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/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::ServerTimestampTransform;
using firebase::firestore::model::TransformOperation;
NS_ASSUME_NONNULL_BEGIN
-#pragma mark - FSTFieldTransform
-
-@implementation FSTFieldTransform {
- FieldPath _path;
- std::unique_ptr<TransformOperation> _transform;
-}
-
-- (instancetype)initWithPath:(FieldPath)path
- transform:(std::unique_ptr<TransformOperation>)transform {
- self = [super init];
- if (self) {
- _path = std::move(path);
- _transform = std::move(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 == *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;
-}
-
-- (const firebase::firestore::model::TransformOperation *)transform {
- return _transform.get();
-}
-
-@end
-
#pragma mark - FSTPrecondition
@implementation FSTPrecondition
@@ -399,20 +363,27 @@ 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;
+ _fieldTransforms = std::move(fieldTransforms);
}
return self;
}
+- (const std::vector<FieldTransform> &)fieldTransforms {
+ return _fieldTransforms;
+}
+
- (BOOL)isEqual:(id)other {
if (other == self) {
return YES;
@@ -423,20 +394,26 @@ NS_ASSUME_NONNULL_BEGIN
FSTTransformMutation *otherMutation = (FSTTransformMutation *)other;
return [self.key isEqual:otherMutation.key] &&
- [self.fieldTransforms isEqual:otherMutation.fieldTransforms] &&
+ self.fieldTransforms == otherMutation.fieldTransforms &&
[self.precondition isEqual:otherMutation.precondition];
}
- (NSUInteger)hash {
NSUInteger result = [self.key hash];
result = 31 * result + [self.precondition hash];
- result = 31 * result + [self.fieldTransforms 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,
+ 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];
}
@@ -486,19 +463,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->type() == TransformOperation::Type::ServerTimestamp) {
+ 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;
@@ -506,17 +483,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];
- const TransformOperation *transform = fieldTransform.transform;
- FieldPath fieldPath = fieldTransform.path;
- if (transform->type() == TransformOperation::Type::ServerTimestamp) {
+ 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: %d type", transform->type());
+ FSTFail(@"Encountered unknown transform: %d type", transform.type());
}
}
return objectValue;
diff --git a/Firestore/Source/Remote/FSTSerializerBeta.mm b/Firestore/Source/Remote/FSTSerializerBeta.mm
index 095d731..1d9ad30 100644
--- a/Firestore/Source/Remote/FSTSerializerBeta.mm
+++ b/Firestore/Source/Remote/FSTSerializerBeta.mm
@@ -49,6 +49,7 @@
#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/resource_path.h"
#include "Firestore/core/src/firebase/firestore/model/transform_operations.h"
#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
@@ -59,6 +60,7 @@ 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::ResourcePath;
using firebase::firestore::model::ServerTimestampTransform;
using firebase::firestore::model::TransformOperation;
@@ -557,7 +559,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (FieldMask)decodedFieldMask:(GCFSDocumentMask *)fieldMask {
- std::vector<FieldPath> fields{};
+ std::vector<FieldPath> fields;
fields.reserve(fieldMask.fieldPathsArray_Count);
for (NSString *path in fieldMask.fieldPathsArray) {
fields.push_back(FieldPath::FromServerFormat(util::MakeStringView(path)));
@@ -566,31 +568,30 @@ NS_ASSUME_NONNULL_BEGIN
}
- (NSMutableArray<GCFSDocumentTransform_FieldTransform *> *)encodedFieldTransforms:
- (NSArray<FSTFieldTransform *> *)fieldTransforms {
+ (const std::vector<FieldTransform> &)fieldTransforms {
NSMutableArray *protos = [NSMutableArray array];
- for (FSTFieldTransform *fieldTransform in fieldTransforms) {
- FSTAssert(fieldTransform.transform->type() == TransformOperation::Type::ServerTimestamp,
- @"Unknown transform: %d type", fieldTransform.transform->type());
+ 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:absl::make_unique<ServerTimestampTransform>(
- ServerTimestampTransform::Get())]];
+ fieldTransforms.emplace_back(
+ FieldPath::FromServerFormat(util::MakeStringView(proto.fieldPath)),
+ absl::make_unique<ServerTimestampTransform>(ServerTimestampTransform::Get()));
}
return fieldTransforms;
}
diff --git a/Firestore/core/src/firebase/firestore/model/CMakeLists.txt b/Firestore/core/src/firebase/firestore/model/CMakeLists.txt
index d83c0aa..de783ad 100644
--- a/Firestore/core/src/firebase/firestore/model/CMakeLists.txt
+++ b/Firestore/core/src/firebase/firestore/model/CMakeLists.txt
@@ -25,6 +25,7 @@ cc_library(
field_mask.h
field_path.cc
field_path.h
+ field_transform.h
field_value.cc
field_value.h
maybe_document.cc
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/test/firebase/firestore/model/CMakeLists.txt b/Firestore/core/test/firebase/firestore/model/CMakeLists.txt
index 5e494f1..3bac89d 100644
--- a/Firestore/core/test/firebase/firestore/model/CMakeLists.txt
+++ b/Firestore/core/test/firebase/firestore/model/CMakeLists.txt
@@ -20,6 +20,7 @@ cc_test(
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
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