csvbinmatrix 0.8.0

Binary matrix Compressed Sparse Vector
Documentation
#![doc = include_str!("../../docs/matrix/items.md")]

/// Coordinates of a cell in the matrix.
///
/// # Example
///
/// ## Instantiate coordinates
///
/// ```rust
/// use csvbinmatrix::prelude::Coordinates;
///
/// let mut coordinates = Coordinates::new(1, 2);
/// println!("row: {}", coordinates.row());
/// println!("column: {}", coordinates.column());
///
/// assert_eq!(coordinates, Coordinates::from((1, 2)));
///
/// *coordinates.mut_row() = 3;
/// let (row, column) = coordinates.into();
/// assert_eq!((row, column), (3, 2));
/// ```
///
/// ## Comparison
///
/// ```rust
/// # use csvbinmatrix::prelude::Coordinates;
/// #
/// assert!(Coordinates::new(1, 2) == Coordinates::new(1, 2));
/// assert!(Coordinates::new(1, 2) < Coordinates::new(2, 1));
/// assert!(Coordinates::new(1, 2) > Coordinates::new(0, 3));
/// ```
///
#[derive(PartialEq, Clone, Debug)]
pub struct Coordinates {
    row: usize,
    column: usize,
}

impl Coordinates {
    /// Create new coordinates.
    #[must_use]
    pub fn new(row: usize, column: usize) -> Self {
        Self { row, column }
    }

    /// Give the row coordinate.
    #[must_use]
    pub fn row(&self) -> usize {
        self.row
    }

    /// Give the column coordinate.
    #[must_use]
    pub fn column(&self) -> usize {
        self.column
    }

    /// Give a mutable reference to the row coordinate.
    pub fn mut_row(&mut self) -> &mut usize {
        &mut self.row
    }

    /// Give a mutable reference to the column coordinate.
    pub fn mut_column(&mut self) -> &mut usize {
        &mut self.column
    }

    /// Returns true if the coordinates represent the origin.
    #[must_use]
    pub fn is_origin(&self) -> bool {
        self.row == 0 && self.column == 0
    }
}

impl std::fmt::Display for Coordinates {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "({}, {})", self.row, self.column)
    }
}

impl From<Coordinates> for (usize, usize) {
    fn from(coordinates: Coordinates) -> Self {
        (coordinates.row, coordinates.column)
    }
}

impl From<(usize, usize)> for Coordinates {
    fn from(coordinates: (usize, usize)) -> Self {
        Self::new(coordinates.0, coordinates.1)
    }
}

impl PartialOrd for Coordinates {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        match self.row.cmp(&other.row) {
            std::cmp::Ordering::Greater => Some(std::cmp::Ordering::Greater),
            std::cmp::Ordering::Less => Some(std::cmp::Ordering::Less),
            std::cmp::Ordering::Equal => match self.column.cmp(&other.column) {
                std::cmp::Ordering::Greater => Some(std::cmp::Ordering::Greater),
                std::cmp::Ordering::Less => Some(std::cmp::Ordering::Less),
                std::cmp::Ordering::Equal => Some(std::cmp::Ordering::Equal),
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use rstest::{fixture, rstest};

    #[fixture]
    fn coordinates() -> Coordinates {
        Coordinates { row: 1, column: 2 }
    }

    #[rstest]
    fn clone(coordinates: Coordinates) {
        assert_eq!(coordinates.clone(), coordinates);
    }

    #[rstest]
    fn debug(coordinates: Coordinates) {
        assert_eq!(
            format!("{coordinates:?}"),
            "Coordinates { row: 1, column: 2 }"
        );
    }

    #[rstest]
    fn display(coordinates: Coordinates) {
        assert_eq!(format!("{coordinates}"), "(1, 2)");
    }

    #[rstest]
    fn new(coordinates: Coordinates) {
        assert_eq!(Coordinates::new(1, 2), coordinates);
    }

    #[rstest]
    fn row(coordinates: Coordinates) {
        assert_eq!(coordinates.row(), 1);
    }

    #[rstest]
    fn column(coordinates: Coordinates) {
        assert_eq!(coordinates.column(), 2);
    }

    #[rstest]
    fn mut_row(mut coordinates: Coordinates) {
        *coordinates.mut_row() = 3;
        assert_eq!(Coordinates::new(3, 2), coordinates);
    }

    #[rstest]
    fn mut_column(mut coordinates: Coordinates) {
        *coordinates.mut_column() = 4;
        assert_eq!(Coordinates::new(1, 4), coordinates);
    }

    #[rstest]
    fn is_origin(coordinates: Coordinates) {
        assert!(!coordinates.is_origin());
        assert!(Coordinates::new(0, 0).is_origin());
    }

    #[rstest]
    fn from_coordinates_to_couple_usize(coordinates: Coordinates) {
        assert_eq!(<(usize, usize)>::from(coordinates), (1, 2));
    }

    #[rstest]
    fn from_couple_usize_to_coordinates(coordinates: Coordinates) {
        assert_eq!(Coordinates::from((1, 2)), coordinates);
    }

    #[rstest]
    fn partial_cmp(coordinates: Coordinates) {
        assert!(coordinates == Coordinates::new(1, 2));
        assert!(coordinates < Coordinates::new(2, 2));
        assert!(coordinates > Coordinates::new(0, 2));
        assert!(coordinates < Coordinates::new(1, 3));
        assert!(coordinates > Coordinates::new(1, 1));
        assert_eq!(
            coordinates.partial_cmp(&coordinates),
            Some(std::cmp::Ordering::Equal)
        );
    }
}