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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use primitive_types::U256;
use proc_macro::TokenStream;
use std::str::FromStr;
use syn::{parse_macro_input, Lit};
#[proc_macro]
pub fn u256(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as Lit);
let number = match input {
Lit::Int(lit) => parse_int(lit.base10_digits()),
Lit::Float(lit) => parse_float(lit.base10_digits()),
_ => panic!("only integer and float are allowed!"),
};
format!(
"primitive_types::U256([{}u64, {}u64, {}u64, {}u64])",
number.0[0], number.0[1], number.0[2], number.0[3]
)
.parse()
.unwrap()
}
fn parse_int(s: &str) -> U256 {
U256::from_dec_str(s).expect("the number can't fit into U256")
}
fn parse_float(s: &str) -> U256 {
let dot_pos = s.find(".");
let e_pos = s.find("e");
match (dot_pos, e_pos) {
(Some(dot_pos), Some(e_pos)) => {
assert!(dot_pos < e_pos);
let fraction_len = s[dot_pos + 1..e_pos].len();
let exp = usize::from_str(&s[e_pos + 1..]).unwrap();
if fraction_len > exp {
panic!("don't support fractions");
}
let mut expanded = s[0..dot_pos].to_string();
expanded.push_str(&s[dot_pos + 1..e_pos]);
for _ in 0..(exp - fraction_len) {
expanded.push('0');
}
parse_int(expanded.as_str())
}
(None, Some(e_pos)) => {
let exp = usize::from_str(&s[e_pos + 1..]).unwrap();
let mut expanded = s[0..e_pos].to_string();
for _ in 0..exp {
expanded.push('0');
}
parse_int(expanded.as_str())
}
(Some(dot_pos), None) => {
if !s[dot_pos + 1..].is_empty() {
panic!("can't handle number with fractions")
} else {
U256::from_dec_str(&s[0..dot_pos]).expect("the number can't fit into u256")
}
}
_ => unreachable!("it should be covered in LitInt case"),
}
}