1use std::fmt::{Debug, Display};
2use std::hash::Hash;
3
4use num_traits::{AsPrimitive, FromPrimitive, PrimInt, Signed, ToPrimitive, Unsigned};
5
6pub trait Num: PrimInt + Default + Debug + AsPrimitive<usize> + ToPrimitive {}
7
8impl<All: PrimInt + Default + Debug + AsPrimitive<usize> + ToPrimitive> Num for All {}
9
10pub trait SignNum: Num + Signed + FromPrimitive {}
11
12impl<All: Num + Signed + FromPrimitive> SignNum for All {}
13
14pub trait ToSigned {
15 type Type: Num + Signed;
16
17 fn to_signed(&self) -> Self::Type;
18}
19
20macro_rules! signed_type_impl {
21 ($U:ty, $S:ty) => {
22 impl ToSigned for $U {
23 type Type = $S;
24
25 fn to_signed(&self) -> Self::Type {
26 *self as Self::Type
27 }
28 }
29 };
30}
31
32signed_type_impl!(i8, i8);
33signed_type_impl!(u8, i8);
34signed_type_impl!(i16, i16);
35signed_type_impl!(u16, i16);
36signed_type_impl!(i32, i32);
37signed_type_impl!(u32, i32);
38signed_type_impl!(i64, i64);
39signed_type_impl!(u64, i64);
40signed_type_impl!(i128, i128);
41signed_type_impl!(u128, i128);
42signed_type_impl!(isize, isize);
43signed_type_impl!(usize, isize);
44
45pub trait MaxValue {
46 const MAX: Self;
47}
48
49macro_rules! max_value_impl {
50 ($T:ty) => {
51 impl MaxValue for $T {
52 const MAX: Self = <$T>::MAX;
53 }
54 };
55}
56
57max_value_impl!(i8);
59max_value_impl!(u8);
60max_value_impl!(i16);
61max_value_impl!(u16);
62max_value_impl!(i32);
63max_value_impl!(u32);
64max_value_impl!(i64);
65max_value_impl!(u64);
66max_value_impl!(i128);
67max_value_impl!(u128);
68max_value_impl!(isize);
69max_value_impl!(usize);
70
71#[rustfmt::skip]
73pub trait LinkType:
74Num
75+ Unsigned
76+ ToSigned
77+ MaxValue
78+ FromPrimitive
79+ Debug
80+ Display
81+ Hash
82+ Send
83+ Sync
84+ 'static {}
85
86#[rustfmt::skip]
87impl<
88 All: Num
89 + Unsigned
90 + ToSigned
91 + MaxValue
92 + FromPrimitive
93 + Debug
94 + Display
95 + Hash
96 + Send
97 + Sync
98 + 'static,
99> LinkType for All {}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
110 fn test_num_trait_for_i8() {
111 fn assert_num<T: Num>(_val: T) {}
112 assert_num(0i8);
113 }
114
115 #[test]
116 fn test_num_trait_for_u8() {
117 fn assert_num<T: Num>(_val: T) {}
118 assert_num(0u8);
119 }
120
121 #[test]
122 fn test_num_trait_for_i16() {
123 fn assert_num<T: Num>(_val: T) {}
124 assert_num(0i16);
125 }
126
127 #[test]
128 fn test_num_trait_for_u16() {
129 fn assert_num<T: Num>(_val: T) {}
130 assert_num(0u16);
131 }
132
133 #[test]
134 fn test_num_trait_for_i32() {
135 fn assert_num<T: Num>(_val: T) {}
136 assert_num(0i32);
137 }
138
139 #[test]
140 fn test_num_trait_for_u32() {
141 fn assert_num<T: Num>(_val: T) {}
142 assert_num(0u32);
143 }
144
145 #[test]
146 fn test_num_trait_for_i64() {
147 fn assert_num<T: Num>(_val: T) {}
148 assert_num(0i64);
149 }
150
151 #[test]
152 fn test_num_trait_for_u64() {
153 fn assert_num<T: Num>(_val: T) {}
154 assert_num(0u64);
155 }
156
157 #[test]
158 fn test_num_trait_for_i128() {
159 fn assert_num<T: Num>(_val: T) {}
160 assert_num(0i128);
161 }
162
163 #[test]
164 fn test_num_trait_for_u128() {
165 fn assert_num<T: Num>(_val: T) {}
166 assert_num(0u128);
167 }
168
169 #[test]
170 fn test_num_trait_for_isize() {
171 fn assert_num<T: Num>(_val: T) {}
172 assert_num(0isize);
173 }
174
175 #[test]
176 fn test_num_trait_for_usize() {
177 fn assert_num<T: Num>(_val: T) {}
178 assert_num(0usize);
179 }
180
181 #[test]
186 fn test_sign_num_trait_for_i8() {
187 fn assert_sign_num<T: SignNum>(_val: T) {}
188 assert_sign_num(0i8);
189 }
190
191 #[test]
192 fn test_sign_num_trait_for_i16() {
193 fn assert_sign_num<T: SignNum>(_val: T) {}
194 assert_sign_num(0i16);
195 }
196
197 #[test]
198 fn test_sign_num_trait_for_i32() {
199 fn assert_sign_num<T: SignNum>(_val: T) {}
200 assert_sign_num(0i32);
201 }
202
203 #[test]
204 fn test_sign_num_trait_for_i64() {
205 fn assert_sign_num<T: SignNum>(_val: T) {}
206 assert_sign_num(0i64);
207 }
208
209 #[test]
210 fn test_sign_num_trait_for_i128() {
211 fn assert_sign_num<T: SignNum>(_val: T) {}
212 assert_sign_num(0i128);
213 }
214
215 #[test]
216 fn test_sign_num_trait_for_isize() {
217 fn assert_sign_num<T: SignNum>(_val: T) {}
218 assert_sign_num(0isize);
219 }
220
221 #[test]
226 fn test_to_signed_i8() {
227 let val: i8 = 42;
228 let signed: i8 = val.to_signed();
229 assert_eq!(signed, 42i8);
230 }
231
232 #[test]
233 fn test_to_signed_u8() {
234 let val: u8 = 42;
235 let signed: i8 = val.to_signed();
236 assert_eq!(signed, 42i8);
237 }
238
239 #[test]
240 fn test_to_signed_i16() {
241 let val: i16 = 1000;
242 let signed: i16 = val.to_signed();
243 assert_eq!(signed, 1000i16);
244 }
245
246 #[test]
247 fn test_to_signed_u16() {
248 let val: u16 = 1000;
249 let signed: i16 = val.to_signed();
250 assert_eq!(signed, 1000i16);
251 }
252
253 #[test]
254 fn test_to_signed_i32() {
255 let val: i32 = 100000;
256 let signed: i32 = val.to_signed();
257 assert_eq!(signed, 100000i32);
258 }
259
260 #[test]
261 fn test_to_signed_u32() {
262 let val: u32 = 100000;
263 let signed: i32 = val.to_signed();
264 assert_eq!(signed, 100000i32);
265 }
266
267 #[test]
268 fn test_to_signed_i64() {
269 let val: i64 = 1000000000;
270 let signed: i64 = val.to_signed();
271 assert_eq!(signed, 1000000000i64);
272 }
273
274 #[test]
275 fn test_to_signed_u64() {
276 let val: u64 = 1000000000;
277 let signed: i64 = val.to_signed();
278 assert_eq!(signed, 1000000000i64);
279 }
280
281 #[test]
282 fn test_to_signed_i128() {
283 let val: i128 = 1000000000000000;
284 let signed: i128 = val.to_signed();
285 assert_eq!(signed, 1000000000000000i128);
286 }
287
288 #[test]
289 fn test_to_signed_u128() {
290 let val: u128 = 1000000000000000;
291 let signed: i128 = val.to_signed();
292 assert_eq!(signed, 1000000000000000i128);
293 }
294
295 #[test]
296 fn test_to_signed_isize() {
297 let val: isize = 12345;
298 let signed: isize = val.to_signed();
299 assert_eq!(signed, 12345isize);
300 }
301
302 #[test]
303 fn test_to_signed_usize() {
304 let val: usize = 12345;
305 let signed: isize = val.to_signed();
306 assert_eq!(signed, 12345isize);
307 }
308
309 #[test]
310 fn test_to_signed_type_alias_i8() {
311 fn check<T: ToSigned<Type = i8>>(_val: T) {}
312 check(0i8);
313 check(0u8);
314 }
315
316 #[test]
317 fn test_to_signed_type_alias_i16() {
318 fn check<T: ToSigned<Type = i16>>(_val: T) {}
319 check(0i16);
320 check(0u16);
321 }
322
323 #[test]
324 fn test_to_signed_type_alias_i32() {
325 fn check<T: ToSigned<Type = i32>>(_val: T) {}
326 check(0i32);
327 check(0u32);
328 }
329
330 #[test]
331 fn test_to_signed_type_alias_i64() {
332 fn check<T: ToSigned<Type = i64>>(_val: T) {}
333 check(0i64);
334 check(0u64);
335 }
336
337 #[test]
338 fn test_to_signed_type_alias_i128() {
339 fn check<T: ToSigned<Type = i128>>(_val: T) {}
340 check(0i128);
341 check(0u128);
342 }
343
344 #[test]
345 fn test_to_signed_type_alias_isize() {
346 fn check<T: ToSigned<Type = isize>>(_val: T) {}
347 check(0isize);
348 check(0usize);
349 }
350
351 #[test]
356 fn test_max_value_i8() {
357 assert_eq!(i8::MAX, <i8 as MaxValue>::MAX);
358 }
359
360 #[test]
361 fn test_max_value_u8() {
362 assert_eq!(u8::MAX, <u8 as MaxValue>::MAX);
363 }
364
365 #[test]
366 fn test_max_value_i16() {
367 assert_eq!(i16::MAX, <i16 as MaxValue>::MAX);
368 }
369
370 #[test]
371 fn test_max_value_u16() {
372 assert_eq!(u16::MAX, <u16 as MaxValue>::MAX);
373 }
374
375 #[test]
376 fn test_max_value_i32() {
377 assert_eq!(i32::MAX, <i32 as MaxValue>::MAX);
378 }
379
380 #[test]
381 fn test_max_value_u32() {
382 assert_eq!(u32::MAX, <u32 as MaxValue>::MAX);
383 }
384
385 #[test]
386 fn test_max_value_i64() {
387 assert_eq!(i64::MAX, <i64 as MaxValue>::MAX);
388 }
389
390 #[test]
391 fn test_max_value_u64() {
392 assert_eq!(u64::MAX, <u64 as MaxValue>::MAX);
393 }
394
395 #[test]
396 fn test_max_value_i128() {
397 assert_eq!(i128::MAX, <i128 as MaxValue>::MAX);
398 }
399
400 #[test]
401 fn test_max_value_u128() {
402 assert_eq!(u128::MAX, <u128 as MaxValue>::MAX);
403 }
404
405 #[test]
406 fn test_max_value_isize() {
407 assert_eq!(isize::MAX, <isize as MaxValue>::MAX);
408 }
409
410 #[test]
411 fn test_max_value_usize() {
412 assert_eq!(usize::MAX, <usize as MaxValue>::MAX);
413 }
414
415 #[test]
420 fn test_link_type_for_u8() {
421 fn assert_link_type<T: LinkType>(_val: T) {}
422 assert_link_type(0u8);
423 }
424
425 #[test]
426 fn test_link_type_for_u16() {
427 fn assert_link_type<T: LinkType>(_val: T) {}
428 assert_link_type(0u16);
429 }
430
431 #[test]
432 fn test_link_type_for_u32() {
433 fn assert_link_type<T: LinkType>(_val: T) {}
434 assert_link_type(0u32);
435 }
436
437 #[test]
438 fn test_link_type_for_u64() {
439 fn assert_link_type<T: LinkType>(_val: T) {}
440 assert_link_type(0u64);
441 }
442
443 #[test]
444 fn test_link_type_for_usize() {
445 fn assert_link_type<T: LinkType>(_val: T) {}
446 assert_link_type(0usize);
447 }
448
449 #[test]
454 fn test_to_signed_u8_max() {
455 let val: u8 = u8::MAX;
456 let signed: i8 = val.to_signed();
457 assert_eq!(signed, -1i8); }
459
460 #[test]
461 fn test_to_signed_u16_max() {
462 let val: u16 = u16::MAX;
463 let signed: i16 = val.to_signed();
464 assert_eq!(signed, -1i16); }
466
467 #[test]
468 fn test_to_signed_u32_max() {
469 let val: u32 = u32::MAX;
470 let signed: i32 = val.to_signed();
471 assert_eq!(signed, -1i32); }
473
474 #[test]
475 fn test_to_signed_u64_max() {
476 let val: u64 = u64::MAX;
477 let signed: i64 = val.to_signed();
478 assert_eq!(signed, -1i64); }
480
481 #[test]
482 fn test_to_signed_u128_max() {
483 let val: u128 = u128::MAX;
484 let signed: i128 = val.to_signed();
485 assert_eq!(signed, -1i128); }
487
488 #[test]
489 fn test_to_signed_usize_max() {
490 let val: usize = usize::MAX;
491 let signed: isize = val.to_signed();
492 assert_eq!(signed, -1isize); }
494
495 #[test]
496 fn test_to_signed_zero() {
497 assert_eq!(0u8.to_signed(), 0i8);
498 assert_eq!(0u16.to_signed(), 0i16);
499 assert_eq!(0u32.to_signed(), 0i32);
500 assert_eq!(0u64.to_signed(), 0i64);
501 assert_eq!(0u128.to_signed(), 0i128);
502 assert_eq!(0usize.to_signed(), 0isize);
503 }
504
505 #[test]
506 fn test_to_signed_negative() {
507 assert_eq!((-1i8).to_signed(), -1i8);
508 assert_eq!((-1i16).to_signed(), -1i16);
509 assert_eq!((-1i32).to_signed(), -1i32);
510 assert_eq!((-1i64).to_signed(), -1i64);
511 assert_eq!((-1i128).to_signed(), -1i128);
512 assert_eq!((-1isize).to_signed(), -1isize);
513 }
514
515 #[test]
520 fn test_link_type_can_be_converted_to_signed() {
521 fn use_link_type<T: LinkType + ToSigned>(val: T) -> <T as ToSigned>::Type {
522 val.to_signed()
523 }
524 assert_eq!(use_link_type(42u8), 42i8);
525 assert_eq!(use_link_type(42u16), 42i16);
526 assert_eq!(use_link_type(42u32), 42i32);
527 assert_eq!(use_link_type(42u64), 42i64);
528 assert_eq!(use_link_type(42usize), 42isize);
529 }
530
531 #[test]
532 fn test_link_type_has_max_value() {
533 fn get_max<T: LinkType + MaxValue>() -> T {
534 T::MAX
535 }
536 assert_eq!(get_max::<u8>(), u8::MAX);
537 assert_eq!(get_max::<u16>(), u16::MAX);
538 assert_eq!(get_max::<u32>(), u32::MAX);
539 assert_eq!(get_max::<u64>(), u64::MAX);
540 assert_eq!(get_max::<usize>(), usize::MAX);
541 }
542
543 #[test]
544 fn test_num_default_values() {
545 fn check_default<T: Num>() -> T {
546 T::default()
547 }
548 assert_eq!(check_default::<i8>(), 0i8);
549 assert_eq!(check_default::<u8>(), 0u8);
550 assert_eq!(check_default::<i16>(), 0i16);
551 assert_eq!(check_default::<u16>(), 0u16);
552 assert_eq!(check_default::<i32>(), 0i32);
553 assert_eq!(check_default::<u32>(), 0u32);
554 assert_eq!(check_default::<i64>(), 0i64);
555 assert_eq!(check_default::<u64>(), 0u64);
556 assert_eq!(check_default::<i128>(), 0i128);
557 assert_eq!(check_default::<u128>(), 0u128);
558 assert_eq!(check_default::<isize>(), 0isize);
559 assert_eq!(check_default::<usize>(), 0usize);
560 }
561
562 #[test]
563 fn test_num_as_usize() {
564 fn to_usize<T: Num>(val: T) -> usize {
565 val.as_()
566 }
567 assert_eq!(to_usize(42i8), 42usize);
568 assert_eq!(to_usize(42u8), 42usize);
569 assert_eq!(to_usize(42i16), 42usize);
570 assert_eq!(to_usize(42u16), 42usize);
571 assert_eq!(to_usize(42i32), 42usize);
572 assert_eq!(to_usize(42u32), 42usize);
573 }
574
575 #[test]
576 fn test_sign_num_signum() {
577 fn get_signum<T: SignNum>(val: T) -> T {
578 val.signum()
579 }
580 assert_eq!(get_signum(5i8), 1i8);
581 assert_eq!(get_signum(-5i8), -1i8);
582 assert_eq!(get_signum(0i8), 0i8);
583 assert_eq!(get_signum(5i32), 1i32);
584 assert_eq!(get_signum(-5i32), -1i32);
585 assert_eq!(get_signum(0i32), 0i32);
586 }
587
588 #[test]
589 fn test_sign_num_abs() {
590 fn get_abs<T: SignNum>(val: T) -> T {
591 val.abs()
592 }
593 assert_eq!(get_abs(-5i8), 5i8);
594 assert_eq!(get_abs(5i8), 5i8);
595 assert_eq!(get_abs(-100i32), 100i32);
596 assert_eq!(get_abs(100i32), 100i32);
597 }
598}