1pub trait ImageAxisIndex: Copy {
4 fn to_image_axis_index(self) -> Option<u32>;
6 fn clamp_image_axis_index(self, max: u32) -> u32;
9}
10
11impl ImageAxisIndex for u32 {
12 #[inline]
13 fn to_image_axis_index(self) -> Option<u32> {
14 Some(self)
15 }
16 #[inline]
17 fn clamp_image_axis_index(self, max: u32) -> u32 {
18 self.min(max)
19 }
20}
21
22macro_rules! impl_pixel_index {
23 (as_) => {
24 #[inline]
25 fn to_image_axis_index(self) -> Option<u32> {
26 Some(self as u32)
27 }
28 };
29 (try_from) => {
30 #[inline]
31 fn to_image_axis_index(self) -> Option<u32> {
32 u32::try_from(self).ok()
33 }
34 };
35 (unsigned inbound $($t:ty),+) => {
36 $(
37 impl ImageAxisIndex for $t {
38 impl_pixel_index!(as_);
39 #[inline]
40 fn clamp_image_axis_index(self, max: u32) -> u32 {
41 (self as u32).min(max)
42 }
43 }
44 )+
45 };
46 (unsigned $($t:ty),+) => {
47 $(
48 impl ImageAxisIndex for $t {
49 impl_pixel_index!(try_from);
50 #[inline]
51 fn clamp_image_axis_index(self, max: u32) -> u32 {
52 u32::try_from(self).ok().unwrap_or(max)
53 }
54 }
55 )+
56 };
57 (signed inbound $($t:ty),+) => {
58 $(
59 impl ImageAxisIndex for $t {
60 impl_pixel_index!(try_from);
61 #[inline]
62 fn clamp_image_axis_index(self, max: u32) -> u32 {
63 (self.max(0) as u32).min(max)
64 }
65 }
66 )+
67 };
68 (signed $($t:ty),+) => {
69 $(
70 impl ImageAxisIndex for $t {
71 impl_pixel_index!(try_from);
72 #[inline]
73 fn clamp_image_axis_index(self, max: u32) -> u32 {
74 (self.max(0).min(max as $t)) as u32
75 }
76 }
77 )+
78 };
79
80 (float $($t:ty),+) => {
81 $(
82 impl ImageAxisIndex for $t {
83 #[inline]
84 fn to_image_axis_index(self) -> Option<u32> {
85 (self.is_finite() && self.is_sign_positive())
86 .then(|| unsafe { self.to_int_unchecked::<u32>() })
87 }
88 #[inline]
89 fn clamp_image_axis_index(self, max: u32) -> u32 {
90 if self.is_finite() {
91 self.is_sign_positive()
92 .then_some(unsafe { self.to_int_unchecked::<u32>() }.min(max))
93 .unwrap_or(0)
94 } else if !self.is_nan() {
95 self.is_sign_positive().then_some(max).unwrap_or(0)
96 } else {
97 0
98 }
99 }
100 }
101 )+
102 };
103}
104
105#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
106impl_pixel_index!(unsigned inbound u8, u16);
107#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
108impl_pixel_index!(unsigned inbound u8, u16, usize);
109#[cfg(target_pointer_width = "32")]
110impl_pixel_index!(unsigned u128);
111#[cfg(target_pointer_width = "64")]
112impl_pixel_index!(unsigned usize, u128);
113#[cfg(target_pointer_width = "64")]
114impl_pixel_index!(signed inbound i8, i16, i32);
115#[cfg(target_pointer_width = "32")]
116impl_pixel_index!(signed inbound i8, i16, i32, isize);
117#[cfg(target_pointer_width = "64")]
118impl_pixel_index!(signed isize, i64, i128);
119#[cfg(target_pointer_width = "32")]
120impl_pixel_index!(signed i64, i128);
121
122impl_pixel_index!(float f32, f64);
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn pixel_index_u32() {
130 assert_eq!(0u32.to_image_axis_index(), Some(0));
132 assert_eq!(42u32.to_image_axis_index(), Some(42));
133 assert_eq!(u32::MAX.to_image_axis_index(), Some(u32::MAX));
134
135 assert_eq!(0u32.clamp_image_axis_index(100), 0);
137 assert_eq!(50u32.clamp_image_axis_index(100), 50);
138 assert_eq!(100u32.clamp_image_axis_index(100), 100);
139 assert_eq!(150u32.clamp_image_axis_index(100), 100);
140 }
141
142 #[test]
143 fn pixel_index_u8() {
144 assert_eq!(0u8.to_image_axis_index(), Some(0));
146 assert_eq!(42u8.to_image_axis_index(), Some(42));
147 assert_eq!(255u8.to_image_axis_index(), Some(255));
148
149 assert_eq!(0u8.clamp_image_axis_index(100), 0);
151 assert_eq!(50u8.clamp_image_axis_index(100), 50);
152 assert_eq!(100u8.clamp_image_axis_index(100), 100);
153 assert_eq!(200u8.clamp_image_axis_index(100), 100);
154 }
155
156 #[test]
157 fn pixel_index_u16() {
158 assert_eq!(0u16.to_image_axis_index(), Some(0));
160 assert_eq!(42u16.to_image_axis_index(), Some(42));
161 assert_eq!(u16::MAX.to_image_axis_index(), Some(u16::MAX as u32));
162
163 assert_eq!(0u16.clamp_image_axis_index(100), 0);
165 assert_eq!(50u16.clamp_image_axis_index(100), 50);
166 assert_eq!(100u16.clamp_image_axis_index(100), 100);
167 assert_eq!(150u16.clamp_image_axis_index(100), 100);
168 }
169
170 #[test]
171 fn pixel_index_usize() {
172 assert_eq!(0usize.to_image_axis_index(), Some(0));
174 assert_eq!(42usize.to_image_axis_index(), Some(42));
175
176 if std::mem::size_of::<usize>() > std::mem::size_of::<u32>() {
178 assert_eq!((u32::MAX as usize + 1).to_image_axis_index(), None);
179 }
180
181 assert_eq!(0usize.clamp_image_axis_index(100), 0);
183 assert_eq!(50usize.clamp_image_axis_index(100), 50);
184 assert_eq!(100usize.clamp_image_axis_index(100), 100);
185
186 if std::mem::size_of::<usize>() > std::mem::size_of::<u32>() {
188 assert_eq!((u32::MAX as usize + 1).clamp_image_axis_index(100), 100);
189 }
190 }
191
192 #[test]
193 fn pixel_index_u128() {
194 assert_eq!(0u128.to_image_axis_index(), Some(0));
196 assert_eq!(42u128.to_image_axis_index(), Some(42));
197
198 let large_value = u32::MAX as u128 + 1;
200 assert_eq!(large_value.to_image_axis_index(), None);
201
202 assert_eq!(0u128.clamp_image_axis_index(100), 0);
204 assert_eq!(50u128.clamp_image_axis_index(100), 50);
205 assert_eq!(100u128.clamp_image_axis_index(100), 100);
206
207 let large_value = u32::MAX as u128 + 1;
209 assert_eq!(large_value.clamp_image_axis_index(100), 100);
210 }
211
212 #[test]
213 fn pixel_index_i8() {
214 assert_eq!(0i8.to_image_axis_index(), Some(0));
216 assert_eq!(42i8.to_image_axis_index(), Some(42));
217 assert_eq!(127i8.to_image_axis_index(), Some(127));
218 assert_eq!((-1i8).to_image_axis_index(), None);
219 assert_eq!((-128i8).to_image_axis_index(), None);
220
221 assert_eq!(0i8.clamp_image_axis_index(100), 0);
223 assert_eq!(50i8.clamp_image_axis_index(100), 50);
224 assert_eq!(100i8.clamp_image_axis_index(200), 100);
225 assert_eq!(127i8.clamp_image_axis_index(100), 100);
226 assert_eq!((-1i8).clamp_image_axis_index(100), 0);
227 assert_eq!((-128i8).clamp_image_axis_index(100), 0);
228 }
229
230 #[test]
231 fn pixel_index_i16() {
232 assert_eq!(0i16.to_image_axis_index(), Some(0));
234 assert_eq!(42i16.to_image_axis_index(), Some(42));
235 assert_eq!(32767i16.to_image_axis_index(), Some(32767));
236 assert_eq!((-1i16).to_image_axis_index(), None);
237 assert_eq!((-32768i16).to_image_axis_index(), None);
238
239 assert_eq!(0i16.clamp_image_axis_index(100), 0);
241 assert_eq!(50i16.clamp_image_axis_index(100), 50);
242 assert_eq!(100i16.clamp_image_axis_index(200), 100);
243 assert_eq!(150i16.clamp_image_axis_index(100), 100);
244 assert_eq!((-1i16).clamp_image_axis_index(100), 0);
245 assert_eq!((-32768i16).clamp_image_axis_index(100), 0);
246 }
247
248 #[test]
249 fn pixel_index_i32() {
250 assert_eq!(0i32.to_image_axis_index(), Some(0));
252 assert_eq!(42i32.to_image_axis_index(), Some(42));
253 assert_eq!(2147483647i32.to_image_axis_index(), Some(2147483647));
254 assert_eq!((-1i32).to_image_axis_index(), None);
255 assert_eq!((-2147483648i32).to_image_axis_index(), None);
256
257 assert_eq!(0i32.clamp_image_axis_index(100), 0);
259 assert_eq!(50i32.clamp_image_axis_index(100), 50);
260 assert_eq!(100i32.clamp_image_axis_index(200), 100);
261 assert_eq!(150i32.clamp_image_axis_index(100), 100);
262 assert_eq!((-1i32).clamp_image_axis_index(100), 0);
263 assert_eq!((-2147483648i32).clamp_image_axis_index(100), 0);
264 }
265
266 #[test]
267 fn pixel_index_isize() {
268 assert_eq!(0isize.to_image_axis_index(), Some(0));
270 assert_eq!(42isize.to_image_axis_index(), Some(42));
271 assert_eq!((-1isize).to_image_axis_index(), None);
272
273 assert_eq!(0isize.clamp_image_axis_index(100), 0);
275 assert_eq!(50isize.clamp_image_axis_index(100), 50);
276 assert_eq!(100isize.clamp_image_axis_index(200), 100);
277 assert_eq!((-1isize).clamp_image_axis_index(100), 0);
278
279 if std::mem::size_of::<isize>() > std::mem::size_of::<u32>() {
281 let large_positive = u32::MAX as isize + 1;
282 assert_eq!(large_positive.clamp_image_axis_index(100), 100);
283 }
284 }
285
286 #[test]
287 fn pixel_index_i64() {
288 assert_eq!(0i64.to_image_axis_index(), Some(0));
290 assert_eq!(42i64.to_image_axis_index(), Some(42));
291 assert_eq!((-1i64).to_image_axis_index(), None);
292
293 let large_positive = u32::MAX as i64 + 1;
295 assert_eq!(large_positive.to_image_axis_index(), None);
296
297 assert_eq!(0i64.clamp_image_axis_index(100), 0);
299 assert_eq!(50i64.clamp_image_axis_index(100), 50);
300 assert_eq!(100i64.clamp_image_axis_index(200), 100);
301 assert_eq!((-1i64).clamp_image_axis_index(100), 0);
302
303 let large_positive = u32::MAX as i64 + 1;
305 assert_eq!(large_positive.clamp_image_axis_index(100), 100);
306 }
307
308 #[test]
309 fn pixel_index_i128() {
310 assert_eq!(0i128.to_image_axis_index(), Some(0));
312 assert_eq!(42i128.to_image_axis_index(), Some(42));
313 assert_eq!((-1i128).to_image_axis_index(), None);
314
315 let large_positive = u32::MAX as i128 + 1;
317 assert_eq!(large_positive.to_image_axis_index(), None);
318
319 assert_eq!(0i128.clamp_image_axis_index(100), 0);
321 assert_eq!(50i128.clamp_image_axis_index(100), 50);
322 assert_eq!(100i128.clamp_image_axis_index(200), 100);
323 assert_eq!((-1i128).clamp_image_axis_index(100), 0);
324
325 let large_positive = u32::MAX as i128 + 1;
327 assert_eq!(large_positive.clamp_image_axis_index(100), 100);
328 }
329
330 #[test]
331 fn clamp_image_axis_index_edge_cases() {
332 assert_eq!(u32::MAX.clamp_image_axis_index(u32::MAX), u32::MAX);
333 assert_eq!(0u32.clamp_image_axis_index(u32::MAX), 0);
334 assert_eq!(100u32.clamp_image_axis_index(150), 100);
335 assert_eq!(200u32.clamp_image_axis_index(150), 150);
336 assert_eq!(0u32.clamp_image_axis_index(0), 0);
337 assert_eq!(100u32.clamp_image_axis_index(0), 0);
338 assert_eq!((-100i32).clamp_image_axis_index(0), 0);
339 assert_eq!((-100i32).clamp_image_axis_index(100), 0);
340 assert_eq!((-1000i64).clamp_image_axis_index(0), 0);
341 assert_eq!((-1000i64).clamp_image_axis_index(100), 0);
342 }
343
344 #[test]
345 fn pixel_index_f32() {
346 assert_eq!(0.0f32.to_image_axis_index(), Some(0));
348 assert_eq!(1.0f32.to_image_axis_index(), Some(1));
349 assert_eq!(42.7f32.to_image_axis_index(), Some(42));
350 assert_eq!(100.9f32.to_image_axis_index(), Some(100));
351 assert_eq!(999.0f32.to_image_axis_index(), Some(999));
352
353 assert_eq!((-1.0f32).to_image_axis_index(), None);
355 assert_eq!((-42.5f32).to_image_axis_index(), None);
356 assert_eq!((-0.1f32).to_image_axis_index(), None);
357
358 assert_eq!(f32::NAN.to_image_axis_index(), None);
360 assert_eq!(f32::INFINITY.to_image_axis_index(), None);
361 assert_eq!(f32::NEG_INFINITY.to_image_axis_index(), None);
362
363 assert_eq!(0.0f32.clamp_image_axis_index(100), 0);
365 assert_eq!(50.5f32.clamp_image_axis_index(100), 50);
366 assert_eq!(75.9f32.clamp_image_axis_index(100), 75);
367 assert_eq!(150.0f32.clamp_image_axis_index(100), 100);
368
369 assert_eq!((-1.0f32).clamp_image_axis_index(100), 0);
371 assert_eq!((-50.5f32).clamp_image_axis_index(100), 0);
372
373 assert_eq!(f32::NAN.clamp_image_axis_index(100), 0);
375 assert_eq!(f32::INFINITY.clamp_image_axis_index(100), 100);
376 assert_eq!(f32::NEG_INFINITY.clamp_image_axis_index(100), 0);
377
378 assert_eq!(10.0f32.clamp_image_axis_index(0), 0);
380 assert_eq!((-10.0f32).clamp_image_axis_index(0), 0);
381 assert_eq!(f32::INFINITY.clamp_image_axis_index(0), 0);
382 }
383
384 #[test]
385 fn pixel_index_f64() {
386 assert_eq!(0.0f64.to_image_axis_index(), Some(0));
388 assert_eq!(1.0f64.to_image_axis_index(), Some(1));
389 assert_eq!(42.7f64.to_image_axis_index(), Some(42));
390 assert_eq!(100.9f64.to_image_axis_index(), Some(100));
391 assert_eq!(999.0f64.to_image_axis_index(), Some(999));
392 assert_eq!(1000000.0f64.to_image_axis_index(), Some(1000000));
393
394 assert_eq!((-1.0f64).to_image_axis_index(), None);
396 assert_eq!((-42.5f64).to_image_axis_index(), None);
397 assert_eq!((-0.1f64).to_image_axis_index(), None);
398
399 assert_eq!(f64::NAN.to_image_axis_index(), None);
401 assert_eq!(f64::INFINITY.to_image_axis_index(), None);
402 assert_eq!(f64::NEG_INFINITY.to_image_axis_index(), None);
403
404 assert_eq!(0.0f64.clamp_image_axis_index(100), 0);
406 assert_eq!(50.5f64.clamp_image_axis_index(100), 50);
407 assert_eq!(75.9f64.clamp_image_axis_index(100), 75);
408 assert_eq!(150.0f64.clamp_image_axis_index(100), 100);
409
410 assert_eq!((-1.0f64).clamp_image_axis_index(100), 0);
412 assert_eq!((-50.5f64).clamp_image_axis_index(100), 0);
413
414 assert_eq!(f64::NAN.clamp_image_axis_index(100), 0);
416 assert_eq!(f64::INFINITY.clamp_image_axis_index(100), 100);
417 assert_eq!(f64::NEG_INFINITY.clamp_image_axis_index(100), 0);
418
419 assert_eq!(10.0f64.clamp_image_axis_index(0), 0);
421 assert_eq!((-10.0f64).clamp_image_axis_index(0), 0);
422 assert_eq!(f64::INFINITY.clamp_image_axis_index(0), 0);
423
424 assert_eq!(5000000000.0f64.clamp_image_axis_index(100), 100);
426 }
427}