FSTDocument.mm 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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.h"
  20. #include "Firestore/core/src/firebase/firestore/model/document_key.h"
  21. #include "Firestore/core/src/firebase/firestore/model/field_path.h"
  22. #include "Firestore/core/src/firebase/firestore/model/field_value.h"
  23. #include "Firestore/core/src/firebase/firestore/util/comparison.h"
  24. #include "Firestore/core/src/firebase/firestore/util/delayed_constructor.h"
  25. #include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
  26. #include "Firestore/core/src/firebase/firestore/util/hashing.h"
  27. #include "Firestore/core/src/firebase/firestore/util/string_apple.h"
  28. #include "absl/types/optional.h"
  29. namespace util = firebase::firestore::util;
  30. using firebase::firestore::model::Document;
  31. using firebase::firestore::model::DocumentKey;
  32. using firebase::firestore::model::DocumentState;
  33. using firebase::firestore::model::FieldPath;
  34. using firebase::firestore::model::FieldValue;
  35. using firebase::firestore::model::ObjectValue;
  36. using firebase::firestore::model::SnapshotVersion;
  37. NS_ASSUME_NONNULL_BEGIN
  38. @interface FSTMaybeDocument ()
  39. - (instancetype)initWithKey:(DocumentKey)key
  40. version:(SnapshotVersion)version NS_DESIGNATED_INITIALIZER;
  41. @end
  42. @implementation FSTMaybeDocument {
  43. DocumentKey _key;
  44. SnapshotVersion _version;
  45. }
  46. - (instancetype)initWithKey:(DocumentKey)key version:(SnapshotVersion)version {
  47. self = [super init];
  48. if (self) {
  49. _key = std::move(key);
  50. _version = std::move(version);
  51. }
  52. return self;
  53. }
  54. - (bool)hasPendingWrites {
  55. @throw FSTAbstractMethodException(); // NOLINT
  56. }
  57. - (id)copyWithZone:(NSZone *_Nullable)zone {
  58. // All document types are immutable
  59. return self;
  60. }
  61. - (const DocumentKey &)key {
  62. return _key;
  63. }
  64. - (const SnapshotVersion &)version {
  65. return _version;
  66. }
  67. @end
  68. @implementation FSTDocument {
  69. DocumentState _documentState;
  70. util::DelayedConstructor<ObjectValue> _data;
  71. }
  72. + (instancetype)documentWithData:(ObjectValue)data
  73. key:(DocumentKey)key
  74. version:(SnapshotVersion)version
  75. state:(DocumentState)state {
  76. return [[FSTDocument alloc] initWithData:std::move(data)
  77. key:std::move(key)
  78. version:std::move(version)
  79. state:state];
  80. }
  81. + (instancetype)documentWithData:(ObjectValue)data
  82. key:(DocumentKey)key
  83. version:(SnapshotVersion)version
  84. state:(DocumentState)state
  85. proto:(GCFSDocument *)proto {
  86. return [[FSTDocument alloc] initWithData:std::move(data)
  87. key:std::move(key)
  88. version:std::move(version)
  89. state:state
  90. proto:proto];
  91. }
  92. - (instancetype)initWithData:(ObjectValue)data
  93. key:(DocumentKey)key
  94. version:(SnapshotVersion)version
  95. state:(DocumentState)state {
  96. self = [super initWithKey:std::move(key) version:std::move(version)];
  97. if (self) {
  98. _data.Init(std::move(data));
  99. _documentState = state;
  100. _proto = nil;
  101. }
  102. return self;
  103. }
  104. - (instancetype)initWithData:(ObjectValue)data
  105. key:(DocumentKey)key
  106. version:(SnapshotVersion)version
  107. state:(DocumentState)state
  108. proto:(GCFSDocument *)proto {
  109. self = [super initWithKey:std::move(key) version:std::move(version)];
  110. if (self) {
  111. _data.Init(std::move(data));
  112. _documentState = state;
  113. _proto = proto;
  114. }
  115. return self;
  116. }
  117. - (bool)hasLocalMutations {
  118. return _documentState == DocumentState::kLocalMutations;
  119. }
  120. - (bool)hasCommittedMutations {
  121. return _documentState == DocumentState::kCommittedMutations;
  122. }
  123. - (bool)hasPendingWrites {
  124. return self.hasLocalMutations || self.hasCommittedMutations;
  125. }
  126. - (const ObjectValue &)data {
  127. return *_data;
  128. }
  129. - (BOOL)isEqual:(id)other {
  130. if (other == self) {
  131. return YES;
  132. }
  133. if (![other isKindOfClass:[FSTDocument class]]) {
  134. return NO;
  135. }
  136. FSTDocument *otherDoc = other;
  137. return self.key == otherDoc.key && self.version == otherDoc.version &&
  138. _documentState == otherDoc->_documentState && self.data == otherDoc.data;
  139. }
  140. - (NSUInteger)hash {
  141. return util::Hash(self.key, self.version, self.data, static_cast<unsigned long>(_documentState));
  142. }
  143. - (NSString *)description {
  144. return [NSString stringWithFormat:@"<FSTDocument: key:%s version:%s documentState:%ld data:%s>",
  145. self.key.ToString().c_str(),
  146. self.version.timestamp().ToString().c_str(),
  147. (long)_documentState, self.data.ToString().c_str()];
  148. }
  149. - (absl::optional<FieldValue>)fieldForPath:(const FieldPath &)path {
  150. return _data->Get(path);
  151. }
  152. @end
  153. @implementation FSTDeletedDocument {
  154. bool _hasCommittedMutations;
  155. }
  156. + (instancetype)documentWithKey:(DocumentKey)key
  157. version:(SnapshotVersion)version
  158. hasCommittedMutations:(bool)committedMutations {
  159. FSTDeletedDocument *deletedDocument = [[FSTDeletedDocument alloc] initWithKey:std::move(key)
  160. version:std::move(version)];
  161. if (deletedDocument) {
  162. deletedDocument->_hasCommittedMutations = committedMutations;
  163. }
  164. return deletedDocument;
  165. }
  166. - (bool)hasCommittedMutations {
  167. return _hasCommittedMutations;
  168. }
  169. - (bool)hasPendingWrites {
  170. return self.hasCommittedMutations;
  171. }
  172. - (BOOL)isEqual:(id)other {
  173. if (other == self) {
  174. return YES;
  175. }
  176. if (![other isKindOfClass:[FSTDeletedDocument class]]) {
  177. return NO;
  178. }
  179. FSTDeletedDocument *otherDoc = other;
  180. return self.key == otherDoc.key && self.version == otherDoc.version &&
  181. _hasCommittedMutations == otherDoc->_hasCommittedMutations;
  182. }
  183. - (NSUInteger)hash {
  184. NSUInteger result = self.key.Hash();
  185. result = result * 31 + self.version.Hash();
  186. result = result * 31 + (_hasCommittedMutations ? 1 : 0);
  187. return result;
  188. }
  189. - (NSString *)description {
  190. return [NSString
  191. stringWithFormat:@"<FSTDeletedDocument: key:%s version:%s committedMutations:%d>",
  192. self.key.ToString().c_str(), self.version.timestamp().ToString().c_str(),
  193. _hasCommittedMutations];
  194. }
  195. @end
  196. @implementation FSTUnknownDocument
  197. + (instancetype)documentWithKey:(DocumentKey)key version:(SnapshotVersion)version {
  198. return [[FSTUnknownDocument alloc] initWithKey:std::move(key) version:std::move(version)];
  199. }
  200. - (bool)hasPendingWrites {
  201. return true;
  202. }
  203. - (BOOL)isEqual:(id)other {
  204. if (other == self) {
  205. return YES;
  206. }
  207. if (![other isKindOfClass:[FSTUnknownDocument class]]) {
  208. return NO;
  209. }
  210. FSTDocument *otherDoc = other;
  211. return self.key == otherDoc.key && self.version == otherDoc.version;
  212. }
  213. - (NSUInteger)hash {
  214. NSUInteger result = self.key.Hash();
  215. result = result * 31 + self.version.Hash();
  216. return result;
  217. }
  218. - (NSString *)description {
  219. return [NSString stringWithFormat:@"<FSTUnknownDocument: key:%s version:%s>",
  220. self.key.ToString().c_str(),
  221. self.version.timestamp().ToString().c_str()];
  222. }
  223. @end
  224. NS_ASSUME_NONNULL_END