use clap::Parser;
use std::path::PathBuf;
use wow_cdbc::DbcParser;
#[derive(Parser)]
#[command(name = "dbc_schema_discovery")]
#[command(about = "Discover the schema of a DBC file through analysis")]
struct Cli {
file: PathBuf,
#[arg(short, long)]
output: Option<PathBuf>,
#[arg(short, long)]
sample_size: Option<usize>,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let cli = Cli::parse();
println!("Analyzing DBC file: {}", cli.file.display());
let data = std::fs::read(&cli.file)?;
let parser = DbcParser::parse_bytes(&data)?;
let header = parser.header();
println!("\nDBC Header Information:");
println!("======================");
println!("Magic: {}", String::from_utf8_lossy(&header.magic));
println!("Records: {}", header.record_count);
println!("Fields: {}", header.field_count);
println!("Record Size: {} bytes", header.record_size);
println!("String Block Size: {} bytes", header.string_block_size);
println!("\nSuggested Schema:");
println!("================");
let mut schema = serde_yaml_ng::Mapping::new();
let name = cli
.file
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("Unknown")
.to_string();
schema.insert(
serde_yaml_ng::Value::String("name".to_string()),
serde_yaml_ng::Value::String(name.clone()),
);
let mut fields = serde_yaml_ng::Sequence::new();
for i in 0..header.field_count {
let mut field = serde_yaml_ng::Mapping::new();
field.insert(
serde_yaml_ng::Value::String("name".to_string()),
serde_yaml_ng::Value::String(if i == 0 {
"ID".to_string()
} else {
format!("Field{i}")
}),
);
field.insert(
serde_yaml_ng::Value::String("type".to_string()),
serde_yaml_ng::Value::String("UInt32".to_string()),
);
if i == 0 {
field.insert(
serde_yaml_ng::Value::String("is_key".to_string()),
serde_yaml_ng::Value::Bool(true),
);
}
fields.push(serde_yaml_ng::Value::Mapping(field));
}
schema.insert(
serde_yaml_ng::Value::String("fields".to_string()),
serde_yaml_ng::Value::Sequence(fields),
);
if let Some(output_path) = cli.output {
let yaml = serde_yaml_ng::to_string(&serde_yaml_ng::Value::Mapping(schema))?;
std::fs::write(&output_path, yaml)?;
println!("\nSchema saved to: {}", output_path.display());
} else {
let yaml = serde_yaml_ng::to_string(&serde_yaml_ng::Value::Mapping(schema))?;
println!("\n{yaml}");
}
println!("\nNote: This is a basic schema. For accurate field type detection,");
println!("manual analysis or DBD definition files are recommended.");
println!("DBD definitions can be found at: https://github.com/wowdev/WoWDBDefs");
Ok(())
}