1
macro_rules! define_vectorlike {
2
    ($name:ident, $test_mod_name:ident, $x:ident, $y:ident, $doc:literal) => {
3
        #[doc = $doc]
4
        #[allow(missing_docs)]
5
        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6
        pub struct $name<T, Unit> {
7
            pub $x: T,
8
            pub $y: T,
9
            _unit: std::marker::PhantomData<Unit>,
10
        }
11

            
12
        impl<T, Unit> Copy for $name<T, Unit> where T: Copy {}
13

            
14
        impl<T, Unit> Clone for $name<T, Unit>
15
        where
16
            T: Clone,
17
        {
18
            fn clone(&self) -> Self {
19
                Self {
20
                    $x: self.$x.clone(),
21
                    $y: self.$y.clone(),
22
                    _unit: std::marker::PhantomData::default(),
23
                }
24
            }
25
        }
26

            
27
        impl<T, Unit> std::fmt::Debug for $name<T, Unit>
28
        where
29
            T: std::fmt::Debug,
30
        {
31
3
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32
3
                f.debug_struct(stringify!($name))
33
3
                    .field(stringify!($x), &self.$x)
34
3
                    .field(stringify!($y), &self.$y)
35
3
                    .finish()
36
3
            }
37
        }
38

            
39
        impl<T, Unit> $name<T, Unit> {
40
            ///Returns a new `
41
            #[doc = stringify!($name)]
42
            ///`.
43
186
            pub const fn new($x: T, $y: T) -> Self {
44
186
                Self {
45
186
                    $x,
46
186
                    $y,
47
186
                    _unit: std::marker::PhantomData,
48
186
                }
49
186
            }
50
        }
51

            
52
        impl<T, Unit> $name<T, Unit>
53
        where
54
            T: Copy,
55
        {
56
            ///Returns a new `
57
            #[doc = stringify!($name)]
58
            ///`.
59
2
            pub fn from_figures($x: crate::Figure<T, Unit>, $y: crate::Figure<T, Unit>) -> Self {
60
2
                Self::new($x.get(), $y.get())
61
2
            }
62

            
63
            ///Returns the
64
            #[doc = stringify!($x)]
65
            /// component.
66
24
            pub fn $x(&self) -> crate::Figure<T, Unit> {
67
24
                crate::Figure::from(self.$x)
68
24
            }
69

            
70
            ///Returns the
71
            #[doc = stringify!($y)]
72
            /// component.
73
24
            pub fn $y(&self) -> crate::Figure<T, Unit> {
74
24
                crate::Figure::from(self.$y)
75
24
            }
76

            
77
            /// Returns this value with the new unit. Does not affect the underlying
78
            /// value.
79
3
            pub fn cast_unit<NewUnit>(&self) -> $name<T, NewUnit> {
80
3
                $name::new(self.$x, self.$y)
81
3
            }
82
        }
83

            
84
        impl<T, Unit> $name<T, Unit>
85
        where
86
            T: num_traits::NumCast + Copy,
87
        {
88
            /// Attempts to convert from `T` to `Output` using
89
            /// [`NumCast`](num_traits::NumCast). Returns None if the value
90
            /// can't be converted.
91
6
            pub fn try_cast<Output: num_traits::NumCast + Copy>(
92
6
                self,
93
6
            ) -> Option<$name<Output, Unit>> {
94
6
                match (Output::from(self.$x), Output::from(self.$y)) {
95
3
                    (Some($x), Some($y)) => Some($name::new($x, $y)),
96
3
                    _ => None,
97
                }
98
6
            }
99

            
100
            /// Converts from `T` to `Output`.
101
            ///
102
            /// # Panics
103
            ///
104
            /// Panics if `Self::try_cast()` returns `None`.
105
3
            pub fn cast<Output: num_traits::NumCast + Copy>(self) -> $name<Output, Unit> {
106
3
                self.try_cast().expect("could not cast")
107
3
            }
108
        }
109

            
110
        impl<T, Unit> $name<T, Unit>
111
        where
112
            T: num_traits::Signed + Copy,
113
        {
114
            /// Returns a new instance with the absolute value of each
115
            /// component.
116
3
            pub fn abs(self) -> Self {
117
3
                Self::new(self.$x.abs(), self.$y.abs())
118
3
            }
119

            
120
            /// Returns a `Vector` with the result of `signum()` called on each
121
            /// component.
122
6
            pub fn signum(&self) -> crate::Vector<T, Unit> {
123
6
                crate::Vector::new(self.$x.signum(), self.$y.signum())
124
6
            }
125
        }
126

            
127
        impl<T, Unit> $name<T, Unit>
128
        where
129
            T: std::cmp::PartialOrd + Copy,
130
        {
131
            ///Returns a new `
132
            #[doc = stringify!($name)]
133
            ///` with the smaller value of each component.
134
1
            pub fn min(&self, rhs: &Self) -> Self {
135
1
                Self::from_figures(self.$x().min(rhs.$x()), self.$y().min(rhs.$y()))
136
1
            }
137

            
138
            ///Returns a new `
139
            #[doc = stringify!($name)]
140
            ///` with the larger value of each component.
141
1
            pub fn max(&self, rhs: &Self) -> Self {
142
1
                Self::from_figures(self.$x().max(rhs.$x()), self.$y().max(rhs.$y()))
143
1
            }
144
        }
145

            
146
        impl<T, Unit> Default for $name<T, Unit>
147
        where
148
            T: Default,
149
        {
150
            fn default() -> Self {
151
                Self {
152
                    $x: T::default(),
153
                    $y: T::default(),
154
                    _unit: std::marker::PhantomData::default(),
155
                }
156
            }
157
        }
158

            
159
        impl<T, Unit> crate::Vectorlike<T, Unit> for $name<T, Unit>
160
        where
161
            T: Copy,
162
        {
163
3
            fn to_vector(&self) -> crate::Vector<T, Unit> {
164
3
                crate::Vector::new(self.$x, self.$y)
165
3
            }
166

            
167
3
            fn to_size(&self) -> crate::Size<T, Unit> {
168
3
                crate::Size::new(self.$x, self.$y)
169
3
            }
170

            
171
3
            fn to_point(&self) -> crate::Point<T, Unit> {
172
3
                crate::Point::new(self.$x, self.$y)
173
3
            }
174
        }
175

            
176
        impl<T, Unit> std::ops::Add for $name<T, Unit>
177
        where
178
            T: std::ops::Add<Output = T> + Copy,
179
        {
180
            type Output = Self;
181

            
182
3
            fn add(self, rhs: Self) -> Self::Output {
183
3
                Self::new(self.$x + rhs.$x, self.$y + rhs.$y)
184
3
            }
185
        }
186

            
187
        impl<T, Unit> std::ops::Sub for $name<T, Unit>
188
        where
189
            T: std::ops::Sub<Output = T> + Copy,
190
        {
191
            type Output = Self;
192

            
193
3
            fn sub(self, rhs: Self) -> Self::Output {
194
3
                Self::new(self.$x - rhs.$x, self.$y - rhs.$y)
195
3
            }
196
        }
197

            
198
        impl<T, Unit> std::ops::AddAssign for $name<T, Unit>
199
        where
200
            T: std::ops::AddAssign + Copy,
201
        {
202
3
            fn add_assign(&mut self, rhs: Self) {
203
3
                self.$x += rhs.$x;
204
3
                self.$y += rhs.$y;
205
3
            }
206
        }
207

            
208
        impl<T, Unit> std::ops::SubAssign for $name<T, Unit>
209
        where
210
            T: std::ops::SubAssign + Copy,
211
        {
212
3
            fn sub_assign(&mut self, rhs: Self) {
213
3
                self.$x -= rhs.$x;
214
3
                self.$y -= rhs.$y;
215
3
            }
216
        }
217

            
218
        impl<T, Unit> std::ops::Neg for $name<T, Unit>
219
        where
220
            T: std::ops::Neg<Output = T> + Copy,
221
        {
222
            type Output = Self;
223

            
224
3
            fn neg(self) -> Self::Output {
225
3
                Self::new(-self.$x, -self.$y)
226
3
            }
227
        }
228

            
229
        impl<T, Unit> Eq for $name<T, Unit> where T: Eq {}
230

            
231
        impl<T, Unit> PartialEq for $name<T, Unit>
232
        where
233
            T: PartialEq,
234
        {
235
43
            fn eq(&self, other: &Self) -> bool {
236
43
                self.$x.eq(&other.$x) && self.$y.eq(&other.$y)
237
43
            }
238
        }
239

            
240
        impl<T, UnitA, UnitB> std::ops::Mul<crate::Scale<T, UnitA, UnitB>> for $name<T, UnitA>
241
        where
242
            T: std::ops::Mul<T, Output = T> + Copy,
243
        {
244
            type Output = $name<T, UnitB>;
245

            
246
9
            fn mul(self, rhs: crate::Scale<T, UnitA, UnitB>) -> Self::Output {
247
9
                $name::new(self.$x * rhs.get(), self.$y * rhs.get())
248
9
            }
249
        }
250

            
251
        impl<T, UnitA, UnitB> std::ops::Div<crate::Scale<T, UnitA, UnitB>> for $name<T, UnitB>
252
        where
253
            T: std::ops::Div<T, Output = T> + Copy,
254
        {
255
            type Output = $name<T, UnitA>;
256

            
257
9
            fn div(self, rhs: crate::Scale<T, UnitA, UnitB>) -> Self::Output {
258
9
                $name::new(self.$x / rhs.get(), self.$y / rhs.get())
259
9
            }
260
        }
261
        impl<T, Unit> std::ops::Mul<T> for $name<T, Unit>
262
        where
263
            T: std::ops::Mul<T, Output = T> + Copy,
264
        {
265
            type Output = $name<T, Unit>;
266

            
267
3
            fn mul(self, rhs: T) -> Self::Output {
268
3
                $name::new(self.$x * rhs, self.$y * rhs)
269
3
            }
270
        }
271

            
272
        impl<T, Unit> std::ops::Div<T> for $name<T, Unit>
273
        where
274
            T: std::ops::Div<T, Output = T> + Copy,
275
        {
276
            type Output = $name<T, Unit>;
277

            
278
5
            fn div(self, rhs: T) -> Self::Output {
279
5
                $name::new(self.$x / rhs, self.$y / rhs)
280
5
            }
281
        }
282

            
283
        impl<T, Unit> crate::num::Round for $name<T, Unit>
284
        where
285
            T: crate::num::Round,
286
        {
287
3
            fn round(mut self) -> Self {
288
3
                self.$x = self.$x.round();
289
3
                self.$y = self.$y.round();
290
3
                self
291
3
            }
292
        }
293

            
294
        impl<T, Unit> crate::num::Ceil for $name<T, Unit>
295
        where
296
            T: crate::num::Ceil,
297
        {
298
3
            fn ceil(mut self) -> Self {
299
3
                self.$x = self.$x.ceil();
300
3
                self.$y = self.$y.ceil();
301
3
                self
302
3
            }
303
        }
304

            
305
        impl<T, Unit> crate::num::Floor for $name<T, Unit>
306
        where
307
            T: crate::num::Floor,
308
        {
309
3
            fn floor(mut self) -> Self {
310
3
                self.$x = self.$x.floor();
311
3
                self.$y = self.$y.floor();
312
3
                self
313
3
            }
314
        }
315

            
316
        impl<T, Unit> crate::Approx<T> for $name<T, Unit>
317
        where
318
            T: approx::AbsDiffEq + Copy,
319
        {
320
            fn approx_eq(&self, other: &Self) -> bool {
321
9
                self.$x().approx_eq(&other.$x()) && self.$y().approx_eq(&other.$y())
322
9
            }
323
        }
324

            
325
        impl<T, Unit> approx::AbsDiffEq for $name<T, Unit>
326
        where
327
            T: approx::AbsDiffEq<Epsilon = T> + Copy,
328
        {
329
            type Epsilon = T::Epsilon;
330

            
331
            fn default_epsilon() -> Self::Epsilon {
332
                T::default_epsilon()
333
            }
334

            
335
            fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
336
                self.$x.abs_diff_eq(&other.$x, epsilon) && self.$y.abs_diff_eq(&other.$y, epsilon)
337
            }
338

            
339
            fn abs_diff_ne(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
340
                self.$x.abs_diff_ne(&other.$x, epsilon) || self.$y.abs_diff_ne(&other.$y, epsilon)
341
            }
342
        }
