use crate::settings::Settings; use anyhow::{bail, Result}; use larian_formats::{ bg3::{raw::Version, ModPakLsx, ModuleInfo}, lsf, lspk::{self, DecompressedLspk}, }; use std::{fs::File, path::PathBuf}; impl Settings { pub(crate) fn dump_helper(path: PathBuf) -> Result<()> { parse_inner(std::iter::once(path), Style::Dump) } pub(crate) fn parse_helper( paths: impl IntoIterator, verbose: bool, ) -> Result<()> { let style = if verbose { Style::Verbose } else { Style::Basic }; parse_inner(paths, style) } } #[derive(Debug, Clone, Copy)] enum Style { Basic, Dump, Verbose, } impl Style { const fn is_print(self) -> bool { matches!(self, Self::Basic | Self::Verbose) } } fn parse_inner(paths: impl IntoIterator, style: Style) -> Result<()> { for path in paths { if style.is_print() { let displayed_path = path.display().to_string(); println!("{displayed_path}"); for _ in displayed_path.chars() { print!("-"); } println!(); } let file = File::open(&path)?; match path.extension().map(|s| s.to_string_lossy()).as_deref() { Some("zip") => { let data = lspk::entry_from_zipfile(&file)?; print_lspk(data.1, style)?; } Some("lsf") => { let data = lsf::Reader::new(file)?.read()?; if style.is_print() { data.print_summary(); } } Some("pak") => { let data = lspk::Reader::new(file)?.read()?; print_lspk(data, style)?; } _other => { if style.is_print() { bail!("expected .lsf or .pak file"); } bail!("expected .pak file"); } } if style.is_print() { println!(); } } Ok(()) } fn print_lspk(data: DecompressedLspk, style: Style) -> Result<()> { let meta_lsx = data.extract_meta_lsx()?; let raw = String::from_utf8_lossy(&meta_lsx.decompressed_bytes); if !style.is_print() { println!("{raw}"); return Ok(()); } let ModPakLsx { version, module_info, } = meta_lsx.deserialize_as_mod_pak()?; let Version { major, minor, revision, build, } = version; println!("Game version : {major}.{minor}.{revision}.{build}"); let ModuleInfo { author, description, folder, md5, name, num_players, module_type, uuid, version, } = module_info; println!("Name : {name}"); println!("Folder : {folder}"); println!("Version64 : {version}"); println!("UUID : {uuid}"); if !matches!(style, Style::Verbose) { return Ok(()); } if let Some(author) = author { println!("Author : {author}"); } if let Some(description) = description { println!("Description : {description}"); } if let Some(md5) = md5 { println!("MD5 : {md5}"); } if let Some(num_players) = num_players { println!("NumPlayers : {num_players}"); } if let Some(module_type) = module_type { println!("Type : {module_type}"); } Ok(()) }