Refactoring a lending iterator to implement Iterator

I would like to refactor a lending iterator to be able to implement the iterator trait.

use std::io::{Read, Seek};
use std::path::PathBuf;
use std::vec::IntoIter;

use zip::ZipArchive;
use zip::read::ZipFile;
use zip::result::ZipResult;

/// A _lending iterator_ over the entries in a ZIP archive.
pub struct EntriesMut<'a, T> {
    zip_archive: &'a mut ZipArchive<T>,
    file_names: IntoIter<PathBuf>,
}

impl<'a, T> EntriesMut<'a, T> {
    pub fn new(zip_archive: &'a mut ZipArchive<T>, file_names: Vec<PathBuf>) -> Self {
        Self {
            zip_archive,
            file_names: file_names.into_iter(),
        }
    }
}

impl<T> EntriesMut<'_, T>
where
    T: Read + Seek,
{
    /// Return the next entry in the ZIP archive.
    ///
    /// Since [`ZipFile`] needs a lifetime related to the borrow of `self`, this constitutes a
    /// _lending iterator_ and thus cannot be implemented as an [`Iterator`].
    pub fn next(&mut self) -> Option<(PathBuf, ZipResult<ZipFile<'_, T>>)> {
        let path = self.file_names.next()?;
        let file_name = path.as_os_str().to_str()?;
        let zip_result = self.zip_archive.by_name(file_name);
        Some((path, zip_result))
    }
}

I attempted some tricks to try and hide the lifetime of ZipFile, but always failed with some lifetime conflict.
Is it possible to implement such an Iterator yielding ZipFiles at all in current stable Rust?

Looks like zip only allows access to one ZipFile<'_, R> at a time. So at least naively, no, it is not possible to implement Iterator, as that would require access to all ZipFile<'_, R>s simultaneously.

However, if the R is Clone, you could clone the ZipArchive<R>. Whether or not that approach is viable is going to depend on how expensive such a clone is, how the readers potentially interact with each other, and what operations you're performing (e.g. read-only or not). It would also be unergonomic as you'd have to create all the ZipArchive<R> clones and then create an iterator that exclusively borrows them all. So even if it's logically viable, I doubt it's worth it.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.