343

            
344
        impl<T, Unit> approx::UlpsEq for $name<T, Unit>
345
        where
346
            T: approx::UlpsEq<Epsilon = T> + Copy,
347
        {
348
            fn default_max_ulps() -> u32 {
349
                T::default_max_ulps()
350
            }
351

            
352
            fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
353
                self.$x.ulps_eq(&other.$x, epsilon, max_ulps)
354
                    && self.$y.ulps_eq(&other.$y, epsilon, max_ulps)
355
            }
356

            
357
            fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
358
                self.$x.ulps_ne(&other.$x, epsilon, max_ulps)
359
                    || self.$y.ulps_ne(&other.$y, epsilon, max_ulps)
360
            }
361
        }
362

            
363
        impl<T, Unit> approx::RelativeEq for $name<T, Unit>
364
        where
365
            T: approx::RelativeEq<Epsilon = T> + Copy,
366
        {
367
            fn default_max_relative() -> Self::Epsilon {
368
                T::default_max_relative()
369
            }
370

            
371
            fn relative_eq(
372
                &self,
373
                other: &Self,
374
                epsilon: Self::Epsilon,
375
                max_relative: Self::Epsilon,
376
            ) -> bool {
377
                self.$x.relative_eq(&other.$x, epsilon, max_relative)
378
                    && self.$y.relative_eq(&other.$y, epsilon, max_relative)
379
            }
380

            
381
            fn relative_ne(
382
                &self,
383
                other: &Self,
384
                epsilon: Self::Epsilon,
385
                max_relative: Self::Epsilon,
386
            ) -> bool {
387
                self.$x.relative_ne(&other.$x, epsilon, max_relative)
388
                    || self.$y.relative_ne(&other.$y, epsilon, max_relative)
389
            }
390
        }
