use crate::archive::Entry; use crate::archive::Handle; use crate::error::ArchiveError; use crate::read::Archive; use libarchive3_sys::ffi; use std::io; use std::io::Read; use std::marker; pub struct ReadEntry<'a, T: Archive> { archive: *mut ffi::Struct_archive, entry: *mut ffi::Struct_archive_entry, offset: usize, _ignored: marker::PhantomData<&'a T>, } impl<'a, T: Archive> Entry for ReadEntry<'a, T> { unsafe fn entry(&self) -> *const ffi::Struct_archive_entry { self.entry as *const _ } unsafe fn entry_mut(&mut self) -> *mut ffi::Struct_archive_entry { self.entry } } impl<'a, T: Archive> Handle for ReadEntry<'a, T> { unsafe fn handle(&self) -> *const ffi::Struct_archive { self.archive as *const _ } unsafe fn handle_mut(&mut self) -> *mut ffi::Struct_archive { self.archive } } pub struct Entries<'a, T: 'a + Archive> { archive: &'a mut T, } impl<'a, T: 'a + Archive> Entries<'a, T> { pub fn new(archive: &'a mut T) -> Self { Self { archive } } } impl<'a, T: Archive + 'a> Iterator for Entries<'a, T> { type Item = crate::Result>; fn next(&mut self) -> Option { let mut entry_ptr: *mut ffi::Struct_archive_entry = std::ptr::null_mut(); let res = unsafe { ffi::archive_read_next_header(self.archive.handle() as *mut _, &mut entry_ptr) }; match res { ffi::ARCHIVE_OK => { let entry = ReadEntry { archive: unsafe { self.archive.handle_mut() }, entry: entry_ptr, offset: 0, _ignored: marker::PhantomData, }; Some(Ok(entry)) } ffi::ARCHIVE_EOF => None, _ => Some(Err(ArchiveError::from(self.archive as &dyn Handle))), } } } impl<'a, T: Archive> Read for ReadEntry<'a, T> { fn read(&mut self, buf: &mut [u8]) -> io::Result { let res = unsafe { ffi::archive_read_data(self.archive, buf as *mut [u8] as *mut _, buf.len()) }; if res >= 0 { let count: usize = res .try_into() .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; self.offset += count; Ok(count) } else { Err(ArchiveError::from(self as &dyn Handle).into()) } } }