1use std::fmt::{Debug, Display};
2use std::hash::Hash;
3
4use num_traits::{AsPrimitive, FromPrimitive, PrimInt, Signed, ToPrimitive, Unsigned};
5
6pub trait Number: PrimInt + Default + Debug + AsPrimitive<usize> + ToPrimitive {}
24
25impl<All: PrimInt + Default + Debug + AsPrimitive<usize> + ToPrimitive> Number for All {}
26
27pub trait SignedNumber: Number + Signed + FromPrimitive {}
43
44impl<All: Number + Signed + FromPrimitive> SignedNumber for All {}
45
46pub trait ToSigned {
61 type Type: Number + Signed;
63
64 fn to_signed(&self) -> Self::Type;
66}
67
68macro_rules! signed_type_impl {
69 ($U:ty, $S:ty) => {
70 impl ToSigned for $U {
71 type Type = $S;
72
73 fn to_signed(&self) -> Self::Type {
74 *self as Self::Type
75 }
76 }
77 };
78}
79
80signed_type_impl!(i8, i8);
81signed_type_impl!(u8, i8);
82signed_type_impl!(i16, i16);
83signed_type_impl!(u16, i16);
84signed_type_impl!(i32, i32);
85signed_type_impl!(u32, i32);
86signed_type_impl!(i64, i64);
87signed_type_impl!(u64, i64);
88signed_type_impl!(i128, i128);
89signed_type_impl!(u128, i128);
90signed_type_impl!(isize, isize);
91signed_type_impl!(usize, isize);
92
93pub trait MaxValue {
105 const MAX: Self;
107}
108
109macro_rules! max_value_impl {
110 ($T:ty) => {
111 impl MaxValue for $T {
112 const MAX: Self = <$T>::MAX;
113 }
114 };
115}
116
117max_value_impl!(i8);
119max_value_impl!(u8);
120max_value_impl!(i16);
121max_value_impl!(u16);
122max_value_impl!(i32);
123max_value_impl!(u32);
124max_value_impl!(i64);
125max_value_impl!(u64);
126max_value_impl!(i128);
127max_value_impl!(u128);
128max_value_impl!(isize);
129max_value_impl!(usize);
130
131#[rustfmt::skip]
153pub trait LinkReference:
154Number
155+ Unsigned
156+ ToSigned
157+ MaxValue
158+ FromPrimitive
159+ Debug
160+ Display
161+ Hash
162+ Send
163+ Sync
164+ 'static {}
165
166#[rustfmt::skip]
167impl<
168 All: Number
169 + Unsigned
170 + ToSigned
171 + MaxValue
172 + FromPrimitive
173 + Debug
174 + Display
175 + Hash
176 + Send
177 + Sync
178 + 'static,
179> LinkReference for All {}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184
185 #[test]
190 fn test_number_trait_for_i8() {
191 fn assert_number<T: Number>(_val: T) {}
192 assert_number(0i8);
193 }
194
195 #[test]
196 fn test_number_trait_for_u8() {
197 fn assert_number<T: Number>(_val: T) {}
198 assert_number(0u8);
199 }
200
201 #[test]
202 fn test_number_trait_for_i16() {
203 fn assert_number<T: Number>(_val: T) {}
204 assert_number(0i16);
205 }
206
207 #[test]
208 fn test_number_trait_for_u16() {
209 fn assert_number<T: Number>(_val: T) {}
210 assert_number(0u16);
211 }
212
213 #[test]
214 fn test_number_trait_for_i32() {
215 fn assert_number<T: Number>(_val: T) {}
216 assert_number(0i32);
217 }
218
219 #[test]
220 fn test_number_trait_for_u32() {
221 fn assert_number<T: Number>(_val: T) {}
222 assert_number(0u32);
223 }
224
225 #[test]
226 fn test_number_trait_for_i64() {
227 fn assert_number<T: Number>(_val: T) {}
228 assert_number(0i64);
229 }
230
231 #[test]
232 fn test_number_trait_for_u64() {
233 fn assert_number<T: Number>(_val: T) {}
234 assert_number(0u64);
235 }
236
237 #[test]
238 fn test_number_trait_for_i128() {
239 fn assert_number<T: Number>(_val: T) {}
240 assert_number(0i128);
241 }
242
243 #[test]
244 fn test_number_trait_for_u128() {
245 fn assert_number<T: Number>(_val: T) {}
246 assert_number(0u128);
247 }
248
249 #[test]
250 fn test_number_trait_for_isize() {
251 fn assert_number<T: Number>(_val: T) {}
252 assert_number(0isize);
253 }
254
255 #[test]
256 fn test_number_trait_for_usize() {
257 fn assert_number<T: Number>(_val: T) {}
258 assert_number(0usize);
259 }
260
261 #[test]
266 fn test_signed_number_trait_for_i8() {
267 fn assert_signed_number<T: SignedNumber>(_val: T) {}
268 assert_signed_number(0i8);
269 }
270
271 #[test]
272 fn test_signed_number_trait_for_i16() {
273 fn assert_signed_number<T: SignedNumber>(_val: T) {}
274 assert_signed_number(0i16);
275 }
276
277 #[test]
278 fn test_signed_number_trait_for_i32() {
279 fn assert_signed_number<T: SignedNumber>(_val: T) {}
280 assert_signed_number(0i32);
281 }
282
283 #[test]
284 fn test_signed_number_trait_for_i64() {
285 fn assert_signed_number<T: SignedNumber>(_val: T) {}
286 assert_signed_number(0i64);
287 }
288
289 #[test]
290 fn test_signed_number_trait_for_i128() {
291 fn assert_signed_number<T: SignedNumber>(_val: T) {}
292 assert_signed_number(0i128);
293 }
294
295 #[test]
296 fn test_signed_number_trait_for_isize() {
297 fn assert_signed_number<T: SignedNumber>(_val: T) {}
298 assert_signed_number(0isize);
299 }
300
301 #[test]
306 fn test_to_signed_i8() {
307 let val: i8 = 42;
308 let signed: i8 = val.to_signed();
309 assert_eq!(signed, 42i8);
310 }
311
312 #[test]
313 fn test_to_signed_u8() {
314 let val: u8 = 42;
315 let signed: i8 = val.to_signed();
316 assert_eq!(signed, 42i8);
317 }
318
319 #[test]
320 fn test_to_signed_i16() {
321 let val: i16 = 1000;
322 let signed: i16 = val.to_signed();
323 assert_eq!(signed, 1000i16);
324 }
325
326 #[test]
327 fn test_to_signed_u16() {
328 let val: u16 = 1000;
329 let signed: i16 = val.to_signed();
330 assert_eq!(signed, 1000i16);
331 }
332
333 #[test]
334 fn test_to_signed_i32() {
335 let val: i32 = 100000;
336 let signed: i32 = val.to_signed();
337 assert_eq!(signed, 100000i32);
338 }
339
340 #[test]
341 fn test_to_signed_u32() {
342 let val: u32 = 100000;
343 let signed: i32 = val.to_signed();
344 assert_eq!(signed, 100000i32);
345 }
346
347 #[test]
348 fn test_to_signed_i64() {
349 let val: i64 = 1000000000;
350 let signed: i64 = val.to_signed();
351 assert_eq!(signed, 1000000000i64);
352 }
353
354 #[test]
355 fn test_to_signed_u64() {
356 let val: u64 = 1000000000;
357 let signed: i64 = val.to_signed();
358 assert_eq!(signed, 1000000000i64);
359 }
360
361 #[test]
362 fn test_to_signed_i128() {
363 let val: i128 = 1000000000000000;
364 let signed: i128 = val.to_signed();
365 assert_eq!(signed, 1000000000000000i128);
366 }
367
368 #[test]
369 fn test_to_signed_u128() {
370 let val: u128 = 1000000000000000;
371 let signed: i128 = val.to_signed();
372 assert_eq!(signed, 1000000000000000i128);
373 }
374
375 #[test]
376 fn test_to_signed_isize() {
377 let val: isize = 12345;
378 let signed: isize = val.to_signed();
379 assert_eq!(signed, 12345isize);
380 }
381
382 #[test]
383 fn test_to_signed_usize() {
384 let val: usize = 12345;
385 let signed: isize = val.to_signed();
386 assert_eq!(signed, 12345isize);
387 }
388
389 #[test]
390 fn test_to_signed_type_alias_i8() {
391 fn check<T: ToSigned<Type = i8>>(_val: T) {}
392 check(0i8);
393 check(0u8);
394 }
395
396 #[test]
397 fn test_to_signed_type_alias_i16() {
398 fn check<T: ToSigned<Type = i16>>(_val: T) {}
399 check(0i16);
400 check(0u16);
401 }
402
403 #[test]
404 fn test_to_signed_type_alias_i32() {
405 fn check<T: ToSigned<Type = i32>>(_val: T) {}
406 check(0i32);
407 check(0u32);
408 }
409
410 #[test]
411 fn test_to_signed_type_alias_i64() {
412 fn check<T: ToSigned<Type = i64>>(_val: T) {}
413 check(0i64);
414 check(0u64);
415 }
416
417 #[test]
418 fn test_to_signed_type_alias_i128() {
419 fn check<T: ToSigned<Type = i128>>(_val: T) {}
420 check(0i128);
421 check(0u128);
422 }
423
424 #[test]
425 fn test_to_signed_type_alias_isize() {
426 fn check<T: ToSigned<Type = isize>>(_val: T) {}
427 check(0isize);
428 check(0usize);
429 }
430
431 #[test]
436 fn test_max_value_i8() {
437 assert_eq!(i8::MAX, <i8 as MaxValue>::MAX);
438 }
439
440 #[test]
441 fn test_max_value_u8() {
442 assert_eq!(u8::MAX, <u8 as MaxValue>::MAX);
443 }
444
445 #[test]
446 fn test_max_value_i16() {
447 assert_eq!(i16::MAX, <i16 as MaxValue>::MAX);
448 }
449
450 #[test]
451 fn test_max_value_u16() {
452 assert_eq!(u16::MAX, <u16 as MaxValue>::MAX);
453 }
454
455 #[test]
456 fn test_max_value_i32() {
457 assert_eq!(i32::MAX, <i32 as MaxValue>::MAX);
458 }
459
460 #[test]
461 fn test_max_value_u32() {
462 assert_eq!(u32::MAX, <u32 as MaxValue>::MAX);
463 }
464
465 #[test]
466 fn test_max_value_i64() {
467 assert_eq!(i64::MAX, <i64 as MaxValue>::MAX);
468 }
469
470 #[test]
471 fn test_max_value_u64() {
472 assert_eq!(u64::MAX, <u64 as MaxValue>::MAX);
473 }
474
475 #[test]
476 fn test_max_value_i128() {
477 assert_eq!(i128::MAX, <i128 as MaxValue>::MAX);
478 }
479
480 #[test]
481 fn test_max_value_u128() {
482 assert_eq!(u128::MAX, <u128 as MaxValue>::MAX);
483 }
484
485 #[test]
486 fn test_max_value_isize() {
487 assert_eq!(isize::MAX, <isize as MaxValue>::MAX);
488 }
489
490 #[test]
491 fn test_max_value_usize() {
492 assert_eq!(usize::MAX, <usize as MaxValue>::MAX);
493 }
494
495 #[test]
500 fn test_link_reference_for_u8() {
501 fn assert_link_reference<T: LinkReference>(_val: T) {}
502 assert_link_reference(0u8);
503 }
504
505 #[test]
506 fn test_link_reference_for_u16() {
507 fn assert_link_reference<T: LinkReference>(_val: T) {}
508 assert_link_reference(0u16);
509 }
510
511 #[test]
512 fn test_link_reference_for_u32() {
513 fn assert_link_reference<T: LinkReference>(_val: T) {}
514 assert_link_reference(0u32);
515 }
516
517 #[test]
518 fn test_link_reference_for_u64() {
519 fn assert_link_reference<T: LinkReference>(_val: T) {}
520 assert_link_reference(0u64);
521 }
522
523 #[test]
524 fn test_link_reference_for_usize() {
525 fn assert_link_reference<T: LinkReference>(_val: T) {}
526 assert_link_reference(0usize);
527 }
528
529 #[test]
534 fn test_to_signed_u8_max() {
535 let val: u8 = u8::MAX;
536 let signed: i8 = val.to_signed();
537 assert_eq!(signed, -1i8); }
539
540 #[test]
541 fn test_to_signed_u16_max() {
542 let val: u16 = u16::MAX;
543 let signed: i16 = val.to_signed();
544 assert_eq!(signed, -1i16); }
546
547 #[test]
548 fn test_to_signed_u32_max() {
549 let val: u32 = u32::MAX;
550 let signed: i32 = val.to_signed();
551 assert_eq!(signed, -1i32); }
553
554 #[test]
555 fn test_to_signed_u64_max() {
556 let val: u64 = u64::MAX;
557 let signed: i64 = val.to_signed();
558 assert_eq!(signed, -1i64); }
560
561 #[test]
562 fn test_to_signed_u128_max() {
563 let val: u128 = u128::MAX;
564 let signed: i128 = val.to_signed();
565 assert_eq!(signed, -1i128); }
567
568 #[test]
569 fn test_to_signed_usize_max() {
570 let val: usize = usize::MAX;
571 let signed: isize = val.to_signed();
572 assert_eq!(signed, -1isize); }
574
575 #[test]
576 fn test_to_signed_zero() {
577 assert_eq!(0u8.to_signed(), 0i8);
578 assert_eq!(0u16.to_signed(), 0i16);
579 assert_eq!(0u32.to_signed(), 0i32);
580 assert_eq!(0u64.to_signed(), 0i64);
581 assert_eq!(0u128.to_signed(), 0i128);
582 assert_eq!(0usize.to_signed(), 0isize);
583 }
584
585 #[test]
586 fn test_to_signed_negative() {
587 assert_eq!((-1i8).to_signed(), -1i8);
588 assert_eq!((-1i16).to_signed(), -1i16);
589 assert_eq!((-1i32).to_signed(), -1i32);
590 assert_eq!((-1i64).to_signed(), -1i64);
591 assert_eq!((-1i128).to_signed(), -1i128);
592 assert_eq!((-1isize).to_signed(), -1isize);
593 }
594
595 #[test]
600 fn test_link_reference_can_be_converted_to_signed() {
601 fn use_link_reference<T: LinkReference + ToSigned>(val: T) -> <T as ToSigned>::Type {
602 val.to_signed()
603 }
604 assert_eq!(use_link_reference(42u8), 42i8);
605 assert_eq!(use_link_reference(42u16), 42i16);
606 assert_eq!(use_link_reference(42u32), 42i32);
607 assert_eq!(use_link_reference(42u64), 42i64);
608 assert_eq!(use_link_reference(42usize), 42isize);
609 }
610
611 #[test]
612 fn test_link_reference_has_max_value() {
613 fn get_max<T: LinkReference + MaxValue>() -> T {
614 T::MAX
615 }
616 assert_eq!(get_max::<u8>(), u8::MAX);
617 assert_eq!(get_max::<u16>(), u16::MAX);
618 assert_eq!(get_max::<u32>(), u32::MAX);
619 assert_eq!(get_max::<u64>(), u64::MAX);
620 assert_eq!(get_max::<usize>(), usize::MAX);
621 }
622
623 #[test]
624 fn test_number_default_values() {
625 fn check_default<T: Number>() -> T {
626 T::default()
627 }
628 assert_eq!(check_default::<i8>(), 0i8);
629 assert_eq!(check_default::<u8>(), 0u8);
630 assert_eq!(check_default::<i16>(), 0i16);
631 assert_eq!(check_default::<u16>(), 0u16);
632 assert_eq!(check_default::<i32>(), 0i32);
633 assert_eq!(check_default::<u32>(), 0u32);
634 assert_eq!(check_default::<i64>(), 0i64);
635 assert_eq!(check_default::<u64>(), 0u64);
636 assert_eq!(check_default::<i128>(), 0i128);
637 assert_eq!(check_default::<u128>(), 0u128);
638 assert_eq!(check_default::<isize>(), 0isize);
639 assert_eq!(check_default::<usize>(), 0usize);
640 }
641
642 #[test]
643 fn test_number_as_usize() {
644 fn to_usize<T: Number>(val: T) -> usize {
645 val.as_()
646 }
647 assert_eq!(to_usize(42i8), 42usize);
648 assert_eq!(to_usize(42u8), 42usize);
649 assert_eq!(to_usize(42i16), 42usize);
650 assert_eq!(to_usize(42u16), 42usize);
651 assert_eq!(to_usize(42i32), 42usize);
652 assert_eq!(to_usize(42u32), 42usize);
653 }
654
655 #[test]
656 fn test_signed_number_signum() {
657 fn get_signum<T: SignedNumber>(val: T) -> T {
658 val.signum()
659 }
660 assert_eq!(get_signum(5i8), 1i8);
661 assert_eq!(get_signum(-5i8), -1i8);
662 assert_eq!(get_signum(0i8), 0i8);
663 assert_eq!(get_signum(5i32), 1i32);
664 assert_eq!(get_signum(-5i32), -1i32);
665 assert_eq!(get_signum(0i32), 0i32);
666 }
667
668 #[test]
669 fn test_signed_number_abs() {
670 fn get_abs<T: SignedNumber>(val: T) -> T {
671 val.abs()
672 }
673 assert_eq!(get_abs(-5i8), 5i8);
674 assert_eq!(get_abs(5i8), 5i8);
675 assert_eq!(get_abs(-100i32), 100i32);
676 assert_eq!(get_abs(100i32), 100i32);
677 }
678}