]>
Commit | Line | Data |
---|---|---|
7cac9316 XL |
1 | // Copyright 2013-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 | ||
11 | // Extracted from https://github.com/rust-num/num. | |
12 | ||
13 | // Rust 1.5 is unhappy that this private module is undocumented. | |
14 | #![allow(missing_docs)] | |
15 | ||
16 | use core::{usize, u8, u16, u32, u64}; | |
17 | use core::{isize, i8, i16, i32, i64}; | |
18 | use core::{f32, f64}; | |
19 | use core::mem::size_of; | |
20 | ||
21 | /// Numbers which have upper and lower bounds | |
22 | pub trait Bounded { | |
23 | // FIXME (#5527): These should be associated constants | |
24 | /// returns the smallest finite number this type can represent | |
25 | fn min_value() -> Self; | |
26 | /// returns the largest finite number this type can represent | |
27 | fn max_value() -> Self; | |
28 | } | |
29 | ||
30 | macro_rules! bounded_impl { | |
31 | ($t:ty, $min:expr, $max:expr) => { | |
32 | impl Bounded for $t { | |
33 | #[inline] | |
34 | fn min_value() -> $t { $min } | |
35 | ||
36 | #[inline] | |
37 | fn max_value() -> $t { $max } | |
38 | } | |
39 | } | |
40 | } | |
41 | ||
42 | bounded_impl!(usize, usize::MIN, usize::MAX); | |
43 | bounded_impl!(u8, u8::MIN, u8::MAX); | |
44 | bounded_impl!(u16, u16::MIN, u16::MAX); | |
45 | bounded_impl!(u32, u32::MIN, u32::MAX); | |
46 | bounded_impl!(u64, u64::MIN, u64::MAX); | |
47 | ||
48 | bounded_impl!(isize, isize::MIN, isize::MAX); | |
49 | bounded_impl!(i8, i8::MIN, i8::MAX); | |
50 | bounded_impl!(i16, i16::MIN, i16::MAX); | |
51 | bounded_impl!(i32, i32::MIN, i32::MAX); | |
52 | bounded_impl!(i64, i64::MIN, i64::MAX); | |
53 | ||
54 | bounded_impl!(f32, f32::MIN, f32::MAX); | |
55 | bounded_impl!(f64, f64::MIN, f64::MAX); | |
56 | ||
57 | /// A generic trait for converting a value to a number. | |
58 | pub trait ToPrimitive { | |
59 | /// Converts the value of `self` to an `isize`. | |
60 | #[inline] | |
61 | fn to_isize(&self) -> Option<isize> { | |
62 | self.to_i64().and_then(|x| x.to_isize()) | |
63 | } | |
64 | ||
65 | /// Converts the value of `self` to an `i8`. | |
66 | #[inline] | |
67 | fn to_i8(&self) -> Option<i8> { | |
68 | self.to_i64().and_then(|x| x.to_i8()) | |
69 | } | |
70 | ||
71 | /// Converts the value of `self` to an `i16`. | |
72 | #[inline] | |
73 | fn to_i16(&self) -> Option<i16> { | |
74 | self.to_i64().and_then(|x| x.to_i16()) | |
75 | } | |
76 | ||
77 | /// Converts the value of `self` to an `i32`. | |
78 | #[inline] | |
79 | fn to_i32(&self) -> Option<i32> { | |
80 | self.to_i64().and_then(|x| x.to_i32()) | |
81 | } | |
82 | ||
83 | /// Converts the value of `self` to an `i64`. | |
84 | fn to_i64(&self) -> Option<i64>; | |
85 | ||
86 | /// Converts the value of `self` to a `usize`. | |
87 | #[inline] | |
88 | fn to_usize(&self) -> Option<usize> { | |
89 | self.to_u64().and_then(|x| x.to_usize()) | |
90 | } | |
91 | ||
92 | /// Converts the value of `self` to an `u8`. | |
93 | #[inline] | |
94 | fn to_u8(&self) -> Option<u8> { | |
95 | self.to_u64().and_then(|x| x.to_u8()) | |
96 | } | |
97 | ||
98 | /// Converts the value of `self` to an `u16`. | |
99 | #[inline] | |
100 | fn to_u16(&self) -> Option<u16> { | |
101 | self.to_u64().and_then(|x| x.to_u16()) | |
102 | } | |
103 | ||
104 | /// Converts the value of `self` to an `u32`. | |
105 | #[inline] | |
106 | fn to_u32(&self) -> Option<u32> { | |
107 | self.to_u64().and_then(|x| x.to_u32()) | |
108 | } | |
109 | ||
110 | /// Converts the value of `self` to an `u64`. | |
111 | #[inline] | |
112 | fn to_u64(&self) -> Option<u64>; | |
113 | ||
114 | /// Converts the value of `self` to an `f32`. | |
115 | #[inline] | |
116 | fn to_f32(&self) -> Option<f32> { | |
117 | self.to_f64().and_then(|x| x.to_f32()) | |
118 | } | |
119 | ||
120 | /// Converts the value of `self` to an `f64`. | |
121 | #[inline] | |
122 | fn to_f64(&self) -> Option<f64> { | |
123 | self.to_i64().and_then(|x| x.to_f64()) | |
124 | } | |
125 | } | |
126 | ||
127 | macro_rules! impl_to_primitive_int_to_int { | |
128 | ($SrcT:ty, $DstT:ty, $slf:expr) => ( | |
129 | { | |
130 | if size_of::<$SrcT>() <= size_of::<$DstT>() { | |
131 | Some($slf as $DstT) | |
132 | } else { | |
133 | let n = $slf as i64; | |
134 | let min_value: $DstT = Bounded::min_value(); | |
135 | let max_value: $DstT = Bounded::max_value(); | |
136 | if min_value as i64 <= n && n <= max_value as i64 { | |
137 | Some($slf as $DstT) | |
138 | } else { | |
139 | None | |
140 | } | |
141 | } | |
142 | } | |
143 | ) | |
144 | } | |
145 | ||
146 | macro_rules! impl_to_primitive_int_to_uint { | |
147 | ($SrcT:ty, $DstT:ty, $slf:expr) => ( | |
148 | { | |
149 | let zero: $SrcT = 0; | |
150 | let max_value: $DstT = Bounded::max_value(); | |
151 | if zero <= $slf && $slf as u64 <= max_value as u64 { | |
152 | Some($slf as $DstT) | |
153 | } else { | |
154 | None | |
155 | } | |
156 | } | |
157 | ) | |
158 | } | |
159 | ||
160 | macro_rules! impl_to_primitive_int { | |
161 | ($T:ty) => ( | |
162 | impl ToPrimitive for $T { | |
163 | #[inline] | |
164 | fn to_isize(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) } | |
165 | #[inline] | |
166 | fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) } | |
167 | #[inline] | |
168 | fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) } | |
169 | #[inline] | |
170 | fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) } | |
171 | #[inline] | |
172 | fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) } | |
173 | ||
174 | #[inline] | |
175 | fn to_usize(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) } | |
176 | #[inline] | |
177 | fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) } | |
178 | #[inline] | |
179 | fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) } | |
180 | #[inline] | |
181 | fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) } | |
182 | #[inline] | |
183 | fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) } | |
184 | ||
185 | #[inline] | |
186 | fn to_f32(&self) -> Option<f32> { Some(*self as f32) } | |
187 | #[inline] | |
188 | fn to_f64(&self) -> Option<f64> { Some(*self as f64) } | |
189 | } | |
190 | ) | |
191 | } | |
192 | ||
193 | impl_to_primitive_int! { isize } | |
194 | impl_to_primitive_int! { i8 } | |
195 | impl_to_primitive_int! { i16 } | |
196 | impl_to_primitive_int! { i32 } | |
197 | impl_to_primitive_int! { i64 } | |
198 | ||
199 | macro_rules! impl_to_primitive_uint_to_int { | |
200 | ($DstT:ty, $slf:expr) => ( | |
201 | { | |
202 | let max_value: $DstT = Bounded::max_value(); | |
203 | if $slf as u64 <= max_value as u64 { | |
204 | Some($slf as $DstT) | |
205 | } else { | |
206 | None | |
207 | } | |
208 | } | |
209 | ) | |
210 | } | |
211 | ||
212 | macro_rules! impl_to_primitive_uint_to_uint { | |
213 | ($SrcT:ty, $DstT:ty, $slf:expr) => ( | |
214 | { | |
215 | if size_of::<$SrcT>() <= size_of::<$DstT>() { | |
216 | Some($slf as $DstT) | |
217 | } else { | |
218 | let zero: $SrcT = 0; | |
219 | let max_value: $DstT = Bounded::max_value(); | |
220 | if zero <= $slf && $slf as u64 <= max_value as u64 { | |
221 | Some($slf as $DstT) | |
222 | } else { | |
223 | None | |
224 | } | |
225 | } | |
226 | } | |
227 | ) | |
228 | } | |
229 | ||
230 | macro_rules! impl_to_primitive_uint { | |
231 | ($T:ty) => ( | |
232 | impl ToPrimitive for $T { | |
233 | #[inline] | |
234 | fn to_isize(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) } | |
235 | #[inline] | |
236 | fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) } | |
237 | #[inline] | |
238 | fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) } | |
239 | #[inline] | |
240 | fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) } | |
241 | #[inline] | |
242 | fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) } | |
243 | ||
244 | #[inline] | |
245 | fn to_usize(&self) -> Option<usize> { | |
246 | impl_to_primitive_uint_to_uint!($T, usize, *self) | |
247 | } | |
248 | #[inline] | |
249 | fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) } | |
250 | #[inline] | |
251 | fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) } | |
252 | #[inline] | |
253 | fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) } | |
254 | #[inline] | |
255 | fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) } | |
256 | ||
257 | #[inline] | |
258 | fn to_f32(&self) -> Option<f32> { Some(*self as f32) } | |
259 | #[inline] | |
260 | fn to_f64(&self) -> Option<f64> { Some(*self as f64) } | |
261 | } | |
262 | ) | |
263 | } | |
264 | ||
265 | impl_to_primitive_uint! { usize } | |
266 | impl_to_primitive_uint! { u8 } | |
267 | impl_to_primitive_uint! { u16 } | |
268 | impl_to_primitive_uint! { u32 } | |
269 | impl_to_primitive_uint! { u64 } | |
270 | ||
271 | macro_rules! impl_to_primitive_float_to_float { | |
272 | ($SrcT:ident, $DstT:ident, $slf:expr) => ( | |
273 | if size_of::<$SrcT>() <= size_of::<$DstT>() { | |
274 | Some($slf as $DstT) | |
275 | } else { | |
276 | let n = $slf as f64; | |
277 | let max_value: $SrcT = ::core::$SrcT::MAX; | |
278 | if -max_value as f64 <= n && n <= max_value as f64 { | |
279 | Some($slf as $DstT) | |
280 | } else { | |
281 | None | |
282 | } | |
283 | } | |
284 | ) | |
285 | } | |
286 | ||
287 | macro_rules! impl_to_primitive_float { | |
288 | ($T:ident) => ( | |
289 | impl ToPrimitive for $T { | |
290 | #[inline] | |
291 | fn to_isize(&self) -> Option<isize> { Some(*self as isize) } | |
292 | #[inline] | |
293 | fn to_i8(&self) -> Option<i8> { Some(*self as i8) } | |
294 | #[inline] | |
295 | fn to_i16(&self) -> Option<i16> { Some(*self as i16) } | |
296 | #[inline] | |
297 | fn to_i32(&self) -> Option<i32> { Some(*self as i32) } | |
298 | #[inline] | |
299 | fn to_i64(&self) -> Option<i64> { Some(*self as i64) } | |
300 | ||
301 | #[inline] | |
302 | fn to_usize(&self) -> Option<usize> { Some(*self as usize) } | |
303 | #[inline] | |
304 | fn to_u8(&self) -> Option<u8> { Some(*self as u8) } | |
305 | #[inline] | |
306 | fn to_u16(&self) -> Option<u16> { Some(*self as u16) } | |
307 | #[inline] | |
308 | fn to_u32(&self) -> Option<u32> { Some(*self as u32) } | |
309 | #[inline] | |
310 | fn to_u64(&self) -> Option<u64> { Some(*self as u64) } | |
311 | ||
312 | #[inline] | |
313 | fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32, *self) } | |
314 | #[inline] | |
315 | fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64, *self) } | |
316 | } | |
317 | ) | |
318 | } | |
319 | ||
320 | impl_to_primitive_float! { f32 } | |
321 | impl_to_primitive_float! { f64 } | |
322 | ||
323 | pub trait FromPrimitive: Sized { | |
324 | #[inline] | |
325 | fn from_isize(n: isize) -> Option<Self> { | |
326 | FromPrimitive::from_i64(n as i64) | |
327 | } | |
328 | ||
329 | #[inline] | |
330 | fn from_i8(n: i8) -> Option<Self> { | |
331 | FromPrimitive::from_i64(n as i64) | |
332 | } | |
333 | ||
334 | #[inline] | |
335 | fn from_i16(n: i16) -> Option<Self> { | |
336 | FromPrimitive::from_i64(n as i64) | |
337 | } | |
338 | ||
339 | #[inline] | |
340 | fn from_i32(n: i32) -> Option<Self> { | |
341 | FromPrimitive::from_i64(n as i64) | |
342 | } | |
343 | ||
344 | fn from_i64(n: i64) -> Option<Self>; | |
345 | ||
346 | #[inline] | |
347 | fn from_usize(n: usize) -> Option<Self> { | |
348 | FromPrimitive::from_u64(n as u64) | |
349 | } | |
350 | ||
351 | #[inline] | |
352 | fn from_u8(n: u8) -> Option<Self> { | |
353 | FromPrimitive::from_u64(n as u64) | |
354 | } | |
355 | ||
356 | #[inline] | |
357 | fn from_u16(n: u16) -> Option<Self> { | |
358 | FromPrimitive::from_u64(n as u64) | |
359 | } | |
360 | ||
361 | #[inline] | |
362 | fn from_u32(n: u32) -> Option<Self> { | |
363 | FromPrimitive::from_u64(n as u64) | |
364 | } | |
365 | ||
366 | fn from_u64(n: u64) -> Option<Self>; | |
367 | ||
368 | #[inline] | |
369 | fn from_f32(n: f32) -> Option<Self> { | |
370 | FromPrimitive::from_f64(n as f64) | |
371 | } | |
372 | ||
373 | #[inline] | |
374 | fn from_f64(n: f64) -> Option<Self> { | |
375 | FromPrimitive::from_i64(n as i64) | |
376 | } | |
377 | } | |
378 | ||
379 | macro_rules! impl_from_primitive { | |
380 | ($T:ty, $to_ty:ident) => ( | |
381 | impl FromPrimitive for $T { | |
382 | #[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() } | |
383 | #[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() } | |
384 | #[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() } | |
385 | #[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() } | |
386 | ||
387 | #[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() } | |
388 | #[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() } | |
389 | #[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() } | |
390 | #[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() } | |
391 | ||
392 | #[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() } | |
393 | #[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() } | |
394 | } | |
395 | ) | |
396 | } | |
397 | ||
398 | impl_from_primitive! { isize, to_isize } | |
399 | impl_from_primitive! { i8, to_i8 } | |
400 | impl_from_primitive! { i16, to_i16 } | |
401 | impl_from_primitive! { i32, to_i32 } | |
402 | impl_from_primitive! { i64, to_i64 } | |
403 | impl_from_primitive! { usize, to_usize } | |
404 | impl_from_primitive! { u8, to_u8 } | |
405 | impl_from_primitive! { u16, to_u16 } | |
406 | impl_from_primitive! { u32, to_u32 } | |
407 | impl_from_primitive! { u64, to_u64 } | |
408 | impl_from_primitive! { f32, to_f32 } | |
409 | impl_from_primitive! { f64, to_f64 } |