anyreader 0.5.0

Efficiently and recursively read archives and compressed streams of data
Documentation
use crate::container::{Container, Items};
use crate::{FileItem, FileKind, SizeHint};
use std::fmt::Debug;
use std::io;
use std::io::Read;

pub struct ZipContainer<T: Read> {
    reader: T,
}

impl<T: Read> Debug for ZipContainer<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Zip").finish()
    }
}

impl<T: Read> ZipContainer<T> {
    pub fn new(reader: T) -> Self {
        Self { reader }
    }
}

impl<T: Read> Container for ZipContainer<T> {
    fn items(&mut self) -> io::Result<impl Items> {
        Ok(ZipFileIter {
            reader: &mut self.reader,
        })
    }
}

pub struct ZipFileIter<'a, T: Read> {
    reader: &'a mut T,
}

impl<T: Read> Items for ZipFileIter<'_, T> {
    fn next_item(&mut self) -> Option<io::Result<FileItem<impl Read>>> {
        if let Ok(Some(item)) = zip::read::read_zipfile_from_stream(&mut self.reader) {
            let path = item.enclosed_name().unwrap().to_path_buf();
            let kind = if item.is_file() {
                FileKind::File
            } else if item.is_dir() {
                FileKind::Directory
            } else {
                FileKind::Other
            };
            let size_hint = SizeHint::Exact(item.size());
            return Some(Ok(FileItem {
                path,
                reader: item,
                kind,
                size_hint,
            }));
        }
        None
    }
}