use std::{fs, path::Path}; use anyhow::anyhow; use log::error; use zip::ZipArchive; use crate::types::{ModConfig, RootConfig}; pub fn unpack( root_config: &RootConfig, id: &str, path: impl AsRef, ) -> anyhow::Result { let extract_to = root_config.mod_location().join(id); if fs::exists(&extract_to)? { return Err(anyhow!("File already exists")); } match path.as_ref().extension().and_then(|e| e.to_str()) { Some("7z") => unpack_7z_file(path, &extract_to), Some("zip") => unpack_zip_file(path, &extract_to), Some("rar") => unpack_rar(path, &extract_to), Some(ext) => { error!("Unsupported archive format: {}", ext); Err(anyhow!("Unsupported archive format: {}", ext)) } None => { error!( "Failed to determine the file extension for {}", &path.as_ref().to_string_lossy() ); Err(anyhow!("Failed to determine file extension")) } }?; let new_mod = ModConfig::new(id, id); Ok(new_mod) } fn unpack_7z_file(path: impl AsRef, to: impl AsRef) -> anyhow::Result<()> { sevenz_rust2::decompress_file(path, to)?; Ok(()) } fn unpack_zip_file(path: impl AsRef, to: impl AsRef) -> anyhow::Result<()> { let file = fs::File::open(path)?; let mut archive = ZipArchive::new(file)?; archive.extract(to)?; Ok(()) } fn unpack_rar(path: impl AsRef, to: impl AsRef) -> anyhow::Result<()> { let mut archive = unrar::Archive::new(path.as_ref()).open_for_processing()?; while let Some(header) = archive.read_header()? { archive = header.extract_with_base(&to)?; } Ok(()) }