pub struct Obj<'text> { /* private fields */ }Expand description
Object - map from keys to values
Uses IndexMap for O(1) lookup while preserving insertion order.
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.
Sourcepub fn insert(
&mut self,
key: impl Into<Cow<'text, str>>,
value: Value<'text>,
) -> Option<Value<'text>>
pub fn insert( &mut self, key: impl Into<Cow<'text, str>>, value: Value<'text>, ) -> Option<Value<'text>>
Inserts a key-value pair into the object.
Returns the previous value if one existed for this 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