FSTLevelDBKey.mm 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  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/Local/FSTLevelDBKey.h"
  17. #include <string>
  18. #import "Firestore/Source/Model/FSTDocumentKey.h"
  19. #import "Firestore/Source/Model/FSTPath.h"
  20. #include "Firestore/core/src/firebase/firestore/util/ordered_code.h"
  21. NS_ASSUME_NONNULL_BEGIN
  22. using firebase::firestore::util::OrderedCode;
  23. using Firestore::StringView;
  24. using leveldb::Slice;
  25. static const char *kVersionGlobalTable = "version";
  26. static const char *kMutationsTable = "mutation";
  27. static const char *kDocumentMutationsTable = "document_mutation";
  28. static const char *kMutationQueuesTable = "mutation_queue";
  29. static const char *kTargetGlobalTable = "target_global";
  30. static const char *kTargetsTable = "target";
  31. static const char *kQueryTargetsTable = "query_target";
  32. static const char *kTargetDocumentsTable = "target_document";
  33. static const char *kDocumentTargetsTable = "document_target";
  34. static const char *kRemoteDocumentsTable = "remote_document";
  35. /**
  36. * Labels for the components of keys. These serve to make keys self-describing.
  37. *
  38. * These are intended to sort similarly to keys in the server storage format.
  39. *
  40. * Note that the server writes component labels using the equivalent to
  41. * OrderedCode::WriteSignedNumDecreasing. This means that despite the higher numeric value, a
  42. * terminator sorts before a path segment. In order to avoid needing the WriteSignedNumDecreasing
  43. * code just for these values, this enum's values are in the reverse order to the server side.
  44. *
  45. * Most server-side values don't apply here. For example, the server embeds projects, databases,
  46. * namespaces and similar values in its entity keys where the clients just open a different
  47. * leveldb. Similarly, many of these values don't apply to the server since the server is backed
  48. * by spanner which natively has concepts of tables and indexes. Where there's overlap, a comment
  49. * denotes the server value from the storage_format_internal.proto.
  50. */
  51. typedef NS_ENUM(int64_t, FSTComponentLabel) {
  52. /**
  53. * A terminator is the final component of a key. All complete keys have a terminator and a key
  54. * is known to be a key prefix if it doesn't have a terminator.
  55. */
  56. FSTComponentLabelTerminator = 0, // TERMINATOR_COMPONENT = 63, server-side
  57. /** A table name component names the logical table to which the key belongs. */
  58. FSTComponentLabelTableName = 5,
  59. /** A component containing the batch ID of a mutation. */
  60. FSTComponentLabelBatchID = 10,
  61. /** A component containing the canonical ID of a query. */
  62. FSTComponentLabelCanonicalID = 11,
  63. /** A component containing the target ID of a query. */
  64. FSTComponentLabelTargetID = 12,
  65. /** A component containing a user ID. */
  66. FSTComponentLabelUserID = 13,
  67. /**
  68. * A path segment describes just a single segment in a resource path. Path segments that occur
  69. * sequentially in a key represent successive segments in a single path.
  70. *
  71. * This value must be greater than FSTComponentLabelTerminator to ensure that longer paths sort
  72. * after paths that are prefixes of them.
  73. *
  74. * This value must also be larger than other separators so that path suffixes sort after other
  75. * key components.
  76. */
  77. FSTComponentLabelPathSegment = 62, // PATH = 60, server-side
  78. /** The maximum value that can be encoded by WriteSignedNumIncreasing in a single byte. */
  79. FSTComponentLabelUnknown = 63,
  80. };
  81. namespace {
  82. /** Writes a component label to the given key destination. */
  83. void WriteComponentLabel(std::string *dest, FSTComponentLabel label) {
  84. OrderedCode::WriteSignedNumIncreasing(dest, label);
  85. }
  86. /**
  87. * Reads a component label from the given key contents.
  88. *
  89. * If the read is unsuccessful, returns NO, and changes none of its arguments.
  90. *
  91. * If the read is successful, returns YES, contents will be updated to the next unread byte, and
  92. * label will be set to the decoded label value.
  93. */
  94. BOOL ReadComponentLabel(leveldb::Slice *contents, FSTComponentLabel *label) {
  95. int64_t rawResult = 0;
  96. absl::string_view tmp(contents->data(), contents->size());
  97. if (OrderedCode::ReadSignedNumIncreasing(&tmp, &rawResult)) {
  98. if (rawResult >= FSTComponentLabelTerminator && rawResult <= FSTComponentLabelUnknown) {
  99. *label = static_cast<FSTComponentLabel>(rawResult);
  100. *contents = leveldb::Slice(tmp.data(), tmp.size());
  101. return YES;
  102. }
  103. }
  104. return NO;
  105. }
  106. /**
  107. * Reads a component label from the given key contents.
  108. *
  109. * If the read is unsuccessful or if the read was successful but the label that was read did not
  110. * match the expectedLabel returns NO and changes none of its arguments.
  111. *
  112. * If the read is successful, returns YES and contents will be updated to the next unread byte.
  113. */
  114. BOOL ReadComponentLabelMatching(absl::string_view *contents, FSTComponentLabel expectedLabel) {
  115. int64_t rawResult = 0;
  116. absl::string_view tmp = *contents;
  117. if (OrderedCode::ReadSignedNumIncreasing(&tmp, &rawResult)) {
  118. if (rawResult == expectedLabel) {
  119. *contents = tmp;
  120. return YES;
  121. }
  122. }
  123. return NO;
  124. }
  125. /**
  126. * Reads a signed number from the given key contents and verifies that the value fits in a 32-bit
  127. * integer.
  128. *
  129. * If the read is unsuccessful or the number that was read was out of bounds for an int32_t,
  130. * returns NO, and changes none of its arguments.
  131. *
  132. * If the read is successful, returns YES, contents will be updated to the next unread byte, and
  133. * result will be set to the decoded integer value.
  134. */
  135. BOOL ReadInt32(Slice *contents, int32_t *result) {
  136. int64_t rawResult = 0;
  137. absl::string_view tmp(contents->data(), contents->size());
  138. if (OrderedCode::ReadSignedNumIncreasing(&tmp, &rawResult)) {
  139. if (rawResult >= INT32_MIN && rawResult <= INT32_MAX) {
  140. *contents = leveldb::Slice(tmp.data(), tmp.size());
  141. *result = static_cast<int32_t>(rawResult);
  142. return YES;
  143. }
  144. }
  145. return NO;
  146. }
  147. /** Writes a component label and a signed integer to the given key destination. */
  148. void WriteLabeledInt32(std::string *dest, FSTComponentLabel label, int32_t value) {
  149. WriteComponentLabel(dest, label);
  150. OrderedCode::WriteSignedNumIncreasing(dest, value);
  151. }
  152. /**
  153. * Reads a component label and signed number from the given key contents and verifies that the
  154. * label matches the expectedLabel and the value fits in a 32-bit integer.
  155. *
  156. * If the read is unsuccessful, the label didn't match, or the number that was read was out of
  157. * bounds for an int32_t, returns NO, and changes none of its arguments.
  158. *
  159. * If the read is successful, returns YES, contents will be updated to the next unread byte, and
  160. * value will be set to the decoded integer value.
  161. */
  162. BOOL ReadLabeledInt32(Slice *contents, FSTComponentLabel expectedLabel, int32_t *value) {
  163. absl::string_view tmp(contents->data(), contents->size());
  164. if (ReadComponentLabelMatching(&tmp, expectedLabel)) {
  165. Slice tmpSlice = leveldb::Slice(tmp.data(), tmp.size());
  166. if (ReadInt32(&tmpSlice, value)) {
  167. *contents = tmpSlice;
  168. return YES;
  169. }
  170. }
  171. return NO;
  172. }
  173. /** Writes a component label and an encoded string to the given key destination. */
  174. void WriteLabeledString(std::string *dest, FSTComponentLabel label, StringView value) {
  175. WriteComponentLabel(dest, label);
  176. OrderedCode::WriteString(dest, value);
  177. }
  178. /**
  179. * Reads a component label and a string from the given key contents and verifies that the label
  180. * matches the expectedLabel.
  181. *
  182. * If the read is unsuccessful or the label didn't match, returns NO, and changes none of its
  183. * arguments.
  184. *
  185. * If the read is successful, returns YES, contents will be updated to the next unread byte, and
  186. * value will be set to the decoded string value.
  187. */
  188. BOOL ReadLabeledString(Slice *contents, FSTComponentLabel expectedLabel, std::string *value) {
  189. absl::string_view tmp(contents->data(), contents->size());
  190. if (ReadComponentLabelMatching(&tmp, expectedLabel)) {
  191. if (OrderedCode::ReadString(&tmp, value)) {
  192. *contents = leveldb::Slice(tmp.data(), tmp.size());
  193. return YES;
  194. }
  195. }
  196. return NO;
  197. }
  198. /**
  199. * Reads a component label and a string from the given key contents and verifies that the label
  200. * matches the expectedLabel and the string matches the expectedValue.
  201. *
  202. * If the read is unsuccessful, the label or didn't match, or the string value didn't match,
  203. * returns NO, and changes none of its arguments.
  204. *
  205. * If the read is successful, returns YES, contents will be updated to the next unread byte.
  206. */
  207. BOOL ReadLabeledStringMatching(Slice *contents,
  208. FSTComponentLabel expectedLabel,
  209. const char *expectedValue) {
  210. std::string value;
  211. Slice tmp = *contents;
  212. if (ReadLabeledString(&tmp, expectedLabel, &value)) {
  213. if (value == expectedValue) {
  214. *contents = tmp;
  215. return YES;
  216. }
  217. }
  218. return NO;
  219. }
  220. /**
  221. * For each segment in the given resource path writes an FSTComponentLabelPathSegment component
  222. * label and a string containing the path segment.
  223. */
  224. void WriteResourcePath(std::string *dest, FSTResourcePath *path) {
  225. for (int i = 0; i < path.length; i++) {
  226. WriteComponentLabel(dest, FSTComponentLabelPathSegment);
  227. OrderedCode::WriteString(dest, StringView([path segmentAtIndex:i]));
  228. }
  229. }
  230. /**
  231. * Reads component labels and strings from the given key contents until it finds a component label
  232. * other that FSTComponentLabelPathSegment. All matched path segments are assembled into a resource
  233. * path and wrapped in an FSTDocumentKey.
  234. *
  235. * If the read is unsuccessful or the document key is invalid, returns NO, and changes none of its
  236. * arguments.
  237. *
  238. * If the read is successful, returns YES, contents will be updated to the next unread byte, and
  239. * value will be set to the decoded document key.
  240. */
  241. BOOL ReadDocumentKey(Slice *contents, FSTDocumentKey *__strong *result) {
  242. Slice completeSegments = *contents;
  243. std::string segment;
  244. NSMutableArray<NSString *> *pathSegments = [NSMutableArray array];
  245. for (;;) {
  246. // Advance a temporary slice to avoid advancing contents into the next key component which may
  247. // not be a path segment.
  248. absl::string_view readPosition(completeSegments.data(), completeSegments.size());
  249. if (!ReadComponentLabelMatching(&readPosition, FSTComponentLabelPathSegment)) {
  250. break;
  251. }
  252. if (!OrderedCode::ReadString(&readPosition, &segment)) {
  253. return NO;
  254. }
  255. NSString *pathSegment = [[NSString alloc] initWithUTF8String:segment.c_str()];
  256. [pathSegments addObject:pathSegment];
  257. segment.clear();
  258. completeSegments = leveldb::Slice(readPosition.data(), readPosition.size());
  259. }
  260. FSTResourcePath *path = [FSTResourcePath pathWithSegments:pathSegments];
  261. if (path.length > 0 && [FSTDocumentKey isDocumentKey:path]) {
  262. *contents = completeSegments;
  263. *result = [FSTDocumentKey keyWithPath:path];
  264. return YES;
  265. }
  266. return NO;
  267. }
  268. // Trivial shortcuts that make reading and writing components type-safe.
  269. inline void WriteTerminator(std::string *dest) {
  270. OrderedCode::WriteSignedNumIncreasing(dest, FSTComponentLabelTerminator);
  271. }
  272. inline BOOL ReadTerminator(Slice *contents) {
  273. absl::string_view tmp(contents->data(), contents->size());
  274. BOOL result = ReadComponentLabelMatching(&tmp, FSTComponentLabelTerminator);
  275. *contents = leveldb::Slice(tmp.data(), tmp.size());
  276. return result;
  277. }
  278. inline void WriteTableName(std::string *dest, const char *tableName) {
  279. WriteLabeledString(dest, FSTComponentLabelTableName, tableName);
  280. }
  281. inline BOOL ReadTableNameMatching(Slice *contents, const char *expectedTableName) {
  282. return ReadLabeledStringMatching(contents, FSTComponentLabelTableName, expectedTableName);
  283. }
  284. inline void WriteBatchID(std::string *dest, FSTBatchID batchID) {
  285. WriteLabeledInt32(dest, FSTComponentLabelBatchID, batchID);
  286. }
  287. inline BOOL ReadBatchID(Slice *contents, FSTBatchID *batchID) {
  288. return ReadLabeledInt32(contents, FSTComponentLabelBatchID, batchID);
  289. }
  290. inline void WriteCanonicalID(std::string *dest, StringView canonicalID) {
  291. WriteLabeledString(dest, FSTComponentLabelCanonicalID, canonicalID);
  292. }
  293. inline BOOL ReadCanonicalID(Slice *contents, std::string *canonicalID) {
  294. return ReadLabeledString(contents, FSTComponentLabelCanonicalID, canonicalID);
  295. }
  296. inline void WriteTargetID(std::string *dest, FSTTargetID targetID) {
  297. WriteLabeledInt32(dest, FSTComponentLabelTargetID, targetID);
  298. }
  299. inline BOOL ReadTargetID(Slice *contents, FSTTargetID *targetID) {
  300. return ReadLabeledInt32(contents, FSTComponentLabelTargetID, targetID);
  301. }
  302. inline void WriteUserID(std::string *dest, StringView userID) {
  303. WriteLabeledString(dest, FSTComponentLabelUserID, userID);
  304. }
  305. inline BOOL ReadUserID(Slice *contents, std::string *userID) {
  306. return ReadLabeledString(contents, FSTComponentLabelUserID, userID);
  307. }
  308. /** Returns a base64-encoded string for an invalid key, used for debug-friendly description text. */
  309. NSString *InvalidKey(const Slice &key) {
  310. NSData *keyData =
  311. [[NSData alloc] initWithBytesNoCopy:(void *)key.data() length:key.size() freeWhenDone:NO];
  312. return [keyData base64EncodedStringWithOptions:0];
  313. }
  314. } // namespace
  315. @implementation FSTLevelDBKey
  316. + (NSString *)descriptionForKey:(StringView)key {
  317. Slice contents = key;
  318. BOOL isTerminated = NO;
  319. NSMutableString *description = [NSMutableString string];
  320. [description appendString:@"["];
  321. while (contents.size() > 0) {
  322. Slice tmp = contents;
  323. FSTComponentLabel label = FSTComponentLabelUnknown;
  324. if (!ReadComponentLabel(&tmp, &label)) {
  325. break;
  326. }
  327. if (label == FSTComponentLabelTerminator) {
  328. isTerminated = YES;
  329. contents = tmp;
  330. break;
  331. }
  332. // Reset tmp since all the different read routines expect to see the separator first
  333. tmp = contents;
  334. if (label == FSTComponentLabelPathSegment) {
  335. FSTDocumentKey *documentKey = nil;
  336. if (!ReadDocumentKey(&tmp, &documentKey)) {
  337. break;
  338. }
  339. [description appendFormat:@" key=%@", [documentKey.path description]];
  340. } else if (label == FSTComponentLabelTableName) {
  341. std::string table;
  342. if (!ReadLabeledString(&tmp, FSTComponentLabelTableName, &table)) {
  343. break;
  344. }
  345. [description appendFormat:@"%s:", table.c_str()];
  346. } else if (label == FSTComponentLabelBatchID) {
  347. FSTBatchID batchID;
  348. if (!ReadBatchID(&tmp, &batchID)) {
  349. break;
  350. }
  351. [description appendFormat:@" batchID=%d", batchID];
  352. } else if (label == FSTComponentLabelCanonicalID) {
  353. std::string canonicalID;
  354. if (!ReadCanonicalID(&tmp, &canonicalID)) {
  355. break;
  356. }
  357. [description appendFormat:@" canonicalID=%s", canonicalID.c_str()];
  358. } else if (label == FSTComponentLabelTargetID) {
  359. FSTTargetID targetID;
  360. if (!ReadTargetID(&tmp, &targetID)) {
  361. break;
  362. }
  363. [description appendFormat:@" targetID=%d", targetID];
  364. } else if (label == FSTComponentLabelUserID) {
  365. std::string userID;
  366. if (!ReadUserID(&tmp, &userID)) {
  367. break;
  368. }
  369. [description appendFormat:@" userID=%s", userID.c_str()];
  370. } else {
  371. [description appendFormat:@" unknown label=%d", (int)label];
  372. break;
  373. }
  374. contents = tmp;
  375. }
  376. if (contents.size() > 0) {
  377. [description appendFormat:@" invalid key=<%@>", InvalidKey(key)];
  378. } else if (!isTerminated) {
  379. [description appendFormat:@" incomplete key"];
  380. }
  381. [description appendString:@"]"];
  382. return description;
  383. }
  384. @end
  385. @implementation FSTLevelDBVersionKey
  386. + (std::string)key {
  387. std::string result;
  388. WriteTableName(&result, kVersionGlobalTable);
  389. WriteTerminator(&result);
  390. return result;
  391. }
  392. @end
  393. @implementation FSTLevelDBMutationKey {
  394. std::string _userID;
  395. }
  396. + (std::string)keyPrefix {
  397. std::string result;
  398. WriteTableName(&result, kMutationsTable);
  399. return result;
  400. }
  401. + (std::string)keyPrefixWithUserID:(StringView)userID {
  402. std::string result;
  403. WriteTableName(&result, kMutationsTable);
  404. WriteUserID(&result, userID);
  405. return result;
  406. }
  407. + (std::string)keyWithUserID:(StringView)userID batchID:(FSTBatchID)batchID {
  408. std::string result;
  409. WriteTableName(&result, kMutationsTable);
  410. WriteUserID(&result, userID);
  411. WriteBatchID(&result, batchID);
  412. WriteTerminator(&result);
  413. return result;
  414. }
  415. - (const std::string &)userID {
  416. return _userID;
  417. }
  418. - (BOOL)decodeKey:(StringView)key {
  419. _userID.clear();
  420. Slice contents = key;
  421. return ReadTableNameMatching(&contents, kMutationsTable) && ReadUserID(&contents, &_userID) &&
  422. ReadBatchID(&contents, &_batchID) && ReadTerminator(&contents);
  423. }
  424. @end
  425. @implementation FSTLevelDBDocumentMutationKey {
  426. std::string _userID;
  427. }
  428. + (std::string)keyPrefix {
  429. std::string result;
  430. WriteTableName(&result, kDocumentMutationsTable);
  431. return result;
  432. }
  433. + (std::string)keyPrefixWithUserID:(StringView)userID {
  434. std::string result;
  435. WriteTableName(&result, kDocumentMutationsTable);
  436. WriteUserID(&result, userID);
  437. return result;
  438. }
  439. + (std::string)keyPrefixWithUserID:(StringView)userID resourcePath:(FSTResourcePath *)resourcePath {
  440. std::string result;
  441. WriteTableName(&result, kDocumentMutationsTable);
  442. WriteUserID(&result, userID);
  443. WriteResourcePath(&result, resourcePath);
  444. return result;
  445. }
  446. + (std::string)keyWithUserID:(StringView)userID
  447. documentKey:(FSTDocumentKey *)documentKey
  448. batchID:(FSTBatchID)batchID {
  449. std::string result;
  450. WriteTableName(&result, kDocumentMutationsTable);
  451. WriteUserID(&result, userID);
  452. WriteResourcePath(&result, documentKey.path);
  453. WriteBatchID(&result, batchID);
  454. WriteTerminator(&result);
  455. return result;
  456. }
  457. - (const std::string &)userID {
  458. return _userID;
  459. }
  460. - (BOOL)decodeKey:(StringView)key {
  461. _userID.clear();
  462. _documentKey = nil;
  463. Slice contents = key;
  464. return ReadTableNameMatching(&contents, kDocumentMutationsTable) &&
  465. ReadUserID(&contents, &_userID) && ReadDocumentKey(&contents, &_documentKey) &&
  466. ReadBatchID(&contents, &_batchID) && ReadTerminator(&contents);
  467. }
  468. @end
  469. @implementation FSTLevelDBMutationQueueKey {
  470. std::string _userID;
  471. }
  472. + (std::string)keyPrefix {
  473. std::string result;
  474. WriteTableName(&result, kMutationQueuesTable);
  475. return result;
  476. }
  477. + (std::string)keyWithUserID:(StringView)userID {
  478. std::string result;
  479. WriteTableName(&result, kMutationQueuesTable);
  480. WriteUserID(&result, userID);
  481. WriteTerminator(&result);
  482. return result;
  483. }
  484. - (const std::string &)userID {
  485. return _userID;
  486. }
  487. - (BOOL)decodeKey:(StringView)key {
  488. _userID.clear();
  489. Slice contents = key;
  490. return ReadTableNameMatching(&contents, kMutationQueuesTable) &&
  491. ReadUserID(&contents, &_userID) && ReadTerminator(&contents);
  492. }
  493. @end
  494. @implementation FSTLevelDBTargetGlobalKey
  495. + (std::string)key {
  496. std::string result;
  497. WriteTableName(&result, kTargetGlobalTable);
  498. WriteTerminator(&result);
  499. return result;
  500. }
  501. - (BOOL)decodeKey:(StringView)key {
  502. Slice contents = key;
  503. return ReadTableNameMatching(&contents, kTargetGlobalTable) && ReadTerminator(&contents);
  504. }
  505. @end
  506. @implementation FSTLevelDBTargetKey
  507. + (std::string)keyPrefix {
  508. std::string result;
  509. WriteTableName(&result, kTargetsTable);
  510. return result;
  511. }
  512. + (std::string)keyWithTargetID:(FSTTargetID)targetID {
  513. std::string result;
  514. WriteTableName(&result, kTargetsTable);
  515. WriteTargetID(&result, targetID);
  516. WriteTerminator(&result);
  517. return result;
  518. }
  519. - (BOOL)decodeKey:(StringView)key {
  520. Slice contents = key;
  521. return ReadTableNameMatching(&contents, kTargetsTable) && ReadTargetID(&contents, &_targetID) &&
  522. ReadTerminator(&contents);
  523. }
  524. @end
  525. @implementation FSTLevelDBQueryTargetKey {
  526. std::string _canonicalID;
  527. }
  528. + (std::string)keyPrefix {
  529. std::string result;
  530. WriteTableName(&result, kQueryTargetsTable);
  531. return result;
  532. }
  533. + (std::string)keyPrefixWithCanonicalID:(StringView)canonicalID {
  534. std::string result;
  535. WriteTableName(&result, kQueryTargetsTable);
  536. WriteCanonicalID(&result, canonicalID);
  537. return result;
  538. }
  539. + (std::string)keyWithCanonicalID:(StringView)canonicalID targetID:(FSTTargetID)targetID {
  540. std::string result;
  541. WriteTableName(&result, kQueryTargetsTable);
  542. WriteCanonicalID(&result, canonicalID);
  543. WriteTargetID(&result, targetID);
  544. WriteTerminator(&result);
  545. return result;
  546. }
  547. - (const std::string &)canonicalID {
  548. return _canonicalID;
  549. }
  550. - (BOOL)decodeKey:(StringView)key {
  551. _canonicalID.clear();
  552. Slice contents = key;
  553. return ReadTableNameMatching(&contents, kQueryTargetsTable) &&
  554. ReadCanonicalID(&contents, &_canonicalID) && ReadTargetID(&contents, &_targetID) &&
  555. ReadTerminator(&contents);
  556. }
  557. @end
  558. @implementation FSTLevelDBTargetDocumentKey
  559. + (std::string)keyPrefix {
  560. std::string result;
  561. WriteTableName(&result, kTargetDocumentsTable);
  562. return result;
  563. }
  564. + (std::string)keyPrefixWithTargetID:(FSTTargetID)targetID {
  565. std::string result;
  566. WriteTableName(&result, kTargetDocumentsTable);
  567. WriteTargetID(&result, targetID);
  568. return result;
  569. }
  570. + (std::string)keyWithTargetID:(FSTTargetID)targetID documentKey:(FSTDocumentKey *)documentKey {
  571. std::string result;
  572. WriteTableName(&result, kTargetDocumentsTable);
  573. WriteTargetID(&result, targetID);
  574. WriteResourcePath(&result, documentKey.path);
  575. WriteTerminator(&result);
  576. return result;
  577. }
  578. - (BOOL)decodeKey:(Firestore::StringView)key {
  579. _documentKey = nil;
  580. leveldb::Slice contents = key;
  581. return ReadTableNameMatching(&contents, kTargetDocumentsTable) &&
  582. ReadTargetID(&contents, &_targetID) && ReadDocumentKey(&contents, &_documentKey) &&
  583. ReadTerminator(&contents);
  584. }
  585. @end
  586. @implementation FSTLevelDBDocumentTargetKey
  587. + (std::string)keyPrefix {
  588. std::string result;
  589. WriteTableName(&result, kDocumentTargetsTable);
  590. return result;
  591. }
  592. + (std::string)keyPrefixWithResourcePath:(FSTResourcePath *)resourcePath {
  593. std::string result;
  594. WriteTableName(&result, kDocumentTargetsTable);
  595. WriteResourcePath(&result, resourcePath);
  596. return result;
  597. }
  598. + (std::string)keyWithDocumentKey:(FSTDocumentKey *)documentKey targetID:(FSTTargetID)targetID {
  599. std::string result;
  600. WriteTableName(&result, kDocumentTargetsTable);
  601. WriteResourcePath(&result, documentKey.path);
  602. WriteTargetID(&result, targetID);
  603. WriteTerminator(&result);
  604. return result;
  605. }
  606. - (BOOL)decodeKey:(Firestore::StringView)key {
  607. _documentKey = nil;
  608. leveldb::Slice contents = key;
  609. return ReadTableNameMatching(&contents, kDocumentTargetsTable) &&
  610. ReadDocumentKey(&contents, &_documentKey) && ReadTargetID(&contents, &_targetID) &&
  611. ReadTerminator(&contents);
  612. }
  613. @end
  614. @implementation FSTLevelDBRemoteDocumentKey
  615. + (std::string)keyPrefix {
  616. std::string result;
  617. WriteTableName(&result, kRemoteDocumentsTable);
  618. return result;
  619. }
  620. + (std::string)keyPrefixWithResourcePath:(FSTResourcePath *)path {
  621. std::string result;
  622. WriteTableName(&result, kRemoteDocumentsTable);
  623. WriteResourcePath(&result, path);
  624. return result;
  625. }
  626. + (std::string)keyWithDocumentKey:(FSTDocumentKey *)key {
  627. std::string result;
  628. WriteTableName(&result, kRemoteDocumentsTable);
  629. WriteResourcePath(&result, key.path);
  630. WriteTerminator(&result);
  631. return result;
  632. }
  633. - (BOOL)decodeKey:(StringView)key {
  634. _documentKey = nil;
  635. Slice contents = key;
  636. return ReadTableNameMatching(&contents, kRemoteDocumentsTable) &&
  637. ReadDocumentKey(&contents, &_documentKey) && ReadTerminator(&contents);
  638. }
  639. @end
  640. NS_ASSUME_NONNULL_END