]>
Commit | Line | Data |
---|---|---|
8bb4bdeb | 1 | use std::mem::size_of; |
041b39d2 | 2 | use std::num::Wrapping; |
8bb4bdeb XL |
3 | |
4 | use identities::Zero; | |
5 | use bounds::Bounded; | |
6 | ||
7 | /// A generic trait for converting a value to a number. | |
8 | pub trait ToPrimitive { | |
9 | /// Converts the value of `self` to an `isize`. | |
10 | #[inline] | |
11 | fn to_isize(&self) -> Option<isize> { | |
12 | self.to_i64().and_then(|x| x.to_isize()) | |
13 | } | |
14 | ||
15 | /// Converts the value of `self` to an `i8`. | |
16 | #[inline] | |
17 | fn to_i8(&self) -> Option<i8> { | |
18 | self.to_i64().and_then(|x| x.to_i8()) | |
19 | } | |
20 | ||
21 | /// Converts the value of `self` to an `i16`. | |
22 | #[inline] | |
23 | fn to_i16(&self) -> Option<i16> { | |
24 | self.to_i64().and_then(|x| x.to_i16()) | |
25 | } | |
26 | ||
27 | /// Converts the value of `self` to an `i32`. | |
28 | #[inline] | |
29 | fn to_i32(&self) -> Option<i32> { | |
30 | self.to_i64().and_then(|x| x.to_i32()) | |
31 | } | |
32 | ||
33 | /// Converts the value of `self` to an `i64`. | |
34 | fn to_i64(&self) -> Option<i64>; | |
35 | ||
36 | /// Converts the value of `self` to a `usize`. | |
37 | #[inline] | |
38 | fn to_usize(&self) -> Option<usize> { | |
39 | self.to_u64().and_then(|x| x.to_usize()) | |
40 | } | |
41 | ||
42 | /// Converts the value of `self` to an `u8`. | |
43 | #[inline] | |
44 | fn to_u8(&self) -> Option<u8> { | |
45 | self.to_u64().and_then(|x| x.to_u8()) | |
46 | } | |
47 | ||
48 | /// Converts the value of `self` to an `u16`. | |
49 | #[inline] | |
50 | fn to_u16(&self) -> Option<u16> { | |
51 | self.to_u64().and_then(|x| x.to_u16()) | |
52 | } | |
53 | ||
54 | /// Converts the value of `self` to an `u32`. | |
55 | #[inline] | |
56 | fn to_u32(&self) -> Option<u32> { | |
57 | self.to_u64().and_then(|x| x.to_u32()) | |
58 | } | |
59 | ||
60 | /// Converts the value of `self` to an `u64`. | |
61 | #[inline] | |
62 | fn to_u64(&self) -> Option<u64>; | |
63 | ||
64 | /// Converts the value of `self` to an `f32`. | |
65 | #[inline] | |
66 | fn to_f32(&self) -> Option<f32> { | |
67 | self.to_f64().and_then(|x| x.to_f32()) | |
68 | } | |
69 | ||
70 | /// Converts the value of `self` to an `f64`. | |
71 | #[inline] | |
72 | fn to_f64(&self) -> Option<f64> { | |
73 | self.to_i64().and_then(|x| x.to_f64()) | |
74 | } | |
75 | } | |
76 | ||
77 | macro_rules! impl_to_primitive_int_to_int { | |
78 | ($SrcT:ty, $DstT:ty, $slf:expr) => ( | |
79 | { | |
80 | if size_of::<$SrcT>() <= size_of::<$DstT>() { | |
81 | Some($slf as $DstT) | |
82 | } else { | |
83 | let n = $slf as i64; | |
84 | let min_value: $DstT = Bounded::min_value(); | |
85 | let max_value: $DstT = Bounded::max_value(); | |
86 | if min_value as i64 <= n && n <= max_value as i64 { | |
87 | Some($slf as $DstT) | |
88 | } else { | |
89 | None | |
90 | } | |
91 | } | |
92 | } | |
93 | ) | |
94 | } | |
95 | ||
96 | macro_rules! impl_to_primitive_int_to_uint { | |
97 | ($SrcT:ty, $DstT:ty, $slf:expr) => ( | |
98 | { | |
99 | let zero: $SrcT = Zero::zero(); | |
100 | let max_value: $DstT = Bounded::max_value(); | |
101 | if zero <= $slf && $slf as u64 <= max_value as u64 { | |
102 | Some($slf as $DstT) | |
103 | } else { | |
104 | None | |
105 | } | |
106 | } | |
107 | ) | |
108 | } | |
109 | ||
110 | macro_rules! impl_to_primitive_int { | |
111 | ($T:ty) => ( | |
112 | impl ToPrimitive for $T { | |
113 | #[inline] | |
114 | fn to_isize(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) } | |
115 | #[inline] | |
116 | fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) } | |
117 | #[inline] | |
118 | fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) } | |
119 | #[inline] | |
120 | fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) } | |
121 | #[inline] | |
122 | fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) } | |
123 | ||
124 | #[inline] | |
125 | fn to_usize(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) } | |
126 | #[inline] | |
127 | fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) } | |
128 | #[inline] | |
129 | fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) } | |
130 | #[inline] | |
131 | fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) } | |
132 | #[inline] | |
133 | fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) } | |
134 | ||
135 | #[inline] | |
136 | fn to_f32(&self) -> Option<f32> { Some(*self as f32) } | |
137 | #[inline] | |
138 | fn to_f64(&self) -> Option<f64> { Some(*self as f64) } | |
139 | } | |
140 | ) | |
141 | } | |
142 | ||
143 | impl_to_primitive_int!(isize); | |
144 | impl_to_primitive_int!(i8); | |
145 | impl_to_primitive_int!(i16); | |
146 | impl_to_primitive_int!(i32); | |
147 | impl_to_primitive_int!(i64); | |
148 | ||
149 | macro_rules! impl_to_primitive_uint_to_int { | |
150 | ($DstT:ty, $slf:expr) => ( | |
151 | { | |
152 | let max_value: $DstT = Bounded::max_value(); | |
153 | if $slf as u64 <= max_value as u64 { | |
154 | Some($slf as $DstT) | |
155 | } else { | |
156 | None | |
157 | } | |
158 | } | |
159 | ) | |
160 | } | |
161 | ||
162 | macro_rules! impl_to_primitive_uint_to_uint { | |
163 | ($SrcT:ty, $DstT:ty, $slf:expr) => ( | |
164 | { | |
165 | if size_of::<$SrcT>() <= size_of::<$DstT>() { | |
166 | Some($slf as $DstT) | |
167 | } else { | |
168 | let zero: $SrcT = Zero::zero(); | |
169 | let max_value: $DstT = Bounded::max_value(); | |
170 | if zero <= $slf && $slf as u64 <= max_value as u64 { | |
171 | Some($slf as $DstT) | |
172 | } else { | |
173 | None | |
174 | } | |
175 | } | |
176 | } | |
177 | ) | |
178 | } | |
179 | ||
180 | macro_rules! impl_to_primitive_uint { | |
181 | ($T:ty) => ( | |
182 | impl ToPrimitive for $T { | |
183 | #[inline] | |
184 | fn to_isize(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) } | |
185 | #[inline] | |
186 | fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) } | |
187 | #[inline] | |
188 | fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) } | |
189 | #[inline] | |
190 | fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) } | |
191 | #[inline] | |
192 | fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) } | |
193 | ||
194 | #[inline] | |
195 | fn to_usize(&self) -> Option<usize> { | |
196 | impl_to_primitive_uint_to_uint!($T, usize, *self) | |
197 | } | |
198 | #[inline] | |
199 | fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) } | |
200 | #[inline] | |
201 | fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) } | |
202 | #[inline] | |
203 | fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) } | |
204 | #[inline] | |
205 | fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) } | |
206 | ||
207 | #[inline] | |
208 | fn to_f32(&self) -> Option<f32> { Some(*self as f32) } | |
209 | #[inline] | |
210 | fn to_f64(&self) -> Option<f64> { Some(*self as f64) } | |
211 | } | |
212 | ) | |
213 | } | |
214 | ||
215 | impl_to_primitive_uint!(usize); | |
216 | impl_to_primitive_uint!(u8); | |
217 | impl_to_primitive_uint!(u16); | |
218 | impl_to_primitive_uint!(u32); | |
219 | impl_to_primitive_uint!(u64); | |
220 | ||
221 | macro_rules! impl_to_primitive_float_to_float { | |
222 | ($SrcT:ident, $DstT:ident, $slf:expr) => ( | |
223 | if size_of::<$SrcT>() <= size_of::<$DstT>() { | |
224 | Some($slf as $DstT) | |
225 | } else { | |
226 | // Make sure the value is in range for the cast. | |
227 | // NaN and +-inf are cast as they are. | |
228 | let n = $slf as f64; | |
229 | let max_value: $DstT = ::std::$DstT::MAX; | |
230 | if !n.is_finite() || (-max_value as f64 <= n && n <= max_value as f64) { | |
231 | Some($slf as $DstT) | |
232 | } else { | |
233 | None | |
234 | } | |
235 | } | |
236 | ) | |
237 | } | |
238 | ||
239 | macro_rules! impl_to_primitive_float { | |
240 | ($T:ident) => ( | |
241 | impl ToPrimitive for $T { | |
242 | #[inline] | |
243 | fn to_isize(&self) -> Option<isize> { Some(*self as isize) } | |
244 | #[inline] | |
245 | fn to_i8(&self) -> Option<i8> { Some(*self as i8) } | |
246 | #[inline] | |
247 | fn to_i16(&self) -> Option<i16> { Some(*self as i16) } | |
248 | #[inline] | |
249 | fn to_i32(&self) -> Option<i32> { Some(*self as i32) } | |
250 | #[inline] | |
251 | fn to_i64(&self) -> Option<i64> { Some(*self as i64) } | |
252 | ||
253 | #[inline] | |
254 | fn to_usize(&self) -> Option<usize> { Some(*self as usize) } | |
255 | #[inline] | |
256 | fn to_u8(&self) -> Option<u8> { Some(*self as u8) } | |
257 | #[inline] | |
258 | fn to_u16(&self) -> Option<u16> { Some(*self as u16) } | |
259 | #[inline] | |
260 | fn to_u32(&self) -> Option<u32> { Some(*self as u32) } | |
261 | #[inline] | |
262 | fn to_u64(&self) -> Option<u64> { Some(*self as u64) } | |
263 | ||
264 | #[inline] | |
265 | fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32, *self) } | |
266 | #[inline] | |
267 | fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64, *self) } | |
268 | } | |
269 | ) | |
270 | } | |
271 | ||
272 | impl_to_primitive_float!(f32); | |
273 | impl_to_primitive_float!(f64); | |
274 | ||
275 | /// A generic trait for converting a number to a value. | |
276 | pub trait FromPrimitive: Sized { | |
277 | /// Convert an `isize` to return an optional value of this type. If the | |
278 | /// value cannot be represented by this value, the `None` is returned. | |
279 | #[inline] | |
280 | fn from_isize(n: isize) -> Option<Self> { | |
281 | FromPrimitive::from_i64(n as i64) | |
282 | } | |
283 | ||
284 | /// Convert an `i8` to return an optional value of this type. If the | |
285 | /// type cannot be represented by this value, the `None` is returned. | |
286 | #[inline] | |
287 | fn from_i8(n: i8) -> Option<Self> { | |
288 | FromPrimitive::from_i64(n as i64) | |
289 | } | |
290 | ||
291 | /// Convert an `i16` to return an optional value of this type. If the | |
292 | /// type cannot be represented by this value, the `None` is returned. | |
293 | #[inline] | |
294 | fn from_i16(n: i16) -> Option<Self> { | |
295 | FromPrimitive::from_i64(n as i64) | |
296 | } | |
297 | ||
298 | /// Convert an `i32` to return an optional value of this type. If the | |
299 | /// type cannot be represented by this value, the `None` is returned. | |
300 | #[inline] | |
301 | fn from_i32(n: i32) -> Option<Self> { | |
302 | FromPrimitive::from_i64(n as i64) | |
303 | } | |
304 | ||
305 | /// Convert an `i64` to return an optional value of this type. If the | |
306 | /// type cannot be represented by this value, the `None` is returned. | |
307 | fn from_i64(n: i64) -> Option<Self>; | |
308 | ||
309 | /// Convert a `usize` to return an optional value of this type. If the | |
310 | /// type cannot be represented by this value, the `None` is returned. | |
311 | #[inline] | |
312 | fn from_usize(n: usize) -> Option<Self> { | |
313 | FromPrimitive::from_u64(n as u64) | |
314 | } | |
315 | ||
316 | /// Convert an `u8` to return an optional value of this type. If the | |
317 | /// type cannot be represented by this value, the `None` is returned. | |
318 | #[inline] | |
319 | fn from_u8(n: u8) -> Option<Self> { | |
320 | FromPrimitive::from_u64(n as u64) | |
321 | } | |
322 | ||
323 | /// Convert an `u16` to return an optional value of this type. If the | |
324 | /// type cannot be represented by this value, the `None` is returned. | |
325 | #[inline] | |
326 | fn from_u16(n: u16) -> Option<Self> { | |
327 | FromPrimitive::from_u64(n as u64) | |
328 | } | |
329 | ||
330 | /// Convert an `u32` to return an optional value of this type. If the | |
331 | /// type cannot be represented by this value, the `None` is returned. | |
332 | #[inline] | |
333 | fn from_u32(n: u32) -> Option<Self> { | |
334 | FromPrimitive::from_u64(n as u64) | |
335 | } | |
336 | ||
337 | /// Convert an `u64` to return an optional value of this type. If the | |
338 | /// type cannot be represented by this value, the `None` is returned. | |
339 | fn from_u64(n: u64) -> Option<Self>; | |
340 | ||
341 | /// Convert a `f32` to return an optional value of this type. If the | |
342 | /// type cannot be represented by this value, the `None` is returned. | |
343 | #[inline] | |
344 | fn from_f32(n: f32) -> Option<Self> { | |
345 | FromPrimitive::from_f64(n as f64) | |
346 | } | |
347 | ||
348 | /// Convert a `f64` to return an optional value of this type. If the | |
349 | /// type cannot be represented by this value, the `None` is returned. | |
350 | #[inline] | |
351 | fn from_f64(n: f64) -> Option<Self> { | |
352 | FromPrimitive::from_i64(n as i64) | |
353 | } | |
354 | } | |
355 | ||
356 | macro_rules! impl_from_primitive { | |
357 | ($T:ty, $to_ty:ident) => ( | |
358 | #[allow(deprecated)] | |
359 | impl FromPrimitive for $T { | |
360 | #[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() } | |
361 | #[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() } | |
362 | #[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() } | |
363 | #[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() } | |
364 | ||
365 | #[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() } | |
366 | #[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() } | |
367 | #[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() } | |
368 | #[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() } | |
369 | ||
370 | #[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() } | |
371 | #[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() } | |
372 | } | |
373 | ) | |
374 | } | |
375 | ||
376 | impl_from_primitive!(isize, to_isize); | |
377 | impl_from_primitive!(i8, to_i8); | |
378 | impl_from_primitive!(i16, to_i16); | |
379 | impl_from_primitive!(i32, to_i32); | |
380 | impl_from_primitive!(i64, to_i64); | |
381 | impl_from_primitive!(usize, to_usize); | |
382 | impl_from_primitive!(u8, to_u8); | |
383 | impl_from_primitive!(u16, to_u16); | |
384 | impl_from_primitive!(u32, to_u32); | |
385 | impl_from_primitive!(u64, to_u64); | |
386 | impl_from_primitive!(f32, to_f32); | |
387 | impl_from_primitive!(f64, to_f64); | |
388 | ||
041b39d2 XL |
389 | |
390 | impl<T: ToPrimitive> ToPrimitive for Wrapping<T> { | |
391 | fn to_i64(&self) -> Option<i64> { self.0.to_i64() } | |
392 | fn to_u64(&self) -> Option<u64> { self.0.to_u64() } | |
393 | } | |
394 | impl<T: FromPrimitive> FromPrimitive for Wrapping<T> { | |
395 | fn from_u64(n: u64) -> Option<Self> { T::from_u64(n).map(Wrapping) } | |
396 | fn from_i64(n: i64) -> Option<Self> { T::from_i64(n).map(Wrapping) } | |
397 | } | |
398 | ||
399 | ||
8bb4bdeb XL |
400 | /// Cast from one machine scalar to another. |
401 | /// | |
402 | /// # Examples | |
403 | /// | |
404 | /// ``` | |
405 | /// # use num_traits as num; | |
406 | /// let twenty: f32 = num::cast(0x14).unwrap(); | |
407 | /// assert_eq!(twenty, 20f32); | |
408 | /// ``` | |
409 | /// | |
410 | #[inline] | |
411 | pub fn cast<T: NumCast, U: NumCast>(n: T) -> Option<U> { | |
412 | NumCast::from(n) | |
413 | } | |
414 | ||
415 | /// An interface for casting between machine scalars. | |
416 | pub trait NumCast: Sized + ToPrimitive { | |
417 | /// Creates a number from another value that can be converted into | |
418 | /// a primitive via the `ToPrimitive` trait. | |
419 | fn from<T: ToPrimitive>(n: T) -> Option<Self>; | |
420 | } | |
421 | ||
422 | macro_rules! impl_num_cast { | |
423 | ($T:ty, $conv:ident) => ( | |
424 | impl NumCast for $T { | |
425 | #[inline] | |
426 | #[allow(deprecated)] | |
427 | fn from<N: ToPrimitive>(n: N) -> Option<$T> { | |
428 | // `$conv` could be generated using `concat_idents!`, but that | |
429 | // macro seems to be broken at the moment | |
430 | n.$conv() | |
431 | } | |
432 | } | |
433 | ) | |
434 | } | |
435 | ||
436 | impl_num_cast!(u8, to_u8); | |
437 | impl_num_cast!(u16, to_u16); | |
438 | impl_num_cast!(u32, to_u32); | |
439 | impl_num_cast!(u64, to_u64); | |
440 | impl_num_cast!(usize, to_usize); | |
441 | impl_num_cast!(i8, to_i8); | |
442 | impl_num_cast!(i16, to_i16); | |
443 | impl_num_cast!(i32, to_i32); | |
444 | impl_num_cast!(i64, to_i64); | |
445 | impl_num_cast!(isize, to_isize); | |
446 | impl_num_cast!(f32, to_f32); | |
447 | impl_num_cast!(f64, to_f64); | |
448 | ||
041b39d2 XL |
449 | impl<T: NumCast> NumCast for Wrapping<T> { |
450 | fn from<U: ToPrimitive>(n: U) -> Option<Self> { | |
451 | T::from(n).map(Wrapping) | |
452 | } | |
453 | } | |
8bb4bdeb XL |
454 | |
455 | #[test] | |
456 | fn to_primitive_float() { | |
457 | use std::f32; | |
458 | use std::f64; | |
459 | ||
460 | let f32_toolarge = 1e39f64; | |
461 | assert_eq!(f32_toolarge.to_f32(), None); | |
462 | assert_eq!((f32::MAX as f64).to_f32(), Some(f32::MAX)); | |
463 | assert_eq!((-f32::MAX as f64).to_f32(), Some(-f32::MAX)); | |
464 | assert_eq!(f64::INFINITY.to_f32(), Some(f32::INFINITY)); | |
465 | assert_eq!((f64::NEG_INFINITY).to_f32(), Some(f32::NEG_INFINITY)); | |
466 | assert!((f64::NAN).to_f32().map_or(false, |f| f.is_nan())); | |
467 | } | |
041b39d2 XL |
468 | |
469 | macro_rules! test_wrapping_to_primitive { | |
470 | ($($t:ty)+) => { | |
471 | $({ | |
472 | let i: $t = 0; | |
473 | let w = Wrapping(i); | |
474 | assert_eq!(i.to_u8(), w.to_u8()); | |
475 | assert_eq!(i.to_u16(), w.to_u16()); | |
476 | assert_eq!(i.to_u32(), w.to_u32()); | |
477 | assert_eq!(i.to_u64(), w.to_u64()); | |
478 | assert_eq!(i.to_usize(), w.to_usize()); | |
479 | assert_eq!(i.to_i8(), w.to_i8()); | |
480 | assert_eq!(i.to_i16(), w.to_i16()); | |
481 | assert_eq!(i.to_i32(), w.to_i32()); | |
482 | assert_eq!(i.to_i64(), w.to_i64()); | |
483 | assert_eq!(i.to_isize(), w.to_isize()); | |
484 | assert_eq!(i.to_f32(), w.to_f32()); | |
485 | assert_eq!(i.to_f64(), w.to_f64()); | |
486 | })+ | |
487 | }; | |
488 | } | |
489 | ||
490 | #[test] | |
491 | fn wrapping_to_primitive() { | |
492 | test_wrapping_to_primitive!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); | |
493 | } | |
494 | ||
495 | #[test] | |
496 | fn wrapping_is_toprimitive() { | |
497 | fn require_toprimitive<T: ToPrimitive>(_: &T) {} | |
498 | require_toprimitive(&Wrapping(42)); | |
499 | } | |
500 | ||
501 | #[test] | |
502 | fn wrapping_is_fromprimitive() { | |
503 | fn require_fromprimitive<T: FromPrimitive>(_: &T) {} | |
504 | require_fromprimitive(&Wrapping(42)); | |
505 | } | |
506 | ||
507 | #[test] | |
508 | fn wrapping_is_numcast() { | |
509 | fn require_numcast<T: NumCast>(_: &T) {} | |
510 | require_numcast(&Wrapping(42)); | |
511 | } |