balanced_direction/
operations.rs

1use crate::Balance;
2use core::ops::{Add, Mul, Neg, Not, Sub};
3
4impl Balance {
5    /// Moves the current position upwards in the 3x3 grid while staying within bounds.
6    ///
7    /// # Returns
8    ///
9    /// The `Balance` variant representing the position directly above the current one.
10    /// If the current position is at the top edge, the result will stay at the edge.
11    ///
12    /// # Examples
13    ///
14    /// ```
15    /// use balanced_direction::Balance;
16    ///
17    /// let balance = Balance::Center;
18    /// assert_eq!(balance.up(), Balance::Top);
19    ///
20    /// let balance = Balance::Top;
21    /// assert_eq!(balance.up(), Balance::Top);
22    /// ```
23    pub fn up(self) -> Self {
24        let (x, y) = self.to_vector();
25        Self::from_vector(x, (y - 1).clamp(-1, 1))
26    }
27
28    /// Moves the current position downwards in the 3x3 grid while staying within bounds.
29    ///
30    /// # Returns
31    ///
32    /// The `Balance` variant representing the position directly below the current one.
33    /// If the current position is at the bottom edge, the result will stay at the edge.
34    ///
35    /// # Examples
36    ///
37    /// ```
38    /// use balanced_direction::Balance;
39    ///
40    /// let balance = Balance::Center;
41    /// assert_eq!(balance.down(), Balance::Bottom);
42    ///
43    /// let balance = Balance::Bottom;
44    /// assert_eq!(balance.down(), Balance::Bottom);
45    /// ```
46    pub fn down(self) -> Self {
47        let (x, y) = self.to_vector();
48        Self::from_vector(x, (y + 1).clamp(-1, 1))
49    }
50
51    /// Moves the current position to the left in the 3x3 grid while staying within bounds.
52    ///
53    /// # Returns
54    ///
55    /// The `Balance` variant representing the position directly to the left of the current one.
56    /// If the current position is at the left edge, the result will stay at the edge.
57    ///
58    /// # Examples
59    ///
60    /// ```
61    /// use balanced_direction::Balance;
62    ///
63    /// let balance = Balance::Center;
64    /// assert_eq!(balance.left(), Balance::Left);
65    ///
66    /// let balance = Balance::Left;
67    /// assert_eq!(balance.left(), Balance::Left);
68    /// ```
69    pub fn left(self) -> Self {
70        let (x, y) = self.to_vector();
71        Self::from_vector((x - 1).clamp(-1, 1), y)
72    }
73
74    /// Moves the current position to the right in the 3x3 grid while staying within bounds.
75    ///
76    /// # Returns
77    ///
78    /// The `Balance` variant representing the position directly to the right of the current one.
79    /// If the current position is at the right edge, the result will stay at the edge.
80    ///
81    /// # Examples
82    ///
83    /// ```
84    /// use balanced_direction::Balance;
85    ///
86    /// let balance = Balance::Center;
87    /// assert_eq!(balance.right(), Balance::Right);
88    ///
89    /// let balance = Balance::Right;
90    /// assert_eq!(balance.right(), Balance::Right);
91    /// ```
92    pub fn right(self) -> Self {
93        let (x, y) = self.to_vector();
94        Self::from_vector((x + 1).clamp(-1, 1), y)
95    }
96
97    /// Moves the position upwards in the 3x3 grid with wrapping behavior.
98    pub fn up_wrap(self) -> Self {
99        let (x, y) = self.to_vector();
100        Self::from_vector(x, if y == -1 { 1 } else { y - 1 })
101    }
102
103    /// Moves the position downwards in the 3x3 grid with wrapping behavior.
104    pub fn down_wrap(self) -> Self {
105        let (x, y) = self.to_vector();
106        Self::from_vector(x, if y == 1 { -1 } else { y + 1 })
107    }
108
109    /// Moves the position leftwards in the 3x3 grid with wrapping behavior.
110    pub fn left_wrap(self) -> Self {
111        let (x, y) = self.to_vector();
112        Self::from_vector(if x == -1 { 1 } else { x - 1 }, y)
113    }
114
115    /// Moves the position rightwards in the 3x3 grid with wrapping behavior.
116    pub fn right_wrap(self) -> Self {
117        let (x, y) = self.to_vector();
118        Self::from_vector(if x == 1 { -1 } else { x + 1 }, y)
119    }
120
121    /// Flips the current position horizontally in the 3x3 grid.
122    ///
123    /// # Returns
124    ///
125    /// The `Balance` variant that is mirrored horizontally across
126    /// the vertical axis. For example, flipping `Balance::Left` results
127    /// in `Balance::Right`, and vice-versa. Positions on the vertical axis
128    /// (like `Balance::Center` or `Balance::Top`) remain unchanged.
129    ///
130    /// # Examples
131    ///
132    /// ```
133    /// use balanced_direction::Balance;
134    ///
135    /// let balance = Balance::Left;
136    /// assert_eq!(balance.flip_h(), Balance::Right);
137    ///
138    /// let balance = Balance::Center;
139    /// assert_eq!(balance.flip_h(), Balance::Center);
140    /// ```
141    pub fn flip_h(self) -> Self {
142        let (x, y) = self.to_vector();
143        Self::from_vector(-x, y)
144    }
145
146    /// Flips the current position vertically in the 3x3 grid.
147    ///
148    /// # Returns
149    ///
150    /// The `Balance` variant that is mirrored vertically across
151    /// the horizontal axis. For example, flipping `Balance::Top`
152    /// results in `Balance::Bottom`, and vice-versa. Positions on the horizontal axis
153    /// (like `Balance::Center` or `Balance::Left`) remain unchanged.
154    ///
155    /// # Examples
156    ///
157    /// ```
158    /// use balanced_direction::Balance;
159    ///
160    /// let balance = Balance::Top;
161    /// assert_eq!(balance.flip_v(), Balance::Bottom);
162    ///
163    /// let balance = Balance::Center;
164    /// assert_eq!(balance.flip_v(), Balance::Center);
165    /// ```
166    pub fn flip_v(self) -> Self {
167        let (x, y) = self.to_vector();
168        Self::from_vector(x, -y)
169    }
170
171    /// Rotates the current position 90 degrees counterclockwise in the 3x3 grid.
172    ///
173    /// # Returns
174    ///
175    /// The `Balance` variant representing the position after a 90-degree counterclockwise
176    /// rotation around the center. For example, rotating `Balance::Right` counterclockwise
177    /// will result in `Balance::Top`, and `Balance::Top` will result in `Balance::Left`.
178    /// The center position (`Balance::Center`) remains unchanged.
179    ///
180    /// # Examples
181    ///
182    /// ```
183    /// use balanced_direction::Balance;
184    ///
185    /// let balance = Balance::Right;
186    /// assert_eq!(balance.rotate_left(), Balance::Top);
187    ///
188    /// let balance = Balance::Center;
189    /// assert_eq!(balance.rotate_left(), Balance::Center);
190    ///
191    /// let balance = Balance::Top;
192    /// assert_eq!(balance.rotate_left(), Balance::Left);
193    /// ```
194    pub fn rotate_left(self) -> Self {
195        let (x, y) = self.to_vector();
196        Self::from_vector(y, -x)
197    }
198
199    /// Rotates the current position 90 degrees clockwise in the 3x3 grid.
200    ///
201    /// # Returns
202    ///
203    /// The `Balance` variant representing the position after a 90-degree clockwise
204    /// rotation around the center. For example, rotating `Balance::Top` clockwise
205    /// results in `Balance::Right`, and `Balance::Right` will result in `Balance::Bottom`.
206    /// The center position (`Balance::Center`) remains unchanged.
207    ///
208    /// # Examples
209    ///
210    /// ```
211    /// use balanced_direction::Balance;
212    ///
213    /// let balance = Balance::Top;
214    /// assert_eq!(balance.rotate_right(), Balance::Right);
215    ///
216    /// let balance = Balance::Center;
217    /// assert_eq!(balance.rotate_right(), Balance::Center);
218    ///
219    /// let balance = Balance::Right;
220    /// assert_eq!(balance.rotate_right(), Balance::Bottom);
221    /// ```
222    pub fn rotate_right(self) -> Self {
223        let (x, y) = self.to_vector();
224        Self::from_vector(-y, x)
225    }
226}
227
228impl Not for Balance {
229    type Output = Self;
230
231    fn not(self) -> Self::Output {
232        let (x, y) = self.to_vector();
233        Self::from_vector(y, x)
234    }
235}
236
237impl Neg for Balance {
238    type Output = Self;
239
240    fn neg(self) -> Self::Output {
241        let (x, y) = self.to_vector();
242        Balance::from_vector(-x, -y)
243    }
244}
245
246impl Add for Balance {
247    type Output = Self;
248
249    fn add(self, rhs: Self) -> Self::Output {
250        let (x1, y1) = self.to_vector();
251        let (x2, y2) = rhs.to_vector();
252        Balance::from_vector((x1 + x2).clamp(-1, 1), (y1 + y2).clamp(-1, 1))
253    }
254}
255
256impl Mul for Balance {
257    type Output = Self;
258    fn mul(self, rhs: Self) -> Self::Output {
259        let (x1, y1) = self.to_vector();
260        let (x2, y2) = rhs.to_vector();
261        Balance::from_vector(x1 * x2, y1 * y2)
262    }
263}
264
265impl Sub for Balance {
266    type Output = Self;
267    fn sub(self, rhs: Self) -> Self::Output {
268        let (x1, y1) = self.to_vector();
269        let (x2, y2) = rhs.to_vector();
270        Self::from_vector((x1 - x2).clamp(-1, 1), (y1 - y2).clamp(-1, 1))
271    }
272}