@@ -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,74 @@ 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| {
436+ if s. contains ( ' ' ) {
437+ format ! ( "\" {}\" " , s)
438+ } else {
439+ s. clone ( )
440+ }
441+ } )
442+ . collect ( ) ;
443+ serializer. serialize_str ( & quoted. join ( " " ) )
444+ }
433445 }
434446 }
435447}
448+
449+ #[ cfg( test) ]
450+ mod tests {
451+ use super :: * ;
452+ use serde_json;
453+
454+ #[ derive( Deserialize , Serialize ) ]
455+ struct ArgsWrapper {
456+ args : ArgsStringOrList ,
457+ }
458+
459+ #[ test]
460+ fn test_args_list_with_spaces_quotes_elements ( ) {
461+ let json = std:: fs:: read_to_string ( "testdata/args_with_spaces.json" ) . unwrap ( ) ;
462+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
463+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
464+ assert_eq ! (
465+ serialized[ "args" ] ,
466+ r#""C:\path with spaces\some file.txt" arg2"#
467+ ) ;
468+ }
469+
470+ #[ test]
471+ fn test_args_single_string_preserved_as_is ( ) {
472+ let json = std:: fs:: read_to_string ( "testdata/args_single_string.json" ) . unwrap ( ) ;
473+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
474+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
475+ assert_eq ! ( serialized[ "args" ] , r#"C:\path with spaces\some file.txt"# ) ;
476+ }
477+
478+ #[ test]
479+ fn test_args_list_no_spaces_not_quoted ( ) {
480+ let json = std:: fs:: read_to_string ( "testdata/args_list_no_spaces.json" ) . unwrap ( ) ;
481+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
482+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
483+ assert_eq ! ( serialized[ "args" ] , "arg1 arg2" ) ;
484+ }
485+
486+ #[ test]
487+ fn test_args_single_element_with_spaces_quoted ( ) {
488+ let json =
489+ std:: fs:: read_to_string ( "testdata/args_single_element_with_spaces.json" ) . unwrap ( ) ;
490+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
491+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
492+ assert_eq ! ( serialized[ "args" ] , r#""path with spaces""# ) ;
493+ }
494+
495+ #[ test]
496+ fn test_args_empty_list ( ) {
497+ let json = std:: fs:: read_to_string ( "testdata/args_empty_list.json" ) . unwrap ( ) ;
498+ let wrapper: ArgsWrapper = serde_json:: from_str ( & json) . unwrap ( ) ;
499+ let serialized = serde_json:: to_value ( & wrapper) . unwrap ( ) ;
500+ assert_eq ! ( serialized[ "args" ] , "" ) ;
501+ }
502+ }
0 commit comments