termrs_core 0.3.0

The core library of termrs
Documentation
use std::cmp::Ordering;

use super::Offset;

/// Represents a position on a surface.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Position {
    pub column: u16,
    pub row: u16,
}

impl PartialOrd for Position {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        let row_ord = self.row.partial_cmp(&other.row);

        if let Some(row_ord) = row_ord {
            match row_ord {
                Ordering::Equal => self.column.partial_cmp(&other.column),
                _ => Some(row_ord),
            }
        } else {
            None
        }
    }
}

impl Position {
    pub const ZERO: Position = Position { column: 0, row: 0 };

    pub fn new(column: u16, row: u16) -> Self {
        Self { column, row }
    }

    pub fn offset_position(self, position: Position) -> Option<Self> {
        self.offset_u16(position.column, position.row)
    }

    pub fn offset_position_negative(self, position: Position) -> Option<Self> {
        self.offset_u16_negative(position.column, position.row)
    }

    pub fn offset_u16(mut self, x: u16, y: u16) -> Option<Self> {
        self.column = self.column.checked_add(x)?;
        self.row = self.row.checked_add(y)?;

        Some(self)
    }

    pub fn offset_u16_negative(mut self, x: u16, y: u16) -> Option<Self> {
        self.column = self.column.checked_sub(x)?;
        self.row = self.row.checked_sub(y)?;

        Some(self)
    }

    pub fn offset_i16(mut self, x: i16, y: i16) -> Option<Self> {
        let x = x.try_into().ok()?;
        let y = y.try_into().ok()?;

        self.column = self.column.checked_add(x)?;
        self.row = self.row.checked_add(y)?;

        Some(self)
    }

    pub fn offset_i16_negative(mut self, x: i16, y: i16) -> Option<Self> {
        let x = x.try_into().ok()?;
        let y = y.try_into().ok()?;

        self.column = self.column.checked_sub(x)?;
        self.row = self.row.checked_sub(y)?;

        Some(self)
    }
}

impl From<(u16, u16)> for Position {
    fn from(value: (u16, u16)) -> Self {
        Self {
            column: value.0,
            row: value.1,
        }
    }
}

impl From<Offset> for Position {
    fn from(value: Offset) -> Self {
        Self {
            column: value.x,
            row: value.y,
        }
    }
}