| 634 | } |
| 635 | |
| 636 | Status ValidateBinaryView(const BinaryViewType& type) { |
| 637 | int64_t views_byte_size = data.buffers[1]->size(); |
| 638 | int64_t required_view_count = data.length + data.offset; |
| 639 | if (static_cast<int64_t>(views_byte_size / BinaryViewType::kSize) < |
| 640 | required_view_count) { |
| 641 | return Status::Invalid("View buffer size (bytes): ", views_byte_size, |
| 642 | " isn't large enough for length: ", data.length, |
| 643 | " and offset: ", data.offset); |
| 644 | } |
| 645 | |
| 646 | if (!full_validation) return Status::OK(); |
| 647 | |
| 648 | auto CheckPrefix = [&](size_t i, |
| 649 | std::array<uint8_t, BinaryViewType::kPrefixSize> prefix, |
| 650 | const uint8_t* data) { |
| 651 | if (std::memcmp(data, prefix.data(), BinaryViewType::kPrefixSize) == 0) { |
| 652 | return Status::OK(); |
| 653 | } |
| 654 | return Status::Invalid("View at slot ", i, " has inlined prefix 0x", |
| 655 | HexEncode(prefix.data(), BinaryViewType::kPrefixSize), |
| 656 | " but the out-of-line data begins with 0x", |
| 657 | HexEncode(data, BinaryViewType::kPrefixSize)); |
| 658 | }; |
| 659 | |
| 660 | std::span views(data.GetValues<BinaryViewType::c_type>(1), |
| 661 | static_cast<size_t>(data.length)); |
| 662 | std::span data_buffers(data.buffers.data() + 2, data.buffers.size() - 2); |
| 663 | |
| 664 | for (size_t i = 0; i < static_cast<size_t>(data.length); ++i) { |
| 665 | if (data.IsNull(i)) continue; |
| 666 | |
| 667 | if (views[i].size() < 0) { |
| 668 | return Status::Invalid("View at slot ", i, " has negative size ", |
| 669 | views[i].size()); |
| 670 | } |
| 671 | |
| 672 | if (views[i].is_inline()) { |
| 673 | auto padding_bytes = std::span(views[i].inlined.data).subspan(views[i].size()); |
| 674 | for (auto padding_byte : padding_bytes) { |
| 675 | if (padding_byte != 0) { |
| 676 | return Status::Invalid("View at slot ", i, " was inline with size ", |
| 677 | views[i].size(), |
| 678 | " but its padding bytes were not all zero: ", |
| 679 | HexEncode(padding_bytes.data(), padding_bytes.size())); |
| 680 | } |
| 681 | } |
| 682 | continue; |
| 683 | } |
| 684 | |
| 685 | auto [size, prefix, buffer_index, offset] = views[i].ref; |
| 686 | |
| 687 | if (buffer_index < 0) { |
| 688 | return Status::Invalid("View at slot ", i, " has negative buffer index ", |
| 689 | buffer_index); |
| 690 | } |
| 691 | |
| 692 | if (offset < 0) { |
| 693 | return Status::Invalid("View at slot ", i, " has negative offset ", offset); |