This question could be asked in a few different ways but my end-goal is to encapsulate one file from a ZipArchive (Rust zip crate) into a struct called ZipReader that implements Read, like so:
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> { ... }
My effort to do so has involved constructing a new ZipArchive from the src stream, then using ZipArchive.by_name(name) to extract the ZipFile<'a> from which bytes may be read.
The issue I run into is that the ZipFile<'a> struct references the lifetime of the &'a mut ZipArchive from which it was constructed -- meaning the ZipArchive must remain in scope and remain mutably borrowed for the lifetime of the ZipFile.
This combination of constraints seems to make it impossible to encapsulate the zip in a new struct:
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)
}
}
I cannot move file alone into the returned ZipReader because archive will go out of scope, but I cannot move archive to ZipReader because it is borrowed by file.
It seems like modifying the zip crate and incorporating the ZipFile state into ZipArchive to eliminate the lifetime issue would be one way to solve the problem. How could this be solved without modifying anyone else's code?