|
27 | 27 | #import "Firestore/Source/API/FIRGeoPoint+Internal.h"
|
28 | 28 | #import "Firestore/Source/API/FIRSnapshotMetadata+Internal.h"
|
29 | 29 | #import "Firestore/Source/API/FIRTimestamp+Internal.h"
|
| 30 | +#import "Firestore/Source/API/FSTUserDataWriter.h" |
30 | 31 | #import "Firestore/Source/API/converters.h"
|
31 | 32 |
|
| 33 | +#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h" |
32 | 34 | #include "Firestore/core/src/api/document_reference.h"
|
33 | 35 | #include "Firestore/core/src/api/document_snapshot.h"
|
34 | 36 | #include "Firestore/core/src/api/firestore.h"
|
|
39 | 41 | #include "Firestore/core/src/model/field_value.h"
|
40 | 42 | #include "Firestore/core/src/model/field_value_options.h"
|
41 | 43 | #include "Firestore/core/src/nanopb/nanopb_util.h"
|
| 44 | +#include "Firestore/core/src/remote/serializer.h" |
42 | 45 | #include "Firestore/core/src/util/exception.h"
|
43 | 46 | #include "Firestore/core/src/util/hard_assert.h"
|
44 | 47 | #include "Firestore/core/src/util/log.h"
|
|
60 | 63 | using firebase::firestore::model::FieldValueOptions;
|
61 | 64 | using firebase::firestore::model::ObjectValue;
|
62 | 65 | using firebase::firestore::model::ServerTimestampBehavior;
|
| 66 | +using firebase::firestore::remote::Serializer; |
63 | 67 | using firebase::firestore::nanopb::MakeNSData;
|
64 | 68 | using firebase::firestore::util::MakeString;
|
65 | 69 | using firebase::firestore::util::ThrowInvalidArgument;
|
| 70 | +using firebase::firestore::google_firestore_v1_Value; |
66 | 71 |
|
67 | 72 | NS_ASSUME_NONNULL_BEGIN
|
68 | 73 |
|
@@ -90,32 +95,35 @@ ServerTimestampBehavior InternalServerTimestampBehavior(FIRServerTimestampBehavi
|
90 | 95 | @implementation FIRDocumentSnapshot {
|
91 | 96 | DocumentSnapshot _snapshot;
|
92 | 97 |
|
| 98 | + std::unique_ptr<Serializer> _serializer; |
93 | 99 | FIRSnapshotMetadata *_cachedMetadata;
|
94 | 100 | }
|
95 | 101 |
|
96 | 102 | - (instancetype)initWithSnapshot:(DocumentSnapshot &&)snapshot {
|
97 | 103 | if (self = [super init]) {
|
98 | 104 | _snapshot = std::move(snapshot);
|
| 105 | + _serializer.reset(new Serializer(_snapshot.firestore()->database_id())); |
99 | 106 | }
|
100 | 107 | return self;
|
101 | 108 | }
|
102 | 109 |
|
103 |
| -- (instancetype)initWithFirestore:(std::shared_ptr<Firestore>)firestore |
| 110 | +- (instancetype)initWithFirestore:(FIRFirestore *)firestore |
104 | 111 | documentKey:(DocumentKey)documentKey
|
105 | 112 | document:(const absl::optional<Document> &)document
|
106 | 113 | metadata:(SnapshotMetadata)metadata {
|
107 | 114 | DocumentSnapshot wrapped;
|
108 | 115 | if (document.has_value()) {
|
109 | 116 | wrapped =
|
110 |
| - DocumentSnapshot::FromDocument(std::move(firestore), document.value(), std::move(metadata)); |
| 117 | + DocumentSnapshot::FromDocument(firestore.wrapped, document.value(), std::move(metadata)); |
111 | 118 | } else {
|
112 |
| - wrapped = DocumentSnapshot::FromNoDocument(std::move(firestore), std::move(documentKey), |
| 119 | + wrapped = DocumentSnapshot::FromNoDocument(firestore.wrapped, std::move(documentKey), |
113 | 120 | std::move(metadata));
|
114 | 121 | }
|
| 122 | + _serializer.reset(new Serializer(firestore.databaseID)); |
115 | 123 | return [self initWithSnapshot:std::move(wrapped)];
|
116 | 124 | }
|
117 | 125 |
|
118 |
| -- (instancetype)initWithFirestore:(std::shared_ptr<Firestore>)firestore |
| 126 | +- (instancetype)initWithFirestore:(FIRFirestore *)firestore |
119 | 127 | documentKey:(DocumentKey)documentKey
|
120 | 128 | document:(const absl::optional<Document> &)document
|
121 | 129 | fromCache:(bool)fromCache
|
@@ -176,7 +184,7 @@ - (FIRSnapshotMetadata *)metadata {
|
176 | 184 | absl::optional<ObjectValue> data = _snapshot.GetData();
|
177 | 185 | if (!data) return nil;
|
178 | 186 |
|
179 |
| - return [self convertedObject:data->GetInternalValue() options:options]; |
| 187 | + return [self convertedValue:*data options:options]; |
180 | 188 | }
|
181 | 189 |
|
182 | 190 | - (nullable id)valueForField:(id)field {
|
@@ -208,94 +216,27 @@ - (FieldValueOptions)optionsForServerTimestampBehavior:
|
208 | 216 | return FieldValueOptions(InternalServerTimestampBehavior(serverTimestampBehavior));
|
209 | 217 | }
|
210 | 218 |
|
211 |
| -// TODO(mutabledocuments): Replace with UserDataWriter |
| 219 | +// TODO(mutabledocuments): Replace this method and call UserDataWriter directly |
212 | 220 | - (id)convertedValue:(FieldValue)value options:(const FieldValueOptions &)options {
|
213 |
| - switch (value.type()) { |
214 |
| - case FieldValue::Type::Null: |
215 |
| - return [NSNull null]; |
216 |
| - case FieldValue::Type::Boolean: |
217 |
| - return value.boolean_value() ? @YES : @NO; |
218 |
| - case FieldValue::Type::Integer: |
219 |
| - return @(value.integer_value()); |
220 |
| - case FieldValue::Type::Double: |
221 |
| - return @(value.double_value()); |
222 |
| - case FieldValue::Type::Timestamp: |
223 |
| - return [self convertedTimestamp:value]; |
224 |
| - case FieldValue::Type::ServerTimestamp: |
225 |
| - return [self convertedServerTimestamp:value options:options]; |
226 |
| - case FieldValue::Type::String: |
227 |
| - return util::MakeNSString(value.string_value()); |
228 |
| - case FieldValue::Type::Blob: |
229 |
| - return MakeNSData(value.blob_value()); |
230 |
| - case FieldValue::Type::Reference: |
231 |
| - return [self convertedReference:value]; |
232 |
| - case FieldValue::Type::GeoPoint: |
233 |
| - return MakeFIRGeoPoint(value.geo_point_value()); |
234 |
| - case FieldValue::Type::Array: |
235 |
| - return [self convertedArray:value.array_value() options:options]; |
236 |
| - case FieldValue::Type::Object: |
237 |
| - return [self convertedObject:value.object_value() options:options]; |
238 |
| - } |
239 |
| - |
240 |
| - UNREACHABLE(); |
241 |
| -} |
242 |
| - |
243 |
| -- (id)convertedTimestamp:(const FieldValue &)value { |
244 |
| - return MakeFIRTimestamp(value.timestamp_value()); |
245 |
| -} |
246 |
| - |
247 |
| -- (id)convertedServerTimestamp:(const FieldValue &)value |
248 |
| - options:(const FieldValueOptions &)options { |
249 |
| - const auto &sts = value.server_timestamp_value(); |
| 221 | + FIRServerTimestampBehavior behavior; |
250 | 222 | switch (options.server_timestamp_behavior()) {
|
251 | 223 | case ServerTimestampBehavior::kNone:
|
252 |
| - return [NSNull null]; |
253 |
| - case ServerTimestampBehavior::kEstimate: { |
254 |
| - FieldValue local_write_time = FieldValue::FromTimestamp(sts.local_write_time()); |
255 |
| - return [self convertedTimestamp:local_write_time]; |
256 |
| - } |
| 224 | + behavior = FIRServerTimestampBehaviorNone; |
| 225 | + break; |
| 226 | + case ServerTimestampBehavior::kEstimate: |
| 227 | + behavior = FIRServerTimestampBehaviorEstimate; |
| 228 | + break; |
257 | 229 | case ServerTimestampBehavior::kPrevious:
|
258 |
| - return sts.previous_value() ? [self convertedValue:*sts.previous_value() options:options] |
259 |
| - : [NSNull null]; |
260 |
| - } |
261 |
| - |
262 |
| - UNREACHABLE(); |
263 |
| -} |
264 |
| - |
265 |
| -- (id)convertedReference:(const FieldValue &)value { |
266 |
| - const auto &ref = value.reference_value(); |
267 |
| - const DatabaseId &refDatabase = ref.database_id(); |
268 |
| - const DatabaseId &database = _snapshot.firestore()->database_id(); |
269 |
| - if (refDatabase != database) { |
270 |
| - LOG_WARN("Document %s contains a document reference within a different database (%s/%s) which " |
271 |
| - "is not supported. It will be treated as a reference within the current database " |
272 |
| - "(%s/%s) instead.", |
273 |
| - _snapshot.CreateReference().Path(), refDatabase.project_id(), |
274 |
| - refDatabase.database_id(), database.project_id(), database.database_id()); |
275 |
| - } |
276 |
| - const DocumentKey &key = ref.key(); |
277 |
| - return [[FIRDocumentReference alloc] initWithKey:key firestore:_snapshot.firestore()]; |
278 |
| -} |
279 |
| - |
280 |
| -- (NSArray<id> *)convertedArray:(const FieldValue::Array &)arrayContents |
281 |
| - options:(const FieldValueOptions &)options { |
282 |
| - NSMutableArray *result = [NSMutableArray arrayWithCapacity:arrayContents.size()]; |
283 |
| - for (const FieldValue &value : arrayContents) { |
284 |
| - [result addObject:[self convertedValue:value options:options]]; |
| 230 | + behavior = FIRServerTimestampBehaviorPrevious; |
| 231 | + break; |
| 232 | + default: |
| 233 | + HARD_FAIL("Unexpected server timestamp option: %s", options.server_timestamp_behavior()); |
285 | 234 | }
|
286 |
| - return result; |
287 |
| -} |
288 | 235 |
|
289 |
| -- (NSDictionary<NSString *, id> *)convertedObject:(const FieldValue::Map &)objectValue |
290 |
| - options:(const FieldValueOptions &)options { |
291 |
| - NSMutableDictionary *result = [NSMutableDictionary dictionary]; |
292 |
| - for (const auto &kv : objectValue) { |
293 |
| - const std::string &key = kv.first; |
294 |
| - const FieldValue &value = kv.second; |
295 |
| - |
296 |
| - result[util::MakeNSString(key)] = [self convertedValue:value options:options]; |
297 |
| - } |
298 |
| - return result; |
| 236 | + FSTUserDataWriter *dataWriter = [[FSTUserDataWriter alloc] initWithFirestore:_snapshot.firestore() |
| 237 | + serverTimestampBehavior:behavior]; |
| 238 | + google_firestore_v1_Value protoValue = _serializer->EncodeFieldValue(value); |
| 239 | + return [dataWriter convertedValue:protoValue]; |
299 | 240 | }
|
300 | 241 |
|
301 | 242 | @end
|
|
0 commit comments