defaults_rs/
prettifier.rs

1// SPDX-License-Identifier: MIT
2
3use crate::PrefValue;
4
5/// Prettify a `PlistValue` for display.
6///
7/// This essentially takes all complex types such as PrefValue::Dictionary or PrefValue::Array, and turns
8/// them into indented syntactic sugar output for the terminal.
9pub(crate) fn prettify(val: &PrefValue, indent: usize) -> String {
10    let ind = |n| "    ".repeat(n);
11    match val {
12        PrefValue::Dictionary(dict) => {
13            let mut out = String::new();
14            out.push_str("{\n");
15            let iter = dict.iter().peekable();
16            for (k, v) in iter {
17                out.push_str(&format!(
18                    "{}{} = {}",
19                    ind(indent + 1),
20                    quote_key(k),
21                    prettify(v, indent + 1)
22                ));
23                out.push(';');
24                out.push('\n');
25            }
26            out.push_str(&format!("{}}}", ind(indent)));
27            out
28        }
29        PrefValue::Array(arr) => {
30            let mut out = String::new();
31            out.push_str("(\n");
32            let iter = arr.iter().peekable();
33            for v in iter {
34                out.push_str(&ind(indent + 1));
35                out.push_str(&prettify(v, indent + 1));
36                out.push(',');
37                out.push('\n');
38            }
39            out.push_str(&format!("{})", ind(indent)));
40            out
41        }
42        PrefValue::String(s) => quote_string(s),
43        PrefValue::Boolean(b) => b.to_string(),
44        PrefValue::Data(data) => {
45            let mut s = data
46                .iter()
47                .map(|b| format!("0x{:02X}", b))
48                .collect::<Vec<_>>();
49            s.truncate(5);
50
51            format!("<length = {}, bytes = [{}...]>", data.len(), s.join(", "))
52        }
53        PrefValue::Url(url) => format!("<URL: {}>", url),
54        PrefValue::Uuid(uuid) => format!("<UUID: {}>", uuid),
55        PrefValue::Uid(uid) => format!("<UID: {}>", uid),
56        _ => val.to_string(),
57    }
58}
59
60/// Quotes a key for Apple-style output.
61fn quote_key(key: &str) -> String {
62    if key
63        .chars()
64        .all(|c| c.is_alphanumeric() || c == '-' || c == '_')
65    {
66        key.to_string()
67    } else {
68        format!("\"{}\"", key.replace('"', "\\\""))
69    }
70}
71
72/// Quotes a string for Apple-style output.
73fn quote_string(s: &str) -> String {
74    if s.chars()
75        .all(|c| c.is_alphanumeric() || c == '-' || c == '_')
76    {
77        s.to_string()
78    } else {
79        format!("\"{}\"", s.replace('"', "\\\""))
80    }
81}