1macro_rules! max_of {
2 ($name:ident) => { ::std::$name::MAX };
3}
4
5macro_rules! min_of {
6 ($name:ident) => { ::std::$name::MIN };
7}
8
9macro_rules! approx_blind {
10 (($($attrs:tt)*), $src:ty, $dst:ty, $scheme:ty) => {
11 as_item! {
12 $($attrs)*
13 impl ::ApproxFrom<$src, $scheme> for $dst {
14 type Err = ::errors::NoError;
15 #[inline]
16 fn approx_from(src: $src) -> Result<$dst, Self::Err> {
17 Ok(src as $dst)
18 }
19 }
20 }
21 };
22}
23
24macro_rules! approx_z_to_dmax {
25 (($($attrs:tt)*), $src:ty, $dst:ident, $scheme:ty) => {
26 as_item! {
27 $($attrs)*
28 impl ::ApproxFrom<$src, $scheme> for $dst {
29 type Err = ::errors::RangeError<$src>;
30 #[inline]
31 fn approx_from(src: $src) -> Result<$dst, Self::Err> {
32 if !(0 <= src) {
33 return Err(::errors::RangeError::NegOverflow(src));
34 }
35 if !(src <= max_of!($dst) as $src) {
36 return Err(::errors::RangeError::PosOverflow(src));
37 }
38 Ok(src as $dst)
39 }
40 }
41 }
42 };
43}
44
45macro_rules! approx_to_dmax {
46 (($($attrs:tt)*), $src:ty, $dst:ident, $scheme:ty) => {
47 as_item! {
48 $($attrs)*
49 impl ::ApproxFrom<$src, $scheme> for $dst {
50 type Err = ::errors::PosOverflow<$src>;
51 #[inline]
52 fn approx_from(src: $src) -> Result<$dst, Self::Err> {
53 if !(src <= max_of!($dst) as $src) {
54 return Err(::errors::PosOverflow(src));
55 }
56 Ok(src as $dst)
57 }
58 }
59 }
60 };
61}
62
63macro_rules! approx_dmin_to_dmax {
64 (($($attrs:tt)*), $src:ty, $dst:ident, $scheme:ty) => {
65 as_item! {
66 $($attrs)*
67 impl ::ApproxFrom<$src, $scheme> for $dst {
68 type Err = ::errors::RangeError<$src>;
69 #[inline]
70 fn approx_from(src: $src) -> Result<$dst, Self::Err> {
71 if !(min_of!($dst) as $src <= src) {
72 return Err(::errors::RangeError::NegOverflow(src));
73 }
74 if !(src <= max_of!($dst) as $src) {
75 return Err(::errors::RangeError::PosOverflow(src));
76 }
77 Ok(src as $dst)
78 }
79 }
80 }
81 }
82}
83
84macro_rules! approx_z_up {
85 (($($attrs:tt)*), $src:ty, $dst:ident, $scheme:ty) => {
86 as_item! {
87 $($attrs)*
88 impl ::ApproxFrom<$src, $scheme> for $dst {
89 type Err = ::errors::NegOverflow<$src>;
90 #[inline]
91 fn approx_from(src: $src) -> Result<$dst, Self::Err> {
92 if !(0 <= src) {
93 return Err(::errors::NegOverflow(src));
94 }
95 Ok(src as $dst)
96 }
97 }
98 }
99 };
100}
101
102macro_rules! approx_dmin_to_dmax_no_nan {
103 (($($attrs:tt)*), $src:ty, $dst:ident, $scheme:ty) => {
104 approx_dmin_to_dmax_no_nan! { ($($attrs)*), $src, $dst, $scheme, approx: |s| s }
105 };
106
107 (($($attrs:tt)*), $src:ty, $dst:ident, $scheme:ty, approx: |$src_name:ident| $conv:expr) => {
108 approx_range_no_nan! {
109 ($($attrs)*), $src,
110 $dst, [min_of!($dst) as $src, max_of!($dst) as $src],
111 $scheme, approx: |$src_name| $conv
112 }
113 };
114}
115
116macro_rules! approx_range_no_nan {
117 (($($attrs:tt)*), $src:ty, $dst:ident, [$min:expr, $max:expr], $scheme:ty) => {
118 approx_range_no_nan! { ($($attrs)*), $src, $dst, [$min, $max], $scheme, approx: |s| s }
119 };
120
121 (($($attrs:tt)*), $src:ty, $dst:ident, [$min:expr, $max:expr], $scheme:ty, approx: |$src_name:ident| $conv:expr) => {
122 as_item! {
123 $($attrs)*
124 impl ::ApproxFrom<$src, $scheme> for $dst {
125 type Err = ::errors::FloatError<$src>;
126 #[inline]
127 fn approx_from(src: $src) -> Result<$dst, Self::Err> {
128 if src.is_nan() {
129 return Err(::errors::FloatError::NotANumber(src));
130 }
131 let approx = { let $src_name = src; $conv };
132 if !($min <= approx) {
133 return Err(::errors::FloatError::NegOverflow(src));
134 }
135 if !(approx <= $max) {
136 return Err(::errors::FloatError::PosOverflow(src));
137 }
138 Ok(approx as $dst)
139 }
140 }
141 }
142 };
143}
144
145macro_rules! num_conv {
146 (@ $src:ty=> $(,)*) => {};
147
148 (@ $src:ty=> #[32] $($tail:tt)*) => {
149 num_conv! { @ $src=> (#[cfg(target_pointer_width="32")]) $($tail)* }
150 };
151
152 (@ $src:ty=> #[64] $($tail:tt)*) => {
153 num_conv! { @ $src=> (#[cfg(target_pointer_width="64")]) $($tail)* }
154 };
155
156 (@ $src:ty=> e $($tail:tt)*) => { num_conv! { @ $src=> () e $($tail)* } };
157 (@ $src:ty=> n+ $($tail:tt)*) => { num_conv! { @ $src=> () n+ $($tail)* } };
158 (@ $src:ty=> n $($tail:tt)*) => { num_conv! { @ $src=> () n $($tail)* } };
159 (@ $src:ty=> w+ $($tail:tt)*) => { num_conv! { @ $src=> () w+ $($tail)* } };
160 (@ $src:ty=> w $($tail:tt)*) => { num_conv! { @ $src=> () w $($tail)* } };
161 (@ $src:ty=> aW $($tail:tt)*) => { num_conv! { @ $src=> () aW $($tail)* } };
162 (@ $src:ty=> nf $($tail:tt)*) => { num_conv! { @ $src=> () nf $($tail)* } };
163 (@ $src:ty=> fan $($tail:tt)*) => { num_conv! { @ $src=> () fan $($tail)* } };
164
165 (@ $src:ty=> ($($attrs:tt)*) e $dst:ty, $($tail:tt)*) => {
167 as_item! {
168 approx_blind! { ($($attrs)*), $src, $dst, ::DefaultApprox }
169 approx_blind! { ($($attrs)*), $src, $dst, ::Wrapping }
170
171 $($attrs)*
172 impl ::ValueFrom<$src> for $dst {
173 type Err = ::errors::NoError;
174 #[inline]
175 fn value_from(src: $src) -> Result<$dst, Self::Err> {
176 Ok(src as $dst)
177 }
178 }
179 }
180 num_conv! { @ $src=> $($tail)* }
181 };
182
183 (@ $src:ty=> ($($attrs:tt)*) n+ $dst:ident, $($tail:tt)*) => {
185 as_item! {
186 approx_z_to_dmax! { ($($attrs)*), $src, $dst, ::DefaultApprox }
187 approx_blind! { ($($attrs)*), $src, $dst, ::Wrapping }
188
189 $($attrs)*
190 impl ::ValueFrom<$src> for $dst {
191 type Err = ::errors::RangeError<$src>;
192 #[inline]
193 fn value_from(src: $src) -> Result<$dst, Self::Err> {
194 if !(0 <= src) {
195 return Err(::errors::RangeError::NegOverflow(src));
196 }
197 if !(src <= max_of!($dst) as $src) {
198 return Err(::errors::RangeError::PosOverflow(src));
199 }
200 Ok(src as $dst)
201 }
202 }
203 }
204 num_conv! { @ $src=> $($tail)* }
205 };
206
207 (@ $src:ty=> ($($attrs:tt)*) n- $dst:ident, $($tail:tt)*) => {
209 as_item! {
210 approx_to_dmax! { ($($attrs)*), $src, $dst, ::DefaultApprox }
211 approx_blind! { ($($attrs)*), $src, $dst, ::Wrapping }
212
213 $($attrs)*
214 impl ::ValueFrom<$src> for $dst {
215 type Err = ::errors::PosOverflow<$src>;
216 #[inline]
217 fn value_from(src: $src) -> Result<$dst, Self::Err> {
218 if !(src <= max_of!($dst) as $src) {
219 return Err(::errors::PosOverflow(src));
220 }
221 Ok(src as $dst)
222 }
223 }
224 }
225 num_conv! { @ $src=> $($tail)* }
226 };
227
228 (@ $src:ty=> ($($attrs:tt)*) n $dst:ident, $($tail:tt)*) => {
230 as_item! {
231 approx_dmin_to_dmax! { ($($attrs)*), $src, $dst, ::DefaultApprox }
232 approx_blind! { ($($attrs)*), $src, $dst, ::Wrapping }
233
234 $($attrs)*
235 impl ::ValueFrom<$src> for $dst {
236 type Err = ::errors::RangeError<$src>;
237 #[inline]
238 fn value_from(src: $src) -> Result<$dst, Self::Err> {
239 if !(min_of!($dst) as $src <= src) {
240 return Err(::errors::RangeError::NegOverflow(src));
241 }
242 if !(src <= max_of!($dst) as $src) {
243 return Err(::errors::RangeError::PosOverflow(src));
244 }
245 Ok(src as $dst)
246 }
247 }
248 }
249 num_conv! { @ $src=> $($tail)* }
250 };
251
252 (@ $src:ty=> ($($attrs:tt)*) w+ $dst:ident, $($tail:tt)*) => {
254 as_item! {
255 approx_z_up! { ($($attrs)*), $src, $dst, ::DefaultApprox }
256 approx_blind! { ($($attrs)*), $src, $dst, ::Wrapping }
257
258 $($attrs)*
259 impl ::ValueFrom<$src> for $dst {
260 type Err = ::errors::NegOverflow<$src>;
261 #[inline]
262 fn value_from(src: $src) -> Result<$dst, Self::Err> {
263 if !(0 <= src) {
264 return Err(::errors::NegOverflow(src));
265 }
266 Ok(src as $dst)
267 }
268 }
269 }
270 num_conv! { @ $src=> $($tail)* }
271 };
272
273 (@ $src:ty=> ($($attrs:tt)*) w $dst:ident, $($tail:tt)*) => {
275 as_item! {
276 approx_blind! { ($($attrs)*), $src, $dst, ::DefaultApprox }
277 approx_blind! { ($($attrs)*), $src, $dst, ::Wrapping }
278
279 $($attrs)*
280 impl ::ValueFrom<$src> for $dst {
281 type Err = ::errors::NoError;
282 #[inline]
283 fn value_from(src: $src) -> Result<$dst, Self::Err> {
284 Ok(src as $dst)
285 }
286 }
287 }
288 num_conv! { @ $src=> $($tail)* }
289 };
290
291 (@ $src:ty=> ($($attrs:tt)*) nf [+- $bound:expr] $dst:ident, $($tail:tt)*) => {
293 as_item! {
294 approx_blind! { ($($attrs)*), $src, $dst, ::DefaultApprox }
295
296 $($attrs)*
297 impl ::ValueFrom<$src> for $dst {
298 type Err = ::errors::RangeError<$src>;
299 #[inline]
300 fn value_from(src: $src) -> Result<$dst, Self::Err> {
301 if !(-$bound <= src) {
302 return Err(::errors::RangeError::NegOverflow(src));
303 }
304 if !(src <= $bound) {
305 return Err(::errors::RangeError::PosOverflow(src));
306 }
307 Ok(src as $dst)
308 }
309 }
310 }
311 num_conv! { @ $src=> $($tail)* }
312 };
313
314 (@ $src:ty=> ($($attrs:tt)*) nf [, $max:expr] $dst:ident, $($tail:tt)*) => {
315 as_item! {
316 approx_blind! { ($($attrs)*), $src, $dst, ::DefaultApprox }
317
318 $($attrs)*
319 impl ::ValueFrom<$src> for $dst {
320 type Err = ::errors::PosOverflow<$src>;
321 #[inline]
322 fn value_from(src: $src) -> Result<$dst, Self::Err> {
323 if !(src <= $max) {
324 return Err(::errors::PosOverflow(src));
325 }
326 Ok(src as $dst)
327 }
328 }
329 }
330 num_conv! { @ $src=> $($tail)* }
331 };
332
333 (@ $src:ty=> ($($attrs:tt)*) fan [$min:expr, $max:expr] $dst:ident, $($tail:tt)*) => {
335 as_item! {
336 approx_range_no_nan! { ($($attrs)*), $src, $dst, [$min, $max],
337 ::DefaultApprox }
338 approx_range_no_nan! { ($($attrs)*), $src, $dst, [$min, $max],
339 ::RoundToNearest, approx: |s| s.round() }
340 approx_range_no_nan! { ($($attrs)*), $src, $dst, [$min, $max],
341 ::RoundToNegInf, approx: |s| s.floor() }
342 approx_range_no_nan! { ($($attrs)*), $src, $dst, [$min, $max],
343 ::RoundToPosInf, approx: |s| s.ceil() }
344 approx_range_no_nan! { ($($attrs)*), $src, $dst, [$min, $max],
345 ::RoundToZero, approx: |s| s.trunc() }
346 }
347 num_conv! { @ $src=> $($tail)* }
348 };
349
350 (@ $src:ty=> ($($attrs:tt)*) fan $dst:ident, $($tail:tt)*) => {
351 as_item! {
352 approx_dmin_to_dmax_no_nan! { ($($attrs)*), $src, $dst, ::DefaultApprox }
353 approx_dmin_to_dmax_no_nan! { ($($attrs)*), $src, $dst, ::RoundToNearest,
354 approx: |s| s.round() }
355 approx_dmin_to_dmax_no_nan! { ($($attrs)*), $src, $dst, ::RoundToNegInf,
356 approx: |s| s.floor() }
357 approx_dmin_to_dmax_no_nan! { ($($attrs)*), $src, $dst, ::RoundToPosInf,
358 approx: |s| s.ceil() }
359 approx_dmin_to_dmax_no_nan! { ($($attrs)*), $src, $dst, ::RoundToZero,
360 approx: |s| s.trunc() }
361 }
362 num_conv! { @ $src=> $($tail)* }
363 };
364
365 ($src:ty=> $($tail:tt)*) => {
366 num_conv! { @ $src=> $($tail)*, }
367 };
368}
369
370mod lang_ints {
371 num_conv! { i8=> w i16, w i32, w i64, w+u8, w+u16, w+u32, w+u64, w isize, w+usize }
372 num_conv! { i16=> n i8, w i32, w i64, n+u8, w+u16, w+u32, w+u64, w isize, w+usize }
373 num_conv! { i32=> n i8, n i16, w i64, n+u8, n+u16, w+u32, w+u64 }
374 num_conv! { i64=> n i8, n i16, n i32, n+u8, n+u16, n+u32, w+u64 }
375 num_conv! { i32=> #[32] e isize, #[64] w isize, w+usize }
376 num_conv! { i64=> #[32] n isize, #[64] e isize, #[32] n+usize, #[64] w+usize }
377
378 num_conv! { u8=> n-i8, w i16, w i32, w i64, w u16, w u32, w u64, w isize, w usize }
379 num_conv! { u16=> n-i8, n-i16, w i32, w i64, n-u8, w u32, w u64, w isize, w usize }
380 num_conv! { u32=> n-i8, n-i16, n-i32, w i64, n-u8, n-u16, w u64 }
381 num_conv! { u64=> n-i8, n-i16, n-i32, n-i64, n-u8, n-u16, n-u32 }
382 num_conv! { u32=> #[32] n-isize, #[64] w isize, #[32] e usize, #[64] w usize }
383 num_conv! { u64=> n-isize, #[32] n-usize, #[64] e usize }
384
385 num_conv! { isize=> n i8, n i16, #[32] e i32, #[32] w i64, #[64] n i32, #[64] e i64 }
386 num_conv! { isize=> n+u8, n+u16, #[32] w+u32, #[32] w+u64, #[64] n+u32, #[64] w+u64 }
387 num_conv! { isize=> w+usize }
388
389 num_conv! { usize=> n-i8, n-i16, #[32] n-i32, #[32] w i64, #[64] n-i32, #[64] n-i64 }
390 num_conv! { usize=> n-u8, n-u16, #[32] e u32, #[32] w u64, #[64] n-u32, #[64] e u64 }
391 num_conv! { usize=> n-isize }
392}
393
394mod lang_floats {
395 use {ApproxFrom, ApproxScheme};
396 use ValueFrom;
397 use errors::{NoError, RangeError};
398
399 impl<Scheme> ApproxFrom<f32, Scheme> for f64
401 where Scheme: ApproxScheme {
402 type Err = NoError;
403 #[inline]
404 fn approx_from(src: f32) -> Result<f64, Self::Err> {
405 Ok(src as f64)
406 }
407 }
408
409 impl ValueFrom<f32> for f64 {
410 type Err = NoError;
411 #[inline]
412 fn value_from(src: f32) -> Result<f64, Self::Err> {
413 Ok(src as f64)
414 }
415 }
416
417 impl ApproxFrom<f64> for f32 {
419 type Err = RangeError<f64>;
420 #[inline]
421 fn approx_from(src: f64) -> Result<f32, Self::Err> {
422 if !src.is_finite() {
423 return Ok(src as f32);
424 }
425 if !(::std::f32::MIN as f64 <= src) {
426 return Err(RangeError::NegOverflow(src));
427 }
428 if !(src <= ::std::f32::MAX as f64) {
429 return Err(RangeError::PosOverflow(src));
430 }
431 Ok(src as f32)
432 }
433 }
434}
435
436mod lang_int_to_float {
437 num_conv! { i8=> w f32, w f64 }
438 num_conv! { i16=> w f32, w f64 }
439 num_conv! { i32=> nf [+- 16_777_216] f32, w f64 }
440 num_conv! { i64=> nf [+- 16_777_216] f32, nf [+- 9_007_199_254_740_992] f64 }
441
442 num_conv! { u8=> w f32, w f64 }
443 num_conv! { u16=> w f32, w f64 }
444 num_conv! { u32=> nf [, 16_777_216] f32, w f64 }
445 num_conv! { u64=> nf [, 16_777_216] f32, nf [, 9_007_199_254_740_992] f64 }
446
447 num_conv! { isize=> nf [+- 16_777_216] f32,
448 #[32] w f64, #[64] nf [+- 9_007_199_254_740_992] f64 }
449 num_conv! { usize=> nf [, 16_777_216] f32,
450 #[32] w f64, #[64] nf [, 9_007_199_254_740_992] f64 }
451}
452
453mod lang_float_to_int {
454 num_conv! { f32=> fan i8, fan i16,
460 fan [-2.1474836e9, 2.1474835e9] i32,
461 fan [-9.223372e18, 9.2233715e18] i64 }
462 num_conv! { f32=> fan u8, fan u16,
463 fan [0.0, 4.294967e9] u32,
464 fan [0.0, 1.8446743e19] u64 }
465 num_conv! { f32=>
466 #[32] fan [-2.1474836e9, 2.1474835e9] isize,
467 #[32] fan [0.0, 4.294967e9] usize,
468 #[64] fan [-9.223372e18, 9.2233715e18] isize,
469 #[64] fan [0.0, 1.8446743e19] usize }
470
471 num_conv! { f64=> fan i8, fan i16, fan i32,
472 fan [-9.223372036854776e18, 9.223372036854775e18] i64 }
473 num_conv! { f64=> fan u8, fan u16, fan u32,
474 fan [0.0, 1.844674407370955e19] u64 }
475 num_conv! { f64=>
476 #[32] fan isize, #[32] fan usize,
477 #[64] fan [-9.223372036854776e18, 9.223372036854775e18] isize,
478 #[64] fan [0.0, 1.844674407370955e19] usize }
479}
480
481mod lang_char_to_int {
482 use TryFrom;
483 use ValueFrom;
484 use errors::{NoError, PosOverflow};
485
486 impl TryFrom<char> for u32 {
487 type Err = NoError;
488 #[inline]
489 fn try_from(src: char) -> Result<u32, Self::Err> {
490 Ok(src as u32)
491 }
492 }
493
494 impl TryFrom<char> for usize {
495 type Err = NoError;
496 #[inline]
497 fn try_from(src: char) -> Result<usize, Self::Err> {
498 Ok(src as usize)
499 }
500 }
501
502 impl TryFrom<char> for isize {
503 type Err = NoError;
504 #[inline]
505 fn try_from(src: char) -> Result<isize, Self::Err> {
506 Ok(src as isize)
507 }
508 }
509
510 macro_rules! conv_char_to_int {
511 ($($ts:ty),* $(,)*) => {
512 $(
513 impl TryFrom<char> for $ts {
514 type Err = PosOverflow<char>;
515 #[inline]
516 fn try_from(src: char) -> Result<$ts, Self::Err> {
517 <$ts as ValueFrom<_>>::value_from(src as u32)
518 .map_err(|_| PosOverflow(src))
519 }
520 }
521 )*
522 };
523 }
524
525 macro_rules! conv_char_to_int_wide {
526 ($($ts:ty),* $(,)*) => {
527 $(
528 impl TryFrom<char> for $ts {
529 type Err = NoError;
530 #[inline]
531 fn try_from(src: char) -> Result<$ts, Self::Err> {
532 <$ts as ValueFrom<_>>::value_from(src as u32)
533 }
534 }
535 )*
536 };
537 }
538
539 conv_char_to_int! { i8, i16, i32, u8, u16 }
540 conv_char_to_int_wide! { i64, u64 }
541}
542
543mod lang_int_to_char {
544 use TryFrom;
545 use ValueFrom;
546 use errors::{NoError, Unrepresentable, UnwrapOk};
547
548 impl TryFrom<u8> for char {
549 type Err = NoError;
550 #[inline]
551 fn try_from(src: u8) -> Result<char, Self::Err> {
552 Ok(src as char)
553 }
554 }
555 impl TryFrom<u16> for char {
556 type Err = Unrepresentable<u16>;
557 #[inline]
558 fn try_from(src: u16) -> Result<char, Self::Err> {
559 TryFrom::try_from(
560 <u32 as ValueFrom<_>>::value_from(src).unwrap_ok()
561 ).map_err(|_| Unrepresentable(src))
562 }
563 }
564
565 impl TryFrom<u32> for char {
566 type Err = Unrepresentable<u32>;
567 #[inline]
568 fn try_from(src: u32) -> Result<char, Self::Err> {
569 ::std::char::from_u32(src).ok_or_else(|| Unrepresentable(src))
570 }
571 }
572
573 macro_rules! conv_int_to_char {
574 ($($ts:ty),* $(,)*) => {
575 $(
576 impl TryFrom<$ts> for char {
577 type Err = Unrepresentable<$ts>;
578 #[inline]
579 fn try_from(src: $ts) -> Result<char, Self::Err> {
580 <u32 as ValueFrom<_>>::value_from(src)
581 .map_err(|_| Unrepresentable(src))
582 .and_then(|usv| TryFrom::try_from(usv)
583 .map_err(|_| Unrepresentable(src)))
584 }
585 }
586 )*
587 };
588 }
589
590 conv_int_to_char! { i8, i16, i32, i64, isize, u64, usize }
591}