alpm 5.0.2

Rust bindings for libalpm
Documentation
use crate::Pkg;
use alpm_sys::*;

use std::ptr::NonNull;

use libarchive::archive::Handle;
use libarchive::reader::ReaderEntry;
use libarchive3_sys::ffi::*;

use std::{fmt, ptr};

pub struct MTree<'h> {
    pkg: &'h Pkg,
    archive: NonNull<archive>,
}

impl<'h> fmt::Debug for MTree<'h> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MTree").field("pkg", &self.pkg).finish()
    }
}

impl<'h> Handle for MTree<'h> {
    unsafe fn handle(&self) -> *mut Struct_archive {
        self.archive.as_ptr() as *mut Struct_archive
    }
}

impl<'h> Drop for MTree<'h> {
    fn drop(&mut self) {
        unsafe { alpm_pkg_mtree_close(self.pkg.as_ptr(), self.as_ptr()) };
    }
}

impl<'h> Iterator for MTree<'h> {
    type Item = ReaderEntry;

    fn next(&mut self) -> Option<Self::Item> {
        let mut entry = ptr::null_mut();
        let ret = unsafe { alpm_pkg_mtree_next(self.pkg.as_ptr(), self.as_ptr(), &mut entry) };

        if ret == ARCHIVE_OK {
            Some(ReaderEntry::new(entry as *mut Struct_archive_entry))
        } else {
            None
        }
    }
}

impl<'h> MTree<'h> {
    pub(crate) unsafe fn new<'a>(pkg: &'a Pkg, archive: *mut archive) -> MTree<'a> {
        MTree {
            pkg,
            archive: unsafe { NonNull::new_unchecked(archive) },
        }
    }

    pub(crate) fn as_ptr(&self) -> *mut archive {
        self.archive.as_ptr()
    }
}

#[cfg(test)]
mod tests {
    use crate::Alpm;
    use libarchive::archive::Entry;

    #[test]
    fn test_mtree() {
        let handle = Alpm::new("/", "tests/db").unwrap();
        let db = handle.localdb();
        let pkg = db.pkg("vifm").unwrap();
        let mut mtree = pkg.mtree().unwrap();

        println!("entries:");
        let file = mtree.next().unwrap();
        assert!(file.pathname() == "./.BUILDINFO");
        assert!(file.size() == 4900);
        assert!(mtree.count() > 10);
    }
}