FSTLevelDBKey.mm 23 KB

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