1 // If `src` can be promoted to `$dst`, then it must be Ok to cast `dst` back to
2 // `$src`
3 macro_rules! promote_and_back {
4 ($($src:ident => $($dst:ident),+);+;) => {
5 mod demoting_to {
6 $(
7 mod $src {
8 mod from {
9 use crate::From;
10
11 $(
12 quickcheck! {
13 fn $dst(src: $src) -> bool {
14 $src::cast($dst::cast(src)).is_ok()
15 }
16 }
17 )+
18 }
19 }
20 )+
21 }
22 }
23 }
24
25 #[cfg(target_pointer_width = "32")]
26 promote_and_back! {
27 i8 => f32, f64, i16, i32, isize, i64 ;
28 i16 => f32, f64, i32, isize, i64 ;
29 i32 => f32, f64, i64 ;
30 isize => f32, f64, i64 ;
31 i64 => f32, f64 ;
32 u8 => f32, f64, i16, i32, isize, i64, u16, u32, usize, u64;
33 u16 => f32, f64, i32, isize, i64, u32, usize, u64;
34 u32 => f32, f64, i64, u64;
35 usize => f32, f64, i64, u64;
36 u64 => f32, f64 ;
37 }
38
39 #[cfg(target_pointer_width = "64")]
40 promote_and_back! {
41 i8 => f32, f64, i16, i32, i64, isize ;
42 i16 => f32, f64, i32, i64, isize ;
43 i32 => f32, f64, i64, isize ;
44 i64 => f32, f64 ;
45 isize => f32, f64 ;
46 u8 => f32, f64, i16, i32, i64, isize, u16, u32, u64, usize;
47 u16 => f32, f64, i32, i64, isize, u32, u64, usize;
48 u32 => f32, f64, i64, isize, u64, usize;
49 u64 => f32, f64 ;
50 usize => f32, f64 ;
51 }
52
53 // TODO uncomment this once quickcheck supports Arbitrary for i128/u128
54 // https://github.com/BurntSushi/quickcheck/issues/162
55 /*#[cfg(feature = "x128")]
56 promote_and_back! {
57 i8 => i128 ;
58 i16 => i128 ;
59 i32 => i128 ;
60 isize => i128 ;
61 i64 => i128 ;
62 i128 => f32, f64 ;
63 u8 => i128, u128;
64 u16 => i128, u128;
65 u32 => i128, u128;
66 usize => i128, u128;
67 u64 => i128, u128;
68 u128 => f32, f64 ;
69 }*/
70
71 // If it's Ok to cast `src` to `$dst`, it must also be Ok to cast `dst` back to
72 // `$src`
73 macro_rules! symmetric_cast_between {
74 ($($src:ident => $($dst:ident),+);+;) => {
75 mod symmetric_cast_between {
76 $(
77 mod $src {
78 mod and {
79 use quickcheck::TestResult;
80
81 use crate::From;
82
83 $(
84 quickcheck! {
85 fn $dst(src: $src) -> TestResult {
86 if let Ok(dst) = $dst::cast(src) {
87 TestResult::from_bool(
88 $src::cast(dst).is_ok())
89 } else {
90 TestResult::discard()
91 }
92 }
93 }
94 )+
95 }
96 }
97 )+
98 }
99 }
100 }
101
102 #[cfg(target_pointer_width = "32")]
103 symmetric_cast_between! {
104 u8 => i8 ;
105 u16 => i8, i16 ;
106 u32 => i8, i16, i32 ;
107 usize => i8, i16, i32 ;
108 u64 => i8, i16, i32, i64, isize;
109 }
110
111 #[cfg(target_pointer_width = "64")]
112 symmetric_cast_between! {
113 u8 => i8 ;
114 u16 => i8, i16 ;
115 u32 => i8, i16, i32 ;
116 u64 => i8, i16, i32, i64, isize;
117 usize => i8, i16, i32, i64, isize;
118 }
119
120 // TODO uncomment this once quickcheck supports Arbitrary for i128/u128
121 // https://github.com/BurntSushi/quickcheck/issues/162
122 /*#[cfg(feature = "x128")]
123 symmetric_cast_between! {
124 u128 => i8, i16, i32, isize, i64, i128;
125 }*/
126
127 macro_rules! from_float {
128 ($($src:ident => $($dst:ident),+);+;) => {
129 $(
130 mod $src {
131 mod inf {
132 mod to {
133 use crate::{Error, From};
134
135 $(
136 #[test]
137 fn $dst() {
138 let _0: $src = 0.;
139 let _1: $src = 1.;
140 let inf = _1 / _0;
141 let neg_inf = -_1 / _0;
142
143 assert_eq!($dst::cast(inf),
144 Err(Error::Infinite));
145 assert_eq!($dst::cast(neg_inf),
146 Err(Error::Infinite));
147 }
148 )+
149 }
150 }
151
152 mod nan {
153 mod to {
154 use crate::{Error, From};
155
156 $(
157 #[test]
158 fn $dst() {
159 let _0: $src = 0.;
160 let nan = _0 / _0;
161
162 assert_eq!($dst::cast(nan),
163 Err(Error::NaN));
164 }
165 )+
166 }
167 }
168 }
169 )+
170 }
171 }
172
173 from_float! {
174 f32 => i8, i16, i32, i64, isize, u8, u16, u32, u64, usize;
175 f64 => i8, i16, i32, i64, isize, u8, u16, u32, u64, usize;
176 }
177
178 // TODO uncomment this once quickcheck supports Arbitrary for i128/u128
179 // https://github.com/BurntSushi/quickcheck/issues/162
180 /*#[cfg(feature = "x128")]
181 from_float! {
182 f32 => i128, u128;
183 f64 => i128, u128;
184 }*/
185
186 #[test]
187 #[cfg(feature = "x128")]
test_fl_conversion()188 fn test_fl_conversion() {
189 use u128;
190 assert_eq!(u128(42.0f32), Ok(42));
191 }
192
193 #[test]
gh16()194 fn gh16() {
195 assert_eq!(super::u64(-0.01_f64), Ok(0));
196 assert_eq!(super::u64(-0.99_f32), Ok(0));
197
198 assert_eq!(super::u32(-0.99_f64), Ok(0));
199 assert_eq!(super::u32(-0.01_f32), Ok(0));
200
201 assert_eq!(super::u64(0.01_f64), Ok(0));
202 assert_eq!(super::u64(0.99_f32), Ok(0));
203
204 assert_eq!(super::u32(0.99_f64), Ok(0));
205 assert_eq!(super::u32(0.01_f32), Ok(0));
206 }
207
208 #[test]
gh15()209 fn gh15() {
210 assert_eq!(super::u32(32_f32.exp2()), Err(super::Error::Overflow));
211 assert_eq!(super::u32(32_f64.exp2()), Err(super::Error::Overflow));
212
213 assert_eq!(super::u64(64_f32.exp2()), Err(super::Error::Overflow));
214 assert_eq!(super::u64(64_f64.exp2()), Err(super::Error::Overflow));
215
216 assert_eq!(super::u8(8_f32.exp2()), Err(super::Error::Overflow));
217 assert_eq!(super::u8(8_f64.exp2()), Err(super::Error::Overflow));
218
219 assert_eq!(super::u16(16_f32.exp2()), Err(super::Error::Overflow));
220 assert_eq!(super::u16(16_f64.exp2()), Err(super::Error::Overflow));
221 }
222