Skip to content

Commit 15046ff

Browse files
authored
Add C++ stages/expressions and Constant value support (#14588)
1 parent 0cd0224 commit 15046ff

19 files changed

+849
-71
lines changed

Firestore/Source/API/FIRPipelineBridge+Internal.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <memory>
2020

2121
#include "Firestore/core/src/api/expressions.h"
22+
#include "Firestore/core/src/api/firestore.h"
2223
#include "Firestore/core/src/api/pipeline.h"
2324
#include "Firestore/core/src/api/stages.h"
2425

@@ -30,13 +31,13 @@ NS_ASSUME_NONNULL_BEGIN
3031

3132
@interface FIRExprBridge (Internal)
3233

33-
- (std::shared_ptr<api::Expr>)cpp_expr;
34+
- (std::shared_ptr<api::Expr>)cppExprWithReader:(FSTUserDataReader *)reader;
3435

3536
@end
3637

3738
@interface FIRStageBridge (Internal)
3839

39-
- (std::shared_ptr<api::Stage>)cpp_stage;
40+
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader;
4041

4142
@end
4243

@@ -46,4 +47,10 @@ NS_ASSUME_NONNULL_BEGIN
4647

4748
@end
4849

50+
@interface __FIRPipelineResultBridge (Internal)
51+
52+
- (id)initWithCppResult:(api::PipelineResult)result db:(std::shared_ptr<api::Firestore>)db;
53+
54+
@end
55+
4956
NS_ASSUME_NONNULL_END

Firestore/Source/API/FIRPipelineBridge.mm

Lines changed: 127 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@
1818

1919
#include <memory>
2020

21+
#import "Firestore/Source/API/FIRDocumentReference+Internal.h"
2122
#import "Firestore/Source/API/FIRFirestore+Internal.h"
2223
#import "Firestore/Source/API/FIRPipelineBridge+Internal.h"
24+
#import "Firestore/Source/API/FSTUserDataReader.h"
25+
#import "Firestore/Source/API/FSTUserDataWriter.h"
2326

27+
#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
28+
29+
#include "Firestore/core/src/api/document_reference.h"
2430
#include "Firestore/core/src/api/expressions.h"
2531
#include "Firestore/core/src/api/pipeline.h"
2632
#include "Firestore/core/src/api/pipeline_result.h"
@@ -32,12 +38,14 @@
3238

3339
using firebase::firestore::api::CollectionSource;
3440
using firebase::firestore::api::Constant;
41+
using firebase::firestore::api::DocumentReference;
3542
using firebase::firestore::api::Expr;
3643
using firebase::firestore::api::Field;
3744
using firebase::firestore::api::FunctionExpr;
3845
using firebase::firestore::api::Pipeline;
3946
using firebase::firestore::api::Where;
4047
using firebase::firestore::util::MakeCallback;
48+
using firebase::firestore::util::MakeNSString;
4149
using firebase::firestore::util::MakeString;
4250

4351
NS_ASSUME_NONNULL_BEGIN
@@ -57,47 +65,60 @@ - (id)init:(NSString *)name {
5765
return self;
5866
}
5967

60-
- (std::shared_ptr<api::Expr>)cpp_expr {
68+
- (std::shared_ptr<api::Expr>)cppExprWithReader:(FSTUserDataReader *)reader {
6169
return field;
6270
}
6371

6472
@end
6573

6674
@implementation FIRConstantBridge {
6775
std::shared_ptr<Constant> constant;
76+
id _input;
77+
Boolean isUserDataRead;
6878
}
69-
- (id)init:(NSNumber *)value {
79+
- (id)init:(id)input {
7080
self = [super init];
71-
if (self) {
72-
constant = std::make_shared<Constant>(value.doubleValue);
73-
}
81+
_input = input;
82+
isUserDataRead = NO;
7483
return self;
7584
}
7685

77-
- (std::shared_ptr<api::Expr>)cpp_expr {
86+
- (std::shared_ptr<api::Expr>)cppExprWithReader:(FSTUserDataReader *)reader {
87+
if (!isUserDataRead) {
88+
constant = std::make_shared<Constant>([reader parsedQueryValue:_input]);
89+
}
90+
91+
isUserDataRead = YES;
7892
return constant;
7993
}
8094

8195
@end
8296

8397
@implementation FIRFunctionExprBridge {
8498
std::shared_ptr<FunctionExpr> eq;
99+
NSString *_name;
100+
NSArray<FIRExprBridge *> *_args;
101+
Boolean isUserDataRead;
85102
}
86103

87104
- (nonnull id)initWithName:(NSString *)name Args:(nonnull NSArray<FIRExprBridge *> *)args {
88105
self = [super init];
89-
if (self) {
106+
_name = name;
107+
_args = args;
108+
isUserDataRead = NO;
109+
return self;
110+
}
111+
112+
- (std::shared_ptr<api::Expr>)cppExprWithReader:(FSTUserDataReader *)reader {
113+
if (!isUserDataRead) {
90114
std::vector<std::shared_ptr<Expr>> cpp_args;
91-
for (FIRExprBridge *arg in args) {
92-
cpp_args.push_back(arg.cpp_expr);
115+
for (FIRExprBridge *arg in _args) {
116+
cpp_args.push_back([arg cppExprWithReader:reader]);
93117
}
94-
95-
eq = std::make_shared<FunctionExpr>(MakeString(name), std::move(cpp_args));
118+
eq = std::make_shared<FunctionExpr>(MakeString(_name), std::move(cpp_args));
96119
}
97-
return self;
98-
}
99120

100-
- (std::shared_ptr<api::Expr>)cpp_expr {
121+
isUserDataRead = YES;
101122
return eq;
102123
}
103124

@@ -118,63 +139,142 @@ - (id)initWithPath:(NSString *)path {
118139
return self;
119140
}
120141

121-
- (std::shared_ptr<api::Stage>)cpp_stage {
142+
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
122143
return collection_source;
123144
}
124145

125146
@end
126147

127148
@implementation FIRWhereStageBridge {
149+
FIRExprBridge *_exprBridge;
150+
Boolean isUserDataRead;
128151
std::shared_ptr<Where> where;
129152
}
130153

131154
- (id)initWithExpr:(FIRExprBridge *)expr {
132155
self = [super init];
133156
if (self) {
134-
where = std::make_shared<Where>(expr.cpp_expr);
157+
_exprBridge = expr;
158+
isUserDataRead = NO;
135159
}
136160
return self;
137161
}
138162

139-
- (std::shared_ptr<api::Stage>)cpp_stage {
163+
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
164+
if (!isUserDataRead) {
165+
where = std::make_shared<Where>([_exprBridge cppExprWithReader:reader]);
166+
}
167+
168+
isUserDataRead = YES;
140169
return where;
141170
}
142171

143172
@end
144173

174+
@interface __FIRPipelineSnapshotBridge ()
175+
176+
@property(nonatomic, strong, readwrite) NSArray<__FIRPipelineSnapshotBridge *> *results;
177+
178+
@end
179+
145180
@implementation __FIRPipelineSnapshotBridge {
146-
absl::optional<api::PipelineSnapshot> pipeline;
181+
absl::optional<api::PipelineSnapshot> snapshot_;
182+
NSMutableArray<__FIRPipelineResultBridge *> *results_;
147183
}
148184

149185
- (id)initWithCppSnapshot:(api::PipelineSnapshot)snapshot {
150186
self = [super init];
151187
if (self) {
152-
pipeline = std::move(snapshot);
188+
snapshot_ = std::move(snapshot);
189+
if (!snapshot_.has_value()) {
190+
results_ = nil;
191+
} else {
192+
NSMutableArray<__FIRPipelineResultBridge *> *results = [NSMutableArray array];
193+
for (auto &result : snapshot_.value().results()) {
194+
[results addObject:[[__FIRPipelineResultBridge alloc]
195+
initWithCppResult:result
196+
db:snapshot_.value().firestore()]];
197+
}
198+
results_ = results;
199+
}
153200
}
154201

155202
return self;
156203
}
157204

205+
- (NSArray<__FIRPipelineResultBridge *> *)results {
206+
return results_;
207+
}
208+
158209
@end
159210

160-
@implementation FIRPipelineBridge {
161-
std::shared_ptr<Pipeline> pipeline;
211+
@implementation __FIRPipelineResultBridge {
212+
api::PipelineResult _result;
213+
std::shared_ptr<api::Firestore> _db;
162214
}
163215

164-
- (id)initWithStages:(NSArray<FIRStageBridge *> *)stages db:(FIRFirestore *)db {
216+
- (FIRDocumentReference *)reference {
217+
if (!_result.internal_key().has_value()) return nil;
218+
219+
return [[FIRDocumentReference alloc] initWithKey:_result.internal_key().value() firestore:_db];
220+
}
221+
222+
- (NSString *)documentID {
223+
if (!_result.document_id().has_value()) {
224+
return nil;
225+
}
226+
227+
return MakeNSString(_result.document_id().value());
228+
}
229+
230+
- (id)initWithCppResult:(api::PipelineResult)result db:(std::shared_ptr<api::Firestore>)db {
165231
self = [super init];
166232
if (self) {
167-
std::vector<std::shared_ptr<firebase::firestore::api::Stage>> cpp_stages;
168-
for (FIRStageBridge *stage in stages) {
169-
cpp_stages.push_back(stage.cpp_stage);
170-
}
171-
pipeline = std::make_shared<Pipeline>(cpp_stages, db.wrapped);
233+
_result = std::move(result);
234+
_db = std::move(db);
172235
}
236+
173237
return self;
174238
}
175239

240+
- (nullable NSDictionary<NSString *, id> *)data {
241+
return [self dataWithServerTimestampBehavior:FIRServerTimestampBehaviorNone];
242+
}
243+
244+
- (nullable NSDictionary<NSString *, id> *)dataWithServerTimestampBehavior:
245+
(FIRServerTimestampBehavior)serverTimestampBehavior {
246+
absl::optional<firebase::firestore::google_firestore_v1_Value> data =
247+
_result.internal_value()->Get();
248+
if (!data) return nil;
249+
250+
FSTUserDataWriter *dataWriter =
251+
[[FSTUserDataWriter alloc] initWithFirestore:_db
252+
serverTimestampBehavior:serverTimestampBehavior];
253+
return [dataWriter convertedValue:*data];
254+
}
255+
256+
@end
257+
258+
@implementation FIRPipelineBridge {
259+
NSArray<FIRStageBridge *> *_stages;
260+
FIRFirestore *firestore;
261+
std::shared_ptr<Pipeline> pipeline;
262+
}
263+
264+
- (id)initWithStages:(NSArray<FIRStageBridge *> *)stages db:(FIRFirestore *)db {
265+
_stages = stages;
266+
firestore = db;
267+
return [super init];
268+
}
269+
176270
- (void)executeWithCompletion:(void (^)(__FIRPipelineSnapshotBridge *_Nullable result,
177271
NSError *_Nullable error))completion {
272+
std::vector<std::shared_ptr<firebase::firestore::api::Stage>> cpp_stages;
273+
for (FIRStageBridge *stage in _stages) {
274+
cpp_stages.push_back([stage cppStageWithReader:firestore.dataReader]);
275+
}
276+
pipeline = std::make_shared<Pipeline>(cpp_stages, firestore.wrapped);
277+
178278
pipeline->execute([completion](StatusOr<api::PipelineSnapshot> maybe_value) {
179279
if (maybe_value.ok()) {
180280
__FIRPipelineSnapshotBridge *bridge = [[__FIRPipelineSnapshotBridge alloc]

Firestore/Source/Public/FirebaseFirestore/FIRPipelineBridge.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#import <Foundation/Foundation.h>
2020

21+
#import "FIRDocumentSnapshot.h"
22+
2123
NS_ASSUME_NONNULL_BEGIN
2224

2325
NS_SWIFT_NAME(ExprBridge)
@@ -31,7 +33,7 @@ NS_SWIFT_NAME(FieldBridge)
3133

3234
NS_SWIFT_NAME(ConstantBridge)
3335
@interface FIRConstantBridge : FIRExprBridge
34-
- (id)init:(NSNumber *)value;
36+
- (id)init:(id)input;
3537
@end
3638

3739
NS_SWIFT_NAME(FunctionExprBridge)
@@ -72,6 +74,8 @@ NS_SWIFT_NAME(__PipelineResultBridge)
7274
@property(nonatomic, copy, readonly) NSString *documentID;
7375

7476
- (nullable NSDictionary<NSString *, id> *)data;
77+
- (nullable NSDictionary<NSString *, id> *)dataWithServerTimestampBehavior:
78+
(FIRServerTimestampBehavior)serverTimestampBehavior;
7579

7680
@end
7781

Firestore/Swift/Source/SwiftAPI/Expressions.swift

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,28 @@
1616

1717
import Foundation
1818

19-
public protocol Expr {
19+
public protocol Expr {}
20+
21+
protocol BridgeWrapper {
2022
var bridge: ExprBridge { get }
2123
}
2224

23-
public struct Constant: Expr {
24-
public var bridge: ExprBridge
25+
public struct Constant: Expr, BridgeWrapper {
26+
var bridge: ExprBridge
2527

26-
var value: any Numeric
27-
init(value: any Numeric) {
28+
var value: Any
29+
init(value: Any) {
2830
self.value = value
29-
bridge = ConstantBridge(value as! NSNumber)
31+
bridge = ConstantBridge(value)
3032
}
3133
}
3234

33-
public func constant(_ number: any Numeric) -> Constant {
35+
public func constant(_ number: Any) -> Constant {
3436
return Constant(value: number)
3537
}
3638

37-
public struct Field: Expr {
38-
public var bridge: ExprBridge
39+
public struct Field: Expr, BridgeWrapper {
40+
var bridge: ExprBridge
3941

4042
var name: String
4143
init(name: String) {
@@ -52,16 +54,20 @@ protocol Function: Expr {
5254
var name: String { get }
5355
}
5456

55-
public struct FunctionExpr: Function {
56-
public var bridge: ExprBridge
57+
public struct FunctionExpr: Function, BridgeWrapper {
58+
var bridge: ExprBridge
5759

5860
var name: String
5961
private var args: [Expr]
6062

6163
init(name: String, args: [Expr]) {
6264
self.name = name
6365
self.args = args
64-
bridge = FunctionExprBridge(name: name, args: args.map { $0.bridge })
66+
bridge = FunctionExprBridge(
67+
name: name,
68+
args: args.map { ($0 as! (Expr & BridgeWrapper)).bridge
69+
}
70+
)
6571
}
6672
}
6773

Firestore/Swift/Source/SwiftAPI/Stages.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ class Where: Stage {
4242

4343
init(condition: Expr) {
4444
self.condition = condition
45-
bridge = WhereStageBridge(expr: condition.bridge)
45+
bridge = WhereStageBridge(expr: (condition as! (Expr & BridgeWrapper)).bridge)
4646
}
4747
}

0 commit comments

Comments
 (0)