sokoban-elements 0.2.1

Parsing and writing Sokoban, Hexoban, Trioban and Octoban file formats.
Documentation
use std::fmt;
use std::fmt::Display;
use std::num::TryFromIntError;

/// 2D size of game boards.
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Size2D {
    pub width:  usize,
    pub height: usize,
}

impl Size2D {
    pub fn new(width: usize, height: usize) -> Self { Self { width, height } }

    /// Returns the total number of cells in the board.
    pub fn size(&self) -> usize {
        // Having this method return `usize` instead of Option<usize> is deliberate
        // choice of convenience. This is meant to measure sizes of Sokoban boards and,
        // in real world, these boards are much smaller than `usize::MAX`.
        self.width.saturating_mul(self.height)
    }
}

impl Display for Size2D {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}x{}", self.width, self.height)
    }
}

impl From<(u8, u8)> for Size2D {
    fn from(value: (u8, u8)) -> Self {
        Self {
            width:  value.0.into(),
            height: value.1.into(),
        }
    }
}

impl From<(u16, u16)> for Size2D {
    fn from(value: (u16, u16)) -> Self {
        Self {
            width:  value.0.into(),
            height: value.1.into(),
        }
    }
}

impl TryFrom<(u32, u32)> for Size2D {
    type Error = TryFromIntError;

    /// `value` is `(width, height)`
    fn try_from(value: (u32, u32)) -> Result<Self, Self::Error> {
        Ok(Size2D {
            width:  value.0.try_into()?,
            height: value.1.try_into()?,
        })
    }
}

impl TryFrom<(u64, u64)> for Size2D {
    type Error = TryFromIntError;

    /// `value` is `(width, height)`
    fn try_from(value: (u64, u64)) -> Result<Self, Self::Error> {
        Ok(Size2D {
            width:  value.0.try_into()?,
            height: value.1.try_into()?,
        })
    }
}

impl From<(usize, usize)> for Size2D {
    fn from(value: (usize, usize)) -> Self {
        Self {
            width:  value.0,
            height: value.1,
        }
    }
}