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, Order},
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 pub fn diagonal_direction_to(
520 self,
521 other: Self,
522 ) -> CoordPair<Option<DirectionVec<C>>>
523 where
524 C: PartialOrd + Sub<Output = C>,
525 {
526 self.zip2_with_axes(other, |a, b, axis| {
527 Some(match a.partial_cmp(&b)? {
528 Ordering::Less => DirectionVec {
529 direction: Direction::new(axis, Order::Forwards),
530 magnitude: b - a,
531 },
532 Ordering::Greater => DirectionVec {
533 direction: Direction::new(axis, Order::Backwards),
534 magnitude: a - b,
535 },
536 Ordering::Equal => None?,
537 })
538 })
539 }
540
541 pub fn diagonal_direction_from(
542 self,
543 other: Self,
544 ) -> CoordPair<Option<DirectionVec<C>>>
545 where
546 C: PartialOrd + Sub<Output = C>,
547 {
548 other.diagonal_direction_to(self)
549 }
550
551 pub fn max_axis(&self) -> Axis
552 where
553 C: Ord,
554 {
555 self.max_axis_by_key(|v| v)
556 }
557
558 pub fn min_axis(&self) -> Axis
559 where
560 C: Ord,
561 {
562 self.min_axis_by_key(|v| v)
563 }
564
565 pub fn max_axis_by<'a, F>(&'a self, compare: F) -> Axis
566 where
567 F: FnOnce(&'a C, &'a C) -> Ordering,
568 {
569 if compare(&self.y, &self.x) >= Ordering::Equal {
570 Axis::Y
571 } else {
572 Axis::X
573 }
574 }
575
576 pub fn min_axis_by<'a, F>(&'a self, compare: F) -> Axis
577 where
578 F: FnOnce(&'a C, &'a C) -> Ordering,
579 {
580 if compare(&self.y, &self.x) <= Ordering::Equal {
581 Axis::Y
582 } else {
583 Axis::X
584 }
585 }
586
587 pub fn max_axis_by_key<'a, F, D>(&'a self, mut mapper: F) -> Axis
588 where
589 F: FnMut(&'a C) -> D,
590 D: Ord,
591 {
592 self.max_axis_by(|a, b| mapper(a).cmp(&mapper(b)))
593 }
594
595 pub fn min_axis_by_key<'a, F, D>(&'a self, mut mapper: F) -> Axis
596 where
597 F: FnMut(&'a C) -> D,
598 D: Ord,
599 {
600 self.min_axis_by(|a, b| mapper(a).cmp(&mapper(b)))
601 }
602
603 pub fn max_with_axis_by<F>(self, compare: F) -> (Axis, C)
604 where
605 F: for<'a> FnOnce(&'a C, &'a C) -> Ordering,
606 {
607 let axis = self.max_axis_by(compare);
608 (axis, self.extract(axis))
609 }
610
611 pub fn min_with_axis_by<F>(self, compare: F) -> (Axis, C)
612 where
613 F: for<'a> FnOnce(&'a C, &'a C) -> Ordering,
614 {
615 let axis = self.min_axis_by(compare);
616 (axis, self.extract(axis))
617 }
618
619 pub fn max_with_axis_by_key<F, D>(self, mut mapper: F) -> (Axis, C)
620 where
621 F: for<'a> FnMut(&'a C) -> D,
622 D: Ord,
623 {
624 self.max_with_axis_by(|a, b| mapper(a).cmp(&mapper(b)))
625 }
626
627 pub fn min_with_axis_by_key<F, D>(self, mut mapper: F) -> (Axis, C)
628 where
629 F: for<'a> FnMut(&'a C) -> D,
630 D: Ord,
631 {
632 self.min_with_axis_by(|a, b| mapper(a).cmp(&mapper(b)))
633 }
634
635 pub fn max_with_axis(self) -> (Axis, C)
636 where
637 C: Ord,
638 {
639 let axis = self.max_axis();
640 (axis, self.extract(axis))
641 }
642
643 pub fn min_with_axis(self) -> (Axis, C)
644 where
645 C: Ord,
646 {
647 let axis = self.min_axis();
648 (axis, self.extract(axis))
649 }
650}
651
652impl<'a, C> CoordPair<&'a C> {
653 pub fn copied(self) -> CoordPair<C>
654 where
655 C: Copy,
656 {
657 self.map(|a| *a)
658 }
659
660 pub fn cloned(self) -> CoordPair<C>
661 where
662 C: Clone,
663 {
664 self.map(C::clone)
665 }
666
667 pub fn checked_add_by_ref(self, other: Self) -> Option<CoordPair<C>>
668 where
669 C: CheckedAdd,
670 {
671 self.zip2_with(other, C::checked_add).transpose()
672 }
673
674 pub fn checked_add_by_ref_to(self, other: &C) -> Option<CoordPair<C>>
675 where
676 C: CheckedAdd,
677 {
678 self.checked_add_by_ref(CoordPair::from_axes(|_| other))
679 }
680
681 pub fn checked_sub_by_ref(self, other: Self) -> Option<CoordPair<C>>
682 where
683 C: CheckedSub,
684 {
685 self.zip2_with(other, C::checked_sub).transpose()
686 }
687
688 pub fn checked_sub_by_ref_except(self, other: &C) -> Option<CoordPair<C>>
689 where
690 C: CheckedSub,
691 {
692 self.checked_sub_by_ref(CoordPair::from_axes(|_| other))
693 }
694
695 pub fn checked_sub_by_ref_from(self, other: &C) -> Option<CoordPair<C>>
696 where
697 C: CheckedSub,
698 {
699 CoordPair::from_axes(|_| other).checked_sub_by_ref(self)
700 }
701
702 pub fn checked_mul_by_ref(self, other: Self) -> Option<CoordPair<C>>
703 where
704 C: CheckedMul,
705 {
706 self.zip2_with(other, C::checked_mul).transpose()
707 }
708
709 pub fn checked_mul_by_ref_scalar(self, other: &C) -> Option<CoordPair<C>>
710 where
711 C: CheckedMul,
712 {
713 self.checked_mul_by_ref(CoordPair::from_axes(|_| other))
714 }
715
716 pub fn checked_div_by_ref(self, other: Self) -> Option<CoordPair<C>>
717 where
718 C: CheckedDiv,
719 {
720 self.zip2_with(other, C::checked_div).transpose()
721 }
722
723 pub fn checked_div_by_ref_by(self, other: &C) -> Option<CoordPair<C>>
724 where
725 C: CheckedDiv,
726 {
727 self.checked_div_by_ref(CoordPair::from_axes(|_| other))
728 }
729
730 pub fn checked_div_by_ref_on(self, other: &C) -> Option<CoordPair<C>>
731 where
732 C: CheckedDiv,
733 {
734 CoordPair::from_axes(|_| other).checked_div_by_ref(self)
735 }
736
737 pub fn checked_rem_by_ref(self, other: Self) -> Option<CoordPair<C>>
738 where
739 C: CheckedRem,
740 {
741 self.zip2_with(other, C::checked_rem).transpose()
742 }
743
744 pub fn checked_rem_by_ref_by(self, other: &C) -> Option<CoordPair<C>>
745 where
746 C: CheckedRem,
747 {
748 self.checked_rem_by_ref(CoordPair::from_axes(|_| other))
749 }
750
751 pub fn checked_rem_by_ref_on(self, other: &C) -> Option<CoordPair<C>>
752 where
753 C: CheckedRem,
754 {
755 CoordPair::from_axes(|_| other).checked_rem_by_ref(self)
756 }
757
758 pub fn saturating_add_by_ref(self, other: Self) -> CoordPair<C>
759 where
760 C: SaturatingAdd,
761 {
762 self.zip2_with(other, C::saturating_add)
763 }
764
765 pub fn saturating_add_by_ref_to(self, other: &C) -> CoordPair<C>
766 where
767 C: SaturatingAdd,
768 {
769 self.saturating_add_by_ref(CoordPair::from_axes(|_| other))
770 }
771
772 pub fn saturating_sub_by_ref(self, other: Self) -> CoordPair<C>
773 where
774 C: SaturatingSub,
775 {
776 self.zip2_with(other, C::saturating_sub)
777 }
778
779 pub fn saturating_sub_by_ref_except(self, other: &C) -> CoordPair<C>
780 where
781 C: SaturatingSub,
782 {
783 self.saturating_sub_by_ref(CoordPair::from_axes(|_| other))
784 }
785
786 pub fn saturating_sub_by_ref_from(self, other: &C) -> CoordPair<C>
787 where
788 C: SaturatingSub,
789 {
790 self.saturating_sub_by_ref(CoordPair::from_axes(|_| other))
791 }
792
793 pub fn saturating_mul_by_ref(self, other: Self) -> CoordPair<C>
794 where
795 C: SaturatingMul,
796 {
797 self.zip2_with(other, C::saturating_mul)
798 }
799
800 pub fn saturating_mul_by_ref_scalar(self, other: &C) -> CoordPair<C>
801 where
802 C: SaturatingMul,
803 {
804 self.saturating_mul_by_ref(CoordPair::from_axes(|_| other))
805 }
806
807 pub fn div_floor_by_ref_by(self, divisor: &C) -> CoordPair<C>
808 where
809 C: Integer,
810 {
811 self.map(|dividend| dividend.div_floor(divisor))
812 }
813
814 pub fn div_ceil_by_ref_by(self, divisor: &C) -> CoordPair<C>
815 where
816 C: Integer,
817 {
818 self.map(|dividend| dividend.div_ceil(divisor))
819 }
820
821 pub fn div_floor_by_ref_on(self, dividend: &C) -> CoordPair<C>
822 where
823 C: Integer,
824 {
825 self.map(|divisor| divisor.div_floor(dividend))
826 }
827
828 pub fn div_ceil_by_ref_on(self, dividend: &C) -> CoordPair<C>
829 where
830 C: Integer,
831 {
832 self.map(|divisor| divisor.div_ceil(dividend))
833 }
834
835 pub fn div_floor_by_ref(self, other: Self) -> CoordPair<C>
836 where
837 C: Integer,
838 {
839 self.zip2_with(other, C::div_floor)
840 }
841
842 pub fn div_ceil_by_ref(self, other: Self) -> CoordPair<C>
843 where
844 C: Integer,
845 {
846 self.zip2_with(other, C::div_ceil)
847 }
848
849 pub fn checked_move_unit_by_ref(
850 self,
851 direction: Direction,
852 ) -> Option<CoordPair<C>>
853 where
854 C: CheckedAdd + CheckedSub + One + Clone,
855 {
856 direction.checked_move_unit_by_ref(self)
857 }
858
859 pub fn saturating_move_unit_by_ref(
860 self,
861 direction: Direction,
862 ) -> CoordPair<C>
863 where
864 C: SaturatingAdd + SaturatingSub + One + Clone,
865 {
866 direction.saturating_move_unit_by_ref(self)
867 }
868
869 pub fn checked_move_by_ref_by(
870 self,
871 vector: DirectionVec<&C>,
872 ) -> Option<CoordPair<C>>
873 where
874 C: CheckedAdd + CheckedSub + Clone,
875 {
876 vector.checked_move_by_ref(self)
877 }
878
879 pub fn saturating_move_by_ref_by(
880 self,
881 vector: DirectionVec<&C>,
882 ) -> CoordPair<C>
883 where
884 C: SaturatingAdd + SaturatingSub + Clone,
885 {
886 vector.saturating_move_by_ref(self)
887 }
888}
889
890impl<'a, C> CoordPair<&'a mut C> {
891 pub fn copied(self) -> CoordPair<C>
892 where
893 C: Copy,
894 {
895 self.map(|a| *a)
896 }
897
898 pub fn cloned(self) -> CoordPair<C>
899 where
900 C: Clone,
901 {
902 self.map(|a| a.clone())
903 }
904
905 pub fn share(self) -> CoordPair<&'a C> {
906 self.map(|a| &*a)
907 }
908}
909
910impl<C> CoordPair<Option<C>> {
911 pub fn transpose(self) -> Option<CoordPair<C>> {
912 Some(CoordPair { y: self.y?, x: self.x? })
913 }
914
915 pub fn from_transposed(transposed: Option<CoordPair<C>>) -> Self {
916 match transposed {
917 Some(pair) => pair.map(Some),
918 None => Self::from_axes(|_| None),
919 }
920 }
921}
922
923impl<C, E> CoordPair<Result<C, E>> {
924 pub fn transpose(self) -> Result<CoordPair<C>, E> {
925 Ok(CoordPair { y: self.y?, x: self.x? })
926 }
927
928 pub fn from_transposed(transposed: Result<CoordPair<C>, E>) -> Self
929 where
930 E: Clone,
931 {
932 match transposed {
933 Ok(pair) => pair.map(Ok),
934 Err(error) => Self { y: Err(error.clone()), x: Err(error) },
935 }
936 }
937}
938
939impl<C> Index<Axis> for CoordPair<C> {
940 type Output = C;
941
942 fn index(&self, index: Axis) -> &Self::Output {
943 match index {
944 Axis::Y => &self.y,
945 Axis::X => &self.x,
946 }
947 }
948}
949
950impl<C> IndexMut<Axis> for CoordPair<C> {
951 fn index_mut(&mut self, index: Axis) -> &mut Self::Output {
952 match index {
953 Axis::Y => &mut self.y,
954 Axis::X => &mut self.x,
955 }
956 }
957}
958
959impl<C> fmt::Display for CoordPair<C>
960where
961 C: fmt::Display,
962{
963 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
964 write!(f, "(x={}, y={})", self.x, self.y)
965 }
966}
967
968impl<C> Add for CoordPair<C>
969where
970 C: Add,
971{
972 type Output = CoordPair<C::Output>;
973
974 fn add(self, rhs: Self) -> Self::Output {
975 self.zip2_with(rhs, |a, b| a + b)
976 }
977}
978
979impl<C> Add<C> for CoordPair<C>
980where
981 C: Add + Clone,
982{
983 type Output = CoordPair<C::Output>;
984
985 fn add(self, rhs: C) -> Self::Output {
986 CoordPair { y: self.y + rhs.clone(), x: self.x + rhs }
987 }
988}
989
990impl<C> AddAssign for CoordPair<C>
991where
992 C: AddAssign,
993{
994 fn add_assign(&mut self, rhs: Self) {
995 self.as_mut().zip2_with(rhs, |a, b| *a += b);
996 }
997}
998
999impl<C> AddAssign<C> for CoordPair<C>
1000where
1001 C: AddAssign + Clone,
1002{
1003 fn add_assign(&mut self, rhs: C) {
1004 self.x += rhs.clone();
1005 self.y += rhs;
1006 }
1007}
1008
1009impl<C> Sub for CoordPair<C>
1010where
1011 C: Sub,
1012{
1013 type Output = CoordPair<C::Output>;
1014
1015 fn sub(self, rhs: Self) -> Self::Output {
1016 self.zip2_with(rhs, |a, b| a - b)
1017 }
1018}
1019
1020impl<C> Sub<C> for CoordPair<C>
1021where
1022 C: Sub + Clone,
1023{
1024 type Output = CoordPair<C::Output>;
1025
1026 fn sub(self, rhs: C) -> Self::Output {
1027 CoordPair { y: self.y - rhs.clone(), x: self.x - rhs }
1028 }
1029}
1030
1031impl<C> SubAssign for CoordPair<C>
1032where
1033 C: SubAssign,
1034{
1035 fn sub_assign(&mut self, rhs: Self) {
1036 self.as_mut().zip2_with(rhs, |a, b| *a -= b);
1037 }
1038}
1039
1040impl<C> SubAssign<C> for CoordPair<C>
1041where
1042 C: SubAssign + Clone,
1043{
1044 fn sub_assign(&mut self, rhs: C) {
1045 self.x -= rhs.clone();
1046 self.y -= rhs;
1047 }
1048}
1049
1050impl<C> Mul for CoordPair<C>
1051where
1052 C: Mul,
1053{
1054 type Output = CoordPair<C::Output>;
1055
1056 fn mul(self, rhs: Self) -> Self::Output {
1057 self.zip2_with(rhs, |a, b| a * b)
1058 }
1059}
1060
1061impl<C> Mul<C> for CoordPair<C>
1062where
1063 C: Mul + Clone,
1064{
1065 type Output = CoordPair<C::Output>;
1066
1067 fn mul(self, rhs: C) -> Self::Output {
1068 CoordPair { y: self.y * rhs.clone(), x: self.x * rhs }
1069 }
1070}
1071
1072impl<C> MulAssign for CoordPair<C>
1073where
1074 C: MulAssign,
1075{
1076 fn mul_assign(&mut self, rhs: Self) {
1077 self.as_mut().zip2_with(rhs, |a, b| *a *= b);
1078 }
1079}
1080
1081impl<C> MulAssign<C> for CoordPair<C>
1082where
1083 C: MulAssign + Clone,
1084{
1085 fn mul_assign(&mut self, rhs: C) {
1086 self.x *= rhs.clone();
1087 self.y *= rhs;
1088 }
1089}
1090
1091impl<C> Div for CoordPair<C>
1092where
1093 C: Div,
1094{
1095 type Output = CoordPair<C::Output>;
1096
1097 fn div(self, rhs: Self) -> Self::Output {
1098 self.zip2_with(rhs, |a, b| a / b)
1099 }
1100}
1101
1102impl<C> Div<C> for CoordPair<C>
1103where
1104 C: Div + Clone,
1105{
1106 type Output = CoordPair<C::Output>;
1107
1108 fn div(self, rhs: C) -> Self::Output {
1109 CoordPair { y: self.y / rhs.clone(), x: self.x / rhs }
1110 }
1111}
1112
1113impl<C> DivAssign for CoordPair<C>
1114where
1115 C: DivAssign,
1116{
1117 fn div_assign(&mut self, rhs: Self) {
1118 self.as_mut().zip2_with(rhs, |a, b| *a /= b);
1119 }
1120}
1121
1122impl<C> DivAssign<C> for CoordPair<C>
1123where
1124 C: DivAssign + Clone,
1125{
1126 fn div_assign(&mut self, rhs: C) {
1127 self.x /= rhs.clone();
1128 self.y /= rhs;
1129 }
1130}
1131
1132impl<C> Rem for CoordPair<C>
1133where
1134 C: Rem,
1135{
1136 type Output = CoordPair<C::Output>;
1137
1138 fn rem(self, rhs: Self) -> Self::Output {
1139 self.zip2_with(rhs, |a, b| a % b)
1140 }
1141}
1142
1143impl<C> Rem<C> for CoordPair<C>
1144where
1145 C: Rem + Clone,
1146{
1147 type Output = CoordPair<C::Output>;
1148
1149 fn rem(self, rhs: C) -> Self::Output {
1150 CoordPair { y: self.y % rhs.clone(), x: self.x % rhs }
1151 }
1152}
1153
1154impl<C> RemAssign for CoordPair<C>
1155where
1156 C: RemAssign,
1157{
1158 fn rem_assign(&mut self, rhs: Self) {
1159 self.as_mut().zip2_with(rhs, |a, b| *a %= b);
1160 }
1161}
1162
1163impl<C> RemAssign<C> for CoordPair<C>
1164where
1165 C: RemAssign + Clone,
1166{
1167 fn rem_assign(&mut self, rhs: C) {
1168 self.x %= rhs.clone();
1169 self.y %= rhs;
1170 }
1171}
1172
1173impl<C> Zero for CoordPair<C>
1174where
1175 C: Zero + PartialEq,
1176{
1177 fn zero() -> Self {
1178 Self::from_axes(|_| C::zero())
1179 }
1180
1181 fn is_zero(&self) -> bool {
1182 *self == Self::zero()
1183 }
1184}
1185
1186impl<C> One for CoordPair<C>
1187where
1188 C: One,
1189{
1190 fn one() -> Self {
1191 Self::from_axes(|_| C::one())
1192 }
1193}
1194
1195impl<C> Neg for CoordPair<C>
1196where
1197 C: Neg,
1198{
1199 type Output = CoordPair<C::Output>;
1200
1201 fn neg(self) -> Self::Output {
1202 self.map(|a| -a)
1203 }
1204}
1205
1206impl<C> CheckedAdd for CoordPair<C>
1207where
1208 C: CheckedAdd,
1209{
1210 fn checked_add(&self, other: &Self) -> Option<Self> {
1211 self.as_ref().checked_add_by_ref(other.as_ref())
1212 }
1213}
1214
1215impl<C> CheckedSub for CoordPair<C>
1216where
1217 C: CheckedSub,
1218{
1219 fn checked_sub(&self, other: &Self) -> Option<Self> {
1220 self.as_ref().checked_sub_by_ref(other.as_ref())
1221 }
1222}
1223
1224impl<C> CheckedMul for CoordPair<C>
1225where
1226 C: CheckedMul,
1227{
1228 fn checked_mul(&self, other: &Self) -> Option<Self> {
1229 self.as_ref().checked_mul_by_ref(other.as_ref())
1230 }
1231}
1232
1233impl<C> CheckedDiv for CoordPair<C>
1234where
1235 C: CheckedDiv,
1236{
1237 fn checked_div(&self, other: &Self) -> Option<Self> {
1238 self.as_ref().checked_div_by_ref(other.as_ref())
1239 }
1240}
1241
1242impl<C> CheckedRem for CoordPair<C>
1243where
1244 C: CheckedRem,
1245{
1246 fn checked_rem(&self, other: &Self) -> Option<Self> {
1247 self.as_ref().checked_rem_by_ref(other.as_ref())
1248 }
1249}
1250
1251impl<C> SaturatingAdd for CoordPair<C>
1252where
1253 C: SaturatingAdd,
1254{
1255 fn saturating_add(&self, other: &Self) -> Self {
1256 self.as_ref().saturating_add_by_ref(other.as_ref())
1257 }
1258}
1259
1260impl<C> SaturatingSub for CoordPair<C>
1261where
1262 C: SaturatingSub,
1263{
1264 fn saturating_sub(&self, other: &Self) -> Self {
1265 self.as_ref().saturating_sub_by_ref(other.as_ref())
1266 }
1267}
1268
1269impl<C> SaturatingMul for CoordPair<C>
1270where
1271 C: SaturatingMul,
1272{
1273 fn saturating_mul(&self, other: &Self) -> Self {
1274 self.as_ref().saturating_mul_by_ref(other.as_ref())
1275 }
1276}
1277
1278pub type CoordPairBounds<T> = CoordPair<(Bound<T>, Bound<T>)>;
1279
1280#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1281pub struct CoordRange<Ry, Rx> {
1282 pub y: Ry,
1283 pub x: Rx,
1284}
1285
1286impl<Ry, Rx> CoordRange<Ry, Rx> {
1287 pub fn with_order(first: Ry, second: Rx) -> Self {
1288 Self { y: first, x: second }
1289 }
1290
1291 pub fn as_bounds<T>(&self) -> CoordPairBounds<&T>
1292 where
1293 Ry: RangeBounds<T>,
1294 Rx: RangeBounds<T>,
1295 {
1296 CoordPair {
1297 y: (self.y.start_bound(), self.y.end_bound()),
1298 x: (self.x.start_bound(), self.x.end_bound()),
1299 }
1300 }
1301
1302 pub fn to_bounds<T>(&self) -> CoordPairBounds<T>
1303 where
1304 Ry: RangeBounds<T>,
1305 Rx: RangeBounds<T>,
1306 T: Clone,
1307 {
1308 CoordPair {
1309 y: (self.y.start_bound().cloned(), self.y.end_bound().cloned()),
1310 x: (self.x.start_bound().cloned(), self.x.end_bound().cloned()),
1311 }
1312 }
1313}
1314
1315impl<'a, Ry, Rx, T> From<&'a CoordRange<Ry, Rx>> for CoordPairBounds<&'a T>
1316where
1317 Ry: RangeBounds<T>,
1318 Rx: RangeBounds<T>,
1319{
1320 fn from(ranges: &'a CoordRange<Ry, Rx>) -> Self {
1321 ranges.as_bounds()
1322 }
1323}