| 1881 | } |
| 1882 | |
| 1883 | Future<> ReadFooterAsync(arrow::internal::Executor* executor) { |
| 1884 | constexpr int32_t kMagicSize = static_cast<int>(kArrowMagicBytes.size()); |
| 1885 | |
| 1886 | if (footer_offset_ <= kMagicSize * 2 + 4) { |
| 1887 | return Status::Invalid("File is too small: ", footer_offset_); |
| 1888 | } |
| 1889 | |
| 1890 | constexpr int64_t kTotalMagicSize = kMagicSize + sizeof(int32_t); |
| 1891 | auto self = std::dynamic_pointer_cast<RecordBatchFileReaderImpl>(shared_from_this()); |
| 1892 | auto read_magic = file_->ReadAsync(footer_offset_ - kTotalMagicSize, kTotalMagicSize, |
| 1893 | /*allow_short_read=*/false); |
| 1894 | if (executor) read_magic = executor->Transfer(std::move(read_magic)); |
| 1895 | return read_magic |
| 1896 | .Then([=](const std::shared_ptr<Buffer>& buffer) |
| 1897 | -> Future<std::shared_ptr<Buffer>> { |
| 1898 | DCHECK_EQ(buffer->size(), kTotalMagicSize); |
| 1899 | const auto magic_start = buffer->data() + sizeof(int32_t); |
| 1900 | if (std::string_view(reinterpret_cast<const char*>(magic_start), kMagicSize) != |
| 1901 | kArrowMagicBytes) { |
| 1902 | return Status::Invalid("Not an Arrow file"); |
| 1903 | } |
| 1904 | |
| 1905 | int32_t footer_length = bit_util::FromLittleEndian( |
| 1906 | *reinterpret_cast<const int32_t*>(buffer->data())); |
| 1907 | |
| 1908 | if (footer_length <= 0 || |
| 1909 | footer_length > self->footer_offset_ - kMagicSize * 2 - 4) { |
| 1910 | return Status::Invalid("File is smaller than indicated metadata size"); |
| 1911 | } |
| 1912 | |
| 1913 | // Now read the footer |
| 1914 | auto read_footer = self->file_->ReadAsync( |
| 1915 | self->footer_offset_ - footer_length - kTotalMagicSize, footer_length, |
| 1916 | /*allow_short_read=*/false); |
| 1917 | if (executor) read_footer = executor->Transfer(std::move(read_footer)); |
| 1918 | return read_footer; |
| 1919 | }) |
| 1920 | .Then([=](const std::shared_ptr<Buffer>& buffer) -> Status { |
| 1921 | self->footer_buffer_ = buffer; |
| 1922 | const auto data = self->footer_buffer_->data(); |
| 1923 | const auto size = self->footer_buffer_->size(); |
| 1924 | if (!internal::VerifyFlatbuffers<flatbuf::Footer>(data, size)) { |
| 1925 | return Status::IOError("Verification of flatbuffer-encoded Footer failed."); |
| 1926 | } |
| 1927 | self->footer_ = flatbuf::GetFooter(data); |
| 1928 | |
| 1929 | auto fb_metadata = self->footer_->custom_metadata(); |
| 1930 | if (fb_metadata != nullptr) { |
| 1931 | std::shared_ptr<KeyValueMetadata> md; |
| 1932 | ARROW_ASSIGN_OR_RAISE(self->metadata_, |
| 1933 | internal::GetKeyValueMetadata(fb_metadata)); |
| 1934 | } |
| 1935 | return Status::OK(); |
| 1936 | }); |
| 1937 | } |
| 1938 | |
| 1939 | int num_dictionaries() const { |
| 1940 | return static_cast<int>(internal::FlatBuffersVectorSize(footer_->dictionaries())); |
nothing calls this directly
no test coverage detected