如何将 Rust ZipArchive 和 ZipFile 放入单个读取实现结构中,同时处理生命周期和借用规则

How to fit a Rust ZipArchive and ZipFile into a single Read-implementing struct, while dealing with lifetime and borrowing rules

这个问题可以用几种不同的方式提出,但我的最终目标是将一个文件从 ZipArchive(Rust zip crate)封装到一个名为 ZipReader 的结构中,该结构实现了 Read,像这样:

struct ZipReader<R: Read + Seek> { ... }
impl<R: Read + Seek> ZipReader<R> {
    fn from(src: R, filename: &str) -> ZipReader<R> { ... }
}
impl <R: Read + Seek> Read for ZipReader<R> { ... }

我这样做的努力包括从 src 流构建一个新的 ZipArchive,然后使用 ZipArchive.by_name(name) 提取可以从中读取字节的 ZipFile<'a>

我 运行 遇到的问题是 ZipFile<'a> 结构引用了构造它的 &'a mut ZipArchive 的生命周期——这意味着 ZipArchive 必须保留在范围 ZipFile.

的生命周期内保持可变借用

这种约束组合似乎无法将 zip 封装在新结构中:

pub struct ZipReader<R: Read + Seek> {
    file: zip::read::ZipFile<'_>, // Have experimented with lifetimes here with no success
    archive: ZipArchive<R>,
}
impl <R: Read + Seek> ZipReader<R> {
    fn from(mut zip: R, name: &str) -> ZipReader<R> {
        let archive = ZipArchive::new(zip);
        let file = archive.by_name(name).unwrap();
        ZipReader {
            file: file,
            archive: archive.unwrap(),
        }
    }
}
impl <R: Read + Seek> Read for ZipReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.file.read(buf)
    }
}

我不能将 file 单独移动到返回的 ZipReader 中,因为 archive 会超出范围,但我不能将 archive 移动到 ZipReader 因为被file.

借用

似乎修改 zip crate 并将 ZipFile 状态合并到 ZipArchive 中以消除生命周期问题是解决问题的一种方法。不修改别人的代码怎么能解决这个问题?

正如 Coder-256 提到的,owning_ref::OwningHandle 提供解决借用问题的功能,但不提供生命周期问题。有一个 open issue on the repo for owning_ref 描述了一个相同的情况并请求额外的功能来解决它​​,但它自 2017 年以来一直开放,没有解决方案。

我最终 modifying the zip crate 转移了基础流的所有权,而不是持有对 ZipArchive 的引用。这对我的目的来说已经足够令人满意了,但是像 owning_ref 这样的解决方案似乎是解决此类问题的正确方法。