parse_appinfo

Function parse_appinfo 

Source
pub fn parse_appinfo(input: &[u8]) -> Result<Vdf<'_>>
Expand description

Parse appinfo.vdf format binary data.

This function returns zero-copy data where possible - strings are borrowed from the input buffer (including string table entries in v41 format).

Format:

  • 4 bytes: Magic number (0x07564428 or 0x07564429)
  • 4 bytes: Universe
  • If magic == 0x07564429: 8 bytes: String table offset
  • Apps continue until EOF (or string table for v41)
  • For each app:
    • 4 bytes: App ID
    • 4 bytes: Size (remaining data size for this entry)
    • 4 bytes: InfoState
    • 4 bytes: LastUpdated (Unix timestamp)
    • 8 bytes: AccessToken
    • 20 bytes: SHA1 of text data
    • 4 bytes: ChangeNumber
    • 20 bytes: SHA1 of binary data
    • Then the VDF data for the app (starts with 0x00)
  • String table (if magic == 0x07564429, at string_table_offset)

App entry header is APPINFO_ENTRY_HEADER_SIZE (68) bytes.

Examples found in repository?
examples/verify_compactified.rs (line 26)
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
Hide additional examples
examples/dump_vdf.rs (line 74)
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}