91 lines
2.4 KiB
Rust
91 lines
2.4 KiB
Rust
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<ReadEntry<'a, T>>;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
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<usize> {
|
|
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())
|
|
}
|
|
}
|
|
}
|