391

            
392
        impl<T> crate::Displayable<T> for $name<T, crate::Scaled>
393
        where
394
            T: std::ops::Div<T, Output = T> + std::ops::Mul<T, Output = T> + Copy,
395
        {
396
            type Pixels = $name<T, crate::Pixels>;
397
            type Points = $name<T, crate::Points>;
398
            type Scaled = Self;
399

            
400
3
            fn to_pixels(&self, scale: &crate::DisplayScale<T>) -> Self::Pixels {
401
3
                *self * scale.total
402
3
            }
403

            
404
3
            fn to_points(&self, scale: &crate::DisplayScale<T>) -> Self::Points {
405
3
                *self * scale.additional
406
3
            }
407

            
408
3
            fn to_scaled(&self, _scale: &crate::DisplayScale<T>) -> Self::Scaled {
409
3
                *self
410
3
            }
411
        }
412

            
413
        impl<T> crate::Displayable<T> for $name<T, crate::Points>
414
        where
415
            T: std::ops::Div<T, Output = T> + std::ops::Mul<T, Output = T> + Copy,
416
        {
417
            type Pixels = $name<T, crate::Pixels>;
418
            type Points = Self;
419
            type Scaled = $name<T, crate::Scaled>;
420

            
421
3
            fn to_pixels(&self, scale: &crate::DisplayScale<T>) -> Self::Pixels {
422
3
                *self * scale.dpi
423
3
            }
424

            
425
3
            fn to_points(&self, _scale: &crate::DisplayScale<T>) -> Self::Points {
426
3
                *self
427
3
            }
428

            
429
3
            fn to_scaled(&self, scale: &crate::DisplayScale<T>) -> Self::Scaled {
430
3
                *self / scale.additional
431
3
            }
432
        }
