FSTUserDataWriter.mm 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright 2021 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "Firestore/Source/API/FSTUserDataWriter.h"
  15. #import <Foundation/Foundation.h>
  16. #include <string>
  17. #include <utility>
  18. #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
  19. #include "Firestore/Source/API/FIRDocumentReference+Internal.h"
  20. #include "Firestore/Source/API/converters.h"
  21. #include "Firestore/core/include/firebase/firestore/geo_point.h"
  22. #include "Firestore/core/include/firebase/firestore/timestamp.h"
  23. #include "Firestore/core/src/api/firestore.h"
  24. #include "Firestore/core/src/model/database_id.h"
  25. #include "Firestore/core/src/model/document_key.h"
  26. #include "Firestore/core/src/model/server_timestamp_util.h"
  27. #include "Firestore/core/src/model/value_util.h"
  28. #include "Firestore/core/src/nanopb/nanopb_util.h"
  29. #include "Firestore/core/src/util/hard_assert.h"
  30. #include "Firestore/core/src/util/log.h"
  31. #include "Firestore/core/src/util/string_apple.h"
  32. @class FIRTimestamp;
  33. namespace api = firebase::firestore::api;
  34. namespace model = firebase::firestore::model;
  35. namespace nanopb = firebase::firestore::nanopb;
  36. using api::MakeFIRDocumentReference;
  37. using api::MakeFIRGeoPoint;
  38. using api::MakeFIRTimestamp;
  39. using firebase::firestore::GeoPoint;
  40. using firebase::firestore::google_firestore_v1_ArrayValue;
  41. using firebase::firestore::google_firestore_v1_MapValue;
  42. using firebase::firestore::google_firestore_v1_Value;
  43. using firebase::firestore::google_protobuf_Timestamp;
  44. using firebase::firestore::util::MakeNSString;
  45. using model::DatabaseId;
  46. using model::DocumentKey;
  47. using model::GetLocalWriteTime;
  48. using model::GetPreviousValue;
  49. using model::GetTypeOrder;
  50. using model::TypeOrder;
  51. using nanopb::MakeBytesArray;
  52. using nanopb::MakeByteString;
  53. using nanopb::MakeNSData;
  54. using nanopb::MakeString;
  55. using nanopb::MakeStringView;
  56. NS_ASSUME_NONNULL_BEGIN
  57. @implementation FSTUserDataWriter {
  58. std::shared_ptr<api::Firestore> _firestore;
  59. FIRServerTimestampBehavior _serverTimestampBehavior;
  60. }
  61. - (instancetype)initWithFirestore:(std::shared_ptr<api::Firestore>)firestore
  62. serverTimestampBehavior:(FIRServerTimestampBehavior)serverTimestampBehavior {
  63. self = [super init];
  64. if (self) {
  65. _firestore = std::move(firestore);
  66. _serverTimestampBehavior = serverTimestampBehavior;
  67. }
  68. return self;
  69. }
  70. - (id)convertedValue:(const google_firestore_v1_Value &)value {
  71. switch (GetTypeOrder(value)) {
  72. case TypeOrder::kMap:
  73. return [self convertedObject:value.map_value];
  74. case TypeOrder::kArray:
  75. return [self convertedArray:value.array_value];
  76. case TypeOrder::kReference:
  77. return [self convertedReference:value];
  78. case TypeOrder::kTimestamp:
  79. return [self convertedTimestamp:value.timestamp_value];
  80. case TypeOrder::kServerTimestamp:
  81. return [self convertedServerTimestamp:value];
  82. case TypeOrder::kNull:
  83. return [NSNull null];
  84. case TypeOrder::kBoolean:
  85. return value.boolean_value ? @YES : @NO;
  86. case TypeOrder::kNumber:
  87. return value.which_value_type == google_firestore_v1_Value_integer_value_tag
  88. ? @(value.integer_value)
  89. : @(value.double_value);
  90. case TypeOrder::kString:
  91. return MakeNSString(MakeStringView(value.string_value));
  92. case TypeOrder::kBlob:
  93. return MakeNSData(value.bytes_value);
  94. case TypeOrder::kGeoPoint:
  95. return MakeFIRGeoPoint(
  96. GeoPoint(value.geo_point_value.latitude, value.geo_point_value.longitude));
  97. case TypeOrder::kMaxValue:
  98. // It is not possible for users to construct a kMaxValue manually.
  99. break;
  100. }
  101. UNREACHABLE();
  102. }
  103. - (NSDictionary<NSString *, id> *)convertedObject:(const google_firestore_v1_MapValue &)mapValue {
  104. NSMutableDictionary *result = [NSMutableDictionary dictionary];
  105. for (pb_size_t i = 0; i < mapValue.fields_count; ++i) {
  106. absl::string_view key = MakeStringView(mapValue.fields[i].key);
  107. const google_firestore_v1_Value &value = mapValue.fields[i].value;
  108. result[MakeNSString(key)] = [self convertedValue:value];
  109. }
  110. return result;
  111. }
  112. - (NSArray<id> *)convertedArray:(const google_firestore_v1_ArrayValue &)arrayValue {
  113. NSMutableArray *result = [NSMutableArray arrayWithCapacity:arrayValue.values_count];
  114. for (pb_size_t i = 0; i < arrayValue.values_count; ++i) {
  115. [result addObject:[self convertedValue:arrayValue.values[i]]];
  116. }
  117. return result;
  118. }
  119. - (id)convertedServerTimestamp:(const google_firestore_v1_Value &)serverTimestampValue {
  120. switch (_serverTimestampBehavior) {
  121. case FIRServerTimestampBehavior::FIRServerTimestampBehaviorNone:
  122. return [NSNull null];
  123. case FIRServerTimestampBehavior::FIRServerTimestampBehaviorEstimate:
  124. return [self convertedTimestamp:GetLocalWriteTime(serverTimestampValue)];
  125. case FIRServerTimestampBehavior::FIRServerTimestampBehaviorPrevious: {
  126. auto previous_value = GetPreviousValue(serverTimestampValue);
  127. return previous_value ? [self convertedValue:*previous_value] : [NSNull null];
  128. }
  129. }
  130. UNREACHABLE();
  131. }
  132. - (FIRTimestamp *)convertedTimestamp:(const google_protobuf_Timestamp &)value {
  133. return MakeFIRTimestamp(firebase::Timestamp{value.seconds, value.nanos});
  134. }
  135. - (FIRDocumentReference *)convertedReference:(const google_firestore_v1_Value &)value {
  136. std::string ref = MakeString(value.reference_value);
  137. DatabaseId databaseID = DatabaseId::FromName(ref);
  138. DocumentKey key = DocumentKey::FromName(ref);
  139. if (databaseID != _firestore->database_id()) {
  140. LOG_WARN("Document reference is for a different database (%s/%s) which "
  141. "is not supported. It will be treated as a reference within the current database "
  142. "(%s/%s) instead.",
  143. databaseID.project_id(), databaseID.database_id(), databaseID.project_id(),
  144. databaseID.database_id());
  145. }
  146. return MakeFIRDocumentReference(key, _firestore);
  147. }
  148. @end
  149. NS_ASSUME_NONNULL_END