rieter/libarchive/src/read/entries.rs

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())
}
}
}