milk_tea/
pair.rs

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;