dump_vdf/
dump_vdf.rs

1use std::env;
2use std::path::Path;
3use steam_vdf_parser::{binary, parse_binary, parse_text};
4
5fn dump_value(value: &steam_vdf_parser::Value, indent: usize) -> String {
6    let indent_str = "  ".repeat(indent);
7    match value {
8        steam_vdf_parser::Value::Str(s) => format!("{}\"{}\"", indent_str, s),
9        steam_vdf_parser::Value::I32(n) => format!("{}{}", indent_str, n),
10        steam_vdf_parser::Value::U64(n) => format!("{}{}", indent_str, n),
11        steam_vdf_parser::Value::Float(n) => format!("{}{}", indent_str, n),
12        steam_vdf_parser::Value::Pointer(n) => format!("{}(pointer: {})", indent_str, n),
13        steam_vdf_parser::Value::Color(c) => format!(
14            "{}(color: #{:02x}{:02x}{:02x}{:02x})",
15            indent_str, c[0], c[1], c[2], c[3]
16        ),
17        steam_vdf_parser::Value::Obj(obj) => {
18            let mut out = format!("{}{{\n", indent_str);
19            for (k, v) in obj.iter() {
20                out.push_str(&format!("{}\"\"{}\"\": ", indent_str, k));
21                match v {
22                    steam_vdf_parser::Value::Obj(_) => {
23                        out.push_str(&dump_value(v, indent + 1));
24                    }
25                    steam_vdf_parser::Value::Str(s) => out.push_str(&format!("\"{}\"\n", s)),
26                    steam_vdf_parser::Value::I32(n) => out.push_str(&format!("{}\n", n)),
27                    steam_vdf_parser::Value::U64(n) => out.push_str(&format!("{}\n", n)),
28                    steam_vdf_parser::Value::Float(n) => out.push_str(&format!("{}\n", n)),
29                    steam_vdf_parser::Value::Pointer(n) => {
30                        out.push_str(&format!("(pointer: {})\n", n))
31                    }
32                    steam_vdf_parser::Value::Color(c) => out.push_str(&format!(
33                        "(color: #{:02x}{:02x}{:02x}{:02x})\n",
34                        c[0], c[1], c[2], c[3]
35                    )),
36                }
37            }
38            out.push_str(&format!("{}}}\n", indent_str));
39            out
40        }
41    }
42}
43
44fn main() {
45    let args: Vec<String> = env::args().collect();
46    if args.len() < 2 {
47        eprintln!("Usage: {} <vdf_file> [--text]", args[0]);
48        eprintln!(
49            "  --text: force text format parsing (default: auto-detect based on file extension)"
50        );
51        std::process::exit(1);
52    }
53
54    let path = Path::new(&args[1]);
55    let force_text = args.len() > 2 && args[2] == "--text";
56
57    let result = if force_text || path.extension().is_some_and(|e| e == "vdf") {
58        // Try text first for .vdf files
59        let content = std::fs::read_to_string(path);
60        if let Ok(content) = content {
61            parse_text(&content).map(|v| v.into_owned())
62        } else {
63            // Fall back to binary
64            let data = std::fs::read(path).expect("Failed to read file");
65            if path
66                .file_name()
67                .is_some_and(|n| n.to_str().is_some_and(|s| s.contains("packageinfo")))
68            {
69                binary::parse_packageinfo(&data).map(|v| v.into_owned())
70            } else if path
71                .file_name()
72                .is_some_and(|n| n.to_str().is_some_and(|s| s.contains("appinfo")))
73            {
74                binary::parse_appinfo(&data).map(|v| v.into_owned())
75            } else {
76                parse_binary(&data).map(|v| v.into_owned())
77            }
78        }
79    } else {
80        // Binary parsing
81        let data = std::fs::read(path).expect("Failed to read file");
82        if path
83            .file_name()
84            .is_some_and(|n| n.to_str().is_some_and(|s| s.contains("packageinfo")))
85        {
86            binary::parse_packageinfo(&data).map(|v| v.into_owned())
87        } else if path
88            .file_name()
89            .is_some_and(|n| n.to_str().is_some_and(|s| s.contains("appinfo")))
90        {
91            binary::parse_appinfo(&data).map(|v| v.into_owned())
92        } else {
93            parse_binary(&data).map(|v| v.into_owned())
94        }
95    };
96
97    match result {
98        Ok(vdf) => {
99            println!("\"{}\" {}", vdf.key(), dump_value(vdf.value(), 0));
100        }
101        Err(e) => {
102            eprintln!("Error parsing VDF: {:?}", e);
103            std::process::exit(1);
104        }
105    }
106}