diff --git a/Cargo.lock b/Cargo.lock index 1d8e512..3963a9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,11 +2,26 @@ name = "mason" version = "0.1.0" dependencies = [ + "alchemy 0.1.0 (git+https://gitlab.com/CyberMages/alchemy.git)", "scribe 0.1.0 (git+https://gitlab.com/CyberMages/scribe.git)", ] +[[package]] +name = "alchemy" +version = "0.1.0" +source = "git+https://gitlab.com/CyberMages/alchemy.git#26080427c02c99b172cd34ed32b5a31684e59694" +dependencies = [ + "scribe 0.1.0 (git+https://gitlab.com/CyberMages/scribe.git)", + "sigils 0.1.0 (git+https://gitlab.com/CyberMages/sigils.git)", +] + [[package]] name = "scribe" version = "0.1.0" source = "git+https://gitlab.com/CyberMages/scribe.git#e52418d3bfc28cd1f03cc7f31af06fce2e03f844" +[[package]] +name = "sigils" +version = "0.1.0" +source = "git+https://gitlab.com/CyberMages/sigils.git#e64c3b0fbecca351e0a078fefc4273a0f0b8e6ad" + diff --git a/Cargo.toml b/Cargo.toml index 6d0c0c7..4a60907 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,6 @@ keywords = ["mason", "build"] [dependencies.scribe] git = "https://gitlab.com/CyberMages/scribe.git" + +[dependencies.alchemy] +git = "https://gitlab.com/CyberMages/alchemy.git" diff --git a/examples/build.rs b/examples/build.rs index 63035be..2b7b0ac 100644 --- a/examples/build.rs +++ b/examples/build.rs @@ -11,6 +11,7 @@ use std::path::PathBuf; use mason::Processor; + pub const RESOURCES_DIR: &'static str = "resources"; pub const MANIFEST_FILENAME: &'static str = "resources.msnr"; diff --git a/resources/resources.msnr b/resources/resources.msnr index 82d295c..ae08fb5 100644 --- a/resources/resources.msnr +++ b/resources/resources.msnr @@ -1,10 +1,12 @@ name=test +type=temp src=resources.msnr dst=files/resources.msnr compiler=echo args=-i -o -kkfjfllsaf name=test2 +type=temp src=resources.msnr dst=files/resources.msnr compiler=echo diff --git a/src/lib.rs b/src/lib.rs index f6dbcf6..ab010ec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,8 @@ #[macro_use] extern crate scribe; +extern crate alchemy; + mod loader; diff --git a/src/loader.rs b/src/loader.rs index 9f1bce7..0ff0300 100644 --- a/src/loader.rs +++ b/src/loader.rs @@ -1,3 +1,24 @@ +use std::fs::File; +use std::io::{Error, ErrorKind, BufReader, BufWriter, Read, Write}; + +use alchemy::*; + + + +/// +const LOADER_MAJOR_VERSION: u8 = 0; + +/// +const LOADER_MINOR_VERSION: u8 = 1; + +/// +const HEADER_BYTE_SIZE: usize = 6; + +/// +const MAGIC_NUMBER: &'static str = "MSNL"; + + + /// pub struct Entry { @@ -53,6 +74,56 @@ impl Entry } } +impl Transmutable for Entry +{ + fn to_bytes(&self, endianess: Endianess) -> Vec + { + let mut buffer: Vec; + + // Create the new buffer to hold the data from this type. + buffer = Vec::new(); + + // Add the buffer data of the three paths to the data buffer. + buffer.append(&mut self.name.to_bytes(endianess)); + buffer.append(&mut self.type_hint.to_bytes(endianess)); + buffer.append(&mut self.path.to_bytes(endianess)); + + // Return the data buffer. + buffer.shrink_to_fit(); + buffer + } + + fn from_bytes(buffer: &[u8], endianess: Endianess) -> Entry + { + let buffer_size: usize; + let name: String; + let type_hint: String; + let path: String; + let mut skip_size: usize; + + buffer_size = buffer.len() - 1; + + skip_size = 0; + name = String::from_bytes(&buffer[skip_size..buffer_size], endianess); + + skip_size = skip_size + get_byte_size_of_string(&name); + type_hint = String::from_bytes(&buffer[skip_size..buffer_size], + endianess); + + skip_size = skip_size + get_byte_size_of_string(&type_hint); + path = String::from_bytes(&buffer[skip_size..buffer_size], endianess); + + Entry::new(name, type_hint, path) + } + + fn determine_byte_size(&self) -> usize + { + get_byte_size_of_string(&self.name) + + get_byte_size_of_string(&self.type_hint) + + get_byte_size_of_string(&self.path) + } +} + impl Loader { /// @@ -64,6 +135,34 @@ impl Loader } } + /// + pub fn from_file(file: File) -> Loader + { + let mut loader: Loader; + + // Create a new loader. + loader = Loader + { + entries: Vec::new() + }; + + // Read the given file. + match loader.read_from_file(file) + { + Ok(_) => + { + } + + Err(error) => + { + error!("{}", error); + } + } + + // Return the loader. + loader + } + /// pub fn add_resource_entry(&mut self, name: String, type_hint: String, path: String) @@ -79,4 +178,100 @@ impl Loader { &self.entries } + + /// Write the resource entries out to a file. + pub fn write_to_file(&self, file: File) -> ::std::io::Result<()> + { + let mut data: Vec; + let mut writer: BufWriter; + + // Create the writer for the file. + writer = BufWriter::new(file); + + // Create a Vector for the data of this loader data. + data = Vec::new(); + + // Write the header of the file. + data.extend_from_slice(MAGIC_NUMBER.as_bytes()); + data.append(&mut LOADER_MAJOR_VERSION.to_bytes(Endianess::Little)); + data.append(&mut LOADER_MINOR_VERSION.to_bytes(Endianess::Little)); + + // Write all the entries of the file. + for entry in self.entries.iter() + { + data.append(&mut entry.to_bytes(Endianess::Little)); + } + + // Try to write all the data to the file. + try!(writer.write_all(data.as_slice())); + + Ok(()) + } + + /// Read resource entries from a file. + fn read_from_file(&mut self, file: File) -> ::std::io::Result<()> + { + let mut pos: usize; + let mut data: Vec; + let mut reader: BufReader; + let data_size: usize; + let data_slice: &[u8]; + let mut entry: Entry; + debug!("Parsing loader manifest."); + + // Create a new reader of the file. + reader = BufReader::new(file); + + // Try to read in all of the file. + data = Vec::new(); + try!(reader.read_to_end(&mut data)); + data_slice = data.as_slice(); + data_size = data_slice.len() - 1; + + // Check the header information. + pos = 0; + try!(self.parse_header(&data_slice[pos..HEADER_BYTE_SIZE])); + pos = pos + HEADER_BYTE_SIZE; + + // Read in each entry. + while pos <= data_size + { + debug!("\tParsing entry."); + entry = Entry::from_bytes(&data_slice[pos..data_size], + Endianess::Little); + pos = pos + entry.determine_byte_size(); + + self.entries.push(entry); + } + + debug!("Loader manifest parsed successfully."); + Ok(()) + } + + fn parse_header(&self, header: &[u8]) -> ::std::io::Result<()> + { + let magic_number: &[u8]; + + // Make sure the header starts with the magic number. + magic_number = MAGIC_NUMBER.as_bytes(); + for (i, byte) in magic_number.iter().enumerate() + { + if *byte != header[i] + { + return Err(Error::new(ErrorKind::InvalidData, + "Header magic number mismatch.")); + } + } + + // Make sure the version is correct. + if header[4] != LOADER_MAJOR_VERSION || header[5] != LOADER_MINOR_VERSION + { + return Err(Error::new(ErrorKind::InvalidData, + "Header wrong version.")); + } + + // This is a good header. + debug!("Header parsed successfully."); + Ok(()) + } } diff --git a/src/processor.rs b/src/processor.rs index 9685af7..64107a3 100644 --- a/src/processor.rs +++ b/src/processor.rs @@ -4,6 +4,8 @@ use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use std::process::Command; +use ::loader::Loader; + /// The default name of the resources directory. @@ -12,6 +14,9 @@ const DEFAULT_RESOURCES_DIR: &'static str = "resources"; /// The default name to be used for the resource manifest file. const DEFAULT_MANIFEST_FILENAME: &'static str = "resources.msnr"; +/// The default name to be used for the resource manifest file. +const DEFAULT_LOADER_FILENAME: &'static str = "resources.msnl"; + /// Defines a resource to be compiled. @@ -142,7 +147,7 @@ impl Processor println!("Task count: {}", self.task_count); } - /// Process the resource manifest file. + /// Process the resource manifest file into a loader manifest file. pub fn process_manifest_file(&mut self) { // Read the manifest file from the resources directory. @@ -150,6 +155,9 @@ impl Processor // Compile all the resources from the manifest file. self.compile_resources(); + + // Create the loader manifest file. + self.create_loader_manifest(); } /// Read the manifest file. @@ -470,4 +478,46 @@ impl Processor args } + + /// + fn create_loader_manifest(&self) + { + let mut loader: Loader; + + // Create a new Loader. + loader = Loader::new(); + + // Add all the resource entries to the loader. + for section in self.sections.iter() + { + loader.add_resource_entry(section.name.clone(), + section.type_hint.clone(), + section.dst_path.clone()); + } + + // Create the file to write to. + match ::std::fs::File::create(DEFAULT_LOADER_FILENAME) + { + Ok(file) => + { + // Wrtie the loader manifest file. + match loader.write_to_file(file) + { + Ok(_) => + { + } + + Err(error) => + { + error!("{}", error); + } + } + } + + Err(error) => + { + error!("{}", error); + } + } + } }