num_convert/
convert_into_by_add.rs

1/// A generic trait for converting into possible types with different signs.
2///
3/// # Usage
4/// Basic use of the trait.
5///
6/// ```
7/// use num_convert::IntoByAdd;
8///
9/// assert_eq!(IntoByAdd::<u64>::into_by_add(i8::MAX), u8::MAX as u64);
10/// assert_eq!(<i16 as IntoByAdd<u16>>::into_by_add(i16::MIN), u16::MIN);
11/// ```
12///
13/// # Examples
14///
15/// ```
16/// # use num_convert::IntoByAdd;
17/// fn convert_into_u8<T: IntoByAdd<u8>>(min: T, max: T) -> (u8, u8) {
18///     (min.into_by_add(), max.into_by_add())
19/// }
20///
21/// assert_eq!(convert_into_u8(i8::MIN, i8::MAX), (u8::MIN, u8::MAX));
22/// assert_eq!(<i32 as IntoByAdd<u128>>::into_by_add(i32::MIN), u32::MIN as u128);
23/// ```
24pub trait IntoByAdd<T> {
25    /// Converts the value of `self` to an `T`.
26    fn into_by_add(self) -> T;
27}
28
29macro_rules! signed_or_unsigned_impls {
30    ( $( $for_type:ty; $($into_type:ty),* );* ) => {
31        $(
32            //signed = to signed
33            //unsigned = to unsigned
34            impl IntoByAdd<$for_type> for $for_type {
35                #[doc = concat!("Returns the same type ", stringify!($for_type), ".")]
36                #[inline]
37                fn into_by_add(self) -> $for_type {
38                    self
39                }
40            }
41
42            $(
43                //signed < to signed
44                //unsigned < to unsigned
45                impl IntoByAdd<$into_type> for $for_type {
46                    #[doc = concat!("Converts ", stringify!($for_type), " to ", stringify!($into_type), " losslessly.")]
47                    #[inline]
48                    fn into_by_add(self) -> $into_type {
49                        self as $into_type
50                    }
51                }
52            )*
53        )*
54    }
55}
56
57macro_rules! unsigned_to_signed_impls {
58    ( $( $for_type:ty, $as_type:ty; $($into_type:ty),* );* ) => {
59        $(
60            //unsigned = to signed
61            impl IntoByAdd<$as_type> for $for_type {
62                #[doc = concat!("Converts ", stringify!($for_type), " to equvalent ", stringify!($as_type), ".")]
63                #[inline]
64                fn into_by_add(self) -> $as_type {
65                    ((self as $as_type).wrapping_add(<$as_type>::MAX)).wrapping_add(1)
66                }
67            }
68
69            $(
70                //unsigned < to signed
71                impl IntoByAdd<$into_type> for $for_type {
72                    #[doc = concat!("Converts ", stringify!($for_type), " to equvalent ", stringify!($into_type), ".")]
73                    #[inline]
74                    fn into_by_add(self) -> $into_type {
75                        ((self as $as_type).wrapping_add(<$as_type>::MAX)).wrapping_add(1) as $into_type
76                    }
77                }
78            )*
79        )*
80    };
81}
82
83macro_rules! signed_to_unsigned_impls {
84    //signed < to unsigned
85    ( $for_type:ty; $add_value:expr; $($into_type:ty),*) => {
86        $(
87            impl IntoByAdd<$into_type> for $for_type {
88                #[doc = concat!("Converts ", stringify!($for_type), " to equvalent ", stringify!($into_type), ".")]
89                #[inline]
90                fn into_by_add(self) -> $into_type {
91                    (self as $into_type).wrapping_add($add_value)
92                }
93            }
94        )*
95    };
96}
97
98signed_or_unsigned_impls! { i8; i16, i32, i64, isize, i128; i16; i32, i64, isize, i128 }
99signed_or_unsigned_impls! { i32; i64, isize, i128; i64; isize, i128; isize; i64, i128; i128; }
100signed_or_unsigned_impls! { u8; u16, u32, u64, usize, u128; u16; u32, u64, usize, u128 }
101signed_or_unsigned_impls! { u32; u64, usize, u128; u64; usize, u128; usize; u64, u128; u128; }
102
103signed_to_unsigned_impls! { i8; 128; u8, u16, u32, u64, usize, u128 }
104signed_to_unsigned_impls! { i16; 32_768; u16, u32, u64, usize, u128 }
105signed_to_unsigned_impls! { i32; 2_147_483_648; u32, u64, usize, u128 }
106signed_to_unsigned_impls! { i64; 9_223_372_036_854_775_808; u64, usize, u128 }
107signed_to_unsigned_impls! { isize; 9_223_372_036_854_775_808; u64, usize, u128 }
108signed_to_unsigned_impls! { i128; 170_141_183_460_469_231_731_687_303_715_884_105_728; u128 }
109
110unsigned_to_signed_impls! { u8, i8; i16, i32, i64, isize, i128; u16, i16; i32, i64, isize, i128 }
111unsigned_to_signed_impls! { u32, i32; i64, isize, i128; u64, i64; isize, i128; usize, isize; i64, i128; u128, i128; }