diff --git a/generator-native/src/main.rs b/generator-native/src/main.rs index 94196ed..be1a6a4 100644 --- a/generator-native/src/main.rs +++ b/generator-native/src/main.rs @@ -6,7 +6,7 @@ use std::{ fs::{ self, File, OpenOptions, }, - io, + io::{self, Write,Read,}, error::Error, }; @@ -15,19 +15,43 @@ use iter::prelude::*; mod translate; +#[macro_use] mod opt; mod arg; +use opt::Opt; + fn usage() -> ! { let prog = &arg::program_name(); - println!("Usage: {} [-s] [-e ] [-o ] ", prog); + println!("Usage: {} [-s] [-e ] [-o ] [-] ", prog); println!("Usage: {} -h", prog); println!(); + println!(" -\t\tStop reading options."); println!(" -h\t\tPrint this message."); println!(" -s\t\tSilent mode."); println!(" -e \tScript to run after extraction."); println!(" -o \tOutput filename."); - std::process::exit(1); + std::process::exit(1) +} + +fn write_file(from: From, to: &mut To) -> io::Result +where From: Read, + To: Write + ?Sized +{ + let mut count =0; + for buf in from.into_iter(8) + .map(|byte| { + count += 1; + byte + }) + .map(|byte| format!("0x{:02x},", byte)) + .group_at(8) + .map(|strs| format!("\t{}", strs.join(" "))) + { + println!("{}", buf); + } + + Ok(count) } fn main() -> Result<(), Box>{ @@ -49,7 +73,48 @@ fn main() -> Result<(), Box>{ match arg::parse()? { arg::OperationMode::Normal(options, files) => { - //TODO: Operations + let output = options.find(|opt| match opt { + Opt::Output(output) => Some(output.as_str()), + _ => None + }).unwrap_or("file.h"); + let exec = options.find(|opt| match opt { + Opt::Execute(exec) => Some(exec.as_str()), + _ => None + }); + let silent = options.has_tag(&Opt::Silent); + + println!("Writing to {}...", output); + let mut fp = OpenOptions::new() + .write(true) + .truncate(true) + .open(output)?; + + if silent { + writeln!(fp, "#define SILENT")?; + } + + writeln!(fp, "constexpr const int DATA_COUNT = {};", files.len())?; + + if let Some(exec) = exec { + let exec = translate::c_escape(exec); + writeln!(fp, "constexpr const char* const DATA_EXEC_AFTER = {};", exec)?; + writeln!(fp, "static constexpr auto DATA_EXEC_AFTER_HASH = {}_sha256;", exec)?; + } else { + writeln!(fp, "constexpr const char* const DATA_EXEC_AFTER = nullptr;")?; + writeln!(fp, "static constexpr auto DATA_EXEC_AFTER_HASH = \"unbound\"_sha256;")?; + } + + let mut sizes = Vec::with_capacity(files.len()); + writeln!(fp, "constexpr const unsigned char DATA[] = {{")?; + + for file in files.iter() { + let rfp = OpenOptions::new() + .read(true) + .open(file)?; + print!(" + {}", file); + + sizes.push(write_file(rfp, &mut fp)?); + } }, arg::OperationMode::Help => { usage(); diff --git a/generator-native/src/opt/mod.rs b/generator-native/src/opt/mod.rs index 9e46baf..c31c799 100644 --- a/generator-native/src/opt/mod.rs +++ b/generator-native/src/opt/mod.rs @@ -20,6 +20,16 @@ impl Options { Self(HashSet::new()) } + pub fn find<'a, T,F>(&'a self, pred: F) -> Option + where F: Fn(&'a Opt) -> Option + { + for opt in self.0.iter() { + if let Some(ret) = pred(opt) { + return Some(ret); + } + } + None + } pub fn has_tag(&self, opt: &Opt) -> bool { for x in self.0.iter() {