Skip to content

Commit

Permalink
Merge pull request #220 from wyatt-herkamp/master
Browse files Browse the repository at this point in the history
Move Panics to Compile Errors, Update shellexpand, and remove deprecated feature from rustfmt.toml
  • Loading branch information
Peter John authored Oct 7, 2023
2 parents ea7de47 + 7a14d89 commit 207d1be
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 27 deletions.
4 changes: 2 additions & 2 deletions impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ proc-macro = true
[dependencies]
rust-embed-utils = { version = "8.0.0", path = "../utils"}

syn = { version = "2", default-features = false, features = ["derive", "parsing", "proc-macro"] }
syn = { version = "2", default-features = false, features = ["derive", "parsing", "proc-macro", "printing"] }
quote = "1"
proc-macro2 = "1"
walkdir = "2.3.1"

[dependencies.shellexpand]
version = "2"
version = "3"
optional = true

[features]
Expand Down
62 changes: 38 additions & 24 deletions impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ use std::{
iter::FromIterator,
path::{Path, PathBuf},
};
use syn::{Data, DeriveInput, Expr, ExprLit, Fields, Lit, Meta, MetaNameValue};
use syn::{parse_macro_input, Data, DeriveInput, Expr, ExprLit, Fields, Lit, Meta, MetaNameValue};

