如何在处理生命周期和借用规则的同时将Rust ZipArchive和ZipFile放入单个Read-implementing结构中

问题描述

可以用几种不同的方式来问这个问题,但我的最终目标是将一个文件ZipArchive(Rust zip板条箱)封装到一个名为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借用。

似乎修改拉链箱并将ZipFile状态合并到ZipArchive中以消除生命周期问题将是解决问题的一种方法。在不修改任何人代码的情况下如何解决

解决方法

如Coder-256所述,owning_ref::OwningHandle提供了解决借入问题的功能,但没有解决生存期问题的功能。 open issue的存储库中有一个owning_ref,它描述了一种等效情况,并要求使用其他功能来解决该问题,但该解决方案自2017年以来一直开放,没有解决方案。

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