FSTDocument.mm 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "Firestore/Source/Model/FSTDocument.h"
  17. #include <utility>
  18. #import "Firestore/Source/Util/FSTClasses.h"
  19. #include "Firestore/core/src/firebase/firestore/model/document_key.h"
  20. #include "Firestore/core/src/firebase/firestore/model/field_path.h"
  21. #include "Firestore/core/src/firebase/firestore/model/field_value.h"
  22. #include "Firestore/core/src/firebase/firestore/util/comparison.h"
  23. #include "Firestore/core/src/firebase/firestore/util/delayed_constructor.h"
  24. #include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
  25. #include "Firestore/core/src/firebase/firestore/util/hashing.h"
  26. #include "Firestore/core/src/firebase/firestore/util/string_apple.h"
  27. #include "absl/types/optional.h"
  28. namespace util = firebase::firestore::util;
  29. using firebase::firestore::model::DocumentKey;
  30. using firebase::firestore::model::DocumentState;
  31. using firebase::firestore::model::FieldPath;
  32. using firebase::firestore::model::FieldValue;
  33. using firebase::firestore::model::ObjectValue;
  34. using firebase::firestore::model::SnapshotVersion;
  35. NS_ASSUME_NONNULL_BEGIN
  36. @interface FSTMaybeDocument ()
  37. - (instancetype)initWithKey:(DocumentKey)key
  38. version:(SnapshotVersion)version NS_DESIGNATED_INITIALIZER;
  39. @end
  40. @implementation FSTMaybeDocument {
  41. DocumentKey _key;
  42. SnapshotVersion _version;
  43. }
  44. - (instancetype)initWithKey:(DocumentKey)key version:(SnapshotVersion)version {
  45. self = [super init];
  46. if (self) {
  47. _key = std::move(key);
  48. _version = std::move(version);
  49. }
  50. return self;
  51. }
  52. - (bool)hasPendingWrites {
  53. @throw FSTAbstractMethodException(); // NOLINT
  54. }
  55. - (id)copyWithZone:(NSZone *_Nullable)zone {
  56. // All document types are immutable
  57. return self;
  58. }
  59. - (const DocumentKey &)key {
  60. return _key;
  61. }
  62. - (const SnapshotVersion &)version {
  63. return _version;
  64. }
  65. @end
  66. @implementation FSTDocument {
  67. DocumentState _documentState;
  68. util::DelayedConstructor<ObjectValue> _data;
  69. }
  70. + (instancetype)documentWithData:(ObjectValue)data
  71. key:(DocumentKey)key
  72. version:(SnapshotVersion)version
  73. state:(DocumentState)state {
  74. return [[FSTDocument alloc] initWithData:std::move(data)
  75. key:std::move(key)
  76. version:std::move(version)
  77. state:state];
  78. }
  79. + (instancetype)documentWithData:(ObjectValue)data
  80. key:(DocumentKey)key
  81. version:(SnapshotVersion)version
  82. state:(DocumentState)state
  83. proto:(GCFSDocument *)proto {
  84. return [[FSTDocument alloc] initWithData:std::move(data)
  85. key:std::move(key)
  86. version:std::move(version)
  87. state:state
  88. proto:proto];
  89. }
  90. - (instancetype)initWithData:(ObjectValue)data
  91. key:(DocumentKey)key
  92. version:(SnapshotVersion)version
  93. state:(DocumentState)state {
  94. self = [super initWithKey:std::move(key) version:std::move(version)];
  95. if (self) {
  96. _data.Init(std::move(data));
  97. _documentState = state;
  98. _proto = nil;
  99. }
  100. return self;
  101. }
  102. - (instancetype)initWithData:(ObjectValue)data
  103. key:(DocumentKey)key
  104. version:(SnapshotVersion)version
  105. state:(DocumentState)state
  106. proto:(GCFSDocument *)proto {
  107. self = [super initWithKey:std::move(key) version:std::move(version)];
  108. if (self) {
  109. _data.Init(std::move(data));
  110. _documentState = state;
  111. _proto = proto;
  112. }
  113. return self;
  114. }
  115. - (bool)hasLocalMutations {
  116. return _documentState == DocumentState::kLocalMutations;
  117. }
  118. - (bool)hasCommittedMutations {
  119. return _documentState == DocumentState::kCommittedMutations;
  120. }
  121. - (bool)hasPendingWrites {
  122. return self.hasLocalMutations || self.hasCommittedMutations;
  123. }
  124. - (const ObjectValue &)data {
  125. return *_data;
  126. }
  127. - (BOOL)isEqual:(id)other {
  128. if (other == self) {
  129. return YES;
  130. }
  131. if (![other isKindOfClass:[FSTDocument class]]) {
  132. return NO;
  133. }
  134. FSTDocument *otherDoc = other;
  135. return self.key == otherDoc.key && self.version == otherDoc.version &&
  136. _documentState == otherDoc->_documentState && self.data == otherDoc.data;
  137. }
  138. - (NSUInteger)hash {
  139. return util::Hash(self.key, self.version, self.data, static_cast<unsigned long>(_documentState));
  140. }
  141. - (NSString *)description {
  142. return [NSString stringWithFormat:@"<FSTDocument: key:%s version:%s documentState:%ld data:%s>",
  143. self.key.ToString().c_str(),
  144. self.version.timestamp().ToString().c_str(),
  145. (long)_documentState, self.data.ToString().c_str()];
  146. }
  147. - (absl::optional<FieldValue>)fieldForPath:(const FieldPath &)path {
  148. return _data->Get(path);
  149. }
  150. @end
  151. @implementation FSTDeletedDocument {
  152. bool _hasCommittedMutations;
  153. }
  154. + (instancetype)documentWithKey:(DocumentKey)key
  155. version:(SnapshotVersion)version
  156. hasCommittedMutations:(bool)committedMutations {
  157. FSTDeletedDocument *deletedDocument = [[FSTDeletedDocument alloc] initWithKey:std::move(key)
  158. version:std::move(version)];
  159. if (deletedDocument) {
  160. deletedDocument->_hasCommittedMutations = committedMutations;
  161. }
  162. return deletedDocument;
  163. }
  164. - (bool)hasCommittedMutations {
  165. return _hasCommittedMutations;
  166. }
  167. - (bool)hasPendingWrites {
  168. return self.hasCommittedMutations;
  169. }
  170. - (BOOL)isEqual:(id)other {
  171. if (other == self) {
  172. return YES;
  173. }
  174. if (![other isKindOfClass:[FSTDeletedDocument class]]) {
  175. return NO;
  176. }
  177. FSTDeletedDocument *otherDoc = other;
  178. return self.key == otherDoc.key && self.version == otherDoc.version &&
  179. _hasCommittedMutations == otherDoc->_hasCommittedMutations;
  180. }
  181. - (NSUInteger)hash {
  182. NSUInteger result = self.key.Hash();
  183. result = result * 31 + self.version.Hash();
  184. result = result * 31 + (_hasCommittedMutations ? 1 : 0);
  185. return result;
  186. }
  187. - (NSString *)description {
  188. return [NSString
  189. stringWithFormat:@"<FSTDeletedDocument: key:%s version:%s committedMutations:%d>",
  190. self.key.ToString().c_str(), self.version.timestamp().ToString().c_str(),
  191. _hasCommittedMutations];
  192. }
  193. @end
  194. @implementation FSTUnknownDocument
  195. + (instancetype)documentWithKey:(DocumentKey)key version:(SnapshotVersion)version {
  196. return [[FSTUnknownDocument alloc] initWithKey:std::move(key) version:std::move(version)];
  197. }
  198. - (bool)hasPendingWrites {
  199. return true;
  200. }
  201. - (BOOL)isEqual:(id)other {
  202. if (other == self) {
  203. return YES;
  204. }
  205. if (![other isKindOfClass:[FSTUnknownDocument class]]) {
  206. return NO;
  207. }
  208. FSTDocument *otherDoc = other;
  209. return self.key == otherDoc.key && self.version == otherDoc.version;
  210. }
  211. - (NSUInteger)hash {
  212. NSUInteger result = self.key.Hash();
  213. result = result * 31 + self.version.Hash();
  214. return result;
  215. }
  216. - (NSString *)description {
  217. return [NSString stringWithFormat:@"<FSTUnknownDocument: key:%s version:%s>",
  218. self.key.ToString().c_str(),
  219. self.version.timestamp().ToString().c_str()];
  220. }
  221. @end
  222. NS_ASSUME_NONNULL_END