What approach should I take to provide an iterator over files in an archive?

Hello, as a challenge for myself, I am trying to write a tar unarchiver in rust. I want to make an api where you can call .iter(), and receive an iterator over all entries. Currently, I have something like this (simplified):

struct ArchiveEntry<R: Read> {
    name: ArchiveEntryName,
    content: R,
}

trait ArchiveFormat {
    fn iter<R: Read>(&self, r: &mut R) -> impl Iterator<Item = ArchiveEntry<impl Read>>;
    fn iter_seek<R: Read + Seek>(&self, r: &mut R) -> impl Iterator<Item = ArchiveEntry<impl Read>> {
        self.iter(r)
    }
}         

struct Tar {}

impl ArchiveFormat for Tar {
    fn iter<R: Read>(&self, r: &mut R) -> impl Iterator<Item = ArchiveEntry<impl Read>> {
        TarIterator {r}
    }
}

struct TarIterator<'a, R: Read> {
    r: &'a mut R,
}
impl<'a, R: Read> Iterator for TarIterator<'a, R> {
    type Item = ArchiveEntry<impl Read + 'a>;

    fn next(&mut self) -> Option<Self::Item> {
        // Parse the archive (with a lot of read_exacts)
        // ...
        Some(ArchiveEntry {
            name: ...,
            content: self.r.by_ref().take(archive_entry_size),
        })
    }
}

However, with this, I can't seem to make the borrow checker happy, and I feel like I may be trying to do something fundamentally incorrect at a high level - so my questions are:

  1. Is this the correct approach at all for something like this? If yes, what should I do?
  2. If this is not the correct approach, what would be the "rusty" way to do this? And why is this an incorrect approach?

I would like the API to be efficient, so reading the entire file content in the archive entry would not be suitable. I also want it to operate on non-Clone Read types.

No.

Use a lending trait to do that. Define your own or use crates.

Lending and giving pattern are unable to be unified.
https://smallcultfollowing.com/babysteps/blog/2023/05/09/giving-lending-and-async-closures/

3 Likes

Thank you! The article and your answer were very insightful.

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.