@@ -414,7 +414,7 @@ pub fn should_use_local_or_download(
414414/// A type that can be deserialized from either a single string or a list of strings.
415415///
416416/// When serialized, it always produces a single string. If it was a list,
417- /// the elements are joined with a space.
417+ /// the elements are joined with a space, quoting elements that contain spaces .
418418#[ derive( Deserialize , Debug , Clone ) ]
419419#[ serde( untagged) ]
420420pub enum ArgsStringOrList {
@@ -429,7 +429,71 @@ impl Serialize for ArgsStringOrList {
429429 {
430430 match self {
431431 ArgsStringOrList :: String ( s) => serializer. serialize_str ( s) ,
432- ArgsStringOrList :: List ( l) => serializer. serialize_str ( & l. join ( " " ) ) ,
432+ ArgsStringOrList :: List ( l) => {
433+ let quoted: Vec < String > = l
434+ . iter ( )
435+ . map ( |s| if s. contains ( ' ' ) { format ! ( "\" {}\" " , s) } else { s. clone ( ) } )
436+ . collect ( ) ;
437+ serializer. serialize_str ( & quoted. join ( " " ) )
438+ }
433439 }
434440 }
435441}
442+
443+ #[ cfg( test) ]
444+ mod tests {
445+ use super :: * ;
446+ use serde_json;
447+
448+ #[ derive( Deserialize , Serialize ) ]
449+ struct ArgsWrapper {
450+ args : ArgsStringOrList ,
451+ }
452+
453+ #[ test]
454+ fn test_args_list_with_spaces_quotes_elements ( ) {
455+ let json = std:: fs:: read_to_string ( "testdata/args_with_spaces.json" ) . unwrap ( ) ;
456+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
457+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
458+ assert_eq ! (
459+ serialized[ "args" ] ,
460+ r#""C:\path with spaces\some file.txt" arg2"#
461+ ) ;
462+ }
463+
464+ #[ test]
465+ fn test_args_single_string_preserved_as_is ( ) {
466+ let json = std:: fs:: read_to_string ( "testdata/args_single_string.json" ) . unwrap ( ) ;
467+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
468+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
469+ assert_eq ! (
470+ serialized[ "args" ] ,
471+ r#"C:\path with spaces\some file.txt"#
472+ ) ;
473+ }
474+
475+ #[ test]
476+ fn test_args_list_no_spaces_not_quoted ( ) {
477+ let json = std:: fs:: read_to_string ( "testdata/args_list_no_spaces.json" ) . unwrap ( ) ;
478+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
479+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
480+ assert_eq ! ( serialized[ "args" ] , "arg1 arg2" ) ;
481+ }
482+
483+ #[ test]
484+ fn test_args_single_element_with_spaces_quoted ( ) {
485+ let json =
486+ std:: fs:: read_to_string ( "testdata/args_single_element_with_spaces.json" ) . unwrap ( ) ;
487+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
488+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
489+ assert_eq ! ( serialized[ "args" ] , r#""path with spaces""# ) ;
490+ }
491+
492+ #[ test]
493+ fn test_args_empty_list ( ) {
494+ let json = std:: fs:: read_to_string ( "testdata/args_empty_list.json" ) . unwrap ( ) ;
495+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
496+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
497+ assert_eq ! ( serialized[ "args" ] , "" ) ;
498+ }
499+ }
0 commit comments