1use std::{
2 cmp::Ordering,
3 fmt,
4 mem,
5 ops::{
6 Add,
7 AddAssign,
8 Bound,
9 Div,
10 DivAssign,
11 Index,
12 IndexMut,
13 Mul,
14 MulAssign,
15 Neg,
16 RangeBounds,
17 Rem,
18 RemAssign,
19 Sub,
20 SubAssign,
21 },
22};
23
24use num::{
25 CheckedAdd,
26 CheckedDiv,
27 CheckedMul,
28 CheckedSub,
29 Integer,
30 One,
31 Zero,
32 traits::{CheckedRem, SaturatingAdd, SaturatingMul, SaturatingSub},
33};
34use serde::{Deserialize, Serialize};
35
36use crate::{
37 orientation::{Axis, Direction, DirectionVec},
38 rect::Rect,
39};
40
41#[derive(
42 Debug,
43 Clone,
44 Copy,
45 PartialEq,
46 Eq,
47 PartialOrd,
48 Ord,
49 Hash,
50 Default,
51 Serialize,
52 Deserialize,
53)]
54pub struct CoordPair<C> {
55 pub y: C,
56 pub x: C,
57}
58
59impl<C> CoordPair<C> {
60 pub fn with_order(first: C, second: C) -> Self {
61 Self { y: first, x: second }
62 }
63
64 pub fn from_axes<F>(mut generator: F) -> Self
65 where
66 F: FnMut(Axis) -> C,
67 {
68 Self { y: generator(Axis::Y), x: generator(Axis::X) }
69 }
70
71 pub fn try_from_axes<F, E>(mut generator: F) -> Result<Self, E>
72 where
73 F: FnMut(Axis) -> Result<C, E>,
74 {
75 Ok(Self { y: generator(Axis::Y)?, x: generator(Axis::X)? })
76 }
77
78 pub fn into_order(self) -> (C, C) {
79 (self.y, self.x)
80 }
81
82 pub fn as_ref(&self) -> CoordPair<&C> {
83 CoordPair::from_axes(|axis| &self[axis])
84 }
85
86 pub fn as_mut(&mut self) -> CoordPair<&mut C> {
87 CoordPair { y: &mut self.y, x: &mut self.x }
88 }
89
90 pub fn map<F, C0>(self, mut mapper: F) -> CoordPair<C0>
91 where
92 F: FnMut(C) -> C0,
93 {
94 CoordPair { y: mapper(self.y), x: mapper(self.x) }
95 }
96
97 pub fn try_map<F, C0, E>(self, mut mapper: F) -> Result<CoordPair<C0>, E>
98 where
99 F: FnMut(C) -> Result<C0, E>,
100 {
101 Ok(CoordPair { y: mapper(self.y)?, x: mapper(self.x)? })
102 }
103
104 pub fn map_with_axes<F, C0>(self, mut mapper: F) -> CoordPair<C0>
105 where
106 F: FnMut(C, Axis) -> C0,
107 {
108 CoordPair { y: mapper(self.y, Axis::Y), x: mapper(self.x, Axis::X) }
109 }
110
111 pub fn try_map_with_axes<F, C0, E>(
112 self,
113 mut mapper: F,
114 ) -> Result<CoordPair<C0>, E>
115 where
116 F: FnMut(C, Axis) -> Result<C0, E>,
117 {
118 Ok(CoordPair {
119 y: mapper(self.y, Axis::Y)?,
120 x: mapper(self.x, Axis::X)?,
121 })
122 }
123
124 pub fn shift(self) -> Self {
125 CoordPair { y: self.x, x: self.y }
126 }
127
128 pub fn shift_rev(self) -> Self {
129 CoordPair { y: self.x, x: self.y }
130 }
131
132 pub fn shift_in_place(&mut self) {
133 mem::swap(&mut self.y, &mut self.x);
134 }
135
136 pub fn shift_rev_in_place(&mut self) {
137 mem::swap(&mut self.x, &mut self.y);
138 }
139
140 pub fn shift_to(self, axis: Axis) -> Self {
141 match axis {
142 Axis::Y => self,
143 Axis::X => self.shift(),
144 }
145 }
146
147 pub fn shift_in_place_to(&mut self, axis: Axis) {
148 match axis {
149 Axis::Y => (),
150 Axis::X => self.shift_in_place(),
151 }
152 }
153
154 pub fn shift_rev_to(self, axis: Axis) -> Self {
155 match axis {
156 Axis::Y => self,
157 Axis::X => self.shift_rev(),
158 }
159 }
160
161 pub fn shift_rev_in_place_to(&mut self, axis: Axis) {
162 match axis {
163 Axis::Y => (),
164 Axis::X => self.shift_rev_in_place(),
165 }
166 }
167
168 pub fn zip2<C0>(self, other: CoordPair<C0>) -> CoordPair<(C, C0)> {
169 CoordPair { y: (self.y, other.y), x: (self.x, other.x) }
170 }
171
172 pub fn zip2_with<F, C0, C1>(
173 self,
174 other: CoordPair<C0>,
175 mut zipper: F,
176 ) -> CoordPair<C1>
177 where
178 F: FnMut(C, C0) -> C1,
179 {
180 self.zip2(other).map(|(a, b)| zipper(a, b))
181 }
182
183 pub fn zip2_with_axes<F, C0, C1>(
184 self,
185 other: CoordPair<C0>,
186 mut zipper: F,
187 ) -> CoordPair<C1>
188 where
189 F: FnMut(C, C0, Axis) -> C1,
190 {
191 self.zip2(other).map_with_axes(|(a, b), axis| zipper(a, b, axis))
192 }
193
194 pub fn try_zip2_with<F, C0, C1, E>(
195 self,
196 other: CoordPair<C0>,
197 mut zipper: F,
198 ) -> Result<CoordPair<C1>, E>
199 where
200 F: FnMut(C, C0) -> Result<C1, E>,
201 {
202 self.zip2(other).try_map(|(a, b)| zipper(a, b))
203 }
204
205 pub fn try_zip2_with_axes<F, C0, C1, E>(
206 self,
207 other: CoordPair<C0>,
208 mut zipper: F,
209 ) -> Result<CoordPair<C1>, E>
210 where
211 F: FnMut(C, C0, Axis) -> Result<C1, E>,
212 {
213 self.zip2(other).try_map_with_axes(|(a, b), axis| zipper(a, b, axis))
214 }
215
216 pub fn zip3<C0, C1>(
217 self,
218 other: CoordPair<C0>,
219 another: CoordPair<C1>,
220 ) -> CoordPair<(C, C0, C1)> {
221 CoordPair {
222 y: (self.y, other.y, another.y),
223 x: (self.x, other.x, another.x),
224 }
225 }
226
227 pub fn zip3_with<F, C0, C1, C2>(
228 self,
229 other: CoordPair<C0>,
230 another: CoordPair<C1>,
231 mut zipper: F,
232 ) -> CoordPair<C2>
233 where
234 F: FnMut(C, C0, C1) -> C2,
235 {
236 self.zip3(other, another).map(|(a, b, c)| zipper(a, b, c))
237 }
238
239 pub fn zip3_with_axes<F, C0, C1, C2>(
240 self,
241 other: CoordPair<C0>,
242 another: CoordPair<C1>,
243 mut zipper: F,
244 ) -> CoordPair<C2>
245 where
246 F: FnMut(C, C0, C1, Axis) -> C2,
247 {
248 self.zip3(other, another)
249 .map_with_axes(|(a, b, c), axis| zipper(a, b, c, axis))
250 }
251
252 pub fn try_zip3_with<F, C0, C1, C2, E>(
253 self,
254 other: CoordPair<C0>,
255 another: CoordPair<C1>,
256 mut zipper: F,
257 ) -> Result<CoordPair<C2>, E>
258 where
259 F: FnMut(C, C0, C1) -> Result<C2, E>,
260 {
261 self.zip3(other, another).try_map(|(a, b, c)| zipper(a, b, c))
262 }
263
264 pub fn try_zip3_with_axes<F, C0, C1, C2, E>(
265 self,
266 other: CoordPair<C0>,
267 another: CoordPair<C1>,
268 mut zipper: F,
269 ) -> Result<CoordPair<C2>, E>
270 where
271 F: FnMut(C, C0, C1, Axis) -> Result<C2, E>,
272 {
273 self.zip3(other, another)
274 .try_map_with_axes(|(a, b, c), axis| zipper(a, b, c, axis))
275 }
276
277 pub fn extract(self, axis: Axis) -> C {
278 match axis {
279 Axis::Y => self.y,
280 Axis::X => self.x,
281 }
282 }
283
284 pub fn all<F>(self, mut predicate: F) -> bool
285 where
286 F: FnMut(C) -> bool,
287 {
288 predicate(self.y) && predicate(self.x)
289 }
290
291 pub fn any<F>(self, mut predicate: F) -> bool
292 where
293 F: FnMut(C) -> bool,
294 {
295 predicate(self.y) || predicate(self.x)
296 }
297
298 pub fn checked_add_to(&self, other: &C) -> Option<Self>
299 where
300 C: CheckedAdd,
301 {
302 self.as_ref().checked_add_by_ref_to(other)
303 }
304
305 pub fn checked_sub_except(&self, other: &C) -> Option<Self>
306 where
307 C: CheckedSub,
308 {
309 self.as_ref().checked_sub_by_ref_except(other)
310 }
311
312 pub fn checked_sub_from(&self, other: &C) -> Option<Self>
313 where
314 C: CheckedSub,
315 {
316 self.as_ref().checked_sub_by_ref_from(other)
317 }
318
319 pub fn checked_mul_scalar(&self, other: &C) -> Option<Self>
320 where
321 C: CheckedMul,
322 {
323 self.as_ref().checked_mul_by_ref_scalar(other)
324 }
325
326 pub fn checked_div_by(&self, other: &C) -> Option<Self>
327 where
328 C: CheckedDiv,
329 {
330 self.as_ref().checked_div_by_ref_by(other)
331 }
332
333 pub fn checked_div_on(&self, other: &C) -> Option<Self>
334 where
335 C: CheckedDiv,
336 {
337 self.as_ref().checked_div_by_ref_on(other)
338 }
339
340 pub fn checked_rem_by(&self, other: &C) -> Option<Self>
341 where
342 C: CheckedRem,
343 {
344 self.as_ref().checked_rem_by_ref_by(other)
345 }
346
347 pub fn checked_rem_on(&self, other: &C) -> Option<Self>
348 where
349 C: CheckedRem,
350 {
351 self.as_ref().checked_rem_by_ref_on(other)
352 }
353
354 pub fn saturating_add_to(&self, other: &C) -> Self
355 where
356 C: SaturatingAdd,
357 {
358 self.as_ref().saturating_add_by_ref_to(other)
359 }
360
361 pub fn saturating_sub_except(&self, other: &C) -> Self
362 where
363 C: SaturatingSub,
364 {
365 self.as_ref().saturating_sub_by_ref_except(other)
366 }
367
368 pub fn saturating_sub_from(&self, other: &C) -> Self
369 where
370 C: SaturatingSub,
371 {
372 self.as_ref().saturating_sub_by_ref_from(other)
373 }
374
375 pub fn saturating_mul_scalar(&self, other: &C) -> Self
376 where
377 C: SaturatingMul,
378 {
379 self.as_ref().saturating_mul_by_ref_scalar(other)
380 }
381
382 pub fn div_floor_by(&self, divisor: &C) -> Self
383 where
384 C: Integer,
385 {
386 self.as_ref().div_floor_by_ref_by(divisor)
387 }
388
389 pub fn div_ceil_by(&self, divisor: &C) -> Self
390 where
391 C: Integer,
392 {
393 self.as_ref().div_ceil_by_ref_by(divisor)
394 }
395
396 pub fn div_floor_on(&self, dividend: &C) -> Self
397 where
398 C: Integer,
399 {
400 self.as_ref().div_floor_by_ref_on(dividend)
401 }
402
403 pub fn div_ceil_on(&self, dividend: &C) -> Self
404 where
405 C: Integer,
406 {
407 self.as_ref().div_ceil_by_ref_on(dividend)
408 }
409
410 pub fn div_floor(&self, other: &Self) -> Self
411 where
412 C: Integer,
413 {
414 self.as_ref().div_floor_by_ref(other.as_ref())
415 }
416
417 pub fn div_ceil(&self, other: &Self) -> Self
418 where
419 C: Integer,
420 {
421 self.as_ref().div_ceil_by_ref(other.as_ref())
422 }
423
424 pub fn move_unit(self, direction: Direction) -> Self
425 where
426 C: Add<Output = C> + Sub<Output = C> + One,
427 {
428 direction.move_unit(self)
429 }
430
431 pub fn checked_move_unit(&self, direction: Direction) -> Option<Self>
432 where
433 C: CheckedAdd + CheckedSub + One + Clone,
434 {
435 direction.checked_move_unit(self)
436 }
437
438 pub fn saturating_move_unit(&self, direction: Direction) -> Self
439 where
440 C: SaturatingAdd + SaturatingSub + One + Clone,
441 {
442 direction.saturating_move_unit(self)
443 }
444
445 pub fn move_by(self, vector: DirectionVec<C>) -> Self
446 where
447 C: Add<Output = C> + Sub<Output = C>,
448 {
449 vector.mov(self)
450 }
451
452 pub fn checked_move_by(&self, vector: DirectionVec<&C>) -> Option<Self>
453 where
454 C: CheckedAdd + CheckedSub + Clone,
455 {
456 vector.checked_move(self)
457 }
458
459 pub fn saturating_move_by(&self, vector: DirectionVec<&C>) -> Self
460 where
461 C: SaturatingAdd + SaturatingSub + Clone,
462 {
463 vector.saturating_move(self)
464 }
465
466 pub fn as_rect_size(self, top_left: Self) -> Rect<C> {
467 Rect { top_left, size: self }
468 }
469
470 pub fn as_rect_top_left(self, size: Self) -> Rect<C> {
471 Rect { top_left: self, size }
472 }
473
474 pub fn direction_to(self, other: Self) -> Option<DirectionVec<C>>
475 where
476 C: PartialOrd + Sub<Output = C>,
477 {
478 let vector = match self
479 .as_ref()
480 .zip2_with(other.as_ref(), |a, b| a.partial_cmp(&b))
481 .transpose()?
482 {
483 CoordPair { y: Ordering::Greater, x: Ordering::Equal } => {
484 DirectionVec {
485 direction: Direction::Up,
486 magnitude: self.y - other.y,
487 }
488 },
489 CoordPair { y: Ordering::Equal, x: Ordering::Greater } => {
490 DirectionVec {
491 direction: Direction::Left,
492 magnitude: self.x - other.x,
493 }
494 },
495 CoordPair { y: Ordering::Less, x: Ordering::Equal } => {
496 DirectionVec {
497 direction: Direction::Down,
498 magnitude: other.y - self.y,
499 }
500 },
501 CoordPair { y: Ordering::Equal, x: Ordering::Less } => {
502 DirectionVec {
503 direction: Direction::Right,
504 magnitude: other.x - self.x,
505 }
506 },
507 _ => None?,
508 };
509 Some(vector)
510 }
511
512 pub fn direction_from(self, other: Self) -> Option<DirectionVec<C>>
513 where
514 C: PartialOrd + Sub<Output = C>,
515 {
516 other.direction_to(self)
517 }
518}
519
520impl<'a, C> CoordPair<&'a C> {
521 pub fn copied(self) -> CoordPair<C>
522 where
523 C: Copy,
524 {
525 self.map(|a| *a)
526 }
527
528 pub fn cloned(self) -> CoordPair<C>
529 where
530 C: Clone,
531 {
532 self.map(C::clone)
533 }
534
535 pub fn checked_add_by_ref(self, other: Self) -> Option<CoordPair<C>>
536 where
537 C: CheckedAdd,
538 {
539 self.zip2_with(other, C::checked_add).transpose()
540 }
541
542 pub fn checked_add_by_ref_to(self, other: &C) -> Option<CoordPair<C>>
543 where
544 C: CheckedAdd,
545 {
546 self.checked_add_by_ref(CoordPair::from_axes(|_| other))
547 }
548
549 pub fn checked_sub_by_ref(self, other: Self) -> Option<CoordPair<C>>
550 where
551 C: CheckedSub,
552 {
553 self.zip2_with(other, C::checked_sub).transpose()
554 }
555
556 pub fn checked_sub_by_ref_except(self, other: &C) -> Option<CoordPair<C>>
557 where
558 C: CheckedSub,
559 {
560 self.checked_sub_by_ref(CoordPair::from_axes(|_| other))
561 }
562
563 pub fn checked_sub_by_ref_from(self, other: &C) -> Option<CoordPair<C>>
564 where
565 C: CheckedSub,
566 {
567 CoordPair::from_axes(|_| other).checked_sub_by_ref(self)
568 }
569
570 pub fn checked_mul_by_ref(self, other: Self) -> Option<CoordPair<C>>
571 where
572 C: CheckedMul,
573 {
574 self.zip2_with(other, C::checked_mul).transpose()
575 }
576
577 pub fn checked_mul_by_ref_scalar(self, other: &C) -> Option<CoordPair<C>>
578 where
579 C: CheckedMul,
580 {
581 self.checked_mul_by_ref(CoordPair::from_axes(|_| other))
582 }
583
584 pub fn checked_div_by_ref(self, other: Self) -> Option<CoordPair<C>>
585 where
586 C: CheckedDiv,
587 {
588 self.zip2_with(other, C::checked_div).transpose()
589 }
590
591 pub fn checked_div_by_ref_by(self, other: &C) -> Option<CoordPair<C>>
592 where
593 C: CheckedDiv,
594 {
595 self.checked_div_by_ref(CoordPair::from_axes(|_| other))
596 }
597
598 pub fn checked_div_by_ref_on(self, other: &C) -> Option<CoordPair<C>>
599 where
600 C: CheckedDiv,
601 {
602 CoordPair::from_axes(|_| other).checked_div_by_ref(self)
603 }
604
605 pub fn checked_rem_by_ref(self, other: Self) -> Option<CoordPair<C>>
606 where
607 C: CheckedRem,
608 {
609 self.zip2_with(other, C::checked_rem).transpose()
610 }
611
612 pub fn checked_rem_by_ref_by(self, other: &C) -> Option<CoordPair<C>>
613 where
614 C: CheckedRem,
615 {
616 self.checked_rem_by_ref(CoordPair::from_axes(|_| other))
617 }
618
619 pub fn checked_rem_by_ref_on(self, other: &C) -> Option<CoordPair<C>>
620 where
621 C: CheckedRem,
622 {
623 CoordPair::from_axes(|_| other).checked_rem_by_ref(self)
624 }
625
626 pub fn saturating_add_by_ref(self, other: Self) -> CoordPair<C>
627 where
628 C: SaturatingAdd,
629 {
630 self.zip2_with(other, C::saturating_add)
631 }
632
633 pub fn saturating_add_by_ref_to(self, other: &C) -> CoordPair<C>
634 where
635 C: SaturatingAdd,
636 {
637 self.saturating_add_by_ref(CoordPair::from_axes(|_| other))
638 }
639
640 pub fn saturating_sub_by_ref(self, other: Self) -> CoordPair<C>
641 where
642 C: SaturatingSub,
643 {
644 self.zip2_with(other, C::saturating_sub)
645 }
646
647 pub fn saturating_sub_by_ref_except(self, other: &C) -> CoordPair<C>
648 where
649 C: SaturatingSub,
650 {
651 self.saturating_sub_by_ref(CoordPair::from_axes(|_| other))
652 }
653
654 pub fn saturating_sub_by_ref_from(self, other: &C) -> CoordPair<C>
655 where
656 C: SaturatingSub,
657 {
658 self.saturating_sub_by_ref(CoordPair::from_axes(|_| other))
659 }
660
661 pub fn saturating_mul_by_ref(self, other: Self) -> CoordPair<C>
662 where
663 C: SaturatingMul,
664 {
665 self.zip2_with(other, C::saturating_mul)
666 }
667
668 pub fn saturating_mul_by_ref_scalar(self, other: &C) -> CoordPair<C>
669 where
670 C: SaturatingMul,
671 {
672 self.saturating_mul_by_ref(CoordPair::from_axes(|_| other))
673 }
674
675 pub fn div_floor_by_ref_by(self, divisor: &C) -> CoordPair<C>
676 where
677 C: Integer,
678 {
679 self.map(|dividend| dividend.div_floor(divisor))
680 }
681
682 pub fn div_ceil_by_ref_by(self, divisor: &C) -> CoordPair<C>
683 where
684 C: Integer,
685 {
686 self.map(|dividend| dividend.div_ceil(divisor))
687 }
688
689 pub fn div_floor_by_ref_on(self, dividend: &C) -> CoordPair<C>
690 where
691 C: Integer,
692 {
693 self.map(|divisor| divisor.div_floor(dividend))
694 }
695
696 pub fn div_ceil_by_ref_on(self, dividend: &C) -> CoordPair<C>
697 where
698 C: Integer,
699 {
700 self.map(|divisor| divisor.div_ceil(dividend))
701 }
702
703 pub fn div_floor_by_ref(self, other: Self) -> CoordPair<C>
704 where
705 C: Integer,
706 {
707 self.zip2_with(other, C::div_floor)
708 }
709
710 pub fn div_ceil_by_ref(self, other: Self) -> CoordPair<C>
711 where
712 C: Integer,
713 {
714 self.zip2_with(other, C::div_ceil)
715 }
716
717 pub fn checked_move_unit_by_ref(
718 self,
719 direction: Direction,
720 ) -> Option<CoordPair<C>>
721 where
722 C: CheckedAdd + CheckedSub + One + Clone,
723 {
724 direction.checked_move_unit_by_ref(self)
725 }
726
727 pub fn saturating_move_unit_by_ref(
728 self,
729 direction: Direction,
730 ) -> CoordPair<C>
731 where
732 C: SaturatingAdd + SaturatingSub + One + Clone,
733 {
734 direction.saturating_move_unit_by_ref(self)
735 }
736
737 pub fn checked_move_by_ref_by(
738 self,
739 vector: DirectionVec<&C>,
740 ) -> Option<CoordPair<C>>
741 where
742 C: CheckedAdd + CheckedSub + Clone,
743 {
744 vector.checked_move_by_ref(self)
745 }
746
747 pub fn saturating_move_by_ref_by(
748 self,
749 vector: DirectionVec<&C>,
750 ) -> CoordPair<C>
751 where
752 C: SaturatingAdd + SaturatingSub + Clone,
753 {
754 vector.saturating_move_by_ref(self)
755 }
756}
757
758impl<'a, C> CoordPair<&'a mut C> {
759 pub fn copied(self) -> CoordPair<C>
760 where
761 C: Copy,
762 {
763 self.map(|a| *a)
764 }
765
766 pub fn cloned(self) -> CoordPair<C>
767 where
768 C: Clone,
769 {
770 self.map(|a| a.clone())
771 }
772
773 pub fn share(self) -> CoordPair<&'a C> {
774 self.map(|a| &*a)
775 }
776}
777
778impl<C> CoordPair<Option<C>> {
779 pub fn transpose(self) -> Option<CoordPair<C>> {
780 Some(CoordPair { y: self.y?, x: self.x? })
781 }
782
783 pub fn from_transposed(transposed: Option<CoordPair<C>>) -> Self {
784 match transposed {
785 Some(pair) => pair.map(Some),
786 None => Self::from_axes(|_| None),
787 }
788 }
789}
790
791impl<C, E> CoordPair<Result<C, E>> {
792 pub fn transpose(self) -> Result<CoordPair<C>, E> {
793 Ok(CoordPair { y: self.y?, x: self.x? })
794 }
795
796 pub fn from_transposed(transposed: Result<CoordPair<C>, E>) -> Self
797 where
798 E: Clone,
799 {
800 match transposed {
801 Ok(pair) => pair.map(Ok),
802 Err(error) => Self { y: Err(error.clone()), x: Err(error) },
803 }
804 }
805}
806
807impl<C> Index<Axis> for CoordPair<C> {
808 type Output = C;
809
810 fn index(&self, index: Axis) -> &Self::Output {
811 match index {
812 Axis::Y => &self.y,
813 Axis::X => &self.x,
814 }
815 }
816}
817
818impl<C> IndexMut<Axis> for CoordPair<C> {
819 fn index_mut(&mut self, index: Axis) -> &mut Self::Output {
820 match index {
821 Axis::Y => &mut self.y,
822 Axis::X => &mut self.x,
823 }
824 }
825}
826
827impl<C> fmt::Display for CoordPair<C>
828where
829 C: fmt::Display,
830{
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 write!(f, "(x={}, y={})", self.x, self.y)
833 }
834}
835
836impl<C> Add for CoordPair<C>
837where
838 C: Add,
839{
840 type Output = CoordPair<C::Output>;
841
842 fn add(self, rhs: Self) -> Self::Output {
843 self.zip2_with(rhs, |a, b| a + b)
844 }
845}
846
847impl<C> Add<C> for CoordPair<C>
848where
849 C: Add + Clone,
850{
851 type Output = CoordPair<C::Output>;
852
853 fn add(self, rhs: C) -> Self::Output {
854 CoordPair { y: self.y + rhs.clone(), x: self.x + rhs }
855 }
856}
857
858impl<C> AddAssign for CoordPair<C>
859where
860 C: AddAssign,
861{
862 fn add_assign(&mut self, rhs: Self) {
863 self.as_mut().zip2_with(rhs, |a, b| *a += b);
864 }
865}
866
867impl<C> AddAssign<C> for CoordPair<C>
868where
869 C: AddAssign + Clone,
870{
871 fn add_assign(&mut self, rhs: C) {
872 self.x += rhs.clone();
873 self.y += rhs;
874 }
875}
876
877impl<C> Sub for CoordPair<C>
878where
879 C: Sub,
880{
881 type Output = CoordPair<C::Output>;
882
883 fn sub(self, rhs: Self) -> Self::Output {
884 self.zip2_with(rhs, |a, b| a - b)
885 }
886}
887
888impl<C> Sub<C> for CoordPair<C>
889where
890 C: Sub + Clone,
891{
892 type Output = CoordPair<C::Output>;
893
894 fn sub(self, rhs: C) -> Self::Output {
895 CoordPair { y: self.y - rhs.clone(), x: self.x - rhs }
896 }
897}
898
899impl<C> SubAssign for CoordPair<C>
900where
901 C: SubAssign,
902{
903 fn sub_assign(&mut self, rhs: Self) {
904 self.as_mut().zip2_with(rhs, |a, b| *a -= b);
905 }
906}
907
908impl<C> SubAssign<C> for CoordPair<C>
909where
910 C: SubAssign + Clone,
911{
912 fn sub_assign(&mut self, rhs: C) {
913 self.x -= rhs.clone();
914 self.y -= rhs;
915 }
916}
917
918impl<C> Mul for CoordPair<C>
919where
920 C: Mul,
921{
922 type Output = CoordPair<C::Output>;
923
924 fn mul(self, rhs: Self) -> Self::Output {
925 self.zip2_with(rhs, |a, b| a * b)
926 }
927}
928
929impl<C> Mul<C> for CoordPair<C>
930where
931 C: Mul + Clone,
932{
933 type Output = CoordPair<C::Output>;
934
935 fn mul(self, rhs: C) -> Self::Output {
936 CoordPair { y: self.y * rhs.clone(), x: self.x * rhs }
937 }
938}
939
940impl<C> MulAssign for CoordPair<C>
941where
942 C: MulAssign,
943{
944 fn mul_assign(&mut self, rhs: Self) {
945 self.as_mut().zip2_with(rhs, |a, b| *a *= b);
946 }
947}
948
949impl<C> MulAssign<C> for CoordPair<C>
950where
951 C: MulAssign + Clone,
952{
953 fn mul_assign(&mut self, rhs: C) {
954 self.x *= rhs.clone();
955 self.y *= rhs;
956 }
957}
958
959impl<C> Div for CoordPair<C>
960where
961 C: Div,
962{
963 type Output = CoordPair<C::Output>;
964
965 fn div(self, rhs: Self) -> Self::Output {
966 self.zip2_with(rhs, |a, b| a / b)
967 }
968}
969
970impl<C> Div<C> for CoordPair<C>
971where
972 C: Div + Clone,
973{
974 type Output = CoordPair<C::Output>;
975
976 fn div(self, rhs: C) -> Self::Output {
977 CoordPair { y: self.y / rhs.clone(), x: self.x / rhs }
978 }
979}
980
981impl<C> DivAssign for CoordPair<C>
982where
983 C: DivAssign,
984{
985 fn div_assign(&mut self, rhs: Self) {
986 self.as_mut().zip2_with(rhs, |a, b| *a /= b);
987 }
988}
989
990impl<C> DivAssign<C> for CoordPair<C>
991where
992 C: DivAssign + Clone,
993{
994 fn div_assign(&mut self, rhs: C) {
995 self.x /= rhs.clone();
996 self.y /= rhs;
997 }
998}
999
1000impl<C> Rem for CoordPair<C>
1001where
1002 C: Rem,
1003{
1004 type Output = CoordPair<C::Output>;
1005
1006 fn rem(self, rhs: Self) -> Self::Output {
1007 self.zip2_with(rhs, |a, b| a % b)
1008 }
1009}
1010
1011impl<C> Rem<C> for CoordPair<C>
1012where
1013 C: Rem + Clone,
1014{
1015 type Output = CoordPair<C::Output>;
1016
1017 fn rem(self, rhs: C) -> Self::Output {
1018 CoordPair { y: self.y % rhs.clone(), x: self.x % rhs }
1019 }
1020}
1021
1022impl<C> RemAssign for CoordPair<C>
1023where
1024 C: RemAssign,
1025{
1026 fn rem_assign(&mut self, rhs: Self) {
1027 self.as_mut().zip2_with(rhs, |a, b| *a %= b);
1028 }
1029}
1030
1031impl<C> RemAssign<C> for CoordPair<C>
1032where
1033 C: RemAssign + Clone,
1034{
1035 fn rem_assign(&mut self, rhs: C) {
1036 self.x %= rhs.clone();
1037 self.y %= rhs;
1038 }
1039}
1040
1041impl<C> Zero for CoordPair<C>
1042where
1043 C: Zero + PartialEq,
1044{
1045 fn zero() -> Self {
1046 Self::from_axes(|_| C::zero())
1047 }
1048
1049 fn is_zero(&self) -> bool {
1050 *self == Self::zero()
1051 }
1052}
1053
1054impl<C> One for CoordPair<C>
1055where
1056 C: One,
1057{
1058 fn one() -> Self {
1059 Self::from_axes(|_| C::one())
1060 }
1061}
1062
1063impl<C> Neg for CoordPair<C>
1064where
1065 C: Neg,
1066{
1067 type Output = CoordPair<C::Output>;
1068
1069 fn neg(self) -> Self::Output {
1070 self.map(|a| -a)
1071 }
1072}
1073
1074impl<C> CheckedAdd for CoordPair<C>
1075where
1076 C: CheckedAdd,
1077{
1078 fn checked_add(&self, other: &Self) -> Option<Self> {
1079 self.as_ref().checked_add_by_ref(other.as_ref())
1080 }
1081}
1082
1083impl<C> CheckedSub for CoordPair<C>
1084where
1085 C: CheckedSub,
1086{
1087 fn checked_sub(&self, other: &Self) -> Option<Self> {
1088 self.as_ref().checked_sub_by_ref(other.as_ref())
1089 }
1090}
1091
1092impl<C> CheckedMul for CoordPair<C>
1093where
1094 C: CheckedMul,
1095{
1096 fn checked_mul(&self, other: &Self) -> Option<Self> {
1097 self.as_ref().checked_mul_by_ref(other.as_ref())
1098 }
1099}
1100
1101impl<C> CheckedDiv for CoordPair<C>
1102where
1103 C: CheckedDiv,
1104{
1105 fn checked_div(&self, other: &Self) -> Option<Self> {
1106 self.as_ref().checked_div_by_ref(other.as_ref())
1107 }
1108}
1109
1110impl<C> CheckedRem for CoordPair<C>
1111where
1112 C: CheckedRem,
1113{
1114 fn checked_rem(&self, other: &Self) -> Option<Self> {
1115 self.as_ref().checked_rem_by_ref(other.as_ref())
1116 }
1117}
1118
1119impl<C> SaturatingAdd for CoordPair<C>
1120where
1121 C: SaturatingAdd,
1122{
1123 fn saturating_add(&self, other: &Self) -> Self {
1124 self.as_ref().saturating_add_by_ref(other.as_ref())
1125 }
1126}
1127
1128impl<C> SaturatingSub for CoordPair<C>
1129where
1130 C: SaturatingSub,
1131{
1132 fn saturating_sub(&self, other: &Self) -> Self {
1133 self.as_ref().saturating_sub_by_ref(other.as_ref())
1134 }
1135}
1136
1137impl<C> SaturatingMul for CoordPair<C>
1138where
1139 C: SaturatingMul,
1140{
1141 fn saturating_mul(&self, other: &Self) -> Self {
1142 self.as_ref().saturating_mul_by_ref(other.as_ref())
1143 }
1144}
1145
1146pub type CoordPairBounds<T> = CoordPair<(Bound<T>, Bound<T>)>;
1147
1148#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1149pub struct CoordRange<Ry, Rx> {
1150 pub y: Ry,
1151 pub x: Rx,
1152}
1153
1154impl<Ry, Rx> CoordRange<Ry, Rx> {
1155 pub fn with_order(first: Ry, second: Rx) -> Self {
1156 Self { y: first, x: second }
1157 }
1158
1159 pub fn as_bounds<T>(&self) -> CoordPairBounds<&T>
1160 where
1161 Ry: RangeBounds<T>,
1162 Rx: RangeBounds<T>,
1163 {
1164 CoordPair {
1165 y: (self.y.start_bound(), self.y.end_bound()),
1166 x: (self.x.start_bound(), self.x.end_bound()),
1167 }
1168 }
1169
1170 pub fn to_bounds<T>(&self) -> CoordPairBounds<T>
1171 where
1172 Ry: RangeBounds<T>,
1173 Rx: RangeBounds<T>,
1174 T: Clone,
1175 {
1176 CoordPair {
1177 y: (self.y.start_bound().cloned(), self.y.end_bound().cloned()),
1178 x: (self.x.start_bound().cloned(), self.x.end_bound().cloned()),
1179 }
1180 }
1181}
1182
1183impl<'a, Ry, Rx, T> From<&'a CoordRange<Ry, Rx>> for CoordPairBounds<&'a T>
1184where
1185 Ry: RangeBounds<T>,
1186 Rx: RangeBounds<T>,
1187{
1188 fn from(ranges: &'a CoordRange<Ry, Rx>) -> Self {
1189 ranges.as_bounds()
1190 }
1191}