问题描述
可以用几种不同的方式来问这个问题,但我的最终目标是将一个文件从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
这样的解决方案似乎是解决此类问题的正确方法。