Skip to content

Commit baf7e38

Browse files
authored
Quote args containing spaces in ArgsStringOrList (#195)
1 parent 3392cb7 commit baf7e38

6 files changed

Lines changed: 84 additions & 2 deletions

File tree

src/util.rs

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
420420
pub 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+
}

testdata/args_empty_list.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"args": []
3+
}

testdata/args_list_no_spaces.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"args": ["arg1", "arg2"]
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"args": ["path with spaces"]
3+
}

testdata/args_single_string.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"args": "C:\\path with spaces\\some file.txt"
3+
}

testdata/args_with_spaces.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"args": ["C:\\path with spaces\\some file.txt", "arg2"]
3+
}

0 commit comments

Comments
 (0)