From 9e815620e9f7f43b42e03db4e5118d7ad03ddee7 Mon Sep 17 00:00:00 2001 From: zxu Date: Wed, 14 Mar 2018 08:57:31 -0400 Subject: grand PR to port the remaining paths (FieldPath and ResourcePath). (#865) * naively remove FSTPath import and source/test files. * port FieldPath, part I * port FieldPath, part II * port ResourcePath, part I * port ResourcePath, part II * the grand commit to fix build errors * use testutil:: helper instead of those from FSTHelpers * fix test and lint * use c_str in errmsg directly * fix * fix * make code clean * fix integration test I missed * fix to avoid naming collision in preprocessor * address changes * address changes * address changes * fix: fieldMask are actually shared with different context. * address changes * address changes --- Firestore/Source/Remote/FSTDatastore.mm | 12 +- Firestore/Source/Remote/FSTRemoteStore.mm | 4 +- Firestore/Source/Remote/FSTSerializerBeta.mm | 175 +++++++++++++-------------- 3 files changed, 87 insertions(+), 104 deletions(-) (limited to 'Firestore/Source/Remote') diff --git a/Firestore/Source/Remote/FSTDatastore.mm b/Firestore/Source/Remote/FSTDatastore.mm index 3b536ab..e63017a 100644 --- a/Firestore/Source/Remote/FSTDatastore.mm +++ b/Firestore/Source/Remote/FSTDatastore.mm @@ -111,10 +111,9 @@ typedef GRPCProtoCall * (^RPCFactory)(void); } - (NSString *)description { - return [NSString - stringWithFormat:@">", - util::WrapNSStringNoCopy(self.databaseInfo->database_id().database_id()), - util::WrapNSStringNoCopy(self.databaseInfo->host())]; + return [NSString stringWithFormat:@">", + self.databaseInfo->database_id().database_id().c_str(), + self.databaseInfo->host().c_str()]; } /** @@ -186,9 +185,8 @@ typedef GRPCProtoCall * (^RPCFactory)(void); /** Returns the string to be used as google-cloud-resource-prefix header value. */ + (NSString *)googleCloudResourcePrefixForDatabaseID:(const DatabaseId *)databaseID { - return [NSString stringWithFormat:@"projects/%@/databases/%@", - util::WrapNSStringNoCopy(databaseID->project_id()), - util::WrapNSStringNoCopy(databaseID->database_id())]; + return [NSString stringWithFormat:@"projects/%s/databases/%s", databaseID->project_id().c_str(), + databaseID->database_id().c_str()]; } /** * Takes a dictionary of (HTTP) response headers and returns the set of whitelisted headers diff --git a/Firestore/Source/Remote/FSTRemoteStore.mm b/Firestore/Source/Remote/FSTRemoteStore.mm index 2c8e84a..f484278 100644 --- a/Firestore/Source/Remote/FSTRemoteStore.mm +++ b/Firestore/Source/Remote/FSTRemoteStore.mm @@ -27,7 +27,6 @@ #import "Firestore/Source/Model/FSTDocumentKey.h" #import "Firestore/Source/Model/FSTMutation.h" #import "Firestore/Source/Model/FSTMutationBatch.h" -#import "Firestore/Source/Model/FSTPath.h" #import "Firestore/Source/Remote/FSTDatastore.h" #import "Firestore/Source/Remote/FSTExistenceFilter.h" #import "Firestore/Source/Remote/FSTOnlineStateTracker.h" @@ -211,8 +210,7 @@ static const int kMaxPendingWrites = 10; } - (void)userDidChange:(const User &)user { - FSTLog(@"FSTRemoteStore %p changing users: %@", (__bridge void *)self, - util::WrapNSStringNoCopy(user.uid())); + FSTLog(@"FSTRemoteStore %p changing users: %s", (__bridge void *)self, user.uid().c_str()); if ([self isNetworkEnabled]) { // Tear down and re-create our network streams. This will ensure we get a fresh auth token // for the new user and re-fill the write pipeline with new mutations from the LocalStore diff --git a/Firestore/Source/Remote/FSTSerializerBeta.mm b/Firestore/Source/Remote/FSTSerializerBeta.mm index 00391ec..77d2ec7 100644 --- a/Firestore/Source/Remote/FSTSerializerBeta.mm +++ b/Firestore/Source/Remote/FSTSerializerBeta.mm @@ -39,16 +39,19 @@ #import "Firestore/Source/Model/FSTFieldValue.h" #import "Firestore/Source/Model/FSTMutation.h" #import "Firestore/Source/Model/FSTMutationBatch.h" -#import "Firestore/Source/Model/FSTPath.h" #import "Firestore/Source/Remote/FSTExistenceFilter.h" #import "Firestore/Source/Remote/FSTWatchChange.h" #import "Firestore/Source/Util/FSTAssert.h" #include "Firestore/core/src/firebase/firestore/model/database_id.h" +#include "Firestore/core/src/firebase/firestore/model/field_path.h" +#include "Firestore/core/src/firebase/firestore/model/resource_path.h" #include "Firestore/core/src/firebase/firestore/util/string_apple.h" namespace util = firebase::firestore::util; using firebase::firestore::model::DatabaseId; +using firebase::firestore::model::FieldPath; +using firebase::firestore::model::ResourcePath; NS_ASSUME_NONNULL_BEGIN @@ -104,73 +107,67 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - FSTDocumentKey <=> Key proto - (NSString *)encodedDocumentKey:(FSTDocumentKey *)key { - return [self - encodedResourcePathForDatabaseID:self.databaseID - path:[FSTResourcePath resourcePathWithCPPResourcePath:key.path]]; + return [self encodedResourcePathForDatabaseID:self.databaseID path:key.path]; } - (FSTDocumentKey *)decodedDocumentKey:(NSString *)name { - FSTResourcePath *path = [self decodedResourcePathWithDatabaseID:name]; - FSTAssert([[path segmentAtIndex:1] - isEqualToString:util::WrapNSStringNoCopy(self.databaseID->project_id())], + const ResourcePath path = [self decodedResourcePathWithDatabaseID:name]; + FSTAssert(path[1] == self.databaseID->project_id(), @"Tried to deserialize key from different project."); - FSTAssert([[path segmentAtIndex:3] - isEqualToString:util::WrapNSStringNoCopy(self.databaseID->database_id())], + FSTAssert(path[3] == self.databaseID->database_id(), @"Tried to deserialize key from different datbase."); - return [FSTDocumentKey - keyWithPath:[[self localResourcePathForQualifiedResourcePath:path] toCPPResourcePath]]; + return [FSTDocumentKey keyWithPath:[self localResourcePathForQualifiedResourcePath:path]]; } - (NSString *)encodedResourcePathForDatabaseID:(const DatabaseId *)databaseID - path:(FSTResourcePath *)path { - return [[[[self encodedResourcePathForDatabaseID:databaseID] pathByAppendingSegment:@"documents"] - pathByAppendingPath:path] canonicalString]; + path:(const ResourcePath &)path { + return util::WrapNSString([self encodedResourcePathForDatabaseID:databaseID] + .Append("documents") + .Append(path) + .CanonicalString()); } -- (FSTResourcePath *)decodedResourcePathWithDatabaseID:(NSString *)name { - FSTResourcePath *path = [FSTResourcePath pathWithString:name]; - FSTAssert([self validQualifiedResourcePath:path], @"Tried to deserialize invalid key %@", path); +- (ResourcePath)decodedResourcePathWithDatabaseID:(NSString *)name { + const ResourcePath path = ResourcePath::FromString(util::MakeStringView(name)); + FSTAssert([self validQualifiedResourcePath:path], @"Tried to deserialize invalid key %s", + path.CanonicalString().c_str()); return path; } -- (NSString *)encodedQueryPath:(FSTResourcePath *)path { - if (path.length == 0) { +- (NSString *)encodedQueryPath:(const ResourcePath &)path { + if (path.size() == 0) { // If the path is empty, the backend requires we leave off the /documents at the end. return [self encodedDatabaseID]; } return [self encodedResourcePathForDatabaseID:self.databaseID path:path]; } -- (FSTResourcePath *)decodedQueryPath:(NSString *)name { - FSTResourcePath *resource = [self decodedResourcePathWithDatabaseID:name]; - if (resource.length == 4) { - return [FSTResourcePath pathWithSegments:@[]]; +- (ResourcePath)decodedQueryPath:(NSString *)name { + const ResourcePath resource = [self decodedResourcePathWithDatabaseID:name]; + if (resource.size() == 4) { + return ResourcePath{}; } else { return [self localResourcePathForQualifiedResourcePath:resource]; } } -- (FSTResourcePath *)encodedResourcePathForDatabaseID:(const DatabaseId *)databaseID { - return [FSTResourcePath pathWithSegments:@[ - @"projects", util::WrapNSString(databaseID->project_id()), @"databases", - util::WrapNSString(databaseID->database_id()) - ]]; +- (ResourcePath)encodedResourcePathForDatabaseID:(const DatabaseId *)databaseID { + return ResourcePath{"projects", databaseID->project_id(), "databases", databaseID->database_id()}; } -- (FSTResourcePath *)localResourcePathForQualifiedResourcePath:(FSTResourcePath *)resourceName { - FSTAssert( - resourceName.length > 4 && [[resourceName segmentAtIndex:4] isEqualToString:@"documents"], - @"Tried to deserialize invalid key %@", resourceName); - return [resourceName pathByRemovingFirstSegments:5]; +- (ResourcePath)localResourcePathForQualifiedResourcePath:(const ResourcePath &)resourceName { + FSTAssert(resourceName.size() > 4 && resourceName[4] == "documents", + @"Tried to deserialize invalid key %s", resourceName.CanonicalString().c_str()); + return resourceName.PopFirst(5); } -- (BOOL)validQualifiedResourcePath:(FSTResourcePath *)path { - return path.length >= 4 && [[path segmentAtIndex:0] isEqualToString:@"projects"] && - [[path segmentAtIndex:2] isEqualToString:@"databases"]; +- (BOOL)validQualifiedResourcePath:(const ResourcePath &)path { + return path.size() >= 4 && path[0] == "projects" && path[2] == "databases"; } - (NSString *)encodedDatabaseID { - return [[self encodedResourcePathForDatabaseID:self.databaseID] canonicalString]; + return util::WrapNSString( + [self encodedResourcePathForDatabaseID:self.databaseID].CanonicalString()); } #pragma mark - FSTFieldValue <=> Value proto @@ -310,31 +307,25 @@ NS_ASSUME_NONNULL_BEGIN - (GCFSValue *)encodedReferenceValueForDatabaseID:(const DatabaseId *)databaseID key:(FSTDocumentKey *)key { - FSTAssert(*databaseID == *self.databaseID, @"Database %@:%@ cannot encode reference from %@:%@", - util::WrapNSStringNoCopy(self.databaseID->project_id()), - util::WrapNSStringNoCopy(self.databaseID->database_id()), - util::WrapNSStringNoCopy(databaseID->project_id()), - util::WrapNSStringNoCopy(databaseID->database_id())); + FSTAssert(*databaseID == *self.databaseID, @"Database %s:%s cannot encode reference from %s:%s", + self.databaseID->project_id().c_str(), self.databaseID->database_id().c_str(), + databaseID->project_id().c_str(), databaseID->database_id().c_str()); GCFSValue *result = [GCFSValue message]; - result.referenceValue = [self - encodedResourcePathForDatabaseID:databaseID - path:[FSTResourcePath resourcePathWithCPPResourcePath:key.path]]; + result.referenceValue = [self encodedResourcePathForDatabaseID:databaseID path:key.path]; return result; } - (FSTReferenceValue *)decodedReferenceValue:(NSString *)resourceName { - FSTResourcePath *path = [self decodedResourcePathWithDatabaseID:resourceName]; - NSString *project = [path segmentAtIndex:1]; - NSString *database = [path segmentAtIndex:3]; - FSTDocumentKey *key = [FSTDocumentKey - keyWithPath:[[self localResourcePathForQualifiedResourcePath:path] toCPPResourcePath]]; - - const DatabaseId database_id(util::MakeStringView(project), util::MakeStringView(database)); - FSTAssert(database_id == *self.databaseID, @"Database %@:%@ cannot encode reference from %@:%@", - util::WrapNSStringNoCopy(self.databaseID->project_id()), - util::WrapNSStringNoCopy(self.databaseID->database_id()), - util::WrapNSStringNoCopy(database_id.project_id()), - util::WrapNSStringNoCopy(database_id.database_id())); + const ResourcePath path = [self decodedResourcePathWithDatabaseID:resourceName]; + const std::string &project = path[1]; + const std::string &database = path[3]; + FSTDocumentKey *key = + [FSTDocumentKey keyWithPath:[self localResourcePathForQualifiedResourcePath:path]]; + + const DatabaseId database_id(project, database); + FSTAssert(database_id == *self.databaseID, @"Database %s:%s cannot encode reference from %s:%s", + self.databaseID->project_id().c_str(), self.databaseID->database_id().c_str(), + database_id.project_id().c_str(), database_id.database_id().c_str()); return [FSTReferenceValue referenceValue:key databaseID:self.databaseID]; } @@ -389,7 +380,7 @@ NS_ASSUME_NONNULL_BEGIN __block FSTObjectValue *result = [FSTObjectValue objectValue]; [fields enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, GCFSValue *_Nonnull obj, BOOL *_Nonnull stop) { - FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ key ]]; + FieldPath path{util::MakeString(key)}; FSTFieldValue *value = [self decodedFieldValue:obj]; result = [result objectBySettingValue:value forPath:path]; }]; @@ -550,19 +541,19 @@ NS_ASSUME_NONNULL_BEGIN - (GCFSDocumentMask *)encodedFieldMask:(FSTFieldMask *)fieldMask { GCFSDocumentMask *mask = [GCFSDocumentMask message]; - for (FSTFieldPath *field in fieldMask.fields) { - [mask.fieldPathsArray addObject:field.canonicalString]; + for (const FieldPath &field : fieldMask.fields) { + [mask.fieldPathsArray addObject:util::WrapNSString(field.CanonicalString())]; } return mask; } - (FSTFieldMask *)decodedFieldMask:(GCFSDocumentMask *)fieldMask { - NSMutableArray *fields = - [NSMutableArray arrayWithCapacity:fieldMask.fieldPathsArray_Count]; + std::vector fields{}; + fields.reserve(fieldMask.fieldPathsArray_Count); for (NSString *path in fieldMask.fieldPathsArray) { - [fields addObject:[FSTFieldPath pathWithServerFormat:path]]; + fields.push_back(FieldPath::FromServerFormat(util::MakeStringView(path))); } - return [[FSTFieldMask alloc] initWithFields:fields]; + return [[FSTFieldMask alloc] initWithFields:std::move(fields)]; } - (NSMutableArray *)encodedFieldTransforms: @@ -572,7 +563,7 @@ NS_ASSUME_NONNULL_BEGIN FSTAssert([fieldTransform.transform isKindOfClass:[FSTServerTimestampTransform class]], @"Unknown transform: %@", fieldTransform.transform); GCFSDocumentTransform_FieldTransform *proto = [GCFSDocumentTransform_FieldTransform message]; - proto.fieldPath = fieldTransform.path.canonicalString; + proto.fieldPath = util::WrapNSString(fieldTransform.path.CanonicalString()); proto.setToServerValue = GCFSDocumentTransform_FieldTransform_ServerValue_RequestTime; [protos addObject:proto]; } @@ -588,7 +579,8 @@ NS_ASSUME_NONNULL_BEGIN @"Unknown transform setToServerValue: %d", proto.setToServerValue); [fieldTransforms addObject:[[FSTFieldTransform alloc] - initWithPath:[FSTFieldPath pathWithServerFormat:proto.fieldPath] + initWithPath:FieldPath::FromServerFormat( + util::MakeStringView(proto.fieldPath)) transform:[FSTServerTimestampTransform serverTimestampTransform]]]; } return fieldTransforms; @@ -659,8 +651,7 @@ NS_ASSUME_NONNULL_BEGIN - (GCFSTarget_DocumentsTarget *)encodedDocumentsTarget:(FSTQuery *)query { GCFSTarget_DocumentsTarget *result = [GCFSTarget_DocumentsTarget message]; NSMutableArray *docs = result.documentsArray; - [docs addObject:[self encodedQueryPath:[FSTResourcePath - resourcePathWithCPPResourcePath:query.path]]]; + [docs addObject:[self encodedQueryPath:query.path]]; return result; } @@ -670,21 +661,20 @@ NS_ASSUME_NONNULL_BEGIN (unsigned long)documents.count); NSString *name = documents[0]; - return [FSTQuery queryWithPath:[[self decodedQueryPath:name] toCPPResourcePath]]; + return [FSTQuery queryWithPath:[self decodedQueryPath:name]]; } - (GCFSTarget_QueryTarget *)encodedQueryTarget:(FSTQuery *)query { // Dissect the path into parent, collectionId, and optional key filter. GCFSTarget_QueryTarget *queryTarget = [GCFSTarget_QueryTarget message]; - if (query.path.empty()) { - queryTarget.parent = - [self encodedQueryPath:[FSTResourcePath resourcePathWithCPPResourcePath:query.path]]; + if (query.path.size() == 0) { + queryTarget.parent = [self encodedQueryPath:query.path]; } else { - FSTResourcePath *path = [FSTResourcePath resourcePathWithCPPResourcePath:query.path]; - FSTAssert(path.length % 2 != 0, @"Document queries with filters are not supported."); - queryTarget.parent = [self encodedQueryPath:[path pathByRemovingLastSegment]]; + const ResourcePath &path = query.path; + FSTAssert(path.size() % 2 != 0, @"Document queries with filters are not supported."); + queryTarget.parent = [self encodedQueryPath:path.PopLast()]; GCFSStructuredQuery_CollectionSelector *from = [GCFSStructuredQuery_CollectionSelector message]; - from.collectionId = path.lastSegment; + from.collectionId = util::WrapNSString(path.last_segment()); [queryTarget.structuredQuery.fromArray addObject:from]; } @@ -715,7 +705,7 @@ NS_ASSUME_NONNULL_BEGIN } - (FSTQuery *)decodedQueryFromQueryTarget:(GCFSTarget_QueryTarget *)target { - FSTResourcePath *path = [self decodedQueryPath:target.parent]; + ResourcePath path = [self decodedQueryPath:target.parent]; GCFSStructuredQuery *query = target.structuredQuery; NSUInteger fromCount = query.fromArray_Count; @@ -724,7 +714,7 @@ NS_ASSUME_NONNULL_BEGIN @"StructuredQuery.from with more than one collection is not supported."); GCFSStructuredQuery_CollectionSelector *from = query.fromArray[0]; - path = [path pathByAppendingSegment:from.collectionId]; + path = path.Append(util::MakeString(from.collectionId)); } NSArray> *filterBy; @@ -756,7 +746,7 @@ NS_ASSUME_NONNULL_BEGIN endAt = [self decodedBound:query.endAt]; } - return [[FSTQuery alloc] initWithPath:[path toCPPResourcePath] + return [[FSTQuery alloc] initWithPath:path filterBy:filterBy orderBy:orderBy limit:limit @@ -825,25 +815,22 @@ NS_ASSUME_NONNULL_BEGIN - (GCFSStructuredQuery_Filter *)encodedRelationFilter:(FSTRelationFilter *)filter { GCFSStructuredQuery_Filter *proto = [GCFSStructuredQuery_Filter message]; GCFSStructuredQuery_FieldFilter *fieldFilter = proto.fieldFilter; - fieldFilter.field = [self encodedFieldPath:[FSTFieldPath fieldPathWithCPPFieldPath:filter.field]]; + fieldFilter.field = [self encodedFieldPath:filter.field]; fieldFilter.op = [self encodedRelationFilterOperator:filter.filterOperator]; fieldFilter.value = [self encodedFieldValue:filter.value]; return proto; } - (FSTRelationFilter *)decodedRelationFilter:(GCFSStructuredQuery_FieldFilter *)proto { - FSTFieldPath *fieldPath = [FSTFieldPath pathWithServerFormat:proto.field.fieldPath]; + FieldPath fieldPath = FieldPath::FromServerFormat(util::MakeString(proto.field.fieldPath)); FSTRelationFilterOperator filterOperator = [self decodedRelationFilterOperator:proto.op]; FSTFieldValue *value = [self decodedFieldValue:proto.value]; - return [FSTRelationFilter filterWithField:[fieldPath toCPPFieldPath] - filterOperator:filterOperator - value:value]; + return [FSTRelationFilter filterWithField:fieldPath filterOperator:filterOperator value:value]; } - (GCFSStructuredQuery_Filter *)encodedUnaryFilter:(id)filter { GCFSStructuredQuery_Filter *proto = [GCFSStructuredQuery_Filter message]; - proto.unaryFilter.field = - [self encodedFieldPath:[FSTFieldPath fieldPathWithCPPFieldPath:filter.field]]; + proto.unaryFilter.field = [self encodedFieldPath:filter.field]; if ([filter isKindOfClass:[FSTNanFilter class]]) { proto.unaryFilter.op = GCFSStructuredQuery_UnaryFilter_Operator_IsNan; } else if ([filter isKindOfClass:[FSTNullFilter class]]) { @@ -855,22 +842,22 @@ NS_ASSUME_NONNULL_BEGIN } - (id)decodedUnaryFilter:(GCFSStructuredQuery_UnaryFilter *)proto { - FSTFieldPath *field = [FSTFieldPath pathWithServerFormat:proto.field.fieldPath]; + FieldPath field = FieldPath::FromServerFormat(util::MakeString(proto.field.fieldPath)); switch (proto.op) { case GCFSStructuredQuery_UnaryFilter_Operator_IsNan: - return [[FSTNanFilter alloc] initWithField:[field toCPPFieldPath]]; + return [[FSTNanFilter alloc] initWithField:field]; case GCFSStructuredQuery_UnaryFilter_Operator_IsNull: - return [[FSTNullFilter alloc] initWithField:[field toCPPFieldPath]]; + return [[FSTNullFilter alloc] initWithField:field]; default: FSTFail(@"Unrecognized UnaryFilter.operator %d", proto.op); } } -- (GCFSStructuredQuery_FieldReference *)encodedFieldPath:(FSTFieldPath *)fieldPath { +- (GCFSStructuredQuery_FieldReference *)encodedFieldPath:(const FieldPath &)fieldPath { GCFSStructuredQuery_FieldReference *ref = [GCFSStructuredQuery_FieldReference message]; - ref.fieldPath = fieldPath.canonicalString; + ref.fieldPath = util::WrapNSString(fieldPath.CanonicalString()); return ref; } @@ -930,7 +917,7 @@ NS_ASSUME_NONNULL_BEGIN - (GCFSStructuredQuery_Order *)encodedSortOrder:(FSTSortOrder *)sortOrder { GCFSStructuredQuery_Order *proto = [GCFSStructuredQuery_Order message]; - proto.field = [self encodedFieldPath:[FSTFieldPath fieldPathWithCPPFieldPath:sortOrder.field]]; + proto.field = [self encodedFieldPath:sortOrder.field]; if (sortOrder.ascending) { proto.direction = GCFSStructuredQuery_Direction_Ascending; } else { @@ -940,7 +927,7 @@ NS_ASSUME_NONNULL_BEGIN } - (FSTSortOrder *)decodedSortOrder:(GCFSStructuredQuery_Order *)proto { - FSTFieldPath *fieldPath = [FSTFieldPath pathWithServerFormat:proto.field.fieldPath]; + FieldPath fieldPath = FieldPath::FromServerFormat(util::MakeString(proto.field.fieldPath)); BOOL ascending; switch (proto.direction) { case GCFSStructuredQuery_Direction_Ascending: @@ -952,7 +939,7 @@ NS_ASSUME_NONNULL_BEGIN default: FSTFail(@"Unrecognized GCFSStructuredQuery_Direction %d", proto.direction); } - return [FSTSortOrder sortOrderWithFieldPath:[fieldPath toCPPFieldPath] ascending:ascending]; + return [FSTSortOrder sortOrderWithFieldPath:fieldPath ascending:ascending]; } #pragma mark - Bounds/Cursors -- cgit v1.2.3