]> git.proxmox.com Git - rustc.git/blame - src/vendor/num-traits/src/cast.rs
New upstream version 1.20.0+dfsg1
[rustc.git] / src / vendor / num-traits / src / cast.rs
CommitLineData
8bb4bdeb 1use std::mem::size_of;
041b39d2 2use std::num::Wrapping;
8bb4bdeb
XL
3
4use identities::Zero;
5use bounds::Bounded;
6
7/// A generic trait for converting a value to a number.
8pub 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
77macro_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
96macro_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
110macro_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
143impl_to_primitive_int!(isize);
144impl_to_primitive_int!(i8);
145impl_to_primitive_int!(i16);
146impl_to_primitive_int!(i32);
147impl_to_primitive_int!(i64);
148
149macro_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
162macro_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
180macro_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
215impl_to_primitive_uint!(usize);
216impl_to_primitive_uint!(u8);
217impl_to_primitive_uint!(u16);
218impl_to_primitive_uint!(u32);
219impl_to_primitive_uint!(u64);
220
221macro_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
239macro_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
272impl_to_primitive_float!(f32);
273impl_to_primitive_float!(f64);
274
275/// A generic trait for converting a number to a value.
276pub 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
356macro_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
376impl_from_primitive!(isize, to_isize);
377impl_from_primitive!(i8, to_i8);
378impl_from_primitive!(i16, to_i16);
379impl_from_primitive!(i32, to_i32);
380impl_from_primitive!(i64, to_i64);
381impl_from_primitive!(usize, to_usize);
382impl_from_primitive!(u8, to_u8);
383impl_from_primitive!(u16, to_u16);
384impl_from_primitive!(u32, to_u32);
385impl_from_primitive!(u64, to_u64);
386impl_from_primitive!(f32, to_f32);
387impl_from_primitive!(f64, to_f64);
388
041b39d2
XL
389
390impl<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}
394impl<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]
411pub fn cast<T: NumCast, U: NumCast>(n: T) -> Option<U> {
412 NumCast::from(n)
413}
414
415/// An interface for casting between machine scalars.
416pub 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
422macro_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
436impl_num_cast!(u8, to_u8);
437impl_num_cast!(u16, to_u16);
438impl_num_cast!(u32, to_u32);
439impl_num_cast!(u64, to_u64);
440impl_num_cast!(usize, to_usize);
441impl_num_cast!(i8, to_i8);
442impl_num_cast!(i16, to_i16);
443impl_num_cast!(i32, to_i32);
444impl_num_cast!(i64, to_i64);
445impl_num_cast!(isize, to_isize);
446impl_num_cast!(f32, to_f32);
447impl_num_cast!(f64, to_f64);
448
041b39d2
XL
449impl<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]
456fn 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
469macro_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]
491fn wrapping_to_primitive() {
492 test_wrapping_to_primitive!(usize u8 u16 u32 u64 isize i8 i16 i32 i64);
493}
494
495#[test]
496fn wrapping_is_toprimitive() {
497 fn require_toprimitive<T: ToPrimitive>(_: &T) {}
498 require_toprimitive(&Wrapping(42));
499}
500
501#[test]
502fn wrapping_is_fromprimitive() {
503 fn require_fromprimitive<T: FromPrimitive>(_: &T) {}
504 require_fromprimitive(&Wrapping(42));
505}
506
507#[test]
508fn wrapping_is_numcast() {
509 fn require_numcast<T: NumCast>(_: &T) {}
510 require_numcast(&Wrapping(42));
511}