1
Fork 0
mirror of https://github.com/RGBCube/embd-rs synced 2025-07-27 05:27:44 +00:00

Use our own proc-macro2 fork and don't allocate anything at release (somewhat)

This commit is contained in:
RGBCube 2024-01-05 00:22:34 +03:00
parent da1f20a409
commit 2f2ec0f0c4
No known key found for this signature in database
5 changed files with 36 additions and 19 deletions

4
Cargo.lock generated
View file

@ -38,9 +38,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.47" version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -4,11 +4,26 @@ A super simple file and directory embedding crate,
that loads files from the filesystem in debug mode, that loads files from the filesystem in debug mode,
allowing for quick edit-and-test cycles without compilation. 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!` On release mode it falls back to `include_str!`, `include_bytes!`
and our own custom `include_dir!` implementation. and our own custom `include_dir!`-like implementation.
## Usage ## Usage
Add this to your Cargo.toml:
```toml
[dependencies]
embed = { git = "https://github.com/RGBCube/embed-rs" }
[patch.crates-io]
proc-macro2 = { git = "https://github.com/RGBCube/proc-macro2" }
```
Then you can use this crate as so:
```rs ```rs
let contents: Cow<'_, str> = embed::string!("path/to/file.txt"); let contents: Cow<'_, str> = embed::string!("path/to/file.txt");
let bytes: Cow<'_, [u8]> = embed::bytes!("path/to/image.png"); let bytes: Cow<'_, [u8]> = embed::bytes!("path/to/image.png");
@ -17,6 +32,9 @@ let dir: embed::Dir = embed::dir!("path/to");
let files: Vec<embed::File> = dir.flatten(); let files: Vec<embed::File> = dir.flatten();
``` ```
I am not sure what name to publish this
crate in, lmk if you find a good one.
## License ## License
``` ```

View file

@ -1,5 +1,3 @@
#![cfg(procmacro2_semver_exempt)]
use std::{ use std::{
borrow::Cow, borrow::Cow,
fs, fs,
@ -29,15 +27,13 @@ pub fn __string_runtime(neighbor: &str, path: &str) -> String {
#[macro_export] #[macro_export]
macro_rules! string { macro_rules! string {
($path:literal) => {{ ($path:literal) => {{
use ::std::borrow::Cow;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
Cow::Owned(::embed::__string_runtime(file!(), $path)) ::std::borrow::Cow::Owned(::embed::__string_runtime(file!(), $path))
} }
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
{ {
Cow::Borrowed(include_str!($path)) ::std::borrow::Cow::Borrowed(include_str!($path))
} }
}}; }};
} }
@ -90,7 +86,7 @@ pub enum DirEntry {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Dir { pub struct Dir {
/// The entries the directory houses. /// The entries the directory houses.
pub children: Vec<DirEntry>, pub children: Cow<'static, [DirEntry]>,
/// The absolute path of the directory. /// The absolute path of the directory.
pub path: Cow<'static, Path>, pub path: Cow<'static, Path>,
} }
@ -100,7 +96,8 @@ impl Dir {
pub fn flatten(self) -> Vec<File> { pub fn flatten(self) -> Vec<File> {
let mut entries = Vec::new(); let mut entries = Vec::new();
for child in self.children { for child in self.children.into_owned() {
// TODO: Eliminate allocation.
match child { match child {
DirEntry::File(file) => entries.push(file), DirEntry::File(file) => entries.push(file),
DirEntry::Dir(dir) => entries.append(&mut dir.flatten()), DirEntry::Dir(dir) => entries.append(&mut dir.flatten()),
@ -136,7 +133,7 @@ fn read_dir(directory: &Path) -> Vec<DirEntry> {
); );
if filetype.is_dir() { if filetype.is_dir() {
let children = read_dir(path.as_ref()); let children = Cow::Owned(read_dir(path.as_ref()));
entries.push(DirEntry::Dir(Dir { children, path })) entries.push(DirEntry::Dir(Dir { children, path }))
} else if filetype.is_file() { } else if filetype.is_file() {
@ -161,8 +158,8 @@ pub fn __dir_runtime(neighbor: &str, path: &str) -> Dir {
let children = read_dir(&directory); let children = read_dir(&directory);
Dir { Dir {
children, children: children.into(),
path: Cow::Owned(directory), path: directory.into(),
} }
} }

View file

@ -16,3 +16,6 @@ proc-macro = true
proc-macro2 = { version = "1", features = [ "span-locations" ] } proc-macro2 = { version = "1", features = [ "span-locations" ] }
quote = "1" quote = "1"
syn = "2" syn = "2"
[patch.crates-io]
proc-macro2 = { git = "https://github.com/RGBCube/proc-macro2" }

View file

@ -1,5 +1,3 @@
#![cfg(procmacro2_semver_exempt)]
use std::{ use std::{
fs, fs,
path::PathBuf, path::PathBuf,
@ -38,9 +36,10 @@ impl ToTokens for TokenVec {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
let inner = &self.0; let inner = &self.0;
tokens.extend(quote! { tokens.extend(quote! {{
vec![#(#inner),*] const CHILDREN: &[::embed::DirEntry] = &[#(#inner),*]; // FIXME: Not const.
}); ::std::borrow::Cow::Borrowed(CHILDREN)
}});
} }
} }