]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
a7813a04 | 11 | use core::convert::TryFrom; |
1a4d82fc | 12 | use core::cmp::PartialEq; |
85aaf69f | 13 | use core::fmt::Debug; |
1a4d82fc | 14 | use core::marker::Copy; |
a7813a04 XL |
15 | use core::ops::{Add, Sub, Mul, Div, Rem}; |
16 | use core::option::Option; | |
17 | use core::option::Option::{Some, None}; | |
1a4d82fc JJ |
18 | |
19 | #[macro_use] | |
20 | mod int_macros; | |
21 | ||
22 | mod i8; | |
23 | mod i16; | |
24 | mod i32; | |
25 | mod i64; | |
1a4d82fc JJ |
26 | |
27 | #[macro_use] | |
28 | mod uint_macros; | |
29 | ||
30 | mod u8; | |
31 | mod u16; | |
32 | mod u32; | |
33 | mod u64; | |
1a4d82fc | 34 | |
d9579d0f | 35 | mod flt2dec; |
e9174d1e | 36 | mod dec2flt; |
b039eaaf | 37 | mod bignum; |
d9579d0f | 38 | |
1a4d82fc JJ |
39 | /// Helper function for testing numeric operations |
40 | pub fn test_num<T>(ten: T, two: T) where | |
9346a6ac | 41 | T: PartialEq |
1a4d82fc JJ |
42 | + Add<Output=T> + Sub<Output=T> |
43 | + Mul<Output=T> + Div<Output=T> | |
85aaf69f | 44 | + Rem<Output=T> + Debug |
1a4d82fc JJ |
45 | + Copy |
46 | { | |
1a4d82fc JJ |
47 | assert_eq!(ten.add(two), ten + two); |
48 | assert_eq!(ten.sub(two), ten - two); | |
49 | assert_eq!(ten.mul(two), ten * two); | |
50 | assert_eq!(ten.div(two), ten / two); | |
51 | assert_eq!(ten.rem(two), ten % two); | |
52 | } | |
53 | ||
a7813a04 XL |
54 | #[test] |
55 | fn from_str_issue7588() { | |
56 | let u : Option<u8> = u8::from_str_radix("1000", 10).ok(); | |
57 | assert_eq!(u, None); | |
58 | let s : Option<i16> = i16::from_str_radix("80000", 10).ok(); | |
59 | assert_eq!(s, None); | |
60 | } | |
1a4d82fc | 61 | |
a7813a04 XL |
62 | #[test] |
63 | fn test_int_from_str_overflow() { | |
64 | let mut i8_val: i8 = 127; | |
65 | assert_eq!("127".parse::<i8>().ok(), Some(i8_val)); | |
66 | assert_eq!("128".parse::<i8>().ok(), None); | |
1a4d82fc | 67 | |
a7813a04 XL |
68 | i8_val = i8_val.wrapping_add(1); |
69 | assert_eq!("-128".parse::<i8>().ok(), Some(i8_val)); | |
70 | assert_eq!("-129".parse::<i8>().ok(), None); | |
1a4d82fc | 71 | |
a7813a04 XL |
72 | let mut i16_val: i16 = 32_767; |
73 | assert_eq!("32767".parse::<i16>().ok(), Some(i16_val)); | |
74 | assert_eq!("32768".parse::<i16>().ok(), None); | |
1a4d82fc | 75 | |
a7813a04 XL |
76 | i16_val = i16_val.wrapping_add(1); |
77 | assert_eq!("-32768".parse::<i16>().ok(), Some(i16_val)); | |
78 | assert_eq!("-32769".parse::<i16>().ok(), None); | |
1a4d82fc | 79 | |
a7813a04 XL |
80 | let mut i32_val: i32 = 2_147_483_647; |
81 | assert_eq!("2147483647".parse::<i32>().ok(), Some(i32_val)); | |
82 | assert_eq!("2147483648".parse::<i32>().ok(), None); | |
1a4d82fc | 83 | |
a7813a04 XL |
84 | i32_val = i32_val.wrapping_add(1); |
85 | assert_eq!("-2147483648".parse::<i32>().ok(), Some(i32_val)); | |
86 | assert_eq!("-2147483649".parse::<i32>().ok(), None); | |
1a4d82fc | 87 | |
a7813a04 XL |
88 | let mut i64_val: i64 = 9_223_372_036_854_775_807; |
89 | assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(i64_val)); | |
90 | assert_eq!("9223372036854775808".parse::<i64>().ok(), None); | |
1a4d82fc | 91 | |
a7813a04 XL |
92 | i64_val = i64_val.wrapping_add(1); |
93 | assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val)); | |
94 | assert_eq!("-9223372036854775809".parse::<i64>().ok(), None); | |
95 | } | |
96 | ||
97 | #[test] | |
98 | fn test_leading_plus() { | |
99 | assert_eq!("+127".parse::<u8>().ok(), Some(127)); | |
100 | assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807)); | |
101 | } | |
c34b1796 | 102 | |
a7813a04 XL |
103 | #[test] |
104 | fn test_invalid() { | |
105 | assert_eq!("--129".parse::<i8>().ok(), None); | |
106 | assert_eq!("++129".parse::<i8>().ok(), None); | |
107 | assert_eq!("Съешь".parse::<u8>().ok(), None); | |
108 | } | |
109 | ||
110 | #[test] | |
111 | fn test_empty() { | |
112 | assert_eq!("-".parse::<i8>().ok(), None); | |
113 | assert_eq!("+".parse::<i8>().ok(), None); | |
114 | assert_eq!("".parse::<u8>().ok(), None); | |
115 | } | |
116 | ||
117 | macro_rules! test_impl_from { | |
118 | ($fn_name: ident, $Small: ty, $Large: ty) => { | |
119 | #[test] | |
120 | fn $fn_name() { | |
121 | let small_max = <$Small>::max_value(); | |
122 | let small_min = <$Small>::min_value(); | |
123 | let large_max: $Large = small_max.into(); | |
124 | let large_min: $Large = small_min.into(); | |
125 | assert_eq!(large_max as $Small, small_max); | |
126 | assert_eq!(large_min as $Small, small_min); | |
127 | } | |
b039eaaf | 128 | } |
a7813a04 XL |
129 | } |
130 | ||
131 | // Unsigned -> Unsigned | |
132 | test_impl_from! { test_u8u16, u8, u16 } | |
133 | test_impl_from! { test_u8u32, u8, u32 } | |
134 | test_impl_from! { test_u8u64, u8, u64 } | |
135 | test_impl_from! { test_u8usize, u8, usize } | |
136 | test_impl_from! { test_u16u32, u16, u32 } | |
137 | test_impl_from! { test_u16u64, u16, u64 } | |
138 | test_impl_from! { test_u32u64, u32, u64 } | |
139 | ||
140 | // Signed -> Signed | |
141 | test_impl_from! { test_i8i16, i8, i16 } | |
142 | test_impl_from! { test_i8i32, i8, i32 } | |
143 | test_impl_from! { test_i8i64, i8, i64 } | |
144 | test_impl_from! { test_i8isize, i8, isize } | |
145 | test_impl_from! { test_i16i32, i16, i32 } | |
146 | test_impl_from! { test_i16i64, i16, i64 } | |
147 | test_impl_from! { test_i32i64, i32, i64 } | |
148 | ||
149 | // Unsigned -> Signed | |
150 | test_impl_from! { test_u8i16, u8, i16 } | |
151 | test_impl_from! { test_u8i32, u8, i32 } | |
152 | test_impl_from! { test_u8i64, u8, i64 } | |
153 | test_impl_from! { test_u16i32, u16, i32 } | |
154 | test_impl_from! { test_u16i64, u16, i64 } | |
155 | test_impl_from! { test_u32i64, u32, i64 } | |
156 | ||
157 | // Signed -> Float | |
158 | test_impl_from! { test_i8f32, i8, f32 } | |
159 | test_impl_from! { test_i8f64, i8, f64 } | |
160 | test_impl_from! { test_i16f32, i16, f32 } | |
161 | test_impl_from! { test_i16f64, i16, f64 } | |
162 | test_impl_from! { test_i32f64, i32, f64 } | |
163 | ||
164 | // Unsigned -> Float | |
165 | test_impl_from! { test_u8f32, u8, f32 } | |
166 | test_impl_from! { test_u8f64, u8, f64 } | |
167 | test_impl_from! { test_u16f32, u16, f32 } | |
168 | test_impl_from! { test_u16f64, u16, f64 } | |
169 | test_impl_from! { test_u32f64, u32, f64 } | |
170 | ||
171 | // Float -> Float | |
172 | #[test] | |
173 | fn test_f32f64() { | |
174 | use core::f32; | |
175 | ||
176 | let max: f64 = f32::MAX.into(); | |
177 | assert_eq!(max as f32, f32::MAX); | |
178 | assert!(max.is_normal()); | |
179 | ||
180 | let min: f64 = f32::MIN.into(); | |
181 | assert_eq!(min as f32, f32::MIN); | |
182 | assert!(min.is_normal()); | |
183 | ||
184 | let min_positive: f64 = f32::MIN_POSITIVE.into(); | |
185 | assert_eq!(min_positive as f32, f32::MIN_POSITIVE); | |
186 | assert!(min_positive.is_normal()); | |
187 | ||
188 | let epsilon: f64 = f32::EPSILON.into(); | |
189 | assert_eq!(epsilon as f32, f32::EPSILON); | |
190 | assert!(epsilon.is_normal()); | |
191 | ||
192 | let zero: f64 = (0.0f32).into(); | |
193 | assert_eq!(zero as f32, 0.0f32); | |
194 | assert!(zero.is_sign_positive()); | |
195 | ||
196 | let neg_zero: f64 = (-0.0f32).into(); | |
197 | assert_eq!(neg_zero as f32, -0.0f32); | |
198 | assert!(neg_zero.is_sign_negative()); | |
199 | ||
200 | let infinity: f64 = f32::INFINITY.into(); | |
201 | assert_eq!(infinity as f32, f32::INFINITY); | |
202 | assert!(infinity.is_infinite()); | |
203 | assert!(infinity.is_sign_positive()); | |
204 | ||
205 | let neg_infinity: f64 = f32::NEG_INFINITY.into(); | |
206 | assert_eq!(neg_infinity as f32, f32::NEG_INFINITY); | |
207 | assert!(neg_infinity.is_infinite()); | |
208 | assert!(neg_infinity.is_sign_negative()); | |
209 | ||
210 | let nan: f64 = f32::NAN.into(); | |
211 | assert!(nan.is_nan()); | |
212 | } | |
b039eaaf | 213 | |
a7813a04 XL |
214 | macro_rules! test_impl_try_from_always_ok { |
215 | ($fn_name:ident, $source:ty, $target: ty) => { | |
216 | #[test] | |
217 | fn $fn_name() { | |
218 | let max = <$source>::max_value(); | |
219 | let min = <$source>::min_value(); | |
220 | let zero: $source = 0; | |
221 | assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(), | |
222 | max as $target); | |
223 | assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(), | |
224 | min as $target); | |
225 | assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), | |
226 | zero as $target); | |
227 | } | |
c1a9b12d | 228 | } |
a7813a04 | 229 | } |
c1a9b12d | 230 | |
a7813a04 XL |
231 | test_impl_try_from_always_ok! { test_try_u8u8, u8, u8 } |
232 | test_impl_try_from_always_ok! { test_try_u8u16, u8, u16 } | |
233 | test_impl_try_from_always_ok! { test_try_u8u32, u8, u32 } | |
234 | test_impl_try_from_always_ok! { test_try_u8u64, u8, u64 } | |
235 | test_impl_try_from_always_ok! { test_try_u8i16, u8, i16 } | |
236 | test_impl_try_from_always_ok! { test_try_u8i32, u8, i32 } | |
237 | test_impl_try_from_always_ok! { test_try_u8i64, u8, i64 } | |
238 | ||
239 | test_impl_try_from_always_ok! { test_try_u16u16, u16, u16 } | |
240 | test_impl_try_from_always_ok! { test_try_u16u32, u16, u32 } | |
241 | test_impl_try_from_always_ok! { test_try_u16u64, u16, u64 } | |
242 | test_impl_try_from_always_ok! { test_try_u16i32, u16, i32 } | |
243 | test_impl_try_from_always_ok! { test_try_u16i64, u16, i64 } | |
244 | ||
245 | test_impl_try_from_always_ok! { test_try_u32u32, u32, u32 } | |
246 | test_impl_try_from_always_ok! { test_try_u32u64, u32, u64 } | |
247 | test_impl_try_from_always_ok! { test_try_u32i64, u32, i64 } | |
248 | ||
249 | test_impl_try_from_always_ok! { test_try_u64u64, u64, u64 } | |
250 | ||
251 | test_impl_try_from_always_ok! { test_try_i8i8, i8, i8 } | |
252 | test_impl_try_from_always_ok! { test_try_i8i16, i8, i16 } | |
253 | test_impl_try_from_always_ok! { test_try_i8i32, i8, i32 } | |
254 | test_impl_try_from_always_ok! { test_try_i8i64, i8, i64 } | |
255 | ||
256 | test_impl_try_from_always_ok! { test_try_i16i16, i16, i16 } | |
257 | test_impl_try_from_always_ok! { test_try_i16i32, i16, i32 } | |
258 | test_impl_try_from_always_ok! { test_try_i16i64, i16, i64 } | |
259 | ||
260 | test_impl_try_from_always_ok! { test_try_i32i32, i32, i32 } | |
261 | test_impl_try_from_always_ok! { test_try_i32i64, i32, i64 } | |
262 | ||
263 | test_impl_try_from_always_ok! { test_try_i64i64, i64, i64 } | |
264 | ||
265 | macro_rules! test_impl_try_from_signed_to_unsigned_upper_ok { | |
266 | ($fn_name:ident, $source:ty, $target:ty) => { | |
267 | #[test] | |
268 | fn $fn_name() { | |
269 | let max = <$source>::max_value(); | |
270 | let min = <$source>::min_value(); | |
271 | let zero: $source = 0; | |
272 | let neg_one: $source = -1; | |
273 | assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(), | |
274 | max as $target); | |
275 | assert!(<$target as TryFrom<$source>>::try_from(min).is_err()); | |
276 | assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), | |
277 | zero as $target); | |
278 | assert!(<$target as TryFrom<$source>>::try_from(neg_one).is_err()); | |
279 | } | |
c34b1796 | 280 | } |
a7813a04 | 281 | } |
b039eaaf | 282 | |
a7813a04 XL |
283 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u8, i8, u8 } |
284 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u16, i8, u16 } | |
285 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u32, i8, u32 } | |
286 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u64, i8, u64 } | |
287 | ||
288 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u16, i16, u16 } | |
289 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u32, i16, u32 } | |
290 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u64, i16, u64 } | |
291 | ||
292 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u32, i32, u32 } | |
293 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u64, i32, u64 } | |
294 | ||
295 | test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64u64, i64, u64 } | |
296 | ||
297 | macro_rules! test_impl_try_from_unsigned_to_signed_upper_err { | |
298 | ($fn_name:ident, $source:ty, $target:ty) => { | |
299 | #[test] | |
300 | fn $fn_name() { | |
301 | let max = <$source>::max_value(); | |
302 | let min = <$source>::min_value(); | |
303 | let zero: $source = 0; | |
304 | assert!(<$target as TryFrom<$source>>::try_from(max).is_err()); | |
305 | assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(), | |
306 | min as $target); | |
307 | assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), | |
308 | zero as $target); | |
b039eaaf SL |
309 | } |
310 | } | |
a7813a04 | 311 | } |
b039eaaf | 312 | |
a7813a04 XL |
313 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u8i8, u8, i8 } |
314 | ||
315 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i8, u16, i8 } | |
316 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16i16, u16, i16 } | |
317 | ||
318 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i8, u32, i8 } | |
319 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i16, u32, i16 } | |
320 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32i32, u32, i32 } | |
321 | ||
322 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i8, u64, i8 } | |
323 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i16, u64, i16 } | |
324 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i32, u64, i32 } | |
325 | test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i64, u64, i64 } | |
326 | ||
327 | macro_rules! test_impl_try_from_same_sign_err { | |
328 | ($fn_name:ident, $source:ty, $target:ty) => { | |
329 | #[test] | |
330 | fn $fn_name() { | |
331 | let max = <$source>::max_value(); | |
332 | let min = <$source>::min_value(); | |
333 | let zero: $source = 0; | |
334 | let t_max = <$target>::max_value(); | |
335 | let t_min = <$target>::min_value(); | |
336 | assert!(<$target as TryFrom<$source>>::try_from(max).is_err()); | |
337 | if min != 0 { | |
338 | assert!(<$target as TryFrom<$source>>::try_from(min).is_err()); | |
339 | } | |
340 | assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), | |
341 | zero as $target); | |
342 | assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source) | |
343 | .unwrap(), | |
344 | t_max as $target); | |
345 | assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source) | |
346 | .unwrap(), | |
347 | t_min as $target); | |
348 | } | |
92a42be0 | 349 | } |
1a4d82fc | 350 | } |
a7813a04 XL |
351 | |
352 | test_impl_try_from_same_sign_err! { test_try_u16u8, u16, u8 } | |
353 | ||
354 | test_impl_try_from_same_sign_err! { test_try_u32u8, u32, u8 } | |
355 | test_impl_try_from_same_sign_err! { test_try_u32u16, u32, u16 } | |
356 | ||
357 | test_impl_try_from_same_sign_err! { test_try_u64u8, u64, u8 } | |
358 | test_impl_try_from_same_sign_err! { test_try_u64u16, u64, u16 } | |
359 | test_impl_try_from_same_sign_err! { test_try_u64u32, u64, u32 } | |
360 | ||
361 | test_impl_try_from_same_sign_err! { test_try_i16i8, i16, i8 } | |
362 | ||
363 | test_impl_try_from_same_sign_err! { test_try_i32i8, i32, i8 } | |
364 | test_impl_try_from_same_sign_err! { test_try_i32i16, i32, i16 } | |
365 | ||
366 | test_impl_try_from_same_sign_err! { test_try_i64i8, i64, i8 } | |
367 | test_impl_try_from_same_sign_err! { test_try_i64i16, i64, i16 } | |
368 | test_impl_try_from_same_sign_err! { test_try_i64i32, i64, i32 } | |
8bb4bdeb XL |
369 | |
370 | macro_rules! test_impl_try_from_signed_to_unsigned_err { | |
371 | ($fn_name:ident, $source:ty, $target:ty) => { | |
372 | #[test] | |
373 | fn $fn_name() { | |
374 | let max = <$source>::max_value(); | |
375 | let min = <$source>::min_value(); | |
376 | let zero: $source = 0; | |
377 | let t_max = <$target>::max_value(); | |
378 | let t_min = <$target>::min_value(); | |
379 | assert!(<$target as TryFrom<$source>>::try_from(max).is_err()); | |
380 | assert!(<$target as TryFrom<$source>>::try_from(min).is_err()); | |
381 | assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), | |
382 | zero as $target); | |
383 | assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source) | |
384 | .unwrap(), | |
385 | t_max as $target); | |
386 | assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source) | |
387 | .unwrap(), | |
388 | t_min as $target); | |
389 | } | |
390 | } | |
391 | } | |
392 | ||
393 | test_impl_try_from_signed_to_unsigned_err! { test_try_i16u8, i16, u8 } | |
394 | ||
395 | test_impl_try_from_signed_to_unsigned_err! { test_try_i32u8, i32, u8 } | |
396 | test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 } | |
397 | ||
398 | test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 } | |
399 | test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 } | |
400 | test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 } |