use std::mem::MaybeUninit;
use crate::core::errors::SwapsDiffError;
use crate::core::errors::SwapsDiffIterError;
use crate::core::iter::SwapsDiffIter;
use crate::tables::GcItem;
use crate::tables::Swaps;
#[derive(Debug)]
pub struct SwapsDiff<'source, 'other> {
pub(crate) inner: *mut libmount::libmnt_tabdiff,
pub(crate) source: &'source Swaps,
pub(crate) other: &'other Swaps,
pub(crate) gc: Vec<GcItem>,
}
impl<'source, 'other> SwapsDiff<'source, 'other> {
pub fn new(
source: &'source Swaps,
other: &'other Swaps,
) -> Result<SwapsDiff<'source, 'other>, SwapsDiffError> {
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 `SwapsDiff` instance".to_owned();
log::debug!(
"SwapsDiff::new {err_msg}. libmount::mnt_new_tabdiff returned a NULL pointer"
);
Err(SwapsDiffError::Creation(err_msg))
}
inner => {
log::debug!("SwapsDiff::new created a new `SwapsDiff` instance");
let table_diff = Self {
inner,
source,
other,
gc: vec![],
};
Ok(table_diff)
}
}
}
pub fn diff(&self) -> Result<usize, SwapsDiffError> {
log::debug!("SwapsDiff::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!(
"SwapsDiff::diff {}. libmount::mnt_diff_tables returned error code: {:?}",
err_msg,
code
);
Err(SwapsDiffError::Diff(err_msg))
}
nb_changes => {
log::debug!(
"SwapsDiff::diff compared tables. Found {:?} changes",
nb_changes
);
Ok(nb_changes as usize)
}
}
}
pub fn iter(&self) -> SwapsDiffIter<'_, '_, '_> {
log::debug!("SwapsDiff::iter creating a new `SwapsDiffIter` instance");
SwapsDiffIter::new(self).unwrap()
}
pub fn try_iter(&self) -> Result<SwapsDiffIter<'_, '_, '_>, SwapsDiffIterError> {
log::debug!("SwapsDiff::try_iter creating a new `SwapsDiffIter` instance");
SwapsDiffIter::new(self)
}
}
impl<'source, 'other> AsRef<SwapsDiff<'source, 'other>> for SwapsDiff<'source, 'other> {
#[inline]
fn as_ref(&self) -> &SwapsDiff<'source, 'other> {
self
}
}
impl<'source, 'other> Drop for SwapsDiff<'source, 'other> {
fn drop(&mut self) {
log::debug!("SwapsDiff::drop deallocating `SwapsDiff` instance");
unsafe { libmount::mnt_free_tabdiff(self.inner) };
while let Some(gc_item) = self.gc.pop() {
gc_item.destroy();
}
}
}