diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..1d8e512 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,12 @@ +[root] +name = "mason" +version = "0.1.0" +dependencies = [ + "scribe 0.1.0 (git+https://gitlab.com/CyberMages/scribe.git)", +] + +[[package]] +name = "scribe" +version = "0.1.0" +source = "git+https://gitlab.com/CyberMages/scribe.git#e52418d3bfc28cd1f03cc7f31af06fce2e03f844" + diff --git a/Cargo.toml b/Cargo.toml index 8745c18..6d0c0c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ repository = "https://gitlab.com/CyberMages/mason.git" documentation = "" keywords = ["mason", "build"] -[dependencies] +[dependencies.scribe] +git = "https://gitlab.com/CyberMages/scribe.git" diff --git a/examples/build.rs b/examples/build.rs new file mode 100644 index 0000000..985b6a1 --- /dev/null +++ b/examples/build.rs @@ -0,0 +1,85 @@ +#[macro_use] +extern crate scribe; + +extern crate mason; + + + +use std::path::PathBuf; + +use mason::Processor; + + +pub const RESOURCES_DIR: &'static str = "resources"; +pub const MANIFEST_FILENAME: &'static str = "resources.msnr"; + + + +pub fn main() +{ + let task_count: u64; + let output_dir: PathBuf; + let mut resources_dir: PathBuf; + let mut processor: Processor; + + // Get the cargo manifest directory and then append the + // resource directory name to it. + match option_env!("CARGO_MANIFEST_DIR") + { + Some(dir) => + { + resources_dir = PathBuf::from(dir); + } + + None => + { + resources_dir = PathBuf::new(); + } + } + resources_dir.push(RESOURCES_DIR); + + // Get the output directory for the build. + match option_env!("OUT_DIR") + { + Some(dir) => + { + output_dir = PathBuf::from(dir); + } + + None => + { + output_dir = PathBuf::new(); + } + } + + // Get how many compile tasks should be run at one time. + match option_env!("NUM_JOBS") + { + Some(count) => + { + match count.parse::() + { + Ok(val) => + { + task_count = val; + } + + Err(error) => + { + error!("{}", error); + } + } + } + + None => + { + task_count = 1u64; + } + } + + processor = Processor::new(); + processor.set_resources_dir(resources_dir.as_path()); + processor.set_output_dir(output_dir.as_path()); + processor.set_task_count(task_count); + processor.process_manifest_file(); +} diff --git a/resources/resources.msnr b/resources/resources.msnr new file mode 100644 index 0000000..68571ab --- /dev/null +++ b/resources/resources.msnr @@ -0,0 +1,4 @@ +name=test +src=resources.msnr +dst=resources.msnr +compiler=copy diff --git a/src/lib.rs b/src/lib.rs index 8b13789..f6dbcf6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,12 @@ +#[macro_use] +extern crate scribe; + + +mod loader; +mod processor; + + + +pub use self::loader::{Entry, Loader}; +pub use self::processor::Processor; diff --git a/src/loader.rs b/src/loader.rs new file mode 100644 index 0000000..9f1bce7 --- /dev/null +++ b/src/loader.rs @@ -0,0 +1,82 @@ +/// +pub struct Entry +{ + /// + name: String, + + /// + type_hint: String, + + /// + path: String +} + +/// +pub struct Loader +{ + /// + entries: Vec +} + + + +impl Entry +{ + /// + pub fn new(entry_name: String, entry_type: String, entry_path: String) + -> Entry + { + Entry + { + name: entry_name, + type_hint: entry_type, + path: entry_path + } + } + + /// + pub fn get_name(&self) -> &str + { + self.name.as_str() + } + + /// + pub fn get_type(&self) -> &str + { + self.type_hint.as_str() + } + + /// + pub fn get_path(&self) -> &str + { + self.path.as_str() + } +} + +impl Loader +{ + /// + pub fn new() -> Loader + { + Loader + { + entries: Vec::new() + } + } + + /// + pub fn add_resource_entry(&mut self, name: String, + type_hint: String, path: String) + { + let entry: Entry; + + entry = Entry::new(name, type_hint, path); + self.entries.push(entry); + } + + /// + pub fn get_resource_entries(&self) -> &Vec + { + &self.entries + } +} diff --git a/src/processor.rs b/src/processor.rs new file mode 100644 index 0000000..7efa1a5 --- /dev/null +++ b/src/processor.rs @@ -0,0 +1,268 @@ +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::{Path, PathBuf}; + + + +/// +const DEFAULT_RESOURCES_DIR: &'static str = "resources"; + +/// +const DEFAULT_MANIFEST_FILENAME: &'static str = "resources.msnr"; + + + +/// +struct Section +{ + /// + pub name: String, + + /// + pub type_hint: String, + + /// + pub src_path: String, + + /// + pub dst_path: String, + + /// + pub compiler: String, + + /// + pub arguments: String +} + +/// Processes the "resources.msnr" file and turns it +/// into a "resources.msnl" file. +pub struct Processor +{ + /// The name of the resource manifest file. + manifest_filename: String, + + /// The path to the resources directory. + resources_dir: PathBuf, + + /// The path to the output directory. + output_dir: PathBuf, + + /// The amount of tasks to use when processing the + /// resources from the manifest file. + task_count: u64, + + /// The resources sections from the "resources.msnr" file. + sections: Vec
+} + + + +impl Section +{ + /// + pub fn new() -> Section + { + Section + { + name: String::new(), + type_hint: String::new(), + src_path: String::new(), + dst_path: String::new(), + compiler: String::new(), + arguments: String::new() + } + } +} + +impl Processor +{ + /// + pub fn new() -> Processor + { + Processor + { + manifest_filename: String::from(DEFAULT_MANIFEST_FILENAME), + resources_dir: PathBuf::from(DEFAULT_RESOURCES_DIR), + output_dir: PathBuf::new(), + task_count: 1u64, + sections: Vec::new() + } + } + + /// + pub fn set_resources_dir(&mut self, dir: &Path) + { + self.resources_dir = PathBuf::from(dir); + println!("Resource dir: {}", self.resources_dir.to_str().unwrap()); + } + + /// + pub fn set_output_dir(&mut self, dir: &Path) + { + self.output_dir = PathBuf::from(dir); + println!("Output dir: {}", self.output_dir.to_str().unwrap()); + } + + /// + pub fn set_task_count(&mut self, count: u64) + { + self.task_count = count; + println!("Task count: {}", self.task_count); + } + + /// + pub fn process_manifest_file(&mut self) + { + // Read the manifest file from the resources directory. + self.read_manifest_file(); + + // Compile all the resources from the manifest file. + self.compile_resources(); + } + + /// + /// + /// Reading the manifest file can be a blocking + /// operation since there is nothing else to do until + /// the contents of this file have been read. + fn read_manifest_file(&mut self) + { + let file: File; + let mut continue_reading: bool; + let mut line: String; + let mut filepath: PathBuf; + let mut reader: BufReader; + let mut section_buffer: Vec; + + // Create the filepath for the resource manifest. + filepath = self.resources_dir.clone(); + filepath.push(self.manifest_filename.clone()); + + // Open the manifest file for reading. + match File::open(filepath) + { + Ok(opened_file) => + { + file = opened_file + } + + Err(error) => + { + error!("{} -- {:?} {:?}", error, + self.resources_dir, self.manifest_filename); + } + } + + // Create a reader to read all of the sections of + // the manifest file. + reader = BufReader::new(file); + + // Create a buffer to hold the current + // sections information. + section_buffer = Vec::new(); + + // Read all of the file line by line. + continue_reading = true; + while continue_reading == true + { + // Read a line from the file. + line = String::new(); + match reader.read_line(&mut line) + { + Ok(num_bytes) => + { + if num_bytes > 0 + { + if line == "\n" + { + // This is an empty line so if there are any + // lines in the section buffer then they need + // to be read as a section. If not then there + // is nothing to do. + self.read_manifest_section(§ion_buffer); + section_buffer = Vec::new(); + } + else + { + // Add this line to the section buffer. + section_buffer.push(line.clone()); + } + } + else + { + // It looks like there is nothing more to be read. + continue_reading = false; + } + } + + Err(error) => + { + error!("{}", error); + } + } + } + + // Check to make sure that anythin left in + // the section buffer is handled. + self.read_manifest_section(§ion_buffer); + } + + /// + fn read_manifest_section(&mut self, buffer: &Vec) + { + let mut header: &str; + let mut value: &str; + let mut section: Section; + let mut values: Vec<&str>; + + if buffer.len() > 0 + { + section = Section::new(); + for line in buffer.iter() + { + values = line.split("=").collect(); + if values.len() == 2 + { + header = values[0].trim(); + value = values[1].trim(); + if header == "name" + { + section.name = String::from(value); + } + else if header == "type" + { + section.type_hint = String::from(value); + } + else if header == "src" + { + section.src_path = String::from(value); + } + else if header == "dst" + { + section.dst_path = String::from(value); + } + else if header == "compiler" + { + section.compiler = String::from(value); + } + else if header == "args" + { + section.arguments = String::from(value); + } + } + else + { + warn!("Detected a name value entry that is incomplete.\n{}", + line.trim()); + } + } + + self.sections.push(section); + } + } + + /// + fn compile_resources(&self) + { + } +}