1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
macro_rules! to_int_impl {
($($to_int:ident -> $int:ident),*) => {
$(
#[doc = concat!("Converts [Self] into [`prim@", stringify!($int), "`].")]
#[inline]
pub const fn $to_int(self) -> Result<$int, ParseError> {
use intrinsics::{Digit, DIGIT_BIT_SHIFT, DIGIT_BITS};
let neg = self.is_negative();
let (mut out, padding) = if neg {
(-1, Digit::MAX)
} else {
(0, Digit::MIN)
};
let mut i = 0;
let u = self.0.to_bits();
let digits = u.digits();
if DIGIT_BITS > <$int>::BITS {
let small = digits[i] as $int;
let trunc = small as Digit;
if digits[i] != trunc {
return Err(ParseError::PosOverflow);
}
out = small;
i = 1;
} else {
if neg {
loop {
let shift = i << DIGIT_BIT_SHIFT;
if i >= N || shift >= <$int>::BITS as usize {
break;
}
out &= !(((!digits[i]) as $int) << shift);
i += 1;
}
} else {
loop {
let shift = i << DIGIT_BIT_SHIFT;
if i >= N || shift >= <$int>::BITS as usize {
break;
}
out |= (digits[i] as $int) << shift;
i += 1;
}
}
}
while i < N {
if digits[i] != padding {
return Err(ParseError::PosOverflow);
}
i += 1;
}
if out.is_negative() != neg {
return Err(ParseError::PosOverflow);
}
Ok(out)
}
)*
};
}
pub(crate) use to_int_impl;