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
130
131
132
133
134
135
use lazy_static::lazy_static;
use regex::Regex;
pub fn has_tuple_format(type_name: &str) -> bool {
type_name.starts_with('(') && type_name.ends_with(')')
}
pub fn extract_generic_name(type_name: &str) -> Option<String> {
lazy_static! {
static ref RE: Regex = Regex::new(r"^\s*generic\s+(\S+)\s*$").unwrap();
}
RE.captures(type_name)
.map(|captures| String::from(&captures[1]))
}
pub fn extract_array_len(type_name: &str) -> Option<usize> {
lazy_static! {
static ref RE: Regex = Regex::new(r"^\s*\[.+;\s*(\d+)\s*\]\s*$").unwrap();
}
RE.captures(type_name)
.map(|captures| captures[1].to_string())
.map(|length: String| {
length.parse::<usize>().unwrap_or_else(|_| {
panic!("Could not extract array length from {length}! Original field {type_name}")
})
})
}
pub fn extract_str_len(type_name: &str) -> Option<usize> {
lazy_static! {
static ref RE: Regex = Regex::new(r"^\s*str\s*\[\s*(\d+)\s*\]\s*$").unwrap();
}
RE.captures(type_name)
.map(|captures| captures[1].to_string())
.map(|length: String| {
length.parse::<usize>().unwrap_or_else(|_| {
panic!(
"Could not extract string length from {length}! Original field '{type_name}'"
)
})
})
}
pub fn extract_custom_type_name(type_field: &str) -> Option<String> {
lazy_static! {
static ref RE: Regex = Regex::new(r"\s*(?:struct|enum)\s*(\S*)").unwrap();
}
RE.captures(type_field)
.map(|captures| String::from(&captures[1]))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tuples_start_and_end_with_round_brackets() {
assert!(has_tuple_format("(_, _)"));
assert!(!has_tuple_format("(.."));
assert!(!has_tuple_format("..)"));
}
#[test]
fn generic_name_extracted() {
let type_name = " generic T ";
let name = extract_generic_name(type_name).expect("Should have succeeded");
assert_eq!(name, "T");
}
#[test]
fn array_len_extracted() {
let type_name = " [ _ ; 8 ] ";
let size = extract_array_len(type_name).expect("Should have succeeded");
assert_eq!(size, 8);
}
#[test]
fn str_len_extracted() {
let type_name = " str [ 10 ] ";
let str_len = extract_str_len(type_name).expect("Should have succeeded");
assert_eq!(str_len, 10);
}
#[test]
fn custom_struct_type_name_extracted() {
let type_name = " struct SomeStruct ";
let struct_name = extract_custom_type_name(type_name).expect("Should have succeeded");
assert_eq!(struct_name, "SomeStruct");
}
#[test]
fn custom_enum_type_name_extracted() {
let type_name = " enum SomeEnum ";
let enum_name = extract_custom_type_name(type_name).expect("Should have succeeded");
assert_eq!(enum_name, "SomeEnum");
}
}