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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
#[macro_use] extern crate quote; extern crate proc_macro2; pub extern crate regex; extern crate walkdir; mod assets; pub mod prelude; pub mod utils; pub use assets::*; use std::env; use std::fmt::Display; use std::fs::File; use std::io::{BufWriter, Write}; use std::path::{Path, PathBuf}; const DEFAULT_FILENAME: &str = "assets.rs"; /// A code generation builder. /// /// By default the path written to is `$OUT_DIR/assets.rs` where `$OUT_DIR` is /// from your environmental variables. This is usually set by cargo. If /// `$OUT_DIR` is not set, then no path is set. /// /// An unlimited amount of [`Pipelines`] can be added and they will be written /// to the file in the same order as they were added. /// /// [`Pipelines`]: ./trait.Pipeline.html #[derive(Default)] pub struct Codegen { assets_builder: Vec<Box<Pipeline>>, path: Option<PathBuf>, } impl Codegen { /// Creates a Codegen instance. /// /// If the cargo env var `OUT_DIR` is set, the path is automatically set /// to `$OUT_DIR/assets.rs`, otherwise a path is **not** set. In that case /// you are able to explicitly able to specify the path with [`set_path`]. /// /// ``` /// use includer_codegen::prelude::*; /// /// let c = Codegen::new(); /// ``` /// /// [`set_path`]: #method.set_path pub fn new() -> Codegen { Codegen { assets_builder: Vec::new(), path: env::var("OUT_DIR") .ok() .map(PathBuf::from) .map(|dir| dir.join(DEFAULT_FILENAME)), } } /// Returns the currently set path. /// /// ``` /// use std::path::Path; /// use includer_codegen::prelude::*; /// /// let c = Codegen::new().set_path("./out/gen.rs"); /// assert_eq!(c.path(), Some(Path::new("./out/gen.rs"))); /// ``` pub fn path(&self) -> Option<&Path> { self.path.as_ref().map(PathBuf::as_path) } /// Sets the output path for the generated file. /// /// ``` /// use includer_codegen::prelude::*; /// /// Codegen::new().set_path("./out/gen.rs"); /// ``` pub fn set_path<P: Into<PathBuf>>(mut self, path: P) -> Codegen { self.path = Some(path.into()); self } /// Returns a list of all currently set Pipelines pub fn pipelines(&self) -> &[Box<Pipeline>] { &self.assets_builder } /// Add a [`Pipeline`] to the `Codegen` instance. /// /// ``` /// use includer_codegen::prelude::*; /// /// Codegen::new().pipe(Assets::new("ASSETS", "../web/dist").build()); /// ``` /// /// [`Pipeline`]: ./trait.Pipeline.html pub fn pipe(mut self, generator: Box<Pipeline>) -> Codegen { self.assets_builder.push(generator); self } /// Writes everything to file and returns the written amount. /// /// ```no_run /// use includer_codegen::prelude::*; /// /// Codegen::new() /// .pipe(Assets::new("ASSETS", "../web/dist").build()) /// .write(); /// ``` /// /// # Panics /// /// If `path` is not set then this function will panic. /// /// A panic will also happen when any file operation fails - such as /// opening, writing, or closing. pub fn write(&self) -> usize { let path = self.path.as_ref().expect("Codegen output path not set"); let file = File::create(path).expect("Unable to open a file at the path"); let mut writer = BufWriter::new(file); let mut written = 0; for assets in &self.assets_builder { written += writer .write(assets.to_string().as_bytes()) .expect("Unable to write to Codegen file"); } writer .flush() .expect("Unable to close written Codegen file"); println!("written {} bytes to {}", written, path.to_str().unwrap()); written } } /// Assets Pipeline. /// /// `Pipeline` should be implemented on anything that generates code which /// embeds assets in binaries at compile time. For use in [`Codegen`] which /// generates a rust file at build time with the contents of all asset /// pipelines. /// /// [`Codegen`]: ./struct.Codegen.html pub trait Pipeline: Display {}