fn embedded(
ident: &syn::Ident, relative_folder_path: Option<&str>, absolute_folder_path: String, prefix: Option<&str>, includes: &[String], excludes: &[String],
) -> TokenStream2 {
) -> syn::Result<TokenStream2> {
extern crate rust_embed_utils;

let mut match_values = BTreeMap::new();
Expand All @@ -25,7 +25,10 @@ fn embedded(
let includes: Vec<&str> = includes.iter().map(AsRef::as_ref).collect();
let excludes: Vec<&str> = excludes.iter().map(AsRef::as_ref).collect();
for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(absolute_folder_path.clone(), &includes, &excludes) {
match_values.insert(rel_path.clone(), embed_file(relative_folder_path.clone(), &rel_path, &full_canonical_path));
match_values.insert(
rel_path.clone(),
embed_file(relative_folder_path.clone(), ident, &rel_path, &full_canonical_path)?,
);

list_values.push(if let Some(prefix) = prefix {
format!("{}{}", prefix, rel_path)
Expand Down Expand Up @@ -66,7 +69,7 @@ fn embedded(
} else {
quote! {|idx| ENTRIES[idx].1.clone()}
};
quote! {
Ok(quote! {
#not_debug_attr
impl #ident {
/// Get an embedded file and its metadata.
Expand Down Expand Up @@ -100,7 +103,7 @@ fn embedded(
rust_embed::Filenames::Embedded(#ident::names())
}
}
}
})
}

fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includes: &[String], excludes: &[String]) -> TokenStream2 {
Expand Down Expand Up @@ -178,7 +181,7 @@ fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includ

fn generate_assets(
ident: &syn::Ident, relative_folder_path: Option<&str>, absolute_folder_path: String, prefix: Option<String>, includes: Vec<String>, excludes: Vec<String>,
) -> TokenStream2 {
) -> syn::Result<TokenStream2> {
let embedded_impl = embedded(
ident,
relative_folder_path,
Expand All @@ -190,16 +193,16 @@ fn generate_assets(
if cfg!(feature = "debug-embed") {
return embedded_impl;
}

let embedded_impl = embedded_impl?;
let dynamic_impl = dynamic(ident, absolute_folder_path, prefix.as_deref(), &includes, &excludes);

quote! {
Ok(quote! {
#embedded_impl
#dynamic_impl
}
})
}

fn embed_file(folder_path: Option<&str>, rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
fn embed_file(folder_path: Option<&str>, ident: &syn::Ident, rel_path: &str, full_canonical_path: &str) -> syn::Result<TokenStream2> {
let file = rust_embed_utils::read_file_from_fs(Path::new(full_canonical_path)).expect("File should be readable");
let hash = file.metadata.sha256_hash();
let last_modified = match file.metadata.last_modified() {
Expand All @@ -215,8 +218,9 @@ fn embed_file(folder_path: Option<&str>, rel_path: &str, full_canonical_path: &s
let mimetype_tokens = TokenStream2::new();

let embedding_code = if cfg!(feature = "compression") {
let folder_path = folder_path.ok_or(syn::Error::new(ident.span(), "`folder` must be provided under `compression` feature."))?;
// Print some debugging information
let full_relative_path = PathBuf::from_iter([folder_path.expect("folder_path must be provided under `compression` feature"), rel_path]);
let full_relative_path = PathBuf::from_iter([folder_path, rel_path]);
let full_relative_path = full_relative_path.to_string_lossy();
quote! {
rust_embed::flate!(static BYTES: [u8] from #full_relative_path);
Expand All @@ -231,7 +235,7 @@ fn embed_file(folder_path: Option<&str>, rel_path: &str, full_canonical_path: &s
} else {
quote! {}
};
quote! {
Ok(quote! {
#closure_args {
#embedding_code

Expand All @@ -240,7 +244,7 @@ fn embed_file(folder_path: Option<&str>, rel_path: &str, full_canonical_path: &s
metadata: rust_embed::Metadata::__rust_embed_new([#(#hash),*], #last_modified #mimetype_tokens)
}
}
}
})
}

/// Find all pairs of the `name = "value"` attribute from the derive input
Expand All @@ -259,18 +263,21 @@ fn find_attribute_values(ast: &syn::DeriveInput, attr_name: &str) -> Vec<String>
.collect()
}

fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
fn impl_rust_embed(ast: &syn::DeriveInput) -> syn::Result<TokenStream2> {
match ast.data {
Data::Struct(ref data) => match data.fields {
Fields::Unit => {}
_ => panic!("RustEmbed can only be derived for unit structs"),
_ => return Err(syn::Error::new_spanned(ast, "RustEmbed can only be derived for unit structs")),
},
_ => panic!("RustEmbed can only be derived for unit structs"),
_ => return Err(syn::Error::new_spanned(ast, "RustEmbed can only be derived for unit structs")),
};

let mut folder_paths = find_attribute_values(ast, "folder");
if folder_paths.len() != 1 {
panic!("#[derive(RustEmbed)] must contain one attribute like this #[folder = \"examples/public/\"]");
return Err(syn::Error::new_spanned(
ast,
"#[derive(RustEmbed)] must contain one attribute like this #[folder = \"examples/public/\"]",
));
}
let folder_path = folder_paths.remove(0);

Expand All @@ -280,11 +287,16 @@ fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {

#[cfg(not(feature = "include-exclude"))]
if !includes.is_empty() || !excludes.is_empty() {
panic!("Please turn on the `include-exclude` feature to use the `include` and `exclude` attributes")
return Err(syn::Error::new_spanned(
ast,
"Please turn on the `include-exclude` feature to use the `include` and `exclude` attributes",
));
}

#[cfg(feature = "interpolate-folder-path")]
let folder_path = shellexpand::full(&folder_path).unwrap().to_string();
let folder_path = shellexpand::full(&folder_path)
.map_err(|v| syn::Error::new_spanned(ast, v.to_string()))?
.to_string();

// Base relative paths on the Cargo.toml location
let (relative_path, absolute_folder_path) = if Path::new(&folder_path).is_relative() {
Expand All @@ -296,7 +308,7 @@ fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
(Some(folder_path.clone()), absolute_path)
} else {
if cfg!(feature = "compression") {
panic!("`folder` must be a relative path under `compression` feature.")
return Err(syn::Error::new_spanned(ast, "`folder` must be a relative path under `compression` feature."));
}
(None, folder_path)
};
Expand All @@ -315,15 +327,17 @@ fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
when the `interpolate-folder-path` feature is enabled.";
}

panic!("{}", message);
return Err(syn::Error::new_spanned(ast, message));
};

generate_assets(&ast.ident, relative_path.as_deref(), absolute_folder_path, prefix, includes, excludes)
}

#[proc_macro_derive(RustEmbed, attributes(folder, prefix, include, exclude))]
pub fn derive_input_object(input: TokenStream) -> TokenStream {
let ast: DeriveInput = syn::parse(input).unwrap();
let gen = impl_rust_embed(&ast);
gen.into()
let ast = parse_macro_input!(input as DeriveInput);
match impl_rust_embed(&ast) {
Ok(ok) => ok.into(),
Err(e) => e.to_compile_error().into(),
}
}
2 changes: 1 addition & 1 deletion rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ unstable_features = false
wrap_comments = true
normalize_comments = true
merge_derives = true
fn_args_layout = "Compressed"
fn_params_layout = "Compressed"
max_width = 160
tab_spaces = 2
indent_style = "Block"
Expand Down

0 comments on commit 207d1be

Please sign in to comment.