From 5ed79be77032644e9d0887eaaa7262155c2cf59e Mon Sep 17 00:00:00 2001 From: "A. Cody Schuffelen" Date: Tue, 24 Feb 2026 22:00:51 -0800 Subject: [PATCH 1/2] Replace LazilyLoadedFileReadCallback with ReaderSeeker This allows reusing any ReaderSeeker implementation together with LazilyLoadedFile. Bug: b/487500218 --- base/cvd/cuttlefish/host/libs/zip/BUILD.bazel | 4 +-- .../host/libs/zip/cached_zip_source.cc | 36 +++++++++++++------ .../host/libs/zip/lazily_loaded_file.cc | 10 +++--- .../host/libs/zip/lazily_loaded_file.h | 14 ++------ 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/base/cvd/cuttlefish/host/libs/zip/BUILD.bazel b/base/cvd/cuttlefish/host/libs/zip/BUILD.bazel index 6c5d571d7bb..5dac9dec3d5 100644 --- a/base/cvd/cuttlefish/host/libs/zip/BUILD.bazel +++ b/base/cvd/cuttlefish/host/libs/zip/BUILD.bazel @@ -45,8 +45,8 @@ cf_cc_library( "//cuttlefish/host/libs/zip/libzip_cc:seekable_source", "//cuttlefish/host/libs/zip/libzip_cc:source_callback", "//cuttlefish/host/libs/zip/libzip_cc:stat", + "//cuttlefish/io", "//cuttlefish/result", - "//libbase", "@abseil-cpp//absl/log", ], ) @@ -105,8 +105,8 @@ cf_cc_library( "//cuttlefish/common/libs/utils:files", "//cuttlefish/host/libs/zip:disjoint_range_set", "//cuttlefish/host/libs/zip:serialize_disjoint_range_set", + "//cuttlefish/io", "//cuttlefish/result", - "//libbase", "@abseil-cpp//absl/log", ], ) diff --git a/base/cvd/cuttlefish/host/libs/zip/cached_zip_source.cc b/base/cvd/cuttlefish/host/libs/zip/cached_zip_source.cc index b26f193782e..bbcc871540e 100644 --- a/base/cvd/cuttlefish/host/libs/zip/cached_zip_source.cc +++ b/base/cvd/cuttlefish/host/libs/zip/cached_zip_source.cc @@ -28,6 +28,7 @@ #include "cuttlefish/host/libs/zip/libzip_cc/seekable_source.h" #include "cuttlefish/host/libs/zip/libzip_cc/source_callback.h" #include "cuttlefish/host/libs/zip/libzip_cc/stat.h" +#include "cuttlefish/io/io.h" #include "cuttlefish/result/result.h" namespace cuttlefish { @@ -80,18 +81,31 @@ class CachedZipSourceCallbacks : public SeekableZipSourceCallback { const size_t size_; }; -class LazilyLoadedZipSourceFile : public LazilyLoadedFileReadCallback { +class ZipSourceAsReaderSeeker : public ReaderSeeker { public: - LazilyLoadedZipSourceFile(std::unique_ptr source, - SeekingZipSourceReader reader) + ZipSourceAsReaderSeeker(std::unique_ptr source, + SeekingZipSourceReader reader) : source_(std::move(source)), reader_(std::move(reader)) {} - Result Seek(size_t offset) override { - CF_EXPECT(reader_.SeekSet(offset)); - return offset; + Result Read(void* buf, size_t size) override { + return CF_EXPECT(reader_.Read(buf, size)); } - Result Read(char* data, size_t size) override { - return CF_EXPECT(reader_.Read(data, size)); + + Result SeekSet(uint64_t offset) override { + return CF_EXPECT(reader_.SeekSet(offset)); + } + + Result SeekCur(int64_t offset) override { + return CF_EXPECT(reader_.SeekCur(offset)); + } + + Result SeekEnd(int64_t offset) override { + return CF_EXPECT(reader_.SeekEnd(offset)); + } + + Result PRead(void* buf, uint64_t count, + uint64_t offset) const override { + return CF_EXPECT(reader_.PRead(buf, count, offset)); } private: @@ -112,9 +126,9 @@ Result CacheZipSource(SeekableZipSource inner, SeekingZipSourceReader reader = CF_EXPECT(unique_inner->Reader()); - std::unique_ptr file_callbacks = - std::make_unique(std::move(unique_inner), - std::move(reader)); + std::unique_ptr file_callbacks = + std::make_unique(std::move(unique_inner), + std::move(reader)); LazilyLoadedFile file = CF_EXPECT(LazilyLoadedFile::Create( std::move(file_path), size, std::move(file_callbacks))); diff --git a/base/cvd/cuttlefish/host/libs/zip/lazily_loaded_file.cc b/base/cvd/cuttlefish/host/libs/zip/lazily_loaded_file.cc index bcde53778a6..53c9b1c13f3 100644 --- a/base/cvd/cuttlefish/host/libs/zip/lazily_loaded_file.cc +++ b/base/cvd/cuttlefish/host/libs/zip/lazily_loaded_file.cc @@ -35,14 +35,13 @@ #include "cuttlefish/common/libs/utils/files.h" #include "cuttlefish/host/libs/zip/disjoint_range_set.h" #include "cuttlefish/host/libs/zip/serialize_disjoint_range_set.h" +#include "cuttlefish/io/io.h" #include "cuttlefish/result/result.h" namespace cuttlefish { static constexpr size_t kMinReadSize = 1 << 26; -LazilyLoadedFileReadCallback::~LazilyLoadedFileReadCallback() = default; - struct LazilyLoadedFile::Impl { std::string MetadataFile() const; Result ReadMetadata(); @@ -52,7 +51,7 @@ struct LazilyLoadedFile::Impl { std::string filename_; SharedFD contents_file_; - std::unique_ptr callback_; + std::unique_ptr callback_; DisjointRangeSet already_downloaded_; size_t seek_pos_; size_t size_; @@ -60,8 +59,7 @@ struct LazilyLoadedFile::Impl { }; Result LazilyLoadedFile::Create( - std::string filename, size_t size, - std::unique_ptr callback) { + std::string filename, size_t size, std::unique_ptr callback) { std::unique_ptr impl = std::make_unique(); CF_EXPECT(impl.get()); @@ -172,7 +170,7 @@ Result LazilyLoadedFile::Impl::Read(char* data, size_t size) { seek_pos_ += data_read; return data_read; } - CF_EXPECT(callback_->Seek(seek_pos_)); + CF_EXPECT(callback_->SeekSet(seek_pos_)); if (size < kMinReadSize) { size_t extended_read_size = std::min(kMinReadSize, size_ - seek_pos_); VLOG(1) << "Extending read request from " << size << " to " diff --git a/base/cvd/cuttlefish/host/libs/zip/lazily_loaded_file.h b/base/cvd/cuttlefish/host/libs/zip/lazily_loaded_file.h index ee665a6a688..1f1c3e2b424 100644 --- a/base/cvd/cuttlefish/host/libs/zip/lazily_loaded_file.h +++ b/base/cvd/cuttlefish/host/libs/zip/lazily_loaded_file.h @@ -19,23 +19,15 @@ #include #include +#include "cuttlefish/io/io.h" #include "cuttlefish/result/result.h" namespace cuttlefish { -class LazilyLoadedFileReadCallback { - public: - virtual ~LazilyLoadedFileReadCallback(); - - virtual Result Read(char* buf, size_t count) = 0; - virtual Result Seek(size_t offset) = 0; -}; - class LazilyLoadedFile { public: - static Result Create( - std::string filename, size_t size, - std::unique_ptr); + static Result Create(std::string filename, size_t size, + std::unique_ptr); LazilyLoadedFile(LazilyLoadedFile&&); ~LazilyLoadedFile(); From de8635a158908f1816db6f456322eac3673b7e3d Mon Sep 17 00:00:00 2001 From: "A. Cody Schuffelen" Date: Tue, 24 Feb 2026 23:13:35 -0800 Subject: [PATCH 2/2] Expose `ZipSourceAsReaderSeekerImpl` This makes it possible to use `SeekingZipSource`s in places that expect to receive `std::unique_ptr` implementations. It would also be possible to call `SeekingZipSource::Reader()` directly, but `ZipSourceAsReaderSeekerImpl` is self-contained, while the `Reader()` value on its own assumes the `SeekingZipSource` instance is still alive in the background. Bug: b/487500218 --- .../host/libs/zip/cached_zip_source.cc | 47 ++----------------- .../libs/zip/libzip_cc/seekable_source.cc | 47 ++++++++++++++++++- .../host/libs/zip/libzip_cc/seekable_source.h | 3 ++ 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/base/cvd/cuttlefish/host/libs/zip/cached_zip_source.cc b/base/cvd/cuttlefish/host/libs/zip/cached_zip_source.cc index bbcc871540e..b5e3c798dc6 100644 --- a/base/cvd/cuttlefish/host/libs/zip/cached_zip_source.cc +++ b/base/cvd/cuttlefish/host/libs/zip/cached_zip_source.cc @@ -81,38 +81,6 @@ class CachedZipSourceCallbacks : public SeekableZipSourceCallback { const size_t size_; }; -class ZipSourceAsReaderSeeker : public ReaderSeeker { - public: - ZipSourceAsReaderSeeker(std::unique_ptr source, - SeekingZipSourceReader reader) - : source_(std::move(source)), reader_(std::move(reader)) {} - - Result Read(void* buf, size_t size) override { - return CF_EXPECT(reader_.Read(buf, size)); - } - - Result SeekSet(uint64_t offset) override { - return CF_EXPECT(reader_.SeekSet(offset)); - } - - Result SeekCur(int64_t offset) override { - return CF_EXPECT(reader_.SeekCur(offset)); - } - - Result SeekEnd(int64_t offset) override { - return CF_EXPECT(reader_.SeekEnd(offset)); - } - - Result PRead(void* buf, uint64_t count, - uint64_t offset) const override { - return CF_EXPECT(reader_.PRead(buf, count, offset)); - } - - private: - std::unique_ptr source_; - SeekingZipSourceReader reader_; -}; - } // namespace Result CacheZipSource(SeekableZipSource inner, @@ -120,18 +88,11 @@ Result CacheZipSource(SeekableZipSource inner, ZipStat zip_stat = CF_EXPECT(inner.Stat()); size_t size = CF_EXPECT(std::move(zip_stat.size)); - std::unique_ptr unique_inner = - std::make_unique(std::move(inner)); - CF_EXPECT(unique_inner.get()); - - SeekingZipSourceReader reader = CF_EXPECT(unique_inner->Reader()); - - std::unique_ptr file_callbacks = - std::make_unique(std::move(unique_inner), - std::move(reader)); + std::unique_ptr reader = + CF_EXPECT(ZipSourceAsReaderSeeker(std::move(inner))); - LazilyLoadedFile file = CF_EXPECT(LazilyLoadedFile::Create( - std::move(file_path), size, std::move(file_callbacks))); + LazilyLoadedFile file = CF_EXPECT( + LazilyLoadedFile::Create(std::move(file_path), size, std::move(reader))); CachedZipSourceCallbacks callbacks(std::move(file), size); diff --git a/base/cvd/cuttlefish/host/libs/zip/libzip_cc/seekable_source.cc b/base/cvd/cuttlefish/host/libs/zip/libzip_cc/seekable_source.cc index 40bfcce580c..f497381bd1b 100644 --- a/base/cvd/cuttlefish/host/libs/zip/libzip_cc/seekable_source.cc +++ b/base/cvd/cuttlefish/host/libs/zip/libzip_cc/seekable_source.cc @@ -26,11 +26,12 @@ #include "zip.h" -#include "cuttlefish/io/fake_pread_pwrite.h" #include "cuttlefish/host/libs/zip/libzip_cc/error.h" #include "cuttlefish/host/libs/zip/libzip_cc/managed.h" #include "cuttlefish/host/libs/zip/libzip_cc/readable_source.h" #include "cuttlefish/host/libs/zip/libzip_cc/source_callback.h" +#include "cuttlefish/io/fake_pread_pwrite.h" +#include "cuttlefish/io/io.h" #include "cuttlefish/result/result.h" namespace cuttlefish { @@ -82,6 +83,38 @@ int64_t SeekableZipSourceCallbackFn(void* userdata, void* data, uint64_t len, cmd); } +class ZipSourceAsReaderSeekerImpl : public ReaderSeeker { + public: + ZipSourceAsReaderSeekerImpl(std::unique_ptr source, + SeekingZipSourceReader reader) + : source_(std::move(source)), reader_(std::move(reader)) {} + + Result Read(void* buf, size_t size) override { + return CF_EXPECT(reader_.Read(buf, size)); + } + + Result SeekSet(uint64_t offset) override { + return CF_EXPECT(reader_.SeekSet(offset)); + } + + Result SeekCur(int64_t offset) override { + return CF_EXPECT(reader_.SeekCur(offset)); + } + + Result SeekEnd(int64_t offset) override { + return CF_EXPECT(reader_.SeekEnd(offset)); + } + + Result PRead(void* buf, uint64_t count, + uint64_t offset) const override { + return CF_EXPECT(reader_.PRead(buf, count, offset)); + } + + private: + std::unique_ptr source_; + SeekingZipSourceReader reader_; +}; + } // namespace Result SeekableZipSource::FromCallbacks( @@ -157,4 +190,16 @@ Result SeekingZipSourceReader::PRead(void* buf, uint64_t count, return CF_EXPECT(FakePRead(non_const, buf, count, offset)); } +Result> ZipSourceAsReaderSeeker( + SeekableZipSource inner) { + std::unique_ptr unique_inner = + std::make_unique(std::move(inner)); + CF_EXPECT(unique_inner.get()); + + SeekingZipSourceReader reader = CF_EXPECT(unique_inner->Reader()); + + return std::make_unique(std::move(unique_inner), + std::move(reader)); +} + } // namespace cuttlefish diff --git a/base/cvd/cuttlefish/host/libs/zip/libzip_cc/seekable_source.h b/base/cvd/cuttlefish/host/libs/zip/libzip_cc/seekable_source.h index 2b21f2917ee..b49f1a32f88 100644 --- a/base/cvd/cuttlefish/host/libs/zip/libzip_cc/seekable_source.h +++ b/base/cvd/cuttlefish/host/libs/zip/libzip_cc/seekable_source.h @@ -70,4 +70,7 @@ class SeekingZipSourceReader : public ZipSourceReader, public ReaderSeeker { SeekingZipSourceReader(SeekableZipSource*); }; +Result> ZipSourceAsReaderSeeker( + SeekableZipSource inner); + } // namespace cuttlefish