首页 > 解决方案 > 如何将 Rust ZipArchive 和 ZipFile 放入单个 Read-implementing 结构中,同时处理生命周期和借用规则

问题描述

这个问题可以用几种不同的方式提出,但我的最终目标是将一个文件从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> { ... }

我这样做的努力涉及ZipArchive从 src 流构造一个新的,然后使用它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到其中以消除生命周期问题将是解决问题的一种方法。在不修改其他人的代码的情况下如何解决这个问题?

标签: rustlifetimeborrowing

解决方案


正如 Coder-256 所提到的,owning_ref::OwningHandle它提供了解决借用问题的功能,但不是生命周期问题。回购中有一个未解决owning_ref的问题,它描述了一种等效情况并要求提供额外的功能来解决它​​,但它自 2017 年以来一直处于开放状态,但没有解决方案。

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


推荐阅读