@@ -3,7 +3,7 @@ use std::path::PathBuf;
3
3
4
4
use clap:: { App , Arg } ;
5
5
6
- use tracing:: { error, info, warn} ;
6
+ use tracing:: { debug , error, info, warn} ;
7
7
use tracing_subscriber:: prelude:: * ;
8
8
use tracing_subscriber:: { filter:: EnvFilter , fmt} ;
9
9
@@ -103,6 +103,22 @@ fn main() {
103
103
. overrides_with ( "OUTPUT" )
104
104
. overrides_with ( "NOOUTPUT" )
105
105
)
106
+ . arg (
107
+ Arg :: with_name ( "SOURCE_FORMAT" )
108
+ . help ( "Specify the source format explicitly (by default, automatically inferred from filename extension)" )
109
+ . long ( "source" )
110
+ . short ( "s" )
111
+ . takes_value ( true )
112
+ . possible_values ( format:: POSSIBLE_FORMATS )
113
+ )
114
+ . arg (
115
+ Arg :: with_name ( "TARGET_FORMAT" )
116
+ . help ( "Specify the target format explicitly (by default, automatically inferred from filename extension)" )
117
+ . long ( "target" )
118
+ . short ( "t" )
119
+ . takes_value ( true )
120
+ . possible_values ( format:: POSSIBLE_FORMATS )
121
+ )
106
122
. arg (
107
123
Arg :: with_name ( "MOUNT" )
108
124
. help ( "Sets the mountpoint" )
@@ -228,14 +244,90 @@ fn main() {
228
244
} else {
229
245
Output :: Stdout
230
246
} ;
231
- let reader: Box < dyn std:: io:: Read > = if input_source == "-" {
232
- Box :: new ( std:: io:: stdin ( ) )
233
- } else {
234
- let file = std:: fs:: File :: open ( input_source) . unwrap_or_else ( |e| {
235
- error ! ( "Unable to open {} for JSON input: {}" , input_source, e) ;
236
- std:: process:: exit ( 1 ) ;
237
- } ) ;
238
- Box :: new ( file)
247
+
248
+ // try to autodetect the input format.
249
+ //
250
+ // first see if it's specified and parses okay.
251
+ //
252
+ // then see if we can pull it out of the extension.
253
+ //
254
+ // then give up and use json
255
+ config. input_format = match args
256
+ . value_of ( "SOURCE_FORMAT" )
257
+ . ok_or ( format:: ParseFormatError :: NoFormatProvided )
258
+ . and_then ( |s| s. parse :: < Format > ( ) )
259
+ {
260
+ Ok ( source_format) => source_format,
261
+ Err ( e) => {
262
+ match e {
263
+ format:: ParseFormatError :: NoSuchFormat ( s) => {
264
+ warn ! ( "Unrecognized format '{}', inferring from input." , s)
265
+ }
266
+ format:: ParseFormatError :: NoFormatProvided => {
267
+ debug ! ( "Inferring format from input." )
268
+ }
269
+ } ;
270
+
271
+ match Path :: new ( input_source)
272
+ . extension ( ) // will fail for STDIN, no worries
273
+ . map ( |s| s. to_str ( ) . expect ( "utf8 filename" ) . to_lowercase ( ) )
274
+ {
275
+ Some ( s) => match s. parse :: < Format > ( ) {
276
+ Ok ( format) => format,
277
+ Err ( _) => {
278
+ warn ! ( "Unrecognized format {}, defaulting to JSON." , s) ;
279
+ Format :: Json
280
+ }
281
+ } ,
282
+ None => Format :: Json ,
283
+ }
284
+ }
285
+ } ;
286
+
287
+ // try to autodetect the input format.
288
+ //
289
+ // first see if it's specified and parses okay.
290
+ //
291
+ // then see if we can pull it out of the extension (if specified)
292
+ //
293
+ // then give up and use the input format
294
+ config. output_format = match args
295
+ . value_of ( "TARGET_FORMAT" )
296
+ . ok_or ( format:: ParseFormatError :: NoFormatProvided )
297
+ . and_then ( |s| s. parse :: < Format > ( ) )
298
+ {
299
+ Ok ( target_format) => target_format,
300
+ Err ( e) => {
301
+ match e {
302
+ format:: ParseFormatError :: NoSuchFormat ( s) => {
303
+ warn ! (
304
+ "Unrecognized format '{}', inferring from input and output." ,
305
+ s
306
+ )
307
+ }
308
+ format:: ParseFormatError :: NoFormatProvided => {
309
+ debug ! ( "Inferring output format from input." )
310
+ }
311
+ } ;
312
+
313
+ match args
314
+ . value_of ( "OUTPUT" )
315
+ . and_then ( |s| Path :: new ( s) . extension ( ) )
316
+ . and_then ( |s| s. to_str ( ) )
317
+ {
318
+ Some ( s) => match s. parse :: < Format > ( ) {
319
+ Ok ( format) => format,
320
+ Err ( _) => {
321
+ warn ! (
322
+ "Unrecognized format {}, defaulting to input format '{}'." ,
323
+ s, config. input_format
324
+ ) ;
325
+ config. input_format
326
+ }
327
+ } ,
328
+ None => config. input_format ,
329
+ }
330
+ }
239
331
} ;
240
332
241
333
let mut options = vec ! [ MountOption :: FSName ( input_source. into( ) ) ] ;
@@ -246,26 +338,16 @@ fn main() {
246
338
options. push ( MountOption :: RO ) ;
247
339
}
248
340
249
- // try to autodetect the input format... poorly
250
- config. input_format = match Path :: new ( input_source)
251
- . extension ( )
252
- . map ( |s| s. to_str ( ) . expect ( "utf8 filename" ) . to_lowercase ( ) )
253
- {
254
- Some ( s) => {
255
- if & s == "json" {
256
- Format :: Json
257
- } else if & s == "toml" {
258
- Format :: Toml
259
- } else {
260
- warn ! ( "Unrecognized format {}, defaulting to JSON." , s) ;
261
- Format :: Json
262
- }
263
- }
264
- None => Format :: Json ,
265
- } ;
266
- config. output_format = config. input_format ;
267
-
268
341
let input_format = config. input_format ;
342
+ let reader: Box < dyn std:: io:: Read > = if input_source == "-" {
343
+ Box :: new ( std:: io:: stdin ( ) )
344
+ } else {
345
+ let file = std:: fs:: File :: open ( input_source) . unwrap_or_else ( |e| {
346
+ error ! ( "Unable to open {} for JSON input: {}" , input_source, e) ;
347
+ std:: process:: exit ( 1 ) ;
348
+ } ) ;
349
+ Box :: new ( file)
350
+ } ;
269
351
let fs = input_format. load ( reader, config) ;
270
352
271
353
info ! ( "mounting on {:?} with options {:?}" , mount_point, options) ;
0 commit comments