1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
use core::num::Wrapping;


pub trait FromPrimitive {
    fn from_bool(t: bool) -> Self;

    fn from_usize(t: usize) -> Self;
    fn from_u8(t: u8) -> Self;
    fn from_u16(t: u16) -> Self;
    fn from_u32(t: u32) -> Self;
    fn from_u64(t: u64) -> Self;
    fn from_u128(t: u128) -> Self;

    fn from_isize(t: isize) -> Self;
    fn from_i8(t: i8) -> Self;
    fn from_i16(t: i16) -> Self;
    fn from_i32(t: i32) -> Self;
    fn from_i64(t: i64) -> Self;
    fn from_i128(t: i128) -> Self;

    fn from_f32(t: f32) -> Self;
    fn from_f64(t: f64) -> Self;
}


macro_rules! from_primitive {
    ($n:ident, $t:ident, $f:ident) => (
        #[inline(always)]
        fn $n(f: $f) -> Self { f as $t }
    );
    ($n:ident, $t:ident, $f:ident, $a:ident) => (
        #[inline(always)]
        fn $n(f: $f) -> Self { f as $a as $t }
    );
}

macro_rules! trait_from_primitive {
    ($t:ident) => (
        impl FromPrimitive for $t {
            from_primitive!(from_bool, $t, bool);

            from_primitive!(from_usize, $t, usize);
            from_primitive!(from_u8, $t, u8);
            from_primitive!(from_u16, $t, u16);
            from_primitive!(from_u32, $t, u32);
            from_primitive!(from_u64, $t, u64);
            from_primitive!(from_u128, $t, u128);

            from_primitive!(from_isize, $t, isize);
            from_primitive!(from_i8, $t, i8);
            from_primitive!(from_i16, $t, i16);
            from_primitive!(from_i32, $t, i32);
            from_primitive!(from_i64, $t, i64);
            from_primitive!(from_i128, $t, i128);

            from_primitive!(from_f32, $t, f32);
            from_primitive!(from_f64, $t, f64);
        }
    );
}

trait_from_primitive!(usize);
trait_from_primitive!(u8);
trait_from_primitive!(u16);
trait_from_primitive!(u32);
trait_from_primitive!(u64);
trait_from_primitive!(u128);

trait_from_primitive!(isize);
trait_from_primitive!(i8);
trait_from_primitive!(i16);
trait_from_primitive!(i32);
trait_from_primitive!(i64);
trait_from_primitive!(i128);


macro_rules! from_primitive_bool {
    ($n:ident, $f:ident, $zero:expr) => (
        #[inline(always)]
        fn $n(f: $f) -> Self { if f != $zero {true} else {false} }
    );
}

macro_rules! trait_bool_from_primitive {
    ($t:ident) => (
        impl FromPrimitive for $t {
            from_primitive_bool!(from_bool, bool, false);

            from_primitive_bool!(from_usize, usize, 0);
            from_primitive_bool!(from_u8, u8, 0);
            from_primitive_bool!(from_u16, u16, 0);
            from_primitive_bool!(from_u32, u32, 0);
            from_primitive_bool!(from_u64, u64, 0);
            from_primitive_bool!(from_u128, u128, 0);

            from_primitive_bool!(from_isize, isize, 0);
            from_primitive_bool!(from_i8, i8, 0);
            from_primitive_bool!(from_i16, i16, 0);
            from_primitive_bool!(from_i32, i32, 0);
            from_primitive_bool!(from_i64, i64, 0);
            from_primitive_bool!(from_i128, i128, 0);

            from_primitive_bool!(from_f32, f32, 0f32);
            from_primitive_bool!(from_f64, f64, 0f64);
        }
    );
}


trait_bool_from_primitive!(bool);


macro_rules! trait_float_from_primitive {
    ($t:ident, $a:ident) => (
        impl FromPrimitive for $t {
            from_primitive!(from_bool, $t, bool, $a);

            from_primitive!(from_usize, $t, usize);
            from_primitive!(from_u8, $t, u8);
            from_primitive!(from_u16, $t, u16);
            from_primitive!(from_u32, $t, u32);
            from_primitive!(from_u64, $t, u64);
            from_primitive!(from_u128, $t, u128);

            from_primitive!(from_isize, $t, isize);
            from_primitive!(from_i8, $t, i8);
            from_primitive!(from_i16, $t, i16);
            from_primitive!(from_i32, $t, i32);
            from_primitive!(from_i64, $t, i64);
            from_primitive!(from_i128, $t, i128);

            from_primitive!(from_f32, $t, f32);
            from_primitive!(from_f64, $t, f64);
        }
    );
}


trait_float_from_primitive!(f32, i32);
trait_float_from_primitive!(f64, i64);


impl<T> FromPrimitive for Wrapping<T>
    where T: FromPrimitive,
{
    #[inline(always)]
    fn from_bool(t: bool) -> Self { Wrapping(FromPrimitive::from_bool(t)) }

    #[inline(always)]
    fn from_usize(t: usize) -> Self { Wrapping(FromPrimitive::from_usize(t)) }
    #[inline(always)]
    fn from_u8(t: u8) -> Self { Wrapping(FromPrimitive::from_u8(t)) }
    #[inline(always)]
    fn from_u16(t: u16) -> Self { Wrapping(FromPrimitive::from_u16(t)) }
    #[inline(always)]
    fn from_u32(t: u32) -> Self { Wrapping(FromPrimitive::from_u32(t)) }
    #[inline(always)]
    fn from_u64(t: u64) -> Self { Wrapping(FromPrimitive::from_u64(t)) }
    #[inline(always)]
    fn from_u128(t: u128) -> Self { Wrapping(FromPrimitive::from_u128(t)) }

    #[inline(always)]
    fn from_isize(t: isize) -> Self { Wrapping(FromPrimitive::from_isize(t)) }
    #[inline(always)]
    fn from_i8(t: i8) -> Self { Wrapping(FromPrimitive::from_i8(t)) }
    #[inline(always)]
    fn from_i16(t: i16) -> Self { Wrapping(FromPrimitive::from_i16(t)) }
    #[inline(always)]
    fn from_i32(t: i32) -> Self { Wrapping(FromPrimitive::from_i32(t)) }
    #[inline(always)]
    fn from_i64(t: i64) -> Self { Wrapping(FromPrimitive::from_i64(t)) }
    #[inline(always)]
    fn from_i128(t: i128) -> Self { Wrapping(FromPrimitive::from_i128(t)) }

    #[inline(always)]
    fn from_f32(t: f32) -> Self { Wrapping(FromPrimitive::from_f32(t)) }
    #[inline(always)]
    fn from_f64(t: f64) -> Self { Wrapping(FromPrimitive::from_f64(t)) }
}


#[cfg(test)]
mod test {
    use super::FromPrimitive;

    fn create_one<T: FromPrimitive>() -> T {
        T::from_f32(1_f32)
    }

    #[test]
    fn test_from_primitive() {
        assert_eq!(create_one::<bool>(), true);
        assert_eq!(create_one::<usize>(), 1_usize);
        assert_eq!(create_one::<f32>(), 1_f32);
    }
}