use std::mem::MaybeUninit;
use crate::core::errors::GenIteratorError;
use crate::core::iter::Direction;
#[derive(Debug)]
#[repr(transparent)]
pub struct GenIterator {
pub(crate) inner: *mut libmount::libmnt_iter,
}
impl GenIterator {
pub fn new(direction: Direction) -> Result<GenIterator, GenIteratorError> {
log::debug!("GenIterator::new creating a new `GenIterator` instance");
let mut inner = MaybeUninit::<*mut libmount::libmnt_iter>::zeroed();
unsafe {
inner.write(libmount::mnt_new_iter(direction as i32));
}
match unsafe { inner.assume_init() } {
inner if inner.is_null() => {
let err_msg = "failed to create a new `GenIterator` instance".to_owned();
log::debug!(
"GenIterator::new {}. libmount::mnt_new_iter returned a NULL pointer",
err_msg
);
Err(GenIteratorError::Creation(err_msg))
}
inner => {
log::debug!("GenIterator::new created a new `GenIterator` instance");
let iterator = Self { inner };
Ok(iterator)
}
}
}
pub fn direction(&self) -> Direction {
let code = unsafe { libmount::mnt_iter_get_direction(self.inner) };
let direction = Direction::try_from(code).unwrap();
log::debug!(
"GenIterator::direction direction of iteration: {:?}",
direction
);
direction
}
pub fn reset(&mut self) {
log::debug!("GenIterator::reset resetting iterator with direction unchanged");
const UNCHANGED_DIRECTION: libc::c_int = -1;
unsafe { libmount::mnt_reset_iter(self.inner, UNCHANGED_DIRECTION) }
}
pub fn reset_forward(&mut self) {
log::debug!(
"GenIterator::reset_forward resetting iterator, setting direction: {:?}",
Direction::Forward
);
let direction = Direction::Forward;
unsafe { libmount::mnt_reset_iter(self.inner, direction as i32) }
}
pub fn reset_backward(&mut self) {
log::debug!(
"GenIterator::reset_backward resetting iterator, setting direction: {:?}",
Direction::Backward
);
let direction = Direction::Backward;
unsafe { libmount::mnt_reset_iter(self.inner, direction as i32) }
}
}
impl AsRef<GenIterator> for GenIterator {
#[inline]
fn as_ref(&self) -> &GenIterator {
self
}
}
impl Drop for GenIterator {
fn drop(&mut self) {
log::debug!("GenIterator::drop deallocating `GenIterator` instance");
unsafe { libmount::mnt_free_iter(self.inner) }
}
}
#[cfg(test)]
#[allow(unused_imports)]
mod tests {
use super::*;
use crate::core::iter::Direction;
use pretty_assertions::{assert_eq, assert_ne};
#[test]
fn gen_iterator_can_create_a_forward_iterator() -> crate::Result<()> {
let iterator = GenIterator::new(Direction::Forward)?;
let actual = iterator.direction();
let expected = Direction::Forward;
assert_eq!(actual, expected);
Ok(())
}
#[test]
fn gen_iterator_can_reset_backward_a_forward_iterator() -> crate::Result<()> {
let mut iterator = GenIterator::new(Direction::Forward)?;
let actual = iterator.direction();
let expected = Direction::Forward;
assert_eq!(actual, expected);
iterator.reset_backward();
let actual = iterator.direction();
let expected = Direction::Backward;
assert_eq!(actual, expected);
Ok(())
}
#[test]
fn gen_iterator_can_reset_forward_a_backward_iterator() -> crate::Result<()> {
let mut iterator = GenIterator::new(Direction::Backward)?;
let actual = iterator.direction();
let expected = Direction::Backward;
assert_eq!(actual, expected);
iterator.reset_forward();
let actual = iterator.direction();
let expected = Direction::Forward;
assert_eq!(actual, expected);
Ok(())
}
}