diff --git a/.cargo/config.toml b/.cargo/config.toml index d3992b5..ed1e141 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,2 @@ [build] -rustflags = ["--cfg", "procmacro2_semver_exempt"] +rustflags = [ "--cfg", "procmacro2_semver_exempt" ] diff --git a/.rustfmt.toml b/.rustfmt.toml index 8864d7d..02d5415 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,20 +1,19 @@ -condense_wildcard_suffixes = true -max_width = 120 +condense_wildcard_suffixes = true enum_discrim_align_threshold = 25 -force_explicit_abi = false -force_multiline_blocks = true -format_code_in_doc_comments = true -format_macro_matchers = true -format_strings = true -group_imports = "StdExternalCrate" -hex_literal_case = "Upper" -imports_granularity = "Crate" -imports_layout = "Vertical" -match_block_trailing_comma = true -newline_style = "Unix" -normalize_comments = true -normalize_doc_attributes = true -reorder_impl_items = true -unstable_features = true -use_try_shorthand = true -wrap_comments = true +force_explicit_abi = false +force_multiline_blocks = true +format_code_in_doc_comments = true +format_macro_matchers = true +format_strings = true +group_imports = "StdExternalCrate" +hex_literal_case = "Upper" +imports_granularity = "Crate" +imports_layout = "Vertical" +match_block_trailing_comma = true +newline_style = "Unix" +normalize_comments = true +normalize_doc_attributes = true +reorder_impl_items = true +unstable_features = true +use_try_shorthand = true +wrap_comments = true diff --git a/Cargo.lock b/Cargo.lock index a4ab93e..6f47fba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,19 +1,19 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "embd" -version = "0.1.5" +version = "0.1.4" dependencies = [ - "embd-macros 0.1.4", + "embd-macros 0.1.1", ] [[package]] name = "embd-macros" -version = "0.1.4" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad70201855c78504fbd460954eb86c33c8ed9262f3514ea3b6a55162fc231a24" +checksum = "6d8aff0b18a634834d77cf70effb2ee3f5ab2b4f36f1caa7fabe213ac7767b0f" dependencies = [ "proc-macro2", "quote", @@ -22,7 +22,7 @@ dependencies = [ [[package]] name = "embd-macros" -version = "0.1.5" +version = "0.1.4" dependencies = [ "proc-macro2", "quote", @@ -31,27 +31,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.38" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] name = "syn" -version = "2.0.98" +version = "2.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" dependencies = [ "proc-macro2", "quote", @@ -60,6 +60,6 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/Cargo.toml b/Cargo.toml index 64d0b7a..fe651cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] -members = ["embd", "embd-macros"] +members = [ "embd", "embd-macros" ] resolver = "2" diff --git a/embd-macros/Cargo.toml b/embd-macros/Cargo.toml index 185a8e4..00919d8 100644 --- a/embd-macros/Cargo.toml +++ b/embd-macros/Cargo.toml @@ -1,22 +1,22 @@ [package] -name = "embd-macros" +name = "embd-macros" description = "Read files or directories from the filesystem at runtime on debug, embed on release." -repository = "https://github.com/RGBCube/embd-rs" -license = "MIT" -keywords = ["embedding", "files", "debug-optimization", "bundling"] -categories = ["filesystem"] -authors = ["RGBCube"] -version = "0.1.5" -edition = "2021" -include = ["src/**/*.rs", "../README.md"] +repository = "https://github.com/RGBCube/embd-rs" +license = "MIT" +keywords = [ "embedding", "files", "debug-optimization", "bundling" ] +categories = [ "filesystem" ] +authors = [ "RGBCube" ] +version = "0.1.4" +edition = "2021" +include = [ "src/**/*.rs", "README.md" ] [package.metadata.docs.rs] -rustc-args = ["--cfg", "procmacro2_semver_exempt"] +rustc-args = [ "--cfg", "procmacro2_semver_exempt" ] [lib] proc-macro = true [dependencies] -proc-macro2 = { version = "1", features = ["span-locations"] } -quote = "1" -syn = "2" +proc-macro2 = { version = "1", features = [ "span-locations" ] } +quote = "1" +syn = "2" diff --git a/embd-macros/README.md b/embd-macros/README.md new file mode 100644 index 0000000..160a42c --- /dev/null +++ b/embd-macros/README.md @@ -0,0 +1,68 @@ +# embd-rs + +A super simple file and directory embedding crate, +that loads files from the filesystem on debug mode, +allowing for quick edit-and-test cycles without compilation. + +It is also super efficient, and does not heap allocate when the +files are embedded on release mode by utilizing `std::borrow::Cow`. + +On release mode it falls back to `include_str!`, `include_bytes!` +and our own custom `include_dir!`-like implementation. + +## Usage + +Add this to your Cargo.toml: + +```toml +[dependencies] +embd = "0.1" +``` + +Then you can use this crate like so: + +```rs +let contents: Cow<'_, str> = embd::string!("path/to/file.txt"); +let bytes: Cow<'_, [u8]> = embd::bytes!("path/to/image.png"); + +let dir: embd::Dir = embd::dir!("path/to"); +let files: Vec = dir.flatten(); +``` + +Note that you will need to enable the `procmacro2_semver_exempt` cfg +option to use this crate, you can enable it like so, by putting this in +`.cargo/config.toml` in the project root: + +```toml +[build] +rustflags = [ "--cfg", "procmacro2_semver_exempt" ] +``` + +## To-Do + +- [ ] Hot reloading of files in debug mode. +- [ ] Don't depend on `procmacro2_semver_exempt`. + +## License + +``` +Copyright (c) 2023-present RGBCube + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` diff --git a/embd-macros/src/lib.rs b/embd-macros/src/lib.rs index e1408a6..898a55b 100644 --- a/embd-macros/src/lib.rs +++ b/embd-macros/src/lib.rs @@ -74,11 +74,14 @@ fn dir_debug(path: &str) -> TokenStream { #[cfg(procmacro2_semver_exempt)] fn dir_release(input: TokenStream, path: &str) -> TokenStream { - let neighbor = input.span().source_file().path(); + let neighbor = TokenStream::from(input).span().source_file().path(); let base = neighbor.parent().expect("Failed to get the parent of file"); - let directory = base.join(path).canonicalize().expect("Failed to canonicalize path"); + let directory = base + .join(path) + .canonicalize() + .expect("Failed to canonicalize path"); let directory_str = directory.to_str().expect("Failed to convert OsStr to str"); @@ -105,7 +108,9 @@ fn read_dir(directory: &Path) -> TokenVec { .to_str() .expect("Failed to get the string representation of PathBuf"); - let filetype = fs::metadata(&path).expect("Failed to get file metadata").file_type(); + let filetype = fs::metadata(&path) + .expect("Failed to get file metadata") + .file_type(); if filetype.is_dir() { let children = read_dir(&path); diff --git a/embd/Cargo.toml b/embd/Cargo.toml index 27aa938..232b77a 100644 --- a/embd/Cargo.toml +++ b/embd/Cargo.toml @@ -1,17 +1,17 @@ [package] -name = "embd" +name = "embd" description = "Read files or directories from the filesystem at runtime on debug, embed on release." -repository = "https://github.com/RGBCube/embd-rs" -license = "MIT" -keywords = ["embedding", "files", "debug-optimization", "bundling"] -categories = ["filesystem"] -authors = ["RGBCube"] -version = "0.1.5" -edition = "2021" -include = ["src/**/*.rs", "../README.md"] +repository = "https://github.com/RGBCube/embd-rs" +license = "MIT" +keywords = [ "embedding", "files", "debug-optimization", "bundling" ] +categories = [ "filesystem" ] +authors = [ "RGBCube" ] +version = "0.1.4" +edition = "2021" +include = [ "src/**/*.rs", "README.md" ] [package.metadata.docs.rs] -rustc-args = ["--cfg", "procmacro2_semver_exempt"] +rustc-args = [ "--cfg", "procmacro2_semver_exempt" ] [dependencies] embd-macros = "0.1" diff --git a/embd/README.md b/embd/README.md new file mode 100644 index 0000000..160a42c --- /dev/null +++ b/embd/README.md @@ -0,0 +1,68 @@ +# embd-rs + +A super simple file and directory embedding crate, +that loads files from the filesystem on debug mode, +allowing for quick edit-and-test cycles without compilation. + +It is also super efficient, and does not heap allocate when the +files are embedded on release mode by utilizing `std::borrow::Cow`. + +On release mode it falls back to `include_str!`, `include_bytes!` +and our own custom `include_dir!`-like implementation. + +## Usage + +Add this to your Cargo.toml: + +```toml +[dependencies] +embd = "0.1" +``` + +Then you can use this crate like so: + +```rs +let contents: Cow<'_, str> = embd::string!("path/to/file.txt"); +let bytes: Cow<'_, [u8]> = embd::bytes!("path/to/image.png"); + +let dir: embd::Dir = embd::dir!("path/to"); +let files: Vec = dir.flatten(); +``` + +Note that you will need to enable the `procmacro2_semver_exempt` cfg +option to use this crate, you can enable it like so, by putting this in +`.cargo/config.toml` in the project root: + +```toml +[build] +rustflags = [ "--cfg", "procmacro2_semver_exempt" ] +``` + +## To-Do + +- [ ] Hot reloading of files in debug mode. +- [ ] Don't depend on `procmacro2_semver_exempt`. + +## License + +``` +Copyright (c) 2023-present RGBCube + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` diff --git a/embd/src/lib.rs b/embd/src/lib.rs index 10c7d92..0780950 100644 --- a/embd/src/lib.rs +++ b/embd/src/lib.rs @@ -1,8 +1,6 @@ #![allow(unexpected_cfgs)] - use std::{ borrow::Cow, - collections::VecDeque, fs, path::Path, }; @@ -33,7 +31,9 @@ pub fn __string_runtime(neighbor: &str, path: &str) -> String { /// # Example /// /// ``` -/// let content: Cow<'static, str> = embd::string!("main.rs"); +/// fn main() { +/// let content: Cow<'static, str> = embd::string!("main.rs"); +/// } /// ``` #[macro_export] #[cfg(procmacro2_semver_exempt)] @@ -66,8 +66,10 @@ pub fn __bytes_runtime(neighbor: &str, path: &str) -> Vec { /// # Example /// /// ``` -/// // `assets/` is in the same directory as `src/` -/// let content: Cow<'static, [u8]> = embd::string!("../assets/icon.png"); +/// fn main() { +/// // `assets/` is in the same directory as `src/` +/// let content: Cow<'static, [u8]> = embd::string!("../assets/icon.png"); +/// } /// ``` #[macro_export] #[cfg(procmacro2_semver_exempt)] @@ -126,19 +128,17 @@ impl Dir { /// Collects all files from the directory into a vector. pub fn flatten(self) -> Vec { - let mut files = Vec::new(); - let mut dirs = VecDeque::from([self]); + let mut entries = Vec::new(); - while let Some(dir) = dirs.pop_front() { - for child in dir.__children.iter().cloned() { - match child { - DirEntry::File(file) => files.push(file), - DirEntry::Dir(dir) => dirs.push_back(dir), - } + for child in self.__children.into_owned() { + // TODO: Eliminate allocation. + match child { + DirEntry::File(file) => entries.push(file), + DirEntry::Dir(dir) => entries.append(&mut dir.flatten()), } } - files + entries } } @@ -171,9 +171,15 @@ fn read_dir(directory: &Path) -> Vec { let filetype = entry.file_type().expect("Failed to read entry filetype"); - let path = entry.path().canonicalize().expect("Failed to canonicalize path"); + let path = entry + .path() + .canonicalize() + .expect("Failed to canonicalize path"); - let path_str = path.to_str().expect("Failed to convert OsStr to str").to_string(); + let path_str = path + .to_str() + .expect("Failed to convert OsStr to str") + .to_string(); if filetype.is_dir() { let children = read_dir(&path); @@ -204,7 +210,10 @@ pub fn __dir_runtime(neighbor: &str, path: &str) -> Dir { .canonicalize() .expect("Failed to canonicalize path"); - let directory_str = directory.to_str().expect("Failed to convert OsStr to str").to_string(); + let directory_str = directory + .to_str() + .expect("Failed to convert OsStr to str") + .to_string(); let children = read_dir(&directory); @@ -221,7 +230,9 @@ pub fn __dir_runtime(neighbor: &str, path: &str) -> Dir { /// # Example /// /// ``` -/// let content: embd::Dir = embd::dir!("../assets"); +/// fn main() { +/// let content: embd::Dir = embd::dir!("../assets"); +/// } /// ``` #[cfg(procmacro2_semver_exempt)] pub use embd_macros::__dir as dir;