1
1
#![ recursion_limit = "128" ]
2
2
3
- use log:: { error, info} ;
4
- use std:: path:: { Path , PathBuf } ;
3
+ use log:: { debug, error, info} ;
5
4
6
5
use std:: fs:: File ;
7
6
use std:: io:: Write ;
8
7
use std:: process;
9
8
10
9
use anyhow:: { Context , Result } ;
11
- use clap:: { App , Arg } ;
10
+ use clap:: { Arg , Command } ;
12
11
13
12
use svd2rust:: {
14
13
generate, load_from,
15
14
util:: { self , build_rs, Config , SourceType , Target } ,
16
15
} ;
17
16
17
+ fn parse_configs ( app : Command ) -> Result < Config > {
18
+ use irx_config:: parsers:: { cmd, toml} ;
19
+ use irx_config:: ConfigBuilder ;
20
+ let irxconfig = ConfigBuilder :: default ( )
21
+ . append_parser (
22
+ cmd:: ParserBuilder :: new ( app)
23
+ . single_flags_as_bool ( true )
24
+ . build ( ) ?,
25
+ )
26
+ . append_parser (
27
+ toml:: ParserBuilder :: default ( )
28
+ . default_path ( "svd2rust.toml" )
29
+ . path_option ( "config" )
30
+ . ignore_missing_file ( true )
31
+ . build ( ) ?,
32
+ )
33
+ . load ( ) ?;
34
+
35
+ irxconfig. get ( ) . map_err ( Into :: into)
36
+ }
37
+
18
38
fn run ( ) -> Result < ( ) > {
19
- use clap_conf:: prelude:: * ;
20
39
use std:: io:: Read ;
21
40
22
- let matches = App :: new ( "svd2rust" )
41
+ let log_help = format ! (
42
+ "Choose which messages to log (overrides {})" ,
43
+ env_logger:: DEFAULT_FILTER_ENV
44
+ ) ;
45
+
46
+ let app = Command :: new ( "svd2rust" )
23
47
. about ( "Generate a Rust API from SVD files" )
24
48
. arg (
25
49
Arg :: with_name ( "input" )
26
50
. help ( "Input SVD file" )
27
- . short ( "i" )
51
+ . short ( 'i' )
28
52
. takes_value ( true )
29
53
. value_name ( "FILE" ) ,
30
54
)
31
55
. arg (
32
- Arg :: with_name ( "output " )
56
+ Arg :: with_name ( "output_dir " )
33
57
. long ( "output-dir" )
34
58
. help ( "Directory to place generated files" )
35
- . short ( "o" )
59
+ . short ( 'o' )
36
60
. takes_value ( true )
37
61
. value_name ( "PATH" ) ,
38
62
)
39
63
. arg (
40
64
Arg :: with_name ( "config" )
41
65
. long ( "config" )
42
66
. help ( "Config TOML file" )
43
- . short ( "c" )
67
+ . short ( 'c' )
44
68
. takes_value ( true )
45
69
. value_name ( "TOML_FILE" ) ,
46
70
)
@@ -52,7 +76,7 @@ fn run() -> Result<()> {
52
76
. value_name ( "ARCH" ) ,
53
77
)
54
78
. arg (
55
- Arg :: with_name ( "nightly_features " )
79
+ Arg :: with_name ( "nightly " )
56
80
. long ( "nightly" )
57
81
. help ( "Enable features only available to nightly rustc" ) ,
58
82
)
@@ -72,7 +96,7 @@ fn run() -> Result<()> {
72
96
. arg (
73
97
Arg :: with_name ( "generic_mod" )
74
98
. long ( "generic_mod" )
75
- . short ( "g" )
99
+ . short ( 'g' )
76
100
. help ( "Push generic mod in separate file" ) ,
77
101
)
78
102
. arg (
@@ -93,13 +117,13 @@ fn run() -> Result<()> {
93
117
. arg (
94
118
Arg :: with_name ( "make_mod" )
95
119
. long ( "make_mod" )
96
- . short ( "m" )
120
+ . short ( 'm' )
97
121
. help ( "Create mod.rs instead of lib.rs, without inner attributes" ) ,
98
122
)
99
123
. arg (
100
124
Arg :: with_name ( "strict" )
101
125
. long ( "strict" )
102
- . short ( "s" )
126
+ . short ( 's' )
103
127
. help ( "Make advanced checks due to parsing SVD" ) ,
104
128
)
105
129
. arg (
@@ -120,22 +144,31 @@ fn run() -> Result<()> {
120
144
. arg (
121
145
Arg :: with_name ( "log_level" )
122
146
. long ( "log" )
123
- . short ( "l" )
124
- . help ( & format ! (
125
- "Choose which messages to log (overrides {})" ,
126
- env_logger:: DEFAULT_FILTER_ENV
127
- ) )
147
+ . short ( 'l' )
148
+ . help ( log_help. as_ref ( ) )
128
149
. takes_value ( true )
129
150
. possible_values ( & [ "off" , "error" , "warn" , "info" , "debug" , "trace" ] ) ,
130
151
)
131
152
. version ( concat ! (
132
153
env!( "CARGO_PKG_VERSION" ) ,
133
154
include_str!( concat!( env!( "OUT_DIR" ) , "/commit-info.txt" ) )
134
- ) )
135
- . get_matches ( ) ;
155
+ ) ) ;
156
+
157
+ let mut config = match parse_configs ( app) {
158
+ Ok ( config) => {
159
+ setup_logging ( & config. log_level ) ;
160
+ config
161
+ }
162
+ Err ( e) => {
163
+ setup_logging ( & None ) ;
164
+ return Err ( e) ;
165
+ }
166
+ } ;
167
+
168
+ debug ! ( "Current svd2rust config: {config:#?}" ) ;
136
169
137
170
let input = & mut String :: new ( ) ;
138
- match matches . value_of ( " input" ) {
171
+ match config . input . as_ref ( ) {
139
172
Some ( file) => {
140
173
File :: open ( file)
141
174
. context ( "Cannot open the SVD file" ) ?
@@ -151,75 +184,10 @@ fn run() -> Result<()> {
151
184
}
152
185
}
153
186
154
- let path = PathBuf :: from ( matches. value_of ( "output" ) . unwrap_or ( "." ) ) ;
155
-
156
- let config_filename = matches. value_of ( "config" ) . unwrap_or ( "" ) ;
157
-
158
- let cfg = with_toml_env ( & matches, & [ config_filename, "svd2rust.toml" ] ) ;
159
-
160
- setup_logging ( & cfg) ;
161
-
162
- let target = cfg
163
- . grab ( )
164
- . arg ( "target" )
165
- . conf ( "target" )
166
- . done ( )
167
- . map ( |s| Target :: parse ( & s) )
168
- . unwrap_or_else ( || Ok ( Target :: default ( ) ) ) ?;
169
-
170
- let nightly =
171
- cfg. bool_flag ( "nightly_features" , Filter :: Arg ) || cfg. bool_flag ( "nightly" , Filter :: Conf ) ;
172
- let generic_mod =
173
- cfg. bool_flag ( "generic_mod" , Filter :: Arg ) || cfg. bool_flag ( "generic_mod" , Filter :: Conf ) ;
174
- let make_mod =
175
- cfg. bool_flag ( "make_mod" , Filter :: Arg ) || cfg. bool_flag ( "make_mod" , Filter :: Conf ) ;
176
- let const_generic =
177
- cfg. bool_flag ( "const_generic" , Filter :: Arg ) || cfg. bool_flag ( "const_generic" , Filter :: Conf ) ;
178
- let ignore_groups =
179
- cfg. bool_flag ( "ignore_groups" , Filter :: Arg ) || cfg. bool_flag ( "ignore_groups" , Filter :: Conf ) ;
180
- let keep_list =
181
- cfg. bool_flag ( "keep_list" , Filter :: Arg ) || cfg. bool_flag ( "keep_list" , Filter :: Conf ) ;
182
- let strict = cfg. bool_flag ( "strict" , Filter :: Arg ) || cfg. bool_flag ( "strict" , Filter :: Conf ) ;
183
- let pascal_enum_values = cfg. bool_flag ( "pascal_enum_values" , Filter :: Arg )
184
- || cfg. bool_flag ( "pascal_enum_values" , Filter :: Conf ) ;
185
- let derive_more =
186
- cfg. bool_flag ( "derive_more" , Filter :: Arg ) || cfg. bool_flag ( "derive_more" , Filter :: Conf ) ;
187
- let feature_group =
188
- cfg. bool_flag ( "feature_group" , Filter :: Arg ) || cfg. bool_flag ( "feature_group" , Filter :: Conf ) ;
189
- let feature_peripheral = cfg. bool_flag ( "feature_peripheral" , Filter :: Arg )
190
- || cfg. bool_flag ( "feature_peripheral" , Filter :: Conf ) ;
191
- let max_cluster_size = cfg. bool_flag ( "max_cluster_size" , Filter :: Arg )
192
- || cfg. bool_flag ( "max_cluster_size" , Filter :: Conf ) ;
193
-
194
- let mut source_type = cfg
195
- . grab ( )
196
- . arg ( "source_type" )
197
- . conf ( "source_type" )
198
- . done ( )
199
- . and_then ( |s| SourceType :: from_extension ( & s) )
200
- . unwrap_or_default ( ) ;
201
-
202
- if let Some ( file) = matches. value_of ( "input" ) {
203
- source_type = SourceType :: from_path ( Path :: new ( file) )
187
+ if let Some ( file) = config. input . as_ref ( ) {
188
+ config. source_type = SourceType :: from_path ( file)
204
189
}
205
-
206
- let config = Config {
207
- target,
208
- nightly,
209
- generic_mod,
210
- make_mod,
211
- const_generic,
212
- ignore_groups,
213
- keep_list,
214
- strict,
215
- pascal_enum_values,
216
- derive_more,
217
- feature_group,
218
- feature_peripheral,
219
- max_cluster_size,
220
- output_dir : path. clone ( ) ,
221
- source_type,
222
- } ;
190
+ let path = & config. output_dir ;
223
191
224
192
info ! ( "Parsing device from SVD file" ) ;
225
193
let device = load_from ( input, & config) ?;
@@ -229,25 +197,28 @@ fn run() -> Result<()> {
229
197
let items = generate:: device:: render ( & device, & config, & mut device_x)
230
198
. with_context ( || "Error rendering device" ) ?;
231
199
232
- let filename = if make_mod { "mod.rs" } else { "lib.rs" } ;
200
+ let filename = if config . make_mod { "mod.rs" } else { "lib.rs" } ;
233
201
let mut file = File :: create ( path. join ( filename) ) . expect ( "Couldn't create output file" ) ;
234
202
235
203
let data = items. to_string ( ) . replace ( "] " , "]\n " ) ;
236
204
file. write_all ( data. as_ref ( ) )
237
205
. expect ( "Could not write code to lib.rs" ) ;
238
206
239
- if target == Target :: CortexM
240
- || target == Target :: Msp430
241
- || target == Target :: XtensaLX
242
- || target == Target :: RISCV
207
+ if [
208
+ Target :: CortexM ,
209
+ Target :: Msp430 ,
210
+ Target :: XtensaLX ,
211
+ Target :: RISCV ,
212
+ ]
213
+ . contains ( & config. target )
243
214
{
244
215
writeln ! ( File :: create( path. join( "device.x" ) ) ?, "{}" , device_x) ?;
245
216
writeln ! ( File :: create( path. join( "build.rs" ) ) ?, "{}" , build_rs( ) ) ?;
246
217
}
247
218
248
- if feature_group || feature_peripheral {
219
+ if config . feature_group || config . feature_peripheral {
249
220
let mut features = Vec :: new ( ) ;
250
- if feature_group {
221
+ if config . feature_group {
251
222
features. extend (
252
223
util:: group_names ( & device)
253
224
. iter ( )
@@ -259,7 +230,7 @@ fn run() -> Result<()> {
259
230
. collect ( ) ;
260
231
features. push ( format ! ( "all-groups = [{}]\n " , add_groups. join( "," ) ) )
261
232
}
262
- if feature_peripheral {
233
+ if config . feature_peripheral {
263
234
features. extend (
264
235
util:: peripheral_names ( & device)
265
236
. iter ( )
@@ -287,7 +258,7 @@ fn run() -> Result<()> {
287
258
Ok ( ( ) )
288
259
}
289
260
290
- fn setup_logging < ' a > ( getter : & ' a impl clap_conf :: Getter < ' a , String > ) {
261
+ fn setup_logging ( log_level : & Option < String > ) {
291
262
// * Log at info by default.
292
263
// * Allow users the option of setting complex logging filters using
293
264
// env_logger's `RUST_LOG` environment variable.
@@ -302,7 +273,7 @@ fn setup_logging<'a>(getter: &'a impl clap_conf::Getter<'a, String>) {
302
273
if log_lvl_from_env {
303
274
log:: set_max_level ( log:: LevelFilter :: Trace ) ;
304
275
} else {
305
- let level = match getter . grab ( ) . arg ( " log_level" ) . conf ( "log_level" ) . done ( ) {
276
+ let level = match log_level {
306
277
Some ( lvl) => lvl. parse ( ) . unwrap ( ) ,
307
278
None => log:: LevelFilter :: Info ,
308
279
} ;
0 commit comments