1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
extern crate serde; extern crate serde_yaml; use std::path::Path; mod field; mod field_type; mod node; mod options; pub use field::Field; pub use field_type::FieldType; pub use node::Node; pub use options::Options; #[derive(Debug)] pub enum Error { CantFindYaml, FailedToReadYaml(String), YamlHasInvalidFormat(String), FailedToCreateTargetDir(String), FailedToWriteFile(String), } impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Error::CantFindYaml => write!(f, "Error::CantFindYaml()"), Error::FailedToReadYaml(msg) => write!(f, "Error::FailedToReadYaml({})", msg), Error::YamlHasInvalidFormat(msg) => write!(f, "Error::YamlHasInvalidFormat({})", msg), Error::FailedToCreateTargetDir(msg) => { write!(f, "Error::FailedToCreateTargetDir({})", msg) } Error::FailedToWriteFile(msg) => write!(f, "Error::FailedToWriteFile({})", msg), } } } impl std::error::Error for Error {} pub fn nodes() -> Result<Vec<Node>, Error> { let path = Path::new(file!()) .parent() .ok_or_else(|| Error::CantFindYaml)? .join("nodes.yaml") .to_str() .ok_or_else(|| Error::CantFindYaml)? .to_owned(); let f = std::fs::File::open(&path).map_err(|err| Error::FailedToReadYaml(err.to_string()))?; let nodes: Vec<Node> = serde_yaml::from_reader(f).map_err(|err| Error::YamlHasInvalidFormat(err.to_string()))?; Ok(nodes) } pub fn generate_nodes(options: &Options) -> Result<(), Error> { println!("cargo:rerun-if-changed=nodes.yaml"); let nodes = nodes()?; std::fs::create_dir_all(&options.target_dir) .map_err(|err| Error::FailedToCreateTargetDir(err.to_string()))?; for node in nodes.iter() { let code = node.code(options); std::fs::write( &format!("{}/{}.rs", options.target_dir, node.filename), code, ) .map_err(|err| { Error::FailedToWriteFile(format!( "failed to write {}/{}.rs: {}", options.target_dir, node.filename, err )) })?; } Ok(()) } pub fn generate_mod(options: &Options) -> Result<(), Error> { let mod_content = nodes()? .iter() .map(|node| { format!( "mod {mod_name};\npub use {mod_name}::{struct_name};\n", mod_name = node.filename, struct_name = node.struct_name ) }) .collect::<Vec<_>>() .join("\n"); std::fs::write(&format!("{}/mod.rs", options.target_dir), &mod_content).map_err(|err| { Error::FailedToWriteFile(format!( "Failed to write {}/mod.rs: {}", options.target_dir, err )) })?; Ok(()) }