nil_core/continent/
index.rs1use crate::continent::{ContinentSize, Coord};
5use crate::error::{Error, Result};
6use derive_more::{Deref, Display, From, Into};
7use nil_num::BigIntUsize;
8use std::ops::{Div, Rem};
9
10#[derive(
11 Clone, Copy, Debug, Deref, Display, From, Into, PartialEq, Eq, PartialOrd, Ord, Hash, BigIntUsize,
12)]
13pub struct ContinentIndex(usize);
14
15impl ContinentIndex {
16 #[inline]
17 pub const fn new(index: usize) -> Self {
18 Self(index)
19 }
20
21 #[inline]
22 pub const fn as_usize(self) -> usize {
23 self.0
24 }
25
26 pub fn from_coord(coord: Coord, size: ContinentSize) -> Self {
27 let size = usize::from(size);
28 let x = usize::from(coord.x());
29 let y = usize::from(coord.y());
30 let index = (y * size) + x;
31
32 debug_assert!(x < size);
33 debug_assert!(y < size);
34
35 ContinentIndex(index)
36 }
37
38 pub fn to_coord(self, size: ContinentSize) -> Result<Coord> {
39 let x = self % size;
40 let y = self / size;
41
42 debug_assert!(x < size);
43 debug_assert!(y < size);
44
45 Ok(Coord::new(
46 u8::try_from(x).map_err(|_| Error::IndexOutOfBounds(self))?,
47 u8::try_from(y).map_err(|_| Error::IndexOutOfBounds(self))?,
48 ))
49 }
50}
51
52impl Div<usize> for ContinentIndex {
53 type Output = usize;
54
55 fn div(self, rhs: usize) -> Self::Output {
56 self.0 / rhs
57 }
58}
59
60impl Div<ContinentSize> for ContinentIndex {
61 type Output = usize;
62
63 fn div(self, rhs: ContinentSize) -> Self::Output {
64 self.0 / usize::from(rhs)
65 }
66}
67
68impl Rem<usize> for ContinentIndex {
69 type Output = usize;
70
71 fn rem(self, rhs: usize) -> Self::Output {
72 self.0 % rhs
73 }
74}
75
76impl Rem<ContinentSize> for ContinentIndex {
77 type Output = usize;
78
79 fn rem(self, rhs: ContinentSize) -> Self::Output {
80 self.0 % usize::from(rhs)
81 }
82}
83
84pub trait ContinentKey {
85 fn into_index(self, size: ContinentSize) -> ContinentIndex;
86
87 fn into_coord(self, size: ContinentSize) -> Result<Coord>
88 where
89 Self: Sized,
90 {
91 self.into_index(size).to_coord(size)
92 }
93}
94
95impl ContinentKey for ContinentIndex {
96 fn into_index(self, _: ContinentSize) -> ContinentIndex {
97 self
98 }
99}
100
101impl ContinentKey for Coord {
102 fn into_index(self, size: ContinentSize) -> ContinentIndex {
103 ContinentIndex::from_coord(self, size)
104 }
105
106 fn into_coord(self, _: ContinentSize) -> Result<Coord>
107 where
108 Self: Sized,
109 {
110 Ok(self)
111 }
112}
113
114impl ContinentKey for usize {
115 fn into_index(self, _: ContinentSize) -> ContinentIndex {
116 ContinentIndex::new(self)
117 }
118}