pub struct Obj<'text> { /* private fields */ }Expand description
Object - map from keys to values
Uses HashMap for O(1) lookup. Binary VDF doesn’t have duplicate keys,
and for text VDF we use “last value wins” semantics.
Implementations§
Source§impl<'text> Obj<'text>
impl<'text> Obj<'text>
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of key-value pairs in the object.
Examples found in repository?
examples/verify_compactified.rs (line 31)
6fn main() {
7 let args: Vec<String> = env::args().collect();
8
9 if args.len() < 2 {
10 eprintln!("Usage: {} <vdf_file>", args[0]);
11 std::process::exit(1);
12 }
13
14 let path = &args[1];
15
16 // Read the file
17 let data = match std::fs::read(path) {
18 Ok(d) => d,
19 Err(e) => {
20 eprintln!("Error reading file: {}", e);
21 std::process::exit(1);
22 }
23 };
24
25 // Parse it
26 match parse_appinfo(&data) {
27 Ok(vdf) => {
28 println!("Successfully parsed {}", path);
29 println!("Root key: {}", vdf.key());
30 if let Some(obj) = vdf.as_obj() {
31 println!("Number of apps: {}", obj.len());
32 for (key, _) in obj.iter().take(5) {
33 println!(" - app_id: {}", key);
34 }
35 if obj.len() > 5 {
36 println!(" ... and {} more", obj.len() - 5);
37 }
38 }
39 }
40 Err(e) => {
41 eprintln!("Error parsing file: {:?}", e);
42 std::process::exit(1);
43 }
44 }
45}More examples
examples/test_parse_real.rs (line 16)
4fn main() {
5 // Test localconfig.vdf (text format)
6 println!("=== Parsing localconfig.vdf (text format) ===");
7 let localconfig = fs::read_to_string(
8 "/home/mexus/.local/share/Steam/userdata/127648749/config/localconfig.vdf",
9 );
10 match localconfig {
11 Ok(content) => match parse_text(&content) {
12 Ok(vdf) => {
13 println!("Success!");
14 println!("Root key: {}", vdf.key());
15 let obj = vdf.as_obj().unwrap();
16 println!("Root has {} keys", obj.len());
17 }
18 Err(e) => {
19 println!("Parse error: {:?}", e);
20 }
21 },
22 Err(e) => println!("Error reading: {}", e),
23 }
24
25 println!("\n=== Parsing appinfo.vdf (binary format) ===");
26 let appinfo = fs::read("/home/mexus/.local/share/Steam/appcache/appinfo.vdf");
27 match appinfo {
28 Ok(data) => match parse_binary(&data) {
29 Ok(vdf) => {
30 println!("Success!");
31 println!("Root key: {}", vdf.key());
32 let obj = vdf.as_obj().unwrap();
33 println!("Root has {} keys", obj.len());
34 }
35 Err(e) => {
36 println!("Parse error: {:?}", e);
37 }
38 },
39 Err(e) => println!("Error reading: {}", e),
40 }
41}Sourcepub fn get(&self, key: &str) -> Option<&Value<'text>>
pub fn get(&self, key: &str) -> Option<&Value<'text>>
Returns a reference to the value corresponding to the key.
Examples found in repository?
examples/appid_to_name.rs (line 77)
17fn main() -> ExitCode {
18 let args: Vec<String> = env::args().collect();
19
20 if args.len() < 2 {
21 eprintln!("Usage: {} <path/to/appinfo.vdf>", args[0]);
22 eprintln!();
23 eprintln!("Extracts AppId to game name mappings from Steam's appinfo.vdf file.");
24 eprintln!();
25 eprintln!("The appinfo.vdf file is typically located at:");
26 eprintln!(" Windows: C:\\Program Files (x86)\\Steam\\appcache\\appinfo.vdf");
27 eprintln!(" Linux: ~/.steam/steam/appcache/appinfo.vdf");
28 eprintln!(" macOS: ~/Library/Application Support/Steam/appcache/appinfo.vdf");
29 return ExitCode::FAILURE;
30 }
31
32 let path = &args[1];
33
34 // Read the file
35 let data = match fs::read(path) {
36 Ok(data) => data,
37 Err(e) => {
38 eprintln!("Error reading file '{}': {}", path, e);
39 return ExitCode::FAILURE;
40 }
41 };
42
43 // Parse the appinfo.vdf file
44 let vdf = match parse_appinfo(&data) {
45 Ok(vdf) => vdf.into_owned(),
46 Err(e) => {
47 eprintln!("Error parsing appinfo.vdf: {}", e);
48 return ExitCode::FAILURE;
49 }
50 };
51
52 // Get the root object containing all apps
53 let root = match vdf.as_obj() {
54 Some(obj) => obj,
55 None => {
56 eprintln!("Error: root is not an object");
57 return ExitCode::FAILURE;
58 }
59 };
60
61 // Iterate through all apps (keyed by AppID as string)
62 let mut apps = Vec::new();
63
64 for (app_id_str, app_value) in root.iter() {
65 // Skip non-numeric keys (metadata entries)
66 if app_id_str.parse::<u32>().is_err() {
67 continue;
68 }
69
70 let app_obj = match app_value.as_obj() {
71 Some(obj) => obj,
72 None => continue,
73 };
74
75 // Navigate the nested structure: appinfo -> common -> name
76 let name = app_obj
77 .get("appinfo")
78 .and_then(|v| v.as_obj())
79 .and_then(|appinfo| appinfo.get("common"))
80 .and_then(|common| common.as_obj())
81 .and_then(|common| common.get("name"))
82 .and_then(|v| v.as_str());
83
84 if let (Some(name), Ok(app_id)) = (name, app_id_str.parse::<u32>()) {
85 apps.push((app_id, name.to_string()));
86 }
87 }
88
89 // Sort by AppID
90 apps.sort_by_key(|(id, _)| *id);
91
92 // Print the results
93 println!("AppId\tName");
94 println!("------\t{}", "-".repeat(80));
95 for (app_id, name) in &apps {
96 println!("{}\t{}", app_id, name);
97 }
98
99 println!();
100 println!("Total games: {}", apps.len());
101
102 ExitCode::SUCCESS
103}Sourcepub fn iter(&self) -> impl Iterator<Item = (&Cow<'text, str>, &Value<'text>)>
pub fn iter(&self) -> impl Iterator<Item = (&Cow<'text, str>, &Value<'text>)>
Returns an iterator over the key-value pairs.
Examples found in repository?
examples/verify_compactified.rs (line 32)
6fn main() {
7 let args: Vec<String> = env::args().collect();
8
9 if args.len() < 2 {
10 eprintln!("Usage: {} <vdf_file>", args[0]);
11 std::process::exit(1);
12 }
13
14 let path = &args[1];
15
16 // Read the file
17 let data = match std::fs::read(path) {
18 Ok(d) => d,
19 Err(e) => {
20 eprintln!("Error reading file: {}", e);
21 std::process::exit(1);
22 }
23 };
24
25 // Parse it
26 match parse_appinfo(&data) {
27 Ok(vdf) => {
28 println!("Successfully parsed {}", path);
29 println!("Root key: {}", vdf.key());
30 if let Some(obj) = vdf.as_obj() {
31 println!("Number of apps: {}", obj.len());
32 for (key, _) in obj.iter().take(5) {
33 println!(" - app_id: {}", key);
34 }
35 if obj.len() > 5 {
36 println!(" ... and {} more", obj.len() - 5);
37 }
38 }
39 }
40 Err(e) => {
41 eprintln!("Error parsing file: {:?}", e);
42 std::process::exit(1);
43 }
44 }
45}More examples
examples/dump_vdf.rs (line 19)
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}examples/appid_to_name.rs (line 64)
17fn main() -> ExitCode {
18 let args: Vec<String> = env::args().collect();
19
20 if args.len() < 2 {
21 eprintln!("Usage: {} <path/to/appinfo.vdf>", args[0]);
22 eprintln!();
23 eprintln!("Extracts AppId to game name mappings from Steam's appinfo.vdf file.");
24 eprintln!();
25 eprintln!("The appinfo.vdf file is typically located at:");
26 eprintln!(" Windows: C:\\Program Files (x86)\\Steam\\appcache\\appinfo.vdf");
27 eprintln!(" Linux: ~/.steam/steam/appcache/appinfo.vdf");
28 eprintln!(" macOS: ~/Library/Application Support/Steam/appcache/appinfo.vdf");
29 return ExitCode::FAILURE;
30 }
31
32 let path = &args[1];
33
34 // Read the file
35 let data = match fs::read(path) {
36 Ok(data) => data,
37 Err(e) => {
38 eprintln!("Error reading file '{}': {}", path, e);
39 return ExitCode::FAILURE;
40 }
41 };
42
43 // Parse the appinfo.vdf file
44 let vdf = match parse_appinfo(&data) {
45 Ok(vdf) => vdf.into_owned(),
46 Err(e) => {
47 eprintln!("Error parsing appinfo.vdf: {}", e);
48 return ExitCode::FAILURE;
49 }
50 };
51
52 // Get the root object containing all apps
53 let root = match vdf.as_obj() {
54 Some(obj) => obj,
55 None => {
56 eprintln!("Error: root is not an object");
57 return ExitCode::FAILURE;
58 }
59 };
60
61 // Iterate through all apps (keyed by AppID as string)
62 let mut apps = Vec::new();
63
64 for (app_id_str, app_value) in root.iter() {
65 // Skip non-numeric keys (metadata entries)
66 if app_id_str.parse::<u32>().is_err() {
67 continue;
68 }
69
70 let app_obj = match app_value.as_obj() {
71 Some(obj) => obj,
72 None => continue,
73 };
74
75 // Navigate the nested structure: appinfo -> common -> name
76 let name = app_obj
77 .get("appinfo")
78 .and_then(|v| v.as_obj())
79 .and_then(|appinfo| appinfo.get("common"))
80 .and_then(|common| common.as_obj())
81 .and_then(|common| common.get("name"))
82 .and_then(|v| v.as_str());
83
84 if let (Some(name), Ok(app_id)) = (name, app_id_str.parse::<u32>()) {
85 apps.push((app_id, name.to_string()));
86 }
87 }
88
89 // Sort by AppID
90 apps.sort_by_key(|(id, _)| *id);
91
92 // Print the results
93 println!("AppId\tName");
94 println!("------\t{}", "-".repeat(80));
95 for (app_id, name) in &apps {
96 println!("{}\t{}", app_id, name);
97 }
98
99 println!();
100 println!("Total games: {}", apps.len());
101
102 ExitCode::SUCCESS
103}Sourcepub fn values(&self) -> impl Iterator<Item = &Value<'text>>
pub fn values(&self) -> impl Iterator<Item = &Value<'text>>
Returns an iterator over the values.
Sourcepub fn contains_key(&self, key: &str) -> bool
pub fn contains_key(&self, key: &str) -> bool
Returns true if the object contains the given key.
Sourcepub fn get_mut(&mut self, key: &str) -> Option<&mut Value<'text>>
pub fn get_mut(&mut self, key: &str) -> Option<&mut Value<'text>>
Returns a mutable reference to the value corresponding to the key.
Trait Implementations§
Source§impl<'a, 'text> IntoIterator for &'a Obj<'text>
impl<'a, 'text> IntoIterator for &'a Obj<'text>
Source§impl<'text> IntoIterator for Obj<'text>
impl<'text> IntoIterator for Obj<'text>
impl<'text> StructuralPartialEq for Obj<'text>
Auto Trait Implementations§
impl<'text> Freeze for Obj<'text>
impl<'text> RefUnwindSafe for Obj<'text>
impl<'text> Send for Obj<'text>
impl<'text> Sync for Obj<'text>
impl<'text> Unpin for Obj<'text>
impl<'text> UnwindSafe for Obj<'text>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more