433

            
434
        impl<T> crate::Displayable<T> for $name<T, crate::Pixels>
435
        where
436
            T: std::ops::Div<T, Output = T> + std::ops::Mul<T, Output = T> + Copy,
437
        {
438
            type Pixels = Self;
439
            type Points = $name<T, crate::Points>;
440
            type Scaled = $name<T, crate::Scaled>;
441

            
442
3
            fn to_pixels(&self, _scale: &crate::DisplayScale<T>) -> Self::Pixels {
443
3
                *self
444
3
            }
445

            
446
3
            fn to_points(&self, scale: &crate::DisplayScale<T>) -> Self::Points {
447
3
                *self / scale.dpi
448
3
            }
449

            
450
3
            fn to_scaled(&self, scale: &crate::DisplayScale<T>) -> Self::Scaled {
451
3
                *self / scale.total
452
3
            }
453
        }
454

            
455
        impl<T, Unit> From<(T, T)> for $name<T, Unit>
456
        where
457
            T: Copy,
458
        {
459
4
            fn from(tuple: (T, T)) -> Self {
460
4
                Self::new(tuple.0, tuple.1)
461
4
            }
462
        }
463

            
464
        #[cfg(test)]
465
        mod $test_mod_name {
466
            use super::*;
467
            use crate::{
468
                Approx, Ceil, DisplayScale, Displayable, Floor, Pixels, Points, Round, Scale,
469
                Scaled,
470
            };
471

            
472
            #[test]
473
3
            fn cast_unit_test() {
474
3
                let pixels = $name::<i32, Pixels>::new(1, 2);
475
3
                let points: $name<i32, Points> = pixels.cast_unit();
476
3
                assert_eq!(pixels.$x, points.$x);
477
3
                assert_eq!(pixels.$y, points.$y);
478
3
            }
479

            
480
            #[test]
481
3
            fn cast_tests() {
482
3
                let pixels = $name::<i32, Pixels>::new(256, 255);
483
3
                let as_u32 = pixels.cast::<u32>();
484
3
                assert_eq!(as_u32.$x, 256);
485
3
                assert_eq!(as_u32.$y, 255);
486
3
                assert_eq!(pixels.try_cast::<u8>(), None);
487
3
            }
488

            
489
            #[test]
490
3
            fn signed_tests() {
491
3
                let pixels = $name::<i32, Pixels>::new(-256, -255);
492
3
                let signum = pixels.signum();
493
3
                assert_eq!(signum.x, -1);
494
3
                assert_eq!(signum.y, -1);
495
3
                let abs = pixels.abs();
496
3
                assert_eq!(abs.$x, 256);
497
3
                assert_eq!(abs.$y, 255);
498
3
                let signum = abs.signum();
499
3
                assert_eq!(signum.x, 1);
500
3
                assert_eq!(signum.y, 1);
501
3
            }
502

            
503
            #[test]
504
3
            fn vectorlike_conversions() {
505
3
                let original = $name::<i32, Pixels>::new(256, 255);
506
3
                let vector = original.to_vector();
507
3
                assert_eq!(vector.x, 256);
508
3
                assert_eq!(vector.y, 255);
509
3
                let point = original.to_point();
510
3
                assert_eq!(point.x, 256);
511
3
                assert_eq!(point.y, 255);
512
3
                let size = original.to_size();
513
3
                assert_eq!(size.width, 256);
514
3
                assert_eq!(size.height, 255);
515
3
            }
516

            
517
            #[test]
518
3
            fn math_ops() {
519
3
                let one = $name::<i32, Pixels>::new(1, 10);
520
3
                let two = one + one;
521
3
                assert_eq!(two.$x, 2);
522
3
                assert_eq!(two.$y, 20);
523
3
                let one_after_sub = two - one;
524
3
                assert_eq!(one_after_sub.$x, 1);
525
3
                assert_eq!(one_after_sub.$y, 10);
526
3
                let neg_one = -one;
527
3
                assert_eq!(neg_one.$x, -1);
528
3
                assert_eq!(neg_one.$y, -10);
529
3
                let four = two * 2;
530
3
                assert_eq!(four.$x, 4);
531
3
                assert_eq!(four.$y, 40);
532
3
                let two_div = four / 2;
533
3
                assert_eq!(two_div.$x, 2);
534
3
                assert_eq!(two_div.$y, 20);
535

            
536
3
                let mut value = one;
537
3
                value += one;
538
3
                assert_eq!(value.$x, 2);
539
3
                assert_eq!(value.$y, 20);
540
3
                value -= one;
541
3
                assert_eq!(value.$x, 1);
542
3
                assert_eq!(value.$y, 10);
543
3
            }
544

            
545
            #[test]
546
3
            fn display_scale_math() {
547
3
                let scale = DisplayScale::<u32>::new(Scale::new(2), Scale::new(3));
548
3
                let one_scaled = $name::<u32, Scaled>::new(1, 10);
549
3
                assert_eq!(one_scaled.to_scaled(&scale), one_scaled);
550
3
                let two_points = one_scaled.to_points(&scale);
551
3
                assert_eq!(two_points, $name::new(3, 30));
552
3
                assert_eq!(two_points.to_points(&scale), two_points);
553
3
                let six_pixels = one_scaled.to_pixels(&scale);
554
3
                assert_eq!(six_pixels, $name::new(6, 60));
555
3
                assert_eq!(six_pixels.to_pixels(&scale), six_pixels);
556

            
557
3
                assert_eq!(six_pixels.to_points(&scale), two_points);
558
3
                assert_eq!(six_pixels.to_scaled(&scale), one_scaled);
559

            
560
3
                assert_eq!(two_points.to_pixels(&scale), six_pixels);
561
3
                assert_eq!(two_points.to_scaled(&scale), one_scaled);
562
3
            }
563

            
564
            #[test]
565
3
            fn float_ops_test() {
566
3
                let one = $name::<f32, Pixels>::new(1., 10.);
567
3
                assert!($name::<f32, Pixels>::new(0.5, 9.5).round().approx_eq(&one));
568
3
                assert!($name::<f32, Pixels>::new(0.1, 9.1).ceil().approx_eq(&one));
569
3
                assert!($name::<f32, Pixels>::new(1.9, 10.9).floor().approx_eq(&one));
570
3
            }
571
        }
