Skip to content

Commit 64d8a40

Browse files
authored
Migrate FSTReferenceValue to FSTDelegateValue (#3177)
* Add FieldValue::Reference * Migrate FSTReferenceValue to FSTDelegateValue * Build Objective-C components with CMake Build only the things required for FSTFieldValue
1 parent de7eb4f commit 64d8a40

File tree

13 files changed

+81
-126
lines changed

13 files changed

+81
-126
lines changed

Firestore/Example/Tests/API/FSTUserDataConverterTests.mm

+2-2
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,9 @@ - (void)testConvertsResourceNames {
144144
];
145145
for (FSTDocumentKeyReference *value in values) {
146146
FSTFieldValue *wrapped = FSTTestFieldValue(value);
147-
XCTAssertEqualObjects([wrapped class], [FSTReferenceValue class]);
147+
XCTAssertEqualObjects([wrapped class], [FSTDelegateValue class]);
148148
XCTAssertEqualObjects([wrapped value], [FSTDocumentKey keyWithDocumentKey:value.key]);
149-
XCTAssertTrue(((FSTReferenceValue *)wrapped).databaseID == value.databaseID);
149+
XCTAssertTrue(((FSTDelegateValue *)wrapped).referenceValue.database_id() == value.databaseID);
150150
XCTAssertEqual(wrapped.type, FieldValue::Type::Reference);
151151
}
152152
}

Firestore/Example/Tests/Model/FSTFieldValueTests.mm

+2-6
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@
6060
} else if ([value isKindOfClass:[FSTDocumentKeyReference class]]) {
6161
// We directly convert these here so that the databaseIDs can be different.
6262
FSTDocumentKeyReference *reference = (FSTDocumentKeyReference *)value;
63-
wrappedValue =
64-
[FSTReferenceValue referenceValue:[FSTDocumentKey keyWithDocumentKey:reference.key]
65-
databaseID:reference.databaseID];
63+
wrappedValue = FieldValue::FromReference(reference.databaseID, reference.key).Wrap();
6664
} else {
6765
wrappedValue = FSTTestFieldValue(value);
6866
}
@@ -317,9 +315,7 @@ - (void)testValueEquality {
317315
@[ FSTTestFieldValue(FSTTestGeoPoint(0, 1)), FieldValue::FromGeoPoint(GeoPoint(0, 1)).Wrap() ],
318316
@[ FSTTestFieldValue(FSTTestGeoPoint(1, 0)) ],
319317
@[
320-
[FSTReferenceValue
321-
referenceValue:[FSTDocumentKey keyWithDocumentKey:FSTTestDocKey(@"coll/doc1")]
322-
databaseID:database_id],
318+
FieldValue::FromReference(database_id, FSTTestDocKey(@"coll/doc1")).Wrap(),
323319
FSTTestFieldValue(FSTTestRef("project", DatabaseId::kDefault, @"coll/doc1"))
324320
],
325321
@[ FSTTestRef("project", "(default)", @"coll/doc2") ],

Firestore/Source/API/FIRDocumentSnapshot.mm

+3-3
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ - (id)convertedValue:(FSTFieldValue *)value options:(const FieldValueOptions &)o
193193
} else if (value.type == FieldValue::Type::Array) {
194194
return [self convertedArray:(FSTArrayValue *)value options:options];
195195
} else if (value.type == FieldValue::Type::Reference) {
196-
FSTReferenceValue *ref = (FSTReferenceValue *)value;
197-
const DatabaseId &refDatabase = ref.databaseID;
196+
const auto &ref = ((FSTDelegateValue *)value).referenceValue;
197+
const DatabaseId &refDatabase = ref.database_id();
198198
const DatabaseId &database = _snapshot.firestore()->database_id();
199199
if (refDatabase != database) {
200200
// TODO(b/32073923): Log this as a proper warning.
@@ -205,7 +205,7 @@ - (id)convertedValue:(FSTFieldValue *)value options:(const FieldValueOptions &)o
205205
refDatabase.database_id().c_str(), database.project_id().c_str(),
206206
database.database_id().c_str());
207207
}
208-
DocumentKey key = [[ref valueWithOptions:options] key];
208+
const DocumentKey &key = ref.key();
209209
return [[FIRDocumentReference alloc] initWithKey:key firestore:_snapshot.firestore()];
210210
} else {
211211
return [value valueWithOptions:options];

Firestore/Source/API/FIRQuery.mm

+3-5
Original file line numberDiff line numberDiff line change
@@ -467,9 +467,8 @@ - (FSTBound *)boundFromSnapshot:(FIRDocumentSnapshot *)snapshot isBefore:(BOOL)i
467467
// orders), multiple documents could match the position, yielding duplicate results.
468468
for (FSTSortOrder *sortOrder in self.query.sortOrders) {
469469
if (sortOrder.field == FieldPath::KeyFieldPath()) {
470-
[components addObject:[FSTReferenceValue
471-
referenceValue:[FSTDocumentKey keyWithDocumentKey:document.key]
472-
databaseID:self.firestore.databaseID]];
470+
[components
471+
addObject:FieldValue::FromReference(self.firestore.databaseID, document.key).Wrap()];
473472
} else {
474473
FSTFieldValue *value = [document fieldForPath:sortOrder.field];
475474

@@ -524,8 +523,7 @@ - (FSTBound *)boundFromFieldValues:(NSArray<id> *)fieldValues isBefore:(BOOL)isB
524523
path.CanonicalString());
525524
}
526525
DocumentKey key{path};
527-
fieldValue = [FSTReferenceValue referenceValue:[FSTDocumentKey keyWithDocumentKey:key]
528-
databaseID:self.firestore.databaseID];
526+
fieldValue = FieldValue::FromReference(self.firestore.databaseID, key).Wrap();
529527
}
530528

