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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::{num::ParseIntError, str::FromStr};
use lazy_static::lazy_static;
use regex::Regex;
use crate::parsers::regex::RegexParser;
macro_rules! regexes {
( $( $name:ident = $re:expr ; )* ) => {
$(
pub(crate) fn $name() -> &'static Regex {
lazy_static! {
static ref RE: Regex = Regex::new($re).unwrap();
}
&RE
}
)*
}
}
regexes! {
uint_regex = r"\A[0-9]+";
int_regex = r"\A[+-]?[0-9]+";
bool_regex = r"true|false";
uint_bin_regex = r"\A[01]+";
int_bin_regex = r"\A[+-]?[01]+";
uint_hex_regex = r"\A[0-9A-Fa-f]+";
int_hex_regex = r"\A[+-]?[0-9A-Fa-f]+";
}
macro_rules! from_str_parse_impl {
( $( $ty:ident )+ , $re_name:ident) => {
$(
#[allow(non_upper_case_globals)]
pub const $ty: RegexParser<$ty, <$ty as FromStr>::Err> =
RegexParser {
regex: $re_name,
parse_fn: <$ty as FromStr>::from_str,
};
)+
};
}
from_str_parse_impl!(u8 u16 u32 u64 u128 usize, uint_regex);
from_str_parse_impl!(i8 i16 i32 i64 i128 isize, int_regex);
from_str_parse_impl!(bool, bool_regex);
macro_rules! from_str_radix_parsers {
( $( ( $ty:ident , $bin:ident , $hex:ident ) ),* ; $bin_re:ident, $hex_re:ident ) => {
$(
#[allow(non_upper_case_globals)]
pub const $bin: RegexParser<$ty, ParseIntError> = RegexParser {
regex: $bin_re,
parse_fn: |s| $ty::from_str_radix(s, 2),
};
#[allow(non_upper_case_globals)]
pub const $hex: RegexParser<$ty, ParseIntError> = RegexParser {
regex: $hex_re,
parse_fn: |s| $ty::from_str_radix(s, 16),
};
)*
}
}
from_str_radix_parsers!(
(u8, u8_bin, u8_hex),
(u16, u16_bin, u16_hex),
(u32, u32_bin, u32_hex),
(u64, u64_bin, u64_hex),
(u128, u128_bin, u128_hex),
(usize, usize_bin, usize_hex);
uint_bin_regex,
uint_hex_regex
);
from_str_radix_parsers!(
(i8, i8_bin, i8_hex),
(i16, i16_bin, i16_hex),
(i32, i32_bin, i32_hex),
(i64, i64_bin, i64_hex),
(i128, i128_bin, i128_hex),
(isize, isize_bin, isize_hex);
int_bin_regex,
int_hex_regex
);
#[cfg(test)]
mod tests {
use super::*;
use crate::testing::*;
#[test]
fn test_parse_hex() {
assert_no_parse(&i32_hex, "+");
assert_no_parse(&i32_hex, "-");
assert_no_parse(&i32_hex, "+ 4");
assert_no_parse(&i32_hex, "+ 4");
assert_parse_eq(&i32_hex, "7BCDEF01", 0x7bcdef01);
assert_parse_eq(&i32_hex, "7fffffff", i32::MAX);
assert_no_parse(&i32_hex, "80000000");
assert_parse_eq(&i32_hex, "-80000000", i32::MIN);
assert_no_parse(&i32_hex, "-80000001");
let p = sequence(i32_hex, i32_hex);
assert_no_parse(&p, "12");
assert_no_parse(&p, "01230123ABCDABCD");
assert_parse_eq(&p, "-1+1", (-1, 1));
assert_no_parse(&u32_hex, "-1");
assert_no_parse(&u32_hex, "+d3d32e2e");
assert_parse_eq(&u32_hex, "ffffffff", u32::MAX);
assert_parse_eq(&u32_hex, "ffffffff", u32::MAX);
assert_parse_eq(
&u32_hex,
"0000000000000000000000000000000000000000000000000000000000000000ffffffff",
u32::MAX,
);
}
}