Skip to main content

vv_agent/runtime/shell/
metadata.rs

1pub fn normalize_windows_shell_priority(
2    raw: Option<&serde_json::Value>,
3) -> Result<Option<Vec<String>>, String> {
4    let Some(raw) = raw else {
5        return Ok(None);
6    };
7    let Some(items) = raw.as_array() else {
8        return Err("`windows_shell_priority` must be a list of shell names".to_string());
9    };
10    let mut normalized = Vec::new();
11    for item in items {
12        if json_value_is_falsey(item) {
13            continue;
14        }
15        let value = stringify_json_value(item);
16        let value = value.trim();
17        if value.is_empty() || normalized.iter().any(|seen| seen == value) {
18            continue;
19        }
20        normalized.push(value.to_string());
21    }
22    Ok(Some(normalized))
23}
24
25fn json_value_is_falsey(value: &serde_json::Value) -> bool {
26    match value {
27        serde_json::Value::Null => true,
28        serde_json::Value::Bool(value) => !*value,
29        serde_json::Value::Number(number) => number.as_f64() == Some(0.0),
30        serde_json::Value::String(value) => value.is_empty(),
31        serde_json::Value::Array(items) => items.is_empty(),
32        serde_json::Value::Object(object) => object.is_empty(),
33    }
34}
35
36fn stringify_json_value(value: &serde_json::Value) -> String {
37    match value {
38        serde_json::Value::Null => String::new(),
39        serde_json::Value::Bool(true) => "True".to_string(),
40        serde_json::Value::Bool(false) => "False".to_string(),
41        serde_json::Value::Number(number) => number.to_string(),
42        serde_json::Value::String(value) => value.clone(),
43        serde_json::Value::Array(items) => {
44            let items = items
45                .iter()
46                .map(json_value_repr)
47                .collect::<Vec<_>>()
48                .join(", ");
49            format!("[{items}]")
50        }
51        serde_json::Value::Object(object) => {
52            let items = object
53                .iter()
54                .map(|(key, value)| {
55                    format!("{}: {}", quote_json_string(key), json_value_repr(value))
56                })
57                .collect::<Vec<_>>()
58                .join(", ");
59            format!("{{{items}}}")
60        }
61    }
62}
63
64fn json_value_repr(value: &serde_json::Value) -> String {
65    match value {
66        serde_json::Value::String(value) => quote_json_string(value),
67        other => stringify_json_value(other),
68    }
69}
70
71fn quote_json_string(value: &str) -> String {
72    format!("'{}'", value.replace('\\', "\\\\").replace('\'', "\\'"))
73}