aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore
diff options
context:
space:
mode:
authorGravatar Michael Lehenbauer <mikelehen@gmail.com>2018-04-17 15:07:25 -0700
committerGravatar GitHub <noreply@github.com>2018-04-17 15:07:25 -0700
commitf2ec9e11fba82d4a76d989293d270a37ad1373a2 (patch)
tree48df0f0900c8e379557d9e43e385c4fde9f2b90b /Firestore
parent9329e6e09bed6925b3292aa05fea28e2bcd4d9ef (diff)
Serialize array transform mutations. (#1107)
* Serialize array transform mutations. * Improve ArrayTransform constructor to avoid extra copying.
Diffstat (limited to 'Firestore')
-rw-r--r--Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm34
-rw-r--r--Firestore/Source/API/FSTUserDataConverter.mm8
-rw-r--r--Firestore/Source/Remote/FSTSerializerBeta.mm89
-rw-r--r--Firestore/core/src/firebase/firestore/model/transform_operations.h5
4 files changed, 118 insertions, 18 deletions
diff --git a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
index a648cd8..8ddddb0 100644
--- a/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
+++ b/Firestore/Example/Tests/Remote/FSTSerializerBetaTests.mm
@@ -367,7 +367,7 @@ NS_ASSUME_NONNULL_BEGIN
[self assertRoundTripForMutation:mutation proto:proto];
}
-- (void)testEncodesTransformMutation {
+- (void)testEncodesServerTimestampTransformMutation {
FSTTransformMutation *mutation = FSTTestTransformMutation(@"docs/1", @{
@"a" : [FIRFieldValue fieldValueForServerTimestamp],
@"bar.baz" : [FIRFieldValue fieldValueForServerTimestamp]
@@ -382,6 +382,38 @@ NS_ASSUME_NONNULL_BEGIN
[self assertRoundTripForMutation:mutation proto:proto];
}
+- (void)testEncodesArrayTransformMutations {
+ FSTTransformMutation *mutation = FSTTestTransformMutation(@"docs/1", @{
+ @"a" : [FIRFieldValue fieldValueForArrayUnion:@[ @"a", @2 ]],
+ @"bar.baz" : [FIRFieldValue fieldValueForArrayRemove:@[
+ @{ @"x" : @1 }
+ ]]
+ });
+ GCFSWrite *proto = [GCFSWrite message];
+ proto.transform = [GCFSDocumentTransform message];
+ proto.transform.document = [self.serializer encodedDocumentKey:mutation.key];
+
+ GCFSDocumentTransform_FieldTransform *arrayUnion = [GCFSDocumentTransform_FieldTransform message];
+ arrayUnion.fieldPath = @"a";
+ arrayUnion.appendMissingElements = [GCFSArrayValue message];
+ NSMutableArray *unionElements = arrayUnion.appendMissingElements.valuesArray;
+ [unionElements addObject:[self.serializer encodedFieldValue:FSTTestFieldValue(@"a")]];
+ [unionElements addObject:[self.serializer encodedFieldValue:FSTTestFieldValue(@2)]];
+ [proto.transform.fieldTransformsArray addObject:arrayUnion];
+
+ GCFSDocumentTransform_FieldTransform *arrayRemove =
+ [GCFSDocumentTransform_FieldTransform message];
+ arrayRemove.fieldPath = @"bar.baz";
+ arrayRemove.removeAllFromArray_p = [GCFSArrayValue message];
+ NSMutableArray *removeElements = arrayRemove.removeAllFromArray_p.valuesArray;
+ [removeElements addObject:[self.serializer encodedFieldValue:FSTTestFieldValue(@{ @"x" : @1 })]];
+ [proto.transform.fieldTransformsArray addObject:arrayRemove];
+
+ proto.currentDocument.exists = YES;
+
+ [self assertRoundTripForMutation:mutation proto:proto];
+}
+
- (void)testEncodesSetMutationWithPrecondition {
FSTSetMutation *mutation =
[[FSTSetMutation alloc] initWithKey:FSTTestDocKey(@"foo/bar")
diff --git a/Firestore/Source/API/FSTUserDataConverter.mm b/Firestore/Source/API/FSTUserDataConverter.mm
index 719f6f5..cd32cef 100644
--- a/Firestore/Source/API/FSTUserDataConverter.mm
+++ b/Firestore/Source/API/FSTUserDataConverter.mm
@@ -606,16 +606,16 @@ typedef NS_ENUM(NSInteger, FSTUserDataSource) {
} 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);
+ auto array_union = absl::make_unique<ArrayTransform>(TransformOperation::Type::ArrayUnion,
+ std::move(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);
+ auto array_remove = absl::make_unique<ArrayTransform>(TransformOperation::Type::ArrayRemove,
+ std::move(parsedElements));
[context appendToFieldTransformsWithFieldPath:*context.path
transformOperation:std::move(array_remove)];
diff --git a/Firestore/Source/Remote/FSTSerializerBeta.mm b/Firestore/Source/Remote/FSTSerializerBeta.mm
index c8b0fa4..ebb49a7 100644
--- a/Firestore/Source/Remote/FSTSerializerBeta.mm
+++ b/Firestore/Source/Remote/FSTSerializerBeta.mm
@@ -57,6 +57,7 @@
#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;
@@ -572,31 +573,97 @@ NS_ASSUME_NONNULL_BEGIN
(const std::vector<FieldTransform> &)fieldTransforms {
NSMutableArray *protos = [NSMutableArray array];
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.setToServerValue = GCFSDocumentTransform_FieldTransform_ServerValue_RequestTime;
+ GCFSDocumentTransform_FieldTransform *proto = [self encodedFieldTransform:fieldTransform];
[protos addObject:proto];
}
return protos;
}
+- (GCFSDocumentTransform_FieldTransform *)encodedFieldTransform:
+ (const FieldTransform &)fieldTransform {
+ GCFSDocumentTransform_FieldTransform *proto = [GCFSDocumentTransform_FieldTransform message];
+ proto.fieldPath = util::WrapNSString(fieldTransform.path().CanonicalString());
+ if (fieldTransform.transformation().type() == TransformOperation::Type::ServerTimestamp) {
+ proto.setToServerValue = GCFSDocumentTransform_FieldTransform_ServerValue_RequestTime;
+
+ } else if (fieldTransform.transformation().type() == TransformOperation::Type::ArrayUnion) {
+ proto.appendMissingElements = [self
+ encodedArrayTransformElements:ArrayTransform::Elements(fieldTransform.transformation())];
+
+ } else if (fieldTransform.transformation().type() == TransformOperation::Type::ArrayRemove) {
+ proto.removeAllFromArray_p = [self
+ encodedArrayTransformElements:ArrayTransform::Elements(fieldTransform.transformation())];
+
+ } else {
+ FSTFail(@"Unknown transform: %d type", fieldTransform.transformation().type());
+ }
+ return proto;
+}
+
+- (GCFSArrayValue *)encodedArrayTransformElements:(const std::vector<FSTFieldValue *> &)elements {
+ GCFSArrayValue *proto = [GCFSArrayValue message];
+ NSMutableArray<GCFSValue *> *protoContents = [proto valuesArray];
+
+ for (FSTFieldValue *element : elements) {
+ GCFSValue *converted = [self encodedFieldValue:element];
+ [protoContents addObject:converted];
+ }
+ return proto;
+}
+
- (std::vector<FieldTransform>)decodedFieldTransforms:
(NSArray<GCFSDocumentTransform_FieldTransform *> *)protos {
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.emplace_back(
- FieldPath::FromServerFormat(util::MakeStringView(proto.fieldPath)),
- absl::make_unique<ServerTimestampTransform>(ServerTimestampTransform::Get()));
+ switch (proto.transformTypeOneOfCase) {
+ case GCFSDocumentTransform_FieldTransform_TransformType_OneOfCase_SetToServerValue: {
+ FSTAssert(
+ proto.setToServerValue == GCFSDocumentTransform_FieldTransform_ServerValue_RequestTime,
+ @"Unknown transform setToServerValue: %d", proto.setToServerValue);
+ fieldTransforms.emplace_back(
+ FieldPath::FromServerFormat(util::MakeStringView(proto.fieldPath)),
+ absl::make_unique<ServerTimestampTransform>(ServerTimestampTransform::Get()));
+ break;
+ }
+
+ case GCFSDocumentTransform_FieldTransform_TransformType_OneOfCase_AppendMissingElements: {
+ std::vector<FSTFieldValue *> elements =
+ [self decodedArrayTransformElements:proto.appendMissingElements];
+ fieldTransforms.emplace_back(
+ FieldPath::FromServerFormat(util::MakeStringView(proto.fieldPath)),
+ absl::make_unique<ArrayTransform>(TransformOperation::Type::ArrayUnion,
+ std::move(elements)));
+ break;
+ }
+
+ case GCFSDocumentTransform_FieldTransform_TransformType_OneOfCase_RemoveAllFromArray_p: {
+ std::vector<FSTFieldValue *> elements =
+ [self decodedArrayTransformElements:proto.removeAllFromArray_p];
+ fieldTransforms.emplace_back(
+ FieldPath::FromServerFormat(util::MakeStringView(proto.fieldPath)),
+ absl::make_unique<ArrayTransform>(TransformOperation::Type::ArrayRemove,
+ std::move(elements)));
+ break;
+ }
+
+ default:
+ FSTFail(@"Unknown transform: %@", proto);
+ }
}
+
return fieldTransforms;
}
+- (std::vector<FSTFieldValue *>)decodedArrayTransformElements:(GCFSArrayValue *)proto {
+ __block std::vector<FSTFieldValue *> elements;
+ [proto.valuesArray enumerateObjectsUsingBlock:^(GCFSValue *value, NSUInteger idx, BOOL *stop) {
+ elements.push_back([self decodedFieldValue:value]);
+ }];
+ return elements;
+}
+
#pragma mark - FSTMutationResult <= GCFSWriteResult proto
- (FSTMutationResult *)decodedMutationResult:(GCFSWriteResult *)mutation {
diff --git a/Firestore/core/src/firebase/firestore/model/transform_operations.h b/Firestore/core/src/firebase/firestore/model/transform_operations.h
index 2943ea0..a1c2de0 100644
--- a/Firestore/core/src/firebase/firestore/model/transform_operations.h
+++ b/Firestore/core/src/firebase/firestore/model/transform_operations.h
@@ -17,6 +17,7 @@
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_TRANSFORM_OPERATIONS_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_MODEL_TRANSFORM_OPERATIONS_H_
+#include <utility>
#include <vector>
#if defined(__OBJC__)
@@ -107,8 +108,8 @@ class ServerTimestampTransform : public TransformOperation {
*/
class ArrayTransform : public TransformOperation {
public:
- ArrayTransform(const Type& type, const std::vector<FSTFieldValue*> elements)
- : type_(type), elements_(elements) {
+ ArrayTransform(Type type, std::vector<FSTFieldValue*> elements)
+ : type_(type), elements_(std::move(elements)) {
}
~ArrayTransform() override {