use anyhow::Result;
use std::fs;
use std::io::{Read, Seek, SeekFrom};
use tempfile::TempDir;
use valve_pak::VPK;
fn main() -> Result<()> {
println!("VPK Library Example");
println!("===================");
let temp_dir = TempDir::new()?;
let source_dir = temp_dir.path().join("source");
let vpk_path = temp_dir.path().join("example.vpk");
let extract_dir = temp_dir.path().join("extracted");
println!("\n1. Creating example files...");
create_example_files(&source_dir)?;
println!("\n2. Packing directory into VPK...");
let vpk = VPK::from_directory(&source_dir)?;
println!(" Found {} files to pack", vpk.file_count());
vpk.save(&vpk_path)?;
println!(" Saved VPK to: {}", vpk_path.display());
println!("\n3. Opening and inspecting VPK...");
let vpk = VPK::open(&vpk_path)?;
println!(" VPK Version: {:?}", vpk.version());
println!(" Total files: {}", vpk.file_count());
println!(" File listing:");
for file_path in vpk.file_paths() {
println!(" - {file_path}");
}
println!("\n4. Extracting individual files...");
if vpk.contains("readme.txt") {
let mut file = vpk.get_file("readme.txt")?;
println!(" File: readme.txt");
println!(" Size: {} bytes", file.length());
println!(" CRC32: 0x{:08x}", file.metadata().crc32);
let content = file.read_all_string()?;
println!(" Content: {}", content.trim());
if file.verify()? {
println!(" ✓ File integrity verified");
} else {
println!(" ✗ File integrity check failed");
}
}
if vpk.contains("data/binary.dat") {
let mut file = vpk.get_file("data/binary.dat")?;
println!("\n File: data/binary.dat");
println!(" Size: {} bytes", file.length());
let mut buffer = [0u8; 4];
file.read_exact(&mut buffer)?;
let magic = u32::from_le_bytes(buffer);
println!(" Magic number: 0x{magic:08x}");
file.seek(SeekFrom::Start(10))?;
let mut middle_buffer = [0u8; 5];
file.read_exact(&mut middle_buffer)?;
println!(" Bytes 10-14: {middle_buffer:?}");
}
println!("\n5. Extracting all files...");
fs::create_dir_all(&extract_dir)?;
for file_path in vpk.file_paths() {
let mut vpk_file = vpk.get_file(file_path)?;
let output_path = extract_dir.join(file_path);
if let Some(parent) = output_path.parent() {
fs::create_dir_all(parent)?;
}
vpk_file.save(&output_path)?;
println!(" Extracted: {file_path}");
}
println!("\n6. Verifying VPK integrity...");
match vpk.verify() {
Ok(true) => println!(" ✓ VPK verification passed"),
Ok(false) => println!(" ✗ VPK verification failed"),
Err(e) => println!(" ⚠ VPK verification not supported: {e}"),
}
println!("\n✓ Example completed successfully!");
println!("Temporary files created in: {}", temp_dir.path().display());
Ok(())
}
fn create_example_files(source_dir: &std::path::Path) -> Result<()> {
fs::create_dir_all(source_dir)?;
fs::create_dir_all(source_dir.join("data"))?;
fs::create_dir_all(source_dir.join("scripts"))?;
fs::create_dir_all(source_dir.join("textures"))?;
fs::write(
source_dir.join("readme.txt"),
"This is a sample text file for VPK testing.\nIt contains multiple lines.\n",
)?;
fs::write(
source_dir.join("config.cfg"),
"# Configuration file\nwidth=1920\nheight=1080\nfullscreen=true\n",
)?;
fs::write(
source_dir.join("data/binary.dat"),
[
0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x48, 0x65, 0x6C, 0x6C,
0x6F,
], )?;
fs::write(
source_dir.join("scripts/startup.lua"),
r#"-- Startup script
print("Game starting...")
local config = loadConfig("config.cfg")
initializeGame(config)
"#,
)?;
fs::write(
source_dir.join("textures/player.dds"),
vec![0x44, 0x44, 0x53, 0x20] .into_iter()
.chain(vec![0; 100]) .collect::<Vec<u8>>(),
)?;
println!(" Created example files in: {}", source_dir.display());
Ok(())
}