use super::super::types::TrackCounts;
use crate::geometry::Line;
use core::cmp::{max, Ordering};
use core::ops::{Add, AddAssign, Sub};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(transparent)]
pub struct GridLine(i16);
impl From<i16> for GridLine {
fn from(value: i16) -> Self {
Self(value)
}
}
impl GridLine {
pub fn as_i16(self) -> i16 {
self.0
}
pub(crate) fn into_origin_zero_line(self, explicit_track_count: u16) -> OriginZeroLine {
let explicit_line_count = explicit_track_count + 1;
let oz_line = match self.0.cmp(&0) {
Ordering::Greater => self.0 - 1,
Ordering::Less => self.0 + explicit_line_count as i16,
Ordering::Equal => panic!("Grid line of zero is invalid"),
};
OriginZeroLine(oz_line)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct OriginZeroLine(pub i16);
impl Add<OriginZeroLine> for OriginZeroLine {
type Output = Self;
fn add(self, rhs: OriginZeroLine) -> Self::Output {
OriginZeroLine(self.0 + rhs.0)
}
}
impl Sub<OriginZeroLine> for OriginZeroLine {
type Output = Self;
fn sub(self, rhs: OriginZeroLine) -> Self::Output {
OriginZeroLine(self.0 - rhs.0)
}
}
impl Add<u16> for OriginZeroLine {
type Output = Self;
fn add(self, rhs: u16) -> Self::Output {
OriginZeroLine(self.0 + rhs as i16)
}
}
impl AddAssign<u16> for OriginZeroLine {
fn add_assign(&mut self, rhs: u16) {
self.0 += rhs as i16;
}
}
impl Sub<u16> for OriginZeroLine {
type Output = Self;
fn sub(self, rhs: u16) -> Self::Output {
OriginZeroLine(self.0 - rhs as i16)
}
}
impl OriginZeroLine {
pub(crate) fn into_track_vec_index(self, track_counts: TrackCounts) -> usize {
assert!(
self.0 >= -(track_counts.negative_implicit as i16),
"OriginZero grid line cannot be less than the number of negative grid lines"
);
assert!(
self.0 <= (track_counts.explicit + track_counts.positive_implicit) as i16,
"OriginZero grid line cannot be more than the number of positive grid lines"
);
2 * ((self.0 + track_counts.negative_implicit as i16) as usize)
}
pub(crate) fn implied_negative_implicit_tracks(self) -> u16 {
if self.0 < 0 {
self.0.unsigned_abs()
} else {
0
}
}
pub(crate) fn implied_positive_implicit_tracks(self, explicit_track_count: u16) -> u16 {
if self.0 > explicit_track_count as i16 {
self.0 as u16 - explicit_track_count
} else {
0
}
}
}
impl Line<OriginZeroLine> {
pub(crate) fn span(self) -> u16 {
max(self.end.0 - self.start.0, 0) as u16
}
}
pub trait GridCoordinate: Copy {}
impl GridCoordinate for GridLine {}
impl GridCoordinate for OriginZeroLine {}