| 688 | } |
| 689 | |
| 690 | void RowContainer::extractSerializedRows( |
| 691 | folly::Range<char**> rows, |
| 692 | const VectorPtr& result) { |
| 693 | // The format of the extracted row is: null bytes followed by keys and |
| 694 | // dependent columns. Fixed-width columns are serialized into fixed number of |
| 695 | // bytes (see typeKindSize). Variable-width columns are serialized as 4 bytes |
| 696 | // of size followed by that many bytes. |
| 697 | |
| 698 | const int32_t nullBytes = bits::nbytes(nullOffsets_.size()); |
| 699 | |
| 700 | // First, calculate total number of bytes needed to serialize all rows. |
| 701 | |
| 702 | size_t fixedWidthRowSize = 0; |
| 703 | bool hasVariableWidth = false; |
| 704 | for (auto i = 0; i < types_.size(); ++i) { |
| 705 | const auto& type = types_[i]; |
| 706 | if (type->isFixedWidth()) { |
| 707 | fixedWidthRowSize += typeKindSize(type->kind()); |
| 708 | } else { |
| 709 | hasVariableWidth = true; |
| 710 | } |
| 711 | } |
| 712 | |
| 713 | size_t totalBytes = nullBytes * rows.size() + fixedWidthRowSize * rows.size(); |
| 714 | if (hasVariableWidth) { |
| 715 | for (const char* row : rows) { |
| 716 | for (auto i = 0; i < types_.size(); ++i) { |
| 717 | const auto& type = types_[i]; |
| 718 | if (!type->isFixedWidth()) { |
| 719 | // 4 bytes for size + N bytes for data. |
| 720 | totalBytes += 4 + variableSizeAt(row, i); |
| 721 | } |
| 722 | } |
| 723 | } |
| 724 | } |
| 725 | |
| 726 | // Allocate sufficient buffer. |
| 727 | auto* flatResult = result->as<FlatVector<StringView>>(); |
| 728 | flatResult->resize(rows.size()); |
| 729 | auto* rawBuffer = flatResult->getRawStringBufferWithSpace(totalBytes, true); |
| 730 | |
| 731 | // Write serialized data. |
| 732 | size_t totalWritten = 0; |
| 733 | for (auto i = 0; i < rows.size(); ++i) { |
| 734 | auto* row = rows[i]; |
| 735 | size_t offset = 0; |
| 736 | |
| 737 | // Copy nulls. |
| 738 | memcpy(rawBuffer + offset, row + rowColumns_[0].nullByte(), nullBytes); |
| 739 | offset += nullBytes; |
| 740 | |
| 741 | // Copy values. |
| 742 | for (auto j = 0; j < types_.size(); ++j) { |
| 743 | const auto& type = types_[j]; |
| 744 | if (type->isFixedWidth()) { |
| 745 | const auto size = typeKindSize(type->kind()); |
| 746 | memcpy(rawBuffer + offset, row + rowColumns_[j].offset(), size); |
| 747 | offset += size; |