531529
[components addObject:fieldValue];

Firestore/Source/API/FSTUserDataConverter.mm

+1-2
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,7 @@ - (nullable FSTFieldValue *)parseScalarValue:(nullable id)input context:(ParseCo
476476
other.project_id(), other.database_id(), _databaseID.project_id(),
477477
_databaseID.database_id(), context.FieldDescription());
478478
}
479-
return [FSTReferenceValue referenceValue:[FSTDocumentKey keyWithDocumentKey:reference.key]
480-
databaseID:_databaseID];
479+
return FieldValue::FromReference(_databaseID, reference.key).Wrap();
481480

482481
} else {
483482
ThrowInvalidArgument("Unsupported type: %s%s", NSStringFromClass([input class]),

Firestore/Source/Core/FSTQuery.mm

+5-5
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,11 @@ - (BOOL)isEqual:(id)other {
187187
- (BOOL)matchesDocument:(FSTDocument *)document {
188188
if (_field.IsKeyFieldPath()) {
189189
HARD_ASSERT(self.value.type == FieldValue::Type::Reference,
190-
"Comparing on key, but filter value not a FSTReferenceValue.");
190+
"Comparing on key, but filter value not a Reference.");
191191
HARD_ASSERT(self.filterOperator != Filter::Operator::ArrayContains,
192192
"arrayContains queries don't make sense on document keys.");
193-
FSTReferenceValue *refValue = (FSTReferenceValue *)self.value;
194-
NSComparisonResult comparison = util::WrapCompare(document.key, refValue.value.key);
193+
const auto &ref = ((FSTDelegateValue *)self.value).referenceValue;
194+
NSComparisonResult comparison = util::WrapCompare(document.key, ref.key());
195195
return [self matchesComparison:comparison];
196196
} else {
197197
return [self matchesValue:[document fieldForPath:self.field]];
@@ -477,8 +477,8 @@ - (BOOL)sortsBeforeDocument:(FSTDocument *)document
477477
if (sortOrderComponent.field == FieldPath::KeyFieldPath()) {
478478
HARD_ASSERT(fieldValue.type == FieldValue::Type::Reference,
479479
"FSTBound has a non-key value where the key path is being used %s", fieldValue);
480-
FSTReferenceValue *refValue = (FSTReferenceValue *)fieldValue;
481-
comparison = util::Compare(refValue.value.key, document.key);
480+
const auto &ref = ((FSTDelegateValue *)fieldValue).referenceValue;
481+
comparison = util::Compare(ref.key(), document.key);
482482
} else {
483483
FSTFieldValue *docValue = [document fieldForPath:sortOrderComponent.field];
484484
HARD_ASSERT(docValue != nil,

Firestore/Source/Model/FSTFieldValue.h

+2-11
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,6 @@ typedef NS_ENUM(NSInteger, FSTTypeOrder) {
103103

104104
@end
105105

106-
/**
107-
* A reference value stored in Firestore.
108-
*/
109-
@interface FSTReferenceValue : FSTFieldValue <FSTDocumentKey *>
110-
111-
+ (instancetype)referenceValue:(FSTDocumentKey *)value databaseID:(model::DatabaseId)databaseID;
112-
113-
@property(nonatomic, assign, readonly) const model::DatabaseId &databaseID;
114-
115-
@end
116-
117106
/**
118107
* A structured object value stored in Firestore.
119108
*/
@@ -190,6 +179,8 @@ typedef NS_ENUM(NSInteger, FSTTypeOrder) {
190179
@interface FSTDelegateValue : FSTFieldValue <id>
191180
+ (instancetype)delegateWithValue:(model::FieldValue &&)value;
192181
- (const model::FieldValue &)internalValue;
182+
183+
- (const model::FieldValue::Reference &)referenceValue;
193184
@end
194185

195186
NS_ASSUME_NONNULL_END

Firestore/Source/Model/FSTFieldValue.mm

+5-71
Original file line numberDiff line numberDiff line change
@@ -128,76 +128,6 @@ - (double)doubleValue {
128128

129129
@end
130130

131-
#pragma mark - FSTReferenceValue
132-
133-
@interface FSTReferenceValue ()
134-
@property(nonatomic, strong, readonly) FSTDocumentKey *key;
135-
@end
136-
137-
@implementation FSTReferenceValue {
138-
DatabaseId _databaseID;
139-
}
140-
141-
+ (instancetype)referenceValue:(FSTDocumentKey *)value databaseID:(DatabaseId)databaseID {
142-
return [[FSTReferenceValue alloc] initWithValue:value databaseID:std::move(databaseID)];
143-
}
144-
145-
- (id)initWithValue:(FSTDocumentKey *)value databaseID:(DatabaseId)databaseID {
146-
self = [super init];
147-
if (self) {
148-
_key = value;
149-
_databaseID = std::move(databaseID);
150-
}
151-
return self;
152-
}
153-
154-
- (id)value {
155-
return self.key;
156-
}
157-
158-
- (FieldValue::Type)type {
159-
return FieldValue::Type::Reference;
160-
}
161-
162-
- (FSTTypeOrder)typeOrder {
163-
return FSTTypeOrderReference;
164-
}
165-
166-
- (BOOL)isEqual:(id)other {
167-
if (other == self) {
168-
return YES;
169-
}
170-
if (!([other isKindOfClass:[FSTFieldValue class]] &&
171-
((FSTFieldValue *)other).type == FieldValue::Type::Reference)) {
172-
return NO;
173-
}
174-
175-
FSTReferenceValue *otherRef = (FSTReferenceValue *)other;
176-
return self.key.key == otherRef.key.key && self.databaseID == otherRef.databaseID;
177-
}
178-
179-
- (NSUInteger)hash {
180-
NSUInteger result = self.databaseID.Hash();
181-
result = 31 * result + [self.key hash];
182-
return result;
183-
}
184-
185-
- (NSComparisonResult)compare:(FSTFieldValue *)other {
186-
if (other.type == FieldValue::Type::Reference) {
187-
FSTReferenceValue *ref = (FSTReferenceValue *)other;
188-
NSComparisonResult cmp = WrapCompare(self.databaseID.project_id(), ref.databaseID.project_id());
189-
if (cmp != NSOrderedSame) {
190-
return cmp;
191-
}
192-
cmp = WrapCompare(self.databaseID.database_id(), ref.databaseID.database_id());
193-
return cmp != NSOrderedSame ? cmp : WrapCompare(self.key.key, ref.key.key);
194-
} else {
195-
return [self defaultCompare:other];
196-
}
197-
}
198-
199-
@end
200-
201131
#pragma mark - FSTObjectValue
202132

203133
/**
@@ -480,6 +410,10 @@ + (instancetype)delegateWithValue:(FieldValue &&)value {
480410
return _internalValue;
481411
}
482412

413+
- (const FieldValue::Reference &)referenceValue {
414+
return _internalValue.reference_value();
415+
}
416+
483417
- (id)initWithValue:(FieldValue &&)value {
484418
self = [super init];
485419
if (self) {
@@ -560,7 +494,7 @@ - (id)value {
560494
case FieldValue::Type::Blob:
561495
return MakeNSData(self.internalValue.blob_value());
562496
case FieldValue::Type::Reference:
563-
HARD_FAIL("TODO(rsgowman): implement");
497+
return [FSTDocumentKey keyWithDocumentKey:self.referenceValue.key()];
564498
case FieldValue::Type::GeoPoint:
565499
return MakeFIRGeoPoint(self.internalValue.geo_point_value());
566500
case FieldValue::Type::Array:

Firestore/Source/Remote/FSTSerializerBeta.mm

+4-6
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,8 @@ - (GCFSValue *)encodedFieldValue:(FSTFieldValue *)fieldValue {
222222
case FieldValue::Type::Blob:
223223
return [self encodedBlobValue:[fieldValue value]];
224224
case FieldValue::Type::Reference: {
225-
FSTReferenceValue *ref = (FSTReferenceValue *)fieldValue;
226-
DocumentKey key = [[ref value] key];
227-
return [self encodedReferenceValueForDatabaseID:[ref databaseID] key:key];
225+
const auto &ref = ((FSTDelegateValue *)fieldValue).referenceValue;
226+
return [self encodedReferenceValueForDatabaseID:ref.database_id() key:ref.key()];
228227
}
229228
case FieldValue::Type::GeoPoint:
230229
return [self encodedGeoPointValue:[fieldValue value]];
@@ -345,7 +344,7 @@ - (GCFSValue *)encodedReferenceValueForDatabaseID:(const DatabaseId &)databaseID
345344
return result;
346345
}
347346

348-
- (FSTReferenceValue *)decodedReferenceValue:(NSString *)resourceName {
347+
- (FSTFieldValue *)decodedReferenceValue:(NSString *)resourceName {
349348
const ResourcePath path = [self decodedResourcePathWithDatabaseID:resourceName];
350349
const std::string &project = path[1];
351350
const std::string &database = path[3];
@@ -355,8 +354,7 @@ - (FSTReferenceValue *)decodedReferenceValue:(NSString *)resourceName {
355354
HARD_ASSERT(database_id == _databaseID, "Database %s:%s cannot encode reference from %s:%s",
356355
_databaseID.project_id(), _databaseID.database_id(), database_id.project_id(),
357356
database_id.database_id());
358-
return [FSTReferenceValue referenceValue:[FSTDocumentKey keyWithDocumentKey:key]
359-
databaseID:_databaseID];
357+
return FieldValue::FromReference(_databaseID, key).Wrap();
360358
}
361359

362360
- (GCFSArrayValue *)encodedArrayValue:(FSTArrayValue *)arrayValue {

Firestore/core/src/firebase/firestore/api/query_core.mm

+3-3
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,9 @@ QuerySnapshot result(firestore_, query_, std::move(snapshot),
215215
"is not because it has an odd number of segments.",
216216
path.CanonicalString());
217217
}
218-
field_value = [FSTReferenceValue
219-
referenceValue:[FSTDocumentKey keyWithDocumentKey:DocumentKey{path}]
220-
databaseID:firestore_->database_id()];
218+
field_value = FieldValue::FromReference(firestore_->database_id(),
219+
DocumentKey{path})
220+
.Wrap();
221221
} else if (field_value.type != FieldValue::Type::Reference) {
222222
ThrowInvalidArgument(
223223
"Invalid query. When querying by document ID you must provide a "

Firestore/core/src/firebase/firestore/model/field_value.cc

+29-11
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ namespace model {
4242
namespace {
4343

4444
using BaseValue = FieldValue::BaseValue;
45+
using Reference = FieldValue::Reference;
4546
using ServerTimestamp = FieldValue::ServerTimestamp;
4647
using Type = FieldValue::Type;
4748

@@ -332,8 +333,8 @@ class BlobValue : public SimpleFieldValue<Type::Blob, ByteString> {
332333

333334
class ReferenceValue : public FieldValue::BaseValue {
334335
public:
335-
ReferenceValue(DatabaseId database_id, DocumentKey key)
336-
: database_id_(std::move(database_id)), key_(std::move(key)) {
336+
explicit ReferenceValue(Reference reference)
337+
: reference_(std::move(reference)) {
337338
}
338339

339340
Type type() const override {
@@ -344,31 +345,43 @@ class ReferenceValue : public FieldValue::BaseValue {
344345
if (type() != other.type()) return false;
345346

346347
auto& other_value = Cast<ReferenceValue>(other);
347-
return database_id_ == other_value.database_id_ && key_ == other_value.key_;
348+
return database_id() == other_value.database_id() &&
349+
key() == other_value.key();
348350
}
349351

350352
ComparisonResult CompareTo(const BaseValue& other) const override {
351353
ComparisonResult cmp = CompareTypes(other);
352354
if (!util::Same(cmp)) return cmp;
353355

354356
auto& other_value = Cast<ReferenceValue>(other);
355-
cmp = Compare(database_id_, other_value.database_id_);
357+
cmp = Compare(database_id(), other_value.database_id());
356358
if (!util::Same(cmp)) return cmp;
357359

358-
return Compare(key_, other_value.key_);
360+
return Compare(key(), other_value.key());
359361
}
360362

361363
std::string ToString() const override {
362-
return absl::StrCat("Reference(key=", key_.ToString(), ")");
364+
return absl::StrCat("Reference(key=", key().ToString(), ")");
363365
}
364366

365367
size_t Hash() const override {
366-
return util::Hash(database_id_, key_);
368+
return util::Hash(database_id(), key());
369+
}
370+
371+
const Reference& value() const {
372+
return reference_;
373+
}
374+
375+
const DatabaseId& database_id() const {
376+
return reference_.database_id();
377+
}
378+
379+
const DocumentKey& key() const {
380+
return reference_.key();
367381
}
368382

369383
private:
370-
DatabaseId database_id_;
371-
DocumentKey key_;
384+
Reference reference_;
372385
};
373386

374387
class GeoPointValue : public BaseValue {
@@ -548,6 +561,11 @@ const ByteString& FieldValue::blob_value() const {
548561
return Cast<BlobValue>(*rep_).value();
549562
}
550563

564+
const Reference& FieldValue::reference_value() const {
565+
HARD_ASSERT(type() == Type::Reference);
566+
return Cast<ReferenceValue>(*rep_).value();
567+
}
568+
551569
const GeoPoint& FieldValue::geo_point_value() const {
552570
HARD_ASSERT(type() == Type::GeoPoint);
553571
return Cast<GeoPointValue>(*rep_).value();
@@ -712,8 +730,8 @@ FieldValue FieldValue::FromBlob(ByteString blob) {
712730
}
713731

714732
FieldValue FieldValue::FromReference(DatabaseId database_id, DocumentKey key) {
715-
return FieldValue(
716-
std::make_shared<ReferenceValue>(std::move(database_id), std::move(key)));
733+
return FieldValue(std::make_shared<ReferenceValue>(
734+
Reference(std::move(database_id), std::move(key))));
717735
}
718736

719737
FieldValue FieldValue::FromGeoPoint(const GeoPoint& value) {

0 commit comments

Comments
 (0)