1use std::{
2 fmt::{Debug, Display},
3 marker::PhantomData,
4 ops::{Add, AddAssign, Sub, SubAssign},
5};
6use text::Point;
7
8#[repr(transparent)]
9pub struct TypedOffset<T> {
10 pub value: usize,
11 _marker: PhantomData<T>,
12}
13
14#[repr(transparent)]
15pub struct TypedPoint<T> {
16 pub value: Point,
17 _marker: PhantomData<T>,
18}
19
20#[repr(transparent)]
21pub struct TypedRow<T> {
22 pub value: u32,
23 _marker: PhantomData<T>,
24}
25
26impl<T> TypedOffset<T> {
27 pub fn new(offset: usize) -> Self {
28 Self {
29 value: offset,
30 _marker: PhantomData,
31 }
32 }
33
34 pub fn saturating_sub(self, n: TypedOffset<T>) -> Self {
35 Self {
36 value: self.value.saturating_sub(n.value),
37 _marker: PhantomData,
38 }
39 }
40
41 pub fn zero() -> Self {
42 Self::new(0)
43 }
44
45 pub fn is_zero(&self) -> bool {
46 self.value == 0
47 }
48}
49
50impl<T> TypedPoint<T> {
51 pub fn new(row: u32, column: u32) -> Self {
52 Self {
53 value: Point::new(row, column),
54 _marker: PhantomData,
55 }
56 }
57
58 pub fn wrap(point: Point) -> Self {
59 Self {
60 value: point,
61 _marker: PhantomData,
62 }
63 }
64
65 pub fn row(&self) -> u32 {
66 self.value.row
67 }
68
69 pub fn column(&self) -> u32 {
70 self.value.column
71 }
72
73 pub fn zero() -> Self {
74 Self::wrap(Point::zero())
75 }
76
77 pub fn is_zero(&self) -> bool {
78 self.value.is_zero()
79 }
80}
81
82impl<T> TypedRow<T> {
83 pub fn new(row: u32) -> Self {
84 Self {
85 value: row,
86 _marker: PhantomData,
87 }
88 }
89}
90
91impl<T> Copy for TypedOffset<T> {}
92impl<T> Copy for TypedPoint<T> {}
93impl<T> Copy for TypedRow<T> {}
94
95impl<T> Clone for TypedOffset<T> {
96 fn clone(&self) -> Self {
97 *self
98 }
99}
100impl<T> Clone for TypedPoint<T> {
101 fn clone(&self) -> Self {
102 *self
103 }
104}
105impl<T> Clone for TypedRow<T> {
106 fn clone(&self) -> Self {
107 *self
108 }
109}
110
111impl<T> Default for TypedOffset<T> {
112 fn default() -> Self {
113 Self::new(0)
114 }
115}
116impl<T> Default for TypedPoint<T> {
117 fn default() -> Self {
118 Self::wrap(Point::default())
119 }
120}
121impl<T> Default for TypedRow<T> {
122 fn default() -> Self {
123 Self::new(0)
124 }
125}
126
127impl<T> PartialOrd for TypedOffset<T> {
128 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
129 Some(self.cmp(other))
130 }
131}
132impl<T> PartialOrd for TypedPoint<T> {
133 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
134 Some(self.cmp(other))
135 }
136}
137impl<T> PartialOrd for TypedRow<T> {
138 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
139 Some(self.cmp(other))
140 }
141}
142
143impl<T> Ord for TypedOffset<T> {
144 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
145 self.value.cmp(&other.value)
146 }
147}
148impl<T> Ord for TypedPoint<T> {
149 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
150 self.value.cmp(&other.value)
151 }
152}
153impl<T> Ord for TypedRow<T> {
154 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
155 self.value.cmp(&other.value)
156 }
157}
158
159impl<T> PartialEq for TypedOffset<T> {
160 fn eq(&self, other: &Self) -> bool {
161 self.value == other.value
162 }
163}
164impl<T> PartialEq for TypedPoint<T> {
165 fn eq(&self, other: &Self) -> bool {
166 self.value == other.value
167 }
168}
169impl<T> PartialEq for TypedRow<T> {
170 fn eq(&self, other: &Self) -> bool {
171 self.value == other.value
172 }
173}
174
175impl<T> Eq for TypedOffset<T> {}
176impl<T> Eq for TypedPoint<T> {}
177impl<T> Eq for TypedRow<T> {}
178
179impl<T> Debug for TypedOffset<T> {
180 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181 write!(f, "{}Offset({})", type_name::<T>(), self.value)
182 }
183}
184impl<T> Debug for TypedPoint<T> {
185 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
186 write!(
187 f,
188 "{}Point({}, {})",
189 type_name::<T>(),
190 self.value.row,
191 self.value.column
192 )
193 }
194}
195impl<T> Debug for TypedRow<T> {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 write!(f, "{}Row({})", type_name::<T>(), self.value)
198 }
199}
200
201impl<T> Display for TypedOffset<T> {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 Display::fmt(&self.value, f)
204 }
205}
206impl<T> Display for TypedRow<T> {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 Display::fmt(&self.value, f)
209 }
210}
211
212fn type_name<T>() -> &'static str {
213 std::any::type_name::<T>().split("::").last().unwrap()
214}
215
216impl<T> Add<TypedOffset<T>> for TypedOffset<T> {
217 type Output = Self;
218
219 fn add(self, other: Self) -> Self {
220 TypedOffset::new(self.value + other.value)
221 }
222}
223impl<T> Add<TypedPoint<T>> for TypedPoint<T> {
224 type Output = Self;
225
226 fn add(self, other: Self) -> Self {
227 TypedPoint::wrap(self.value + other.value)
228 }
229}
230
231impl<T> Sub<TypedOffset<T>> for TypedOffset<T> {
232 type Output = Self;
233 fn sub(self, other: Self) -> Self {
234 TypedOffset::new(self.value - other.value)
235 }
236}
237impl<T> Sub<TypedPoint<T>> for TypedPoint<T> {
238 type Output = Self;
239 fn sub(self, other: Self) -> Self {
240 TypedPoint::wrap(self.value - other.value)
241 }
242}
243
244impl<T> AddAssign<TypedOffset<T>> for TypedOffset<T> {
245 fn add_assign(&mut self, other: Self) {
246 self.value += other.value;
247 }
248}
249impl<T> AddAssign<TypedPoint<T>> for TypedPoint<T> {
250 fn add_assign(&mut self, other: Self) {
251 self.value += other.value;
252 }
253}
254
255impl<T> SubAssign<Self> for TypedOffset<T> {
256 fn sub_assign(&mut self, other: Self) {
257 self.value -= other.value;
258 }
259}
260impl<T> SubAssign<Self> for TypedRow<T> {
261 fn sub_assign(&mut self, other: Self) {
262 self.value -= other.value;
263 }
264}