1use std::fmt::Debug;
2
3#[macro_export]
14macro_rules! pos {
15 ($x: expr, $y: expr) => {
16 Position::new($x, $y)
17 };
18}
19
20#[derive(Eq, PartialEq, Copy, Clone)]
22pub struct Position {
23 x: u16,
24 y: u16,
25}
26
27impl Position {
28 pub fn new(x: u16, y: u16) -> Position {
39 Position { x, y }
40 }
41
42 pub fn x(&self) -> u16 {
44 self.x
45 }
46
47 pub fn y(&self) -> u16 {
49 self.y
50 }
51
52 pub fn translate(&self, diff_x: u16, diff_y: u16) -> Self {
54 Self {
55 x: self.x + diff_x,
56 y: self.y + diff_y,
57 }
58 }
59}
60
61impl PartialOrd for Position {
62 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
63 Some(self.cmp(other))
64 }
65}
66
67impl Ord for Position {
68 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
69 match self.y().cmp(&other.y()) {
70 std::cmp::Ordering::Equal => self.x().cmp(&other.x()),
71 ordering => ordering,
72 }
73 }
74}
75
76impl Debug for Position {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 write!(f, "Position({}, {})", self.x(), self.y())
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use std::cmp::Ordering;
85
86 use crate::{pos, Position};
87
88 #[test]
89 fn position_initialization() {
90 let cases = [(0, 0), (0, 3), (8, 2), (4, 6)];
91
92 for (x, y) in cases {
93 let position = pos!(x, y);
94
95 assert_eq!(x, position.x());
96 assert_eq!(y, position.y());
97 }
98 }
99
100 #[test]
101 fn position_comparison() {
102 let assert_case = |first: (u16, u16), second: (u16, u16), expected: Ordering| {
103 let first_position = pos!(first.0, first.1);
104 let second_position = pos!(second.0, second.1);
105
106 assert_eq!(
107 expected,
108 first_position.cmp(&second_position),
109 "comparing {:?} and {:?}",
110 first_position,
111 second_position
112 );
113
114 assert_eq!(
115 Some(expected),
116 first_position.partial_cmp(&second_position),
117 "comparing {:?} and {:?}",
118 first_position,
119 second_position,
120 );
121 };
122
123 let positions = [(0, 0), (0, 1), (1, 0), (1, 1)];
124
125 let cases = [
126 (positions[0], positions[0], Ordering::Equal),
127 (positions[0], positions[1], Ordering::Less),
128 (positions[0], positions[2], Ordering::Less),
129 (positions[0], positions[3], Ordering::Less),
130 (positions[1], positions[0], Ordering::Greater),
131 (positions[1], positions[1], Ordering::Equal),
132 (positions[1], positions[2], Ordering::Greater),
133 (positions[1], positions[3], Ordering::Less),
134 (positions[2], positions[0], Ordering::Greater),
135 (positions[2], positions[1], Ordering::Less),
136 (positions[2], positions[2], Ordering::Equal),
137 (positions[2], positions[3], Ordering::Less),
138 (positions[3], positions[0], Ordering::Greater),
139 (positions[3], positions[1], Ordering::Greater),
140 (positions[3], positions[2], Ordering::Greater),
141 (positions[3], positions[3], Ordering::Equal),
142 ];
143
144 for case in cases {
145 assert_case(case.0, case.1, case.2);
146 }
147 }
148}