1use std::{marker::PhantomData, ops};
2
3use crate::rect::Rect;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub struct Pair<T> {
7 pub x: u16,
8 pub y: u16,
9 _kind: PhantomData<T>,
10}
11
12impl<T> Pair<T> {
13 pub fn new(x: u16, y: u16) -> Self {
14 Self {
15 x,
16 y,
17 _kind: PhantomData,
18 }
19 }
20
21 pub fn fill(x: u16) -> Self {
22 Self::new(x, x)
23 }
24
25 pub fn with_x(&self, x: u16) -> Self {
26 self.map_x(|_| x)
27 }
28
29 pub fn with_y(&self, y: u16) -> Self {
30 self.map_y(|_| y)
31 }
32
33 pub fn map(&self, f: impl Fn(u16) -> u16) -> Self {
34 self.map_x(&f).map_y(&f)
35 }
36
37 pub fn map_x(&self, f: impl Fn(u16) -> u16) -> Self {
38 Self::new(f(self.x), self.y)
39 }
40
41 pub fn map_y(&self, f: impl Fn(u16) -> u16) -> Self {
42 Self::new(self.x, f(self.y))
43 }
44
45 pub fn combine(&self, pair: Self, f: impl Fn(u16, u16) -> u16) -> Self {
46 Self::new(f(self.x, pair.x), f(self.y, pair.y))
47 }
48}
49
50impl<T> From<(u16, u16)> for Pair<T> {
51 fn from(value: (u16, u16)) -> Self {
52 Self::new(value.0, value.1)
53 }
54}
55
56impl<T> ops::Add for Pair<T> {
57 type Output = Self;
58
59 fn add(self, pair: Pair<T>) -> Self {
60 self.combine(pair, |a, b| a + b)
61 }
62}
63
64impl<T> ops::Sub for Pair<T> {
65 type Output = Self;
66
67 fn sub(self, pair: Pair<T>) -> Self {
68 self.combine(pair, |a, b| a - b)
69 }
70}
71
72impl From<Pair<Size>> for Pair<Pos> {
73 fn from(value: Pair<Size>) -> Self {
74 Pair::new(value.x, value.y)
75 }
76}
77
78impl Pair<Size> {
79 pub fn as_rect(&self) -> Rect {
80 Rect::from_size(*self)
81 }
82}
83
84#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
85pub struct Pos;
86
87#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
88pub struct Size;