Implemented more operators for point
[kaka/rust-sdl-test.git] / src / common.rs
CommitLineData
2836f506 1use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, Neg};
296187ca 2
b0566120
TW
3pub type Nanoseconds = u64;
4
787dbfb4 5#[macro_export]
296187ca 6macro_rules! point {
6ba7aef1
TW
7 ( $x:expr, $y:expr ) => {
8 Point2D { x: $x, y: $y }
9 };
296187ca
TW
10}
11
b0566120 12#[derive(Debug, Default, Copy, Clone, PartialEq)]
296187ca
TW
13pub struct Point2D<T> {
14 pub x: T,
15 pub y: T,
16}
17
18impl Point2D<f64> {
19 pub fn length(self) -> f64 {
20 ((self.x * self.x) + (self.y * self.y)).sqrt()
21 }
22}
23
2836f506 24////////// add point to point //////////////////////////////////////////////////
6ba7aef1 25impl<T: Add<Output = T>> Add for Point2D<T> {
2836f506 26 type Output = Self;
296187ca 27
2836f506
TW
28 fn add(self, rhs: Self) -> Self {
29 Self {
30 x: self.x + rhs.x,
31 y: self.y + rhs.y,
32 }
33 }
34}
35
36impl<T: Add<Output = T> + Copy> AddAssign for Point2D<T> {
37 fn add_assign(&mut self, rhs: Self) {
38 *self = Self {
6ba7aef1
TW
39 x: self.x + rhs.x,
40 y: self.y + rhs.y,
2836f506
TW
41 }
42 }
43}
44
45////////// add tuple to point //////////////////////////////////////////////////
46impl<T: Add<Output = T>> Add<(T, T)> for Point2D<T> {
47 type Output = Self;
48
49 fn add(self, rhs: (T, T)) -> Self {
50 Self {
51 x: self.x + rhs.0,
52 y: self.y + rhs.1,
53 }
54 }
55}
56
57////////// subtract point from point ///////////////////////////////////////////
58impl<T: Sub<Output = T>> Sub for Point2D<T> {
59 type Output = Self;
60
61 fn sub(self, rhs: Self) -> Self {
62 Self {
63 x: self.x - rhs.x,
64 y: self.y - rhs.y,
6ba7aef1 65 }
296187ca
TW
66 }
67}
68
2836f506
TW
69impl<T: Sub<Output = T> + Copy> SubAssign for Point2D<T> {
70 fn sub_assign(&mut self, rhs: Self) {
71 *self = Self {
72 x: self.x - rhs.x,
73 y: self.y - rhs.y,
74 }
75 }
76}
77
78////////// multiply point with scalar //////////////////////////////////////////
79impl<T: Mul<Output = T> + Copy> Mul<T> for Point2D<T> {
80 type Output = Self;
81
82 fn mul(self, rhs: T) -> Self {
83 Self {
84 x: self.x * rhs,
85 y: self.y * rhs,
86 }
87 }
88}
89
90impl<T: Mul<Output = T> + Copy> MulAssign<T> for Point2D<T> {
91 fn mul_assign(&mut self, rhs: T) {
92 *self = Self {
93 x: self.x * rhs,
94 y: self.y * rhs,
95 }
96 }
97}
98
99////////// multiply components of two points ///////////////////////////////////
100impl<T: Mul<Output = T>> Mul for Point2D<T> {
101 type Output = Self;
102
103 fn mul(self, rhs: Self) -> Self {
104 Self {
105 x: self.x * rhs.x,
106 y: self.y * rhs.y,
107 }
108 }
109}
110
111impl<T: Mul<Output = T> + Copy> MulAssign for Point2D<T> {
112 fn mul_assign(&mut self, rhs: Self) {
113 *self = Self {
114 x: self.x * rhs.x,
115 y: self.y * rhs.y,
116 }
117 }
118}
119
120////////// divide point with scalar ////////////////////////////////////////////
121impl<T: Div<Output = T> + Copy> Div<T> for Point2D<T> {
122 type Output = Self;
123
124 fn div(self, rhs: T) -> Self {
125 Self {
126 x: self.x / rhs,
127 y: self.y / rhs,
128 }
129 }
130}
131
132impl<T: Div<Output = T> + Copy> DivAssign<T> for Point2D<T> {
133 fn div_assign(&mut self, rhs: T) {
134 *self = Self {
135 x: self.x / rhs,
136 y: self.y / rhs,
137 }
138 }
139}
140
141////////// divide components of two points /////////////////////////////////////
142impl<T: Div<Output = T>> Div for Point2D<T> {
143 type Output = Self;
144
145 fn div(self, rhs: Self) -> Self {
146 Self {
147 x: self.x / rhs.x,
148 y: self.y / rhs.y,
149 }
150 }
151}
152
153impl<T: Div<Output = T> + Copy> DivAssign for Point2D<T> {
154 fn div_assign(&mut self, rhs: Self) {
155 *self = Self {
156 x: self.x / rhs.x,
157 y: self.y / rhs.y,
158 }
159 }
160}
161
162impl<T: Neg<Output = T>> Neg for Point2D<T> {
163 type Output = Self;
164
165 fn neg(self) -> Self {
166 Self {
167 x: -self.x,
168 y: -self.y,
169 }
296187ca
TW
170 }
171}
172
b0566120
TW
173impl<T> From<(T, T)> for Point2D<T> {
174 fn from(item: (T, T)) -> Self {
175 Point2D {
176 x: item.0,
177 y: item.1,
178 }
179 }
180}
181
0b5024d1
TW
182#[macro_export]
183macro_rules! rect {
184 ( $x:expr, $y:expr ) => {
185 Rect { x: $x, y: $y }
186 };
187}
188
6edafdc0
TW
189#[derive(Default)]
190pub struct Rect<T> {
191 pub width: T,
192 pub height: T,
193}
194
6ba7aef1 195impl<T: Mul<Output = T> + Copy> Rect<T> {
6edafdc0
TW
196 #[allow(dead_code)]
197 pub fn area(&self) -> T {
6ba7aef1 198 self.width * self.height
6edafdc0
TW
199 }
200}
201
202impl<T> From<(T, T)> for Rect<T> {
203 fn from(item: (T, T)) -> Self {
6ba7aef1
TW
204 Rect {
205 width: item.0,
206 height: item.1,
207 }
6edafdc0
TW
208 }
209}
210
296187ca
TW
211#[cfg(test)]
212mod tests {
213 use super::*;
214
215 #[test]
216 fn immutable_copy_of_point() {
217 let a = point!(0, 0);
218 let mut b = a; // Copy
219 assert_eq!(a, b); // PartialEq
220 b.x = 1;
221 assert_ne!(a, b); // PartialEq
222 }
223
224 #[test]
225 fn add_points() {
226 let mut a = point!(1, 0);
227 assert_eq!(a + point!(2, 2), point!(3, 2)); // Add
228 a += point!(2, 2); // AddAssign
229 assert_eq!(a, point!(3, 2));
2836f506
TW
230 assert_eq!(point!(1, 0) + (2, 3), point!(3, 3));
231 }
232
233 #[test]
234 fn sub_points() {
235 let mut a = point!(1, 0);
236 assert_eq!(a - point!(2, 2), point!(-1, -2));
237 a -= point!(2, 2);
238 assert_eq!(a, point!(-1, -2));
239 }
240
241 #[test]
242 fn mul_points() {
243 let mut a = point!(1, 2);
244 assert_eq!(a * 2, point!(2, 4));
245 assert_eq!(a * point!(2, 3), point!(2, 6));
246 a *= 2;
247 assert_eq!(a, point!(2, 4));
248 a *= point!(3, 1);
249 assert_eq!(a, point!(6, 4));
250 }
251
252 #[test]
253 fn div_points() {
254 let mut a = point!(4, 8);
255 assert_eq!(a / 2, point!(2, 4));
256 assert_eq!(a / point!(2, 4), point!(2, 2));
257 a /= 2;
258 assert_eq!(a, point!(2, 4));
259 a /= point!(2, 4);
260 assert_eq!(a, point!(1, 1));
261 }
262
263 #[test]
264 fn neg_point() {
265 assert_eq!(point!(1, 1), -point!(-1, -1));
296187ca 266 }
6edafdc0
TW
267
268 #[test]
269 fn area_for_rect_of_multipliable_type() {
270 let r: Rect<_> = (30, 20).into(); // the Into trait uses the From trait
6ba7aef1 271 assert_eq!(r.area(), 30 * 20);
6edafdc0
TW
272 // let a = Rect::from(("a".to_string(), "b".to_string())).area(); // this doesn't work, because area() is not implemented for String
273 }
296187ca 274}