diff --git a/src/Tools/cpp_out/src/lib.rs b/src/Tools/cpp_out/src/lib.rs index 0ced3acd..357404aa 100644 --- a/src/Tools/cpp_out/src/lib.rs +++ b/src/Tools/cpp_out/src/lib.rs @@ -1,13 +1,44 @@ use tool_helper::{Input, Output, Result}; pub use tool_helper::Error; -fn write_cpp(_input: Input, output: &mut Output, line_feed: &str) -> Result<()> { - Error::try_with(write!(output, "const char data[] = {{{}", line_feed))?; - Error::try_with(write!(output, "}};"))?; +pub enum LineFeed { + Unix, + Windows +} + +pub enum FileType { + CHeader, + CSource, + CPPHeader, + CPPSource, +} + +pub struct Configuration { + pub file_name: String, + pub data_name: String, + pub line_feed: LineFeed, + pub file_type: FileType, +} + +struct FileVariables<'a> { + include: &'a str, + var_type: &'a str, +} + +const UNIX_LINEFEED: &'static str = "\n"; +const WINDOWS_LINEFEED: &'static str = "\r\n"; + +const C_VARIABLES: FileVariables = FileVariables{include: "", var_type: "char"}; +const CPP_VARIABLES: FileVariables = FileVariables{include: "#include ", var_type: "uint8_t"}; + +fn write_source_file(variables: &FileVariables, input: Input, output: &mut Output, line_feed: &str) -> Result<()> { + Error::try_or_new(write!(output, "{}{}{}", variables.include, line_feed, line_feed), None)?; + Error::try_or_new(write!(output, "const {} data[] = {{{}", variables.var_type, line_feed), None)?; + Error::try_or_new(write!(output, "}};"), None)?; Ok(()) } -pub fn convert(_input: Input, mut output: Output) -> Result<()> { - write_cpp(_input, &mut output, "\r\n") +pub fn convert(_cfg: Configuration, _input: Input, mut output: Output) -> Result<()> { + write_source_file(&CPP_VARIABLES, _input, &mut output, WINDOWS_LINEFEED) } \ No newline at end of file diff --git a/src/Tools/cpp_out/src/main.rs b/src/Tools/cpp_out/src/main.rs index 50f7ae01..4bb07a45 100644 --- a/src/Tools/cpp_out/src/main.rs +++ b/src/Tools/cpp_out/src/main.rs @@ -1,5 +1,6 @@ use clap::{Parser}; use std::path::PathBuf; +use cpp_out::{Configuration, Error, FileType}; #[derive(Parser)] #[clap(about = "Output a file content or stdin to a c++ header/source file", long_about = None)] @@ -11,15 +12,32 @@ struct CommandLine { output_file: PathBuf, } +fn configurate(cmd: &CommandLine) -> tool_helper::Result { + let file_name = tool_helper::get_file_name_from_path_buf(&cmd.output_file, "output")?; + let extension = tool_helper::os_str_to_string(Error::ok_or_new(cmd.output_file.extension(), "File extension required for output".to_owned(), None)?, "extension")?.to_ascii_lowercase(); + let file_type = Error::ok_or_new({ + match extension.as_ref() { + "h" => Some(FileType::CHeader), + "hpp" => Some(FileType::CPPHeader), + "c" => Some(FileType::CSource), + "cpp" => Some(FileType::CPPSource), + _ => None + } + }, format!("{} unkown file extension", extension), None)?; + + Ok(Configuration{file_name, data_name: "Planschbecken".to_owned(), line_feed: cpp_out::LineFeed::Windows, file_type}) +} + fn run_main() -> tool_helper::Result<()> { match CommandLine::try_parse() { Ok(cmd) => { + let cfg = configurate(&cmd)?; let input = tool_helper::open_input(cmd.input_file)?; let output = tool_helper::open_output(Some(cmd.output_file))?; - return cpp_out::convert(input, output); + return cpp_out::convert(cfg, input, output); }, - Err(error) => Err(tool_helper::Error::new(-1, error.to_string())) + Err(error) => Err(tool_helper::Error::new(error.to_string(), None)) } } diff --git a/src/Tools/tool_helper/src/lib.rs b/src/Tools/tool_helper/src/lib.rs index 52f7ffa3..f12bdf84 100644 --- a/src/Tools/tool_helper/src/lib.rs +++ b/src/Tools/tool_helper/src/lib.rs @@ -10,19 +10,19 @@ pub struct Error { } impl Error { - pub fn new(exit_code: i32, text: String) -> Error { - Error{exit_code, text} + pub fn new(text: String, exit_code: Option) -> Error { + Error{exit_code: Self::get_exit_code(exit_code), text} } - pub fn try_with_code(result: std::result::Result, exit_code: Option) -> Result where S: std::fmt::Display { + pub fn try_or_new(result: std::result::Result, exit_code: Option) -> Result where S: std::fmt::Display { match result { Ok(value) => Ok(value), - Err(error) => Err(Error::new(Self::get_exit_code(exit_code), error.to_string())), + Err(error) => Err(Error::new(error.to_string(), exit_code)), } } - pub fn try_with(result: std::result::Result) -> Result where S: std::fmt::Display { - Self::try_with_code(result, None) + pub fn ok_or_new(option: Option, error_text: String, code: Option) -> Result { + Ok(option.ok_or(Error::new(error_text, code))?) } fn get_exit_code(exit_code: Option) -> i32 { @@ -35,14 +35,22 @@ impl Error { pub fn open_output(output_file: Option) -> Result { match output_file { - Some(output_path) => Ok(Box::new(Error::try_with(std::fs::File::create(output_path))?)), + Some(output_path) => Ok(Box::new(Error::try_or_new(std::fs::File::create(output_path), None)?)), None => Ok(Box::new(std::io::stdout())), } } pub fn open_input(input_file: Option) -> Result { match input_file { - Some(input_path) => Ok(Box::new(Error::try_with(std::fs::File::open(input_path))?)), + Some(input_path) => Ok(Box::new(Error::try_or_new(std::fs::File::open(input_path), None)?)), None => Ok(Box::new(std::io::stdin())), } +} + +pub fn os_str_to_string(input: &std::ffi::OsStr, name: &str) -> Result { + Ok(Error::ok_or_new(input.to_str(), format!("Converting {} to UTF-8 failed", name), None)?.to_owned()) +} + +pub fn get_file_name_from_path_buf(input: &PathBuf, name: &str) -> Result { + os_str_to_string(Error::ok_or_new(input.file_name(), format!("No {} file name found", name), None)?, name) } \ No newline at end of file