use std::mem::MaybeUninit;
use crate::core::errors::FsTabDiffError;
use crate::core::errors::FsTabDiffIterError;
use crate::core::iter::FsTabDiffIter;
use crate::tables::FsTab;
use crate::tables::GcItem;
#[derive(Debug)]
pub struct FsTabDiff<'source, 'other> {
pub(crate) inner: *mut libmount::libmnt_tabdiff,
pub(crate) source: &'source FsTab,
pub(crate) other: &'other FsTab,
pub(crate) gc: Vec<GcItem>,
}
impl<'source, 'other> FsTabDiff<'source, 'other> {
pub fn new(
source: &'source FsTab,
other: &'other FsTab,
) -> Result<FsTabDiff<'source, 'other>, FsTabDiffError> {
log::debug!("TableDiff::new creating a new `TableDiff` instance");
let mut inner = MaybeUninit::<*mut libmount::libmnt_tabdiff>::zeroed();
unsafe { inner.write(libmount::mnt_new_tabdiff()) };
match unsafe { inner.assume_init() } {
inner if inner.is_null() => {
let err_msg = "failed to create a new `FsTabDiff` instance".to_owned();
log::debug!(
"FsTabDiff::new {err_msg}. libmount::mnt_new_tabdiff returned a NULL pointer"
);
Err(FsTabDiffError::Creation(err_msg))
}
inner => {
log::debug!("FsTabDiff::new created a new `FsTabDiff` instance");
let table_diff = Self {
inner,
source,
other,
gc: vec![],
};
Ok(table_diff)
}
}
}
pub fn diff(&self) -> Result<usize, FsTabDiffError> {
log::debug!("FsTabDiff::diff comparing tables, entry by entry");
let result =
unsafe { libmount::mnt_diff_tables(self.inner, self.source.inner, self.other.inner) };
match result {
code if code < 0 => {
let err_msg = "failed to compare tables, entry by entry".to_owned();
log::debug!(
"FsTabDiff::diff {err_msg}. libmount::mnt_diff_tables returned error code: {code:?}"
);
Err(FsTabDiffError::Diff(err_msg))
}
nb_changes => {
log::debug!(
"FsTabDiff::diff compared tables. Found {:?} changes",
nb_changes
);
Ok(nb_changes as usize)
}
}
}
pub fn iter(&self) -> FsTabDiffIter<'_, '_, '_> {
log::debug!("FsTabDiff::iter creating a new `FsTabDiffIter` instance");
FsTabDiffIter::new(self).unwrap()
}
pub fn try_iter(&self) -> Result<FsTabDiffIter<'_, '_, '_>, FsTabDiffIterError> {
log::debug!("FsTabDiff::try_iter creating a new `FsTabDiffIter` instance");
FsTabDiffIter::new(self)
}
}
impl<'source, 'other> AsRef<FsTabDiff<'source, 'other>> for FsTabDiff<'source, 'other> {
#[inline]
fn as_ref(&self) -> &FsTabDiff<'source, 'other> {
self
}
}
impl<'source, 'other> Drop for FsTabDiff<'source, 'other> {
fn drop(&mut self) {
log::debug!("FsTabDiff::drop deallocating `FsTabDiff` instance");
unsafe { libmount::mnt_free_tabdiff(self.inner) };
while let Some(gc_item) = self.gc.pop() {
gc_item.destroy();
}
}
}