572
    };
573
}
574

            
575
macro_rules! define_vector_compatibility_ops {
576
    (
577
        $name:ident,
578
        $test_mod_name:ident,
579
        $x:ident,
580
        $y:ident,
581
        $other_name:ident,
582
        $other_x:ident,
583
        $other_y:ident
584
    ) => {
585
        impl<T, Unit> std::ops::Add<$other_name<T, Unit>> for $name<T, Unit>
586
        where
587
            T: std::ops::Add<Output = T> + Copy,
588
        {
589
            type Output = Self;
590

            
591
24
            fn add(self, rhs: $other_name<T, Unit>) -> Self::Output {
592
24
                Self::new(self.$x + rhs.$other_x, self.$y + rhs.$other_y)
593
24
            }
594
        }
595

            
596
        impl<T, Unit> std::ops::Sub<$other_name<T, Unit>> for $name<T, Unit>
597
        where
598
            T: std::ops::Sub<Output = T> + Copy,
599
        {
600
            type Output = Self;
601

            
602
6
            fn sub(self, rhs: $other_name<T, Unit>) -> Self::Output {
603
6
                Self::new(self.$x - rhs.$other_x, self.$y - rhs.$other_y)
604
6
            }
605
        }
606

            
607
        impl<T, Unit> std::ops::AddAssign<$other_name<T, Unit>> for $name<T, Unit>
608
        where
609
            T: std::ops::AddAssign + Copy,
610
        {
611
4
            fn add_assign(&mut self, rhs: $other_name<T, Unit>) {
612
4
                self.$x += rhs.$other_x;
613
4
                self.$y += rhs.$other_y;
614
4
            }
615
        }
616

            
617
        impl<T, Unit> std::ops::SubAssign<$other_name<T, Unit>> for $name<T, Unit>
618
        where
619
            T: std::ops::SubAssign + Copy,
620
        {
621
4
            fn sub_assign(&mut self, rhs: $other_name<T, Unit>) {
622
4
                self.$x -= rhs.$other_x;
623
4
                self.$y -= rhs.$other_y;
624
4
            }
625
        }
626

            
627
        impl<T, Unit> PartialEq<$other_name<T, Unit>> for $name<T, Unit>
628
        where
629
            T: PartialEq,
630
        {
631
8
            fn eq(&self, other: &$other_name<T, Unit>) -> bool {
632
8
                self.$x.eq(&other.$other_x) && self.$y.eq(&other.$other_y)
633
8
            }
634
        }
635

            
636
        #[cfg(test)]
637
        mod $test_mod_name {
638
            use super::*;
639
            use crate::Pixels;
640

            
641
            #[test]
642
4
            fn math_ops() {
643
4
                let one = $name::<i32, Pixels>::new(1, 10);
644
4
                let other_one = $other_name::new(1, 10);
645
4
                let two = one + other_one;
646
4
                assert_eq!(two.$x, 2);
647
4
                assert_eq!(two.$y, 20);
648
4
                let one_after_sub = two - other_one;
649
4
                assert_eq!(one_after_sub, other_one);
650

            
651
4
                let mut value = one;
652
4
                value += other_one;
653
4
                assert_eq!(value.$x, 2);
654
4
                assert_eq!(value.$y, 20);
655
4
                value -= other_one;
656
4
                assert_eq!(value, other_one);
657
4
            }
658

            
659
            #[test]
660
4
            fn tuple_froms() {
661
4
                assert_eq!($name::<i32, Pixels>::new(1, 2), $name::from((1, 2)));
662
4
            }
663
        }
664
    };
665
}
666

            
667
/// Methods that enable converting between 2d types that have two components.
668
pub trait Vectorlike<T, Unit> {
669
    /// Returns `self` as a `Vector`.
670
    fn to_vector(&self) -> Vector<T, Unit>;
671
    /// Returns `self` as a `Size`.
672
    fn to_size(&self) -> Size<T, Unit>;
673
    /// Returns `self` as a `Point`.
674
    fn to_point(&self) -> Point<T, Unit>;
675
}
676

            
677
7
define_vectorlike!(
678
7
    Size,
679
7
    size_tests,
680
7
    width,
681
7
    height,
682
7
    "A measurement of space using width and height."
683
7
);
684
7
define_vectorlike!(
685
7
    Point,
686
7
    point_tests,
687
7
    x,
688
7
    y,
689
7
    "A location represented by an x and y value."
690
7
);
691
7
define_vectorlike!(
692
7
    Vector,
693
7
    vector_tests,
694
7
    x,
695
7
    y,
696
7
    "A 2d measurement using x and y values."
697
7
);
698

            
699
2
define_vector_compatibility_ops!(Size, size_vector_tests, width, height, Vector, x, y);
700
2
define_vector_compatibility_ops!(Point, point_vector_tests, x, y, Vector, x, y);
701
2
define_vector_compatibility_ops!(Point, point_size_tests, x, y, Size, width, height);
702
2
define_vector_compatibility_ops!(Vector, vector_size_tests, x, y, Size, width, height);
703

            
704
1
#[test]
705
1
fn debug_test() {
706
1
    let test = Size::<u32, ()>::new(1, 0);
707
1
    assert_eq!(&format!("{:?}", test), "Size { width: 1, height: 0 }");
708
1
    let test = Point::<u32, ()>::new(1, 0);
709
1
    assert_eq!(&format!("{:?}", test), "Point { x: 1, y: 0 }");
710
1
    let test = Vector::<u32, ()>::new(1, 0);
711
1
    assert_eq!(&format!("{:?}", test), "Vector { x: 1, y: 0 }");
712
1
}
713

            
714
impl<T, Unit> From<Vector<T, Unit>> for Point<T, Unit> {
715
    fn from(other: Vector<T, Unit>) -> Self {
716
        Self::new(other.x, other.y)
717
    }
718
}
719

            
720
impl<T, Unit> From<Point<T, Unit>> for Vector<T, Unit> {
721
    fn from(other: Point<T, Unit>) -> Self {
722
        Self::new(other.x, other.y)
723
    }
724
}
725

            
726
impl<T, Unit> From<Vector<T, Unit>> for Size<T, Unit> {
727
    fn from(other: Vector<T, Unit>) -> Self {
728
        Self::new(other.x, other.y)
729
    }
730
}
731

            
732
impl<T, Unit> From<Size<T, Unit>> for Vector<T, Unit> {
733
    fn from(other: Size<T, Unit>) -> Self {
734
        Self::new(other.width, other.height)
735
    }
736
}