Decode (key, index, value) tuple. A present() Optional will always be returned UNLESS partial is true. If partial is true then the return will not be present() unless at least the full key and index were in the encoded buffer. The value returned will be 0 or more value bytes, however many were available. Note that a short encoded buffer must at *least* contain the header length varint.
| 589 | // more value bytes, however many were available. |
| 590 | // Note that a short encoded buffer must at *least* contain the header length varint. |
| 591 | Optional<KeyValueRef> decodeKVFragment(StringRef encoded, uint32_t* index = nullptr, bool partial = false) { |
| 592 | uint8_t const* d = encoded.begin(); |
| 593 | uint64_t h, len1, len2; |
| 594 | d += sqlite3GetVarint(d, (u64*)&h); |
| 595 | |
| 596 | // Make sure entire header is present, else return nothing |
| 597 | if (partial && encoded.size() < h) |
| 598 | return Optional<KeyValueRef>(); |
| 599 | |
| 600 | d += sqlite3GetVarint(d, (u64*)&len1); |
| 601 | const uint8_t indexLen = *d++; |
| 602 | ASSERT(indexLen <= 4); |
| 603 | d += sqlite3GetVarint(d, (u64*)&len2); |
| 604 | ASSERT(d == encoded.begin() + h); |
| 605 | ASSERT(len1 >= 12 && !(len1 & 1)); |
| 606 | ASSERT(len2 >= 12 && !(len2 & 1)); |
| 607 | len1 = (len1 - 12) / 2; |
| 608 | len2 = (len2 - 12) / 2; |
| 609 | |
| 610 | if (partial) { |
| 611 | // If the key and index aren't complete, return nothing. |
| 612 | if (d + len1 + indexLen > encoded.end()) |
| 613 | return Optional<KeyValueRef>(); |
| 614 | // Encoded size shouldn't be *larger* than the record described by the header no matter what. |
| 615 | ASSERT(d + len1 + indexLen + len2 >= encoded.end()); |
| 616 | // Shorten value length to be whatever bytes remain after the header/key/index |
| 617 | len2 = std::min(len2, (uint64_t)(encoded.end() - indexLen - len1 - d)); |
| 618 | } else { |
| 619 | // But for non partial records encoded size should be exactly the size of the described record. |
| 620 | ASSERT(d + len1 + indexLen + len2 == encoded.end()); |
| 621 | } |
| 622 | |
| 623 | // Decode big endian index |
| 624 | if (index != nullptr) { |
| 625 | if (indexLen == 0) |
| 626 | *index = 0; |
| 627 | else { |
| 628 | const uint8_t* begin = d + len1; |
| 629 | const uint8_t* end = begin + indexLen; |
| 630 | *index = (uint8_t)*begin++; |
| 631 | while (begin < end) { |
| 632 | *index <<= 8; |
| 633 | *index |= *begin++; |
| 634 | } |
| 635 | } |
| 636 | } |
| 637 | return KeyValueRef(KeyRef(d, len1), KeyRef(d + len1 + indexLen, len2)); |
| 638 | } |
| 639 | |
| 640 | KeyValueRef decodeKVPrefix(StringRef encoded, int maxLength) { |
| 641 | uint8_t const* d = encoded.begin(); |