Skip to content

Commit 432064a

Browse files
cherylEnkiduwu-huincooke3
authored
Pipeline tests part 2 (#14951)
Co-authored-by: wu-hui <wu.hui.github@gmail.com> Co-authored-by: Nick Cooke <36927374+ncooke3@users.noreply.github.com>
1 parent 7cafce4 commit 432064a

File tree

17 files changed

+1653
-144
lines changed

17 files changed

+1653
-144
lines changed

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,7 @@
11331133
A7309DAD4A3B5334536ECA46 /* remote_event_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 584AE2C37A55B408541A6FF3 /* remote_event_test.cc */; };
11341134
A7399FB3BEC50BBFF08EC9BA /* mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3068AA9DFBBA86C1FE2A946E /* mutation_queue_test.cc */; };
11351135
A7669E72BCED7FBADA4B1314 /* thread_safe_memoizer_testing_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EA10515F99A42D71DA2D2841 /* thread_safe_memoizer_testing_test.cc */; };
1136+
A78366DBE0BFDE42474A728A /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */; };
11361137
A80D38096052F928B17E1504 /* user_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = CCC9BD953F121B9E29F9AA42 /* user_test.cc */; };
11371138
A833A216988ADFD4876763CD /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C8FB22BCB9F454DA44BA80C8 /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json */; };
11381139
A841EEB5A94A271523EAE459 /* Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = A5D9044B72061CAF284BC9E4 /* Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json */; };
@@ -1172,6 +1173,7 @@
11721173
ACC9369843F5ED3BD2284078 /* timestamp_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ABF6506B201131F8005F2C74 /* timestamp_test.cc */; };
11731174
AD00D000A63837FB47291BFE /* Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 4B59C0A7B2A4548496ED4E7D /* Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json */; };
11741175
AD12205540893CEB48647937 /* filesystem_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA02DA2FCD0001CFC6EB08DA /* filesystem_testing.cc */; };
1176+
AD34726BFD3461FF64BBD56D /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */; };
11751177
AD35AA07F973934BA30C9000 /* remote_event_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 584AE2C37A55B408541A6FF3 /* remote_event_test.cc */; };
11761178
AD3C26630E33BE59C49BEB0D /* grpc_unary_call_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D964942163E63900EB9CFB /* grpc_unary_call_test.cc */; };
11771179
AD74843082C6465A676F16A7 /* async_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6FB467B208E9A8200554BA2 /* async_queue_test.cc */; };
@@ -1572,6 +1574,7 @@
15721574
ED9DF1EB20025227B38736EC /* message_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = CE37875365497FFA8687B745 /* message_test.cc */; };
15731575
EDF35B147B116F659D0D2CA8 /* Validation_BloomFilterTest_MD5_1_0001_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C939D1789E38C09F9A0C1157 /* Validation_BloomFilterTest_MD5_1_0001_membership_test_result.json */; };
15741576
EE470CC3C8FBCDA5F70A8466 /* local_store_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 307FF03D0297024D59348EBD /* local_store_test.cc */; };
1577+
EE4C4BE7F93366AE6368EE02 /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */; };
15751578
EE6DBFB0874A50578CE97A7F /* leveldb_remote_document_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0840319686A223CC4AD3FAB1 /* leveldb_remote_document_cache_test.cc */; };
15761579
EECC1EC64CA963A8376FA55C /* persistence_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9113B6F513D0473AEABBAF1F /* persistence_testing.cc */; };
15771580
EF3518F84255BAF3EBD317F6 /* exponential_backoff_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D1B68420E2AB1A00B35856 /* exponential_backoff_test.cc */; };
@@ -1739,6 +1742,7 @@
17391742
062072B62773A055001655D7 /* AsyncAwaitIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncAwaitIntegrationTests.swift; sourceTree = "<group>"; };
17401743
0840319686A223CC4AD3FAB1 /* leveldb_remote_document_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_remote_document_cache_test.cc; sourceTree = "<group>"; };
17411744
0D964D4936953635AC7E0834 /* Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json; sourceTree = "<group>"; };
1745+
0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TestHelper.swift; path = TestHelper/TestHelper.swift; sourceTree = "<group>"; };
17421746
0EE5300F8233D14025EF0456 /* string_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_apple_test.mm; sourceTree = "<group>"; };
17431747
11984BA0A99D7A7ABA5B0D90 /* Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS/Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS.release.xcconfig"; sourceTree = "<group>"; };
17441748
1235769122B7E915007DDFA9 /* EncodableFieldValueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodableFieldValueTests.swift; sourceTree = "<group>"; };
@@ -2599,6 +2603,7 @@
25992603
544A20ED20F6C046004E52CD /* API */,
26002604
5495EB012040E90200EBA509 /* Codable */,
26012605
124C932A22C1635300CA8C2D /* Integration */,
2606+
C7D3D622BB13EB3C3301DA4F /* TestHelper */,
26022607
620C1427763BA5D3CCFB5A1F /* BridgingHeader.h */,
26032608
54C9EDF52040E16300A969CD /* Info.plist */,
26042609
);
@@ -2978,6 +2983,14 @@
29782983
path = core;
29792984
sourceTree = "<group>";
29802985
};
2986+
C7D3D622BB13EB3C3301DA4F /* TestHelper */ = {
2987+
isa = PBXGroup;
2988+
children = (
2989+
0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */,
2990+
);
2991+
name = TestHelper;
2992+
sourceTree = "<group>";
2993+
};
29812994
DAFF0CF621E64AC30062958F /* macOS */ = {
29822995
isa = PBXGroup;
29832996
children = (
@@ -4699,6 +4712,7 @@
46994712
655F8647F57E5F2155DFF7B5 /* PipelineTests.swift in Sources */,
47004713
621D620C28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */,
47014714
1CFBD4563960D8A20C4679A3 /* SnapshotListenerSourceTests.swift in Sources */,
4715+
EE4C4BE7F93366AE6368EE02 /* TestHelper.swift in Sources */,
47024716
EFF22EAC2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */,
47034717
4D42E5C756229C08560DD731 /* XCTestCase+Await.mm in Sources */,
47044718
09BE8C01EC33D1FD82262D5D /* aggregate_query_test.cc in Sources */,
@@ -4951,6 +4965,7 @@
49514965
C8C2B945D84DD98391145F3F /* PipelineTests.swift in Sources */,
49524966
621D620B28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */,
49534967
A0BC30D482B0ABD1A3A24CDC /* SnapshotListenerSourceTests.swift in Sources */,
4968+
A78366DBE0BFDE42474A728A /* TestHelper.swift in Sources */,
49544969
EFF22EAB2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */,
49554970
736C4E82689F1CA1859C4A3F /* XCTestCase+Await.mm in Sources */,
49564971
412BE974741729A6683C386F /* aggregate_query_test.cc in Sources */,
@@ -5458,6 +5473,7 @@
54585473
E04CB0D580980748D5DC453F /* PipelineTests.swift in Sources */,
54595474
621D620A28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */,
54605475
B00F8D1819EE20C45B660940 /* SnapshotListenerSourceTests.swift in Sources */,
5476+
AD34726BFD3461FF64BBD56D /* TestHelper.swift in Sources */,
54615477
EFF22EAA2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */,
54625478
5492E0442021457E00B64F25 /* XCTestCase+Await.mm in Sources */,
54635479
B04E4FE20930384DF3A402F9 /* aggregate_query_test.cc in Sources */,

Firestore/Source/API/FIRPipelineBridge.mm

Lines changed: 84 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -710,9 +710,11 @@ - (id)initWithPercentage:(double)percentage {
710710
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
711711
if (!isUserDataRead) {
712712
if ([type isEqualToString:@"count"]) {
713-
cpp_sample = std::make_shared<Sample>("count", _count, 0);
713+
cpp_sample =
714+
std::make_shared<Sample>(Sample::SampleMode(Sample::SampleMode::DOCUMENTS), _count, 0);
714715
} else {
715-
cpp_sample = std::make_shared<Sample>("percentage", 0, _percentage);
716+
cpp_sample =
717+
std::make_shared<Sample>(Sample::SampleMode(Sample::SampleMode::PERCENT), 0, _percentage);
716718
}
717719
}
718720

@@ -750,30 +752,35 @@ - (id)initWithOther:(FIRPipelineBridge *)other {
750752

751753
@implementation FIRUnnestStageBridge {
752754
FIRExprBridge *_field;
753-
NSString *_Nullable _indexField;
755+
FIRExprBridge *_Nullable _index_field;
756+
FIRExprBridge *_alias;
754757
Boolean isUserDataRead;
755758
std::shared_ptr<Unnest> cpp_unnest;
756759
}
757760

758-
- (id)initWithField:(FIRExprBridge *)field indexField:(NSString *_Nullable)indexField {
761+
- (id)initWithField:(FIRExprBridge *)field
762+
alias:(FIRExprBridge *)alias
763+
indexField:(FIRExprBridge *_Nullable)index_field {
759764
self = [super init];
760765
if (self) {
761766
_field = field;
762-
_indexField = indexField;
767+
_alias = alias;
768+
_index_field = index_field;
763769
isUserDataRead = NO;
764770
}
765771
return self;
766772
}
767773

768774
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
769775
if (!isUserDataRead) {
770-
absl::optional<std::string> cpp_index_field;
771-
if (_indexField != nil) {
772-
cpp_index_field = MakeString(_indexField);
776+
absl::optional<std::shared_ptr<Expr>> cpp_index_field;
777+
if (_index_field != nil) {
778+
cpp_index_field = [_index_field cppExprWithReader:reader];
773779
} else {
774780
cpp_index_field = absl::nullopt;
775781
}
776-
cpp_unnest = std::make_shared<Unnest>([_field cppExprWithReader:reader], cpp_index_field);
782+
cpp_unnest = std::make_shared<Unnest>([_field cppExprWithReader:reader],
783+
[_alias cppExprWithReader:reader], cpp_index_field);
777784
}
778785

779786
isUserDataRead = YES;
@@ -784,14 +791,14 @@ - (id)initWithField:(FIRExprBridge *)field indexField:(NSString *_Nullable)index
784791

785792
@implementation FIRRawStageBridge {
786793
NSString *_name;
787-
NSArray<FIRExprBridge *> *_params;
794+
NSArray<id> *_params;
788795
NSDictionary<NSString *, FIRExprBridge *> *_Nullable _options;
789796
Boolean isUserDataRead;
790797
std::shared_ptr<RawStage> cpp_generic_stage;
791798
}
792799

793800
- (id)initWithName:(NSString *)name
794-
params:(NSArray<FIRExprBridge *> *)params
801+
params:(NSArray<id> *)params
795802
options:(NSDictionary<NSString *, FIRExprBridge *> *_Nullable)options {
796803
self = [super init];
797804
if (self) {
@@ -803,12 +810,51 @@ - (id)initWithName:(NSString *)name
803810
return self;
804811
}
805812

813+
- (firebase::firestore::google_firestore_v1_Value)convertIdToV1Value:(id)value
814+
reader:(FSTUserDataReader *)reader {
815+
if ([value isKindOfClass:[FIRExprBridge class]]) {
816+
return [((FIRExprBridge *)value) cppExprWithReader:reader]->to_proto();
817+
} else if ([value isKindOfClass:[FIRAggregateFunctionBridge class]]) {
818+
return [((FIRAggregateFunctionBridge *)value) cppExprWithReader:reader]->to_proto();
819+
} else if ([value isKindOfClass:[NSDictionary class]]) {
820+
NSDictionary<NSString *, id> *dictionary = (NSDictionary<NSString *, id> *)value;
821+
822+
std::unordered_map<std::string, firebase::firestore::google_firestore_v1_Value> cpp_dictionary;
823+
for (NSString *key in dictionary) {
824+
if ([dictionary[key] isKindOfClass:[FIRExprBridge class]]) {
825+
cpp_dictionary[MakeString(key)] =
826+
[((FIRExprBridge *)dictionary[key]) cppExprWithReader:reader]->to_proto();
827+
} else if ([dictionary[key] isKindOfClass:[FIRAggregateFunctionBridge class]]) {
828+
cpp_dictionary[MakeString(key)] =
829+
[((FIRAggregateFunctionBridge *)dictionary[key]) cppExprWithReader:reader]->to_proto();
830+
} else {
831+
ThrowInvalidArgument(
832+
"Dictionary value must be an FIRExprBridge or FIRAggregateFunctionBridge.");
833+
}
834+
}
835+
836+
firebase::firestore::google_firestore_v1_Value result;
837+
result.which_value_type = google_firestore_v1_Value_map_value_tag;
838+
839+
nanopb::SetRepeatedField(
840+
&result.map_value.fields, &result.map_value.fields_count, cpp_dictionary,
841+
[](const std::pair<std::string, firebase::firestore::google_firestore_v1_Value> &entry) {
842+
return firebase::firestore::_google_firestore_v1_MapValue_FieldsEntry{
843+
nanopb::MakeBytesArray(entry.first), entry.second};
844+
});
845+
return result;
846+
} else {
847+
ThrowInvalidArgument("Invalid value to convert to google_firestore_v1_Value.");
848+
}
849+
}
850+
806851
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
807852
if (!isUserDataRead) {
808-
std::vector<std::shared_ptr<Expr>> cpp_params;
809-
for (FIRExprBridge *param in _params) {
810-
cpp_params.push_back([param cppExprWithReader:reader]);
853+
std::vector<firebase::firestore::google_firestore_v1_Value> cpp_params;
854+
for (id param in _params) {
855+
cpp_params.push_back([self convertIdToV1Value:param reader:reader]);
811856
}
857+
812858
std::unordered_map<std::string, std::shared_ptr<Expr>> cpp_options;
813859
if (_options) {
814860
for (NSString *key in _options) {
@@ -928,7 +974,9 @@ - (id)initWithCppResult:(api::PipelineResult)result db:(std::shared_ptr<api::Fir
928974
FSTUserDataWriter *dataWriter =
929975
[[FSTUserDataWriter alloc] initWithFirestore:_db
930976
serverTimestampBehavior:serverTimestampBehavior];
931-
return [dataWriter convertedValue:*data];
977+
NSDictionary<NSString *, id> *dictionary = [dataWriter convertedValue:*data];
978+
NSLog(@"Dictionary contents: %@", dictionary);
979+
return dictionary;
932980
}
933981

934982
- (nullable id)get:(id)field {
@@ -959,35 +1007,41 @@ - (nullable id)get:(id)field
9591007
@implementation FIRPipelineBridge {
9601008
NSArray<FIRStageBridge *> *_stages;
9611009
FIRFirestore *firestore;
1010+
Boolean isUserDataRead;
9621011
std::shared_ptr<Pipeline> cpp_pipeline;
9631012
}
9641013

9651014
- (id)initWithStages:(NSArray<FIRStageBridge *> *)stages db:(FIRFirestore *)db {
9661015
_stages = stages;
9671016
firestore = db;
1017+
isUserDataRead = NO;
9681018
return [super init];
9691019
}
9701020

9711021
- (void)executeWithCompletion:(void (^)(__FIRPipelineSnapshotBridge *_Nullable result,
9721022
NSError *_Nullable error))completion {
973-
std::vector<std::shared_ptr<firebase::firestore::api::Stage>> cpp_stages;
974-
for (FIRStageBridge *stage in _stages) {
975-
cpp_stages.push_back([stage cppStageWithReader:firestore.dataReader]);
976-
}
977-
cpp_pipeline = std::make_shared<Pipeline>(cpp_stages, firestore.wrapped);
978-
979-
cpp_pipeline->execute([completion](StatusOr<api::PipelineSnapshot> maybe_value) {
980-
if (maybe_value.ok()) {
981-
__FIRPipelineSnapshotBridge *bridge = [[__FIRPipelineSnapshotBridge alloc]
982-
initWithCppSnapshot:std::move(maybe_value).ValueOrDie()];
983-
completion(bridge, nil);
984-
} else {
985-
completion(nil, MakeNSError(std::move(maybe_value).status()));
986-
}
987-
});
1023+
[self cppPipelineWithReader:firestore.dataReader]->execute(
1024+
[completion](StatusOr<api::PipelineSnapshot> maybe_value) {
1025+
if (maybe_value.ok()) {
1026+
__FIRPipelineSnapshotBridge *bridge = [[__FIRPipelineSnapshotBridge alloc]
1027+
initWithCppSnapshot:std::move(maybe_value).ValueOrDie()];
1028+
completion(bridge, nil);
1029+
} else {
1030+
completion(nil, MakeNSError(std::move(maybe_value).status()));
1031+
}
1032+
});
9881033
}
9891034

9901035
- (std::shared_ptr<api::Pipeline>)cppPipelineWithReader:(FSTUserDataReader *)reader {
1036+
if (!isUserDataRead) {
1037+
std::vector<std::shared_ptr<firebase::firestore::api::Stage>> cpp_stages;
1038+
for (FIRStageBridge *stage in _stages) {
1039+
cpp_stages.push_back([stage cppStageWithReader:firestore.dataReader]);
1040+
}
1041+
cpp_pipeline = std::make_shared<Pipeline>(cpp_stages, firestore.wrapped);
1042+
}
1043+
1044+
isUserDataRead = YES;
9911045
return cpp_pipeline;
9921046
}
9931047

Firestore/Source/Public/FirebaseFirestore/FIRPipelineBridge.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,16 @@ NS_SWIFT_NAME(UnionStageBridge)
191191
NS_SWIFT_SENDABLE
192192
NS_SWIFT_NAME(UnnestStageBridge)
193193
@interface FIRUnnestStageBridge : FIRStageBridge
194-
- (id)initWithField:(FIRExprBridge *)field indexField:(NSString *_Nullable)indexField;
194+
- (id)initWithField:(FIRExprBridge *)field
195+
alias:(FIRExprBridge *)alias
196+
indexField:(FIRExprBridge *_Nullable)index_field;
195197
@end
196198

197199
NS_SWIFT_SENDABLE
198200
NS_SWIFT_NAME(RawStageBridge)
199201
@interface FIRRawStageBridge : FIRStageBridge
200202
- (id)initWithName:(NSString *)name
201-
params:(NSArray<FIRExprBridge *> *)params
203+
params:(NSArray<id> *)params
202204
options:(NSDictionary<NSString *, FIRExprBridge *> *_Nullable)options;
203205
@end
204206

Firestore/Swift/Source/Helper/PipelineHelper.swift

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@
1313
// limitations under the License.
1414

1515
enum Helper {
16-
static func sendableToExpr(_ value: Sendable) -> Expr {
16+
static func sendableToExpr(_ value: Sendable?) -> Expr {
17+
guard let value = value else {
18+
return Constant.nil
19+
}
20+
1721
if value is Expr {
1822
return value as! Expr
19-
} else if value is [String: Sendable] {
20-
return map(value as! [String: Sendable])
21-
} else if value is [Sendable] {
22-
return array(value as! [Sendable])
23+
} else if value is [String: Sendable?] {
24+
return map(value as! [String: Sendable?])
25+
} else if value is [Sendable?] {
26+
return array(value as! [Sendable?])
2327
} else {
2428
return Constant(value)
2529
}
@@ -33,7 +37,7 @@ enum Helper {
3337
return exprMap
3438
}
3539

36-
static func map(_ elements: [String: Sendable]) -> FunctionExpr {
40+
static func map(_ elements: [String: Sendable?]) -> FunctionExpr {
3741
var result: [Expr] = []
3842
for (key, value) in elements {
3943
result.append(Constant(key))
@@ -42,10 +46,37 @@ enum Helper {
4246
return FunctionExpr("map", result)
4347
}
4448

45-
static func array(_ elements: [Sendable]) -> FunctionExpr {
49+
static func array(_ elements: [Sendable?]) -> FunctionExpr {
4650
let transformedElements = elements.map { element in
4751
sendableToExpr(element)
4852
}
4953
return FunctionExpr("array", transformedElements)
5054
}
55+
56+
// This function is used to convert Swift type into Objective-C type.
57+
static func sendableToAnyObjectForRawStage(_ value: Sendable?) -> AnyObject {
58+
guard let value = value else {
59+
return Constant.nil.bridge
60+
}
61+
62+
guard !(value is NSNull) else {
63+
return Constant.nil.bridge
64+
}
65+
66+
if value is Expr {
67+
return (value as! Expr).toBridge()
68+
} else if value is AggregateFunction {
69+
return (value as! AggregateFunction).toBridge()
70+
} else if value is [String: Sendable?] {
71+
let mappedValue: [String: Sendable?] = (value as! [String: Sendable?]).mapValues {
72+
if $0 is AggregateFunction {
73+
return ($0 as! AggregateFunction).toBridge()
74+
}
75+
return sendableToExpr($0).toBridge()
76+
}
77+
return mappedValue as NSDictionary
78+
} else {
79+
return Constant(value).bridge
80+
}
81+
}
5182
}

Firestore/Swift/Source/SwiftAPI/Pipeline/Aggregation/AggregateFunction.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
extension AggregateFunction {
16+
func toBridge() -> AggregateFunctionBridge {
17+
return (self as AggregateBridgeWrapper).bridge
18+
}
19+
}
20+
1521
public class AggregateFunction: AggregateBridgeWrapper, @unchecked Sendable {
1622
let bridge: AggregateFunctionBridge
1723

0 commit comments

Comments
 (0)