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>> {

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.


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

Lending and giving pattern are unable to be unified.


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.