use crate::utils::*;
use alpm_sys::*;
use std::cell::UnsafeCell;
use std::ffi::CString;
use std::fmt;
use std::marker::PhantomData;
use std::slice;
#[repr(transparent)]
pub struct File {
inner: alpm_file_t,
}
unsafe impl Send for File {}
unsafe impl Sync for File {}
impl fmt::Debug for File {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("File")
.field("name", &self.name())
.field("size", &self.size())
.field("mode", &self.mode())
.finish()
}
}
impl File {
pub fn name(&self) -> &str {
unsafe { from_cstr(self.inner.name) }
}
pub fn size(&self) -> i64 {
#[allow(clippy::useless_conversion)]
self.inner.size.into()
}
pub fn mode(&self) -> u32 {
#[allow(clippy::useless_conversion)]
self.inner.mode.into()
}
}
pub struct FileList<'h> {
inner: UnsafeCell<alpm_filelist_t>,
_marker: PhantomData<&'h ()>,
}
#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl<'h> Send for FileList<'h> {}
unsafe impl<'h> Sync for FileList<'h> {}
impl<'h> fmt::Debug for FileList<'h> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("File")
.field("files", &self.files())
.finish()
}
}
impl<'h> FileList<'h> {
pub(crate) unsafe fn new<'a>(files: alpm_filelist_t) -> FileList<'a> {
FileList {
inner: UnsafeCell::new(files),
_marker: PhantomData,
}
}
pub(crate) fn as_ptr(&self) -> *mut alpm_filelist_t {
self.inner.get()
}
pub fn files(&self) -> &[File] {
let files = unsafe { *self.as_ptr() };
if files.files.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(files.files as *const File, files.count) }
}
}
pub fn contains<S: Into<Vec<u8>>>(&self, path: S) -> Option<File> {
let path = CString::new(path).unwrap();
let file = unsafe { alpm_filelist_contains(self.as_ptr(), path.as_ptr()) };
if file.is_null() {
None
} else {
let file = unsafe { *file };
Some(File { inner: file })
}
}
}
#[cfg(test)]
mod tests {
use crate::{Alpm, SigLevel};
#[test]
fn test_files() {
let handle = Alpm::new("/", "tests/db").unwrap();
let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
let pkg = db.pkg("linux").unwrap();
let files = pkg.files();
assert!(files.files().is_empty());
let db = handle.localdb();
let pkg = db.pkg("linux").unwrap();
let files = pkg.files();
assert!(!files.files().is_empty());
let file = files.contains("boot/").unwrap();
assert_eq!(file.name(), "boot/");
assert!(files.contains("aaaaa/").is_none());
}
}