use std::{ fs::File, io::{BufWriter, Read, Write}, path::PathBuf, }; use clap::Args; use zip::{write::FileOptions, ZipWriter}; #[derive(Debug, Args)] pub struct PowerEqualResultOption { #[arg(help = "Certificate file")] key_file: PathBuf, #[arg(short, long, default_value = "false", help = "Export to power.conf")] export: bool, #[arg( short, long, default_value = "false", help = "Replace power.conf in given zip file, will override export option" )] zip_file: Option, } pub fn calculate_equal_result(options: PowerEqualResultOption) { let cert = cert_lib::load_certificate(options.key_file).expect("load certificate failed"); let result = cert_lib::calculate_power_euqal_result(cert).expect("calculate equal result failed"); if let Some(zip_file) = options.zip_file { let mut buffer: Vec = Vec::new(); { let mut buf_writer = BufWriter::new(&mut buffer); buf_writer .write("[Args]\n\n[Result]\n".as_bytes()) .expect("write power.conf failed"); buf_writer .write(result.as_bytes()) .expect("write power.conf failed"); buf_writer.flush().expect("write power.conf failed"); } // 将zip_file的文件名增加一个`_replaced`后缀并形成一个新的位于相同目录的PathBuf实例。 let mut zip_file_path = zip_file.clone(); let file_name = zip_file_path.file_stem().unwrap().to_str().unwrap(); let mut zip_file_name = file_name.to_string(); zip_file_name.push_str("_replaced."); zip_file_name.push_str(&zip_file_path.extension().unwrap().to_string_lossy()); zip_file_path.set_file_name(zip_file_name); // 创建一个新的zip文件并将zip_file的内容复制到新的zip文件中。 let zip_file = File::open(zip_file).expect("open zip file failed"); let mut zip_file = zip::ZipArchive::new(zip_file).expect("open zip file failed"); let zip_file_path = File::create(zip_file_path).expect("create zip file failed"); let mut zip_file_writer = ZipWriter::new(zip_file_path); for i in 0..zip_file.len() { let mut file = zip_file.by_index(i).expect("get file from zip failed"); let options = FileOptions::default() .compression_method(file.compression()) .unix_permissions(file.unix_mode().unwrap()); let file_name = file.name().to_owned(); let file_name = file_name.replace("power.conf", "power.conf"); let content = if file_name.ends_with("power.conf") { buffer.clone() } else { let mut content = Vec::new(); file.read_to_end(&mut content).expect("read file failed"); content }; zip_file_writer .start_file(file_name, options) .expect("start output file failed"); zip_file_writer .write_all(&content) .expect("write output file failed"); } zip_file_writer.finish().expect("write zip file failed"); } else if options.export { let mut power_conf_path = PathBuf::new(); power_conf_path.push("."); power_conf_path.push("power.conf"); let power_conf_file = File::create(power_conf_path).expect("create power.conf failed"); let mut writer = BufWriter::new(power_conf_file); writer .write("[Args]\n\n[Result]\n".as_bytes()) .expect("write power.conf failed"); writer .write(result.as_bytes()) .expect("write power.conf failed"); writer.flush().expect("write power.conf failed"); println!("Export to power.conf completed."); } else { println!("{}", result); } }