Skip to content

Commit

Permalink
Merge pull request #212 from osiewicz/issue-182/include_flate_0.2
Browse files Browse the repository at this point in the history
Pass relative paths to include_flate.
  • Loading branch information
Peter John committed Jun 30, 2023
2 parents 14ec015 + 826d67f commit 1fb9245
Showing 1 changed file with 40 additions and 18 deletions.
58 changes: 40 additions & 18 deletions impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@ extern crate proc_macro;

use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use std::{env, path::Path};
use std::{
env,
iter::FromIterator,
path::{Path, PathBuf},
};
use syn::{Data, DeriveInput, Expr, ExprLit, Fields, Lit, Meta, MetaNameValue};

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

let mut match_values = Vec::<TokenStream2>::new();
let mut list_values = Vec::<String>::new();

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(folder_path, &includes, &excludes) {
match_values.push(embed_file(&rel_path, &full_canonical_path));
for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(absolute_folder_path.clone(), &includes, &excludes) {
match_values.push(embed_file(relative_folder_path.clone(), &rel_path, &full_canonical_path));

list_values.push(if let Some(prefix) = prefix {
format!("{}{}", prefix, rel_path)
Expand Down Expand Up @@ -153,21 +159,30 @@ fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includ
}
}

fn generate_assets(ident: &syn::Ident, folder_path: String, prefix: Option<String>, includes: Vec<String>, excludes: Vec<String>) -> TokenStream2 {
let embedded_impl = embedded(ident, folder_path.clone(), prefix.as_deref(), &includes, &excludes);
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 {
let embedded_impl = embedded(
ident,
relative_folder_path,
absolute_folder_path.clone(),
prefix.as_deref(),
&includes,
&excludes,
);
if cfg!(feature = "debug-embed") {
return embedded_impl;
}

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

quote! {
#embedded_impl
#dynamic_impl
}
}

fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
fn embed_file(folder_path: Option<&str>, rel_path: &str, full_canonical_path: &str) -> 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 @@ -183,8 +198,11 @@ fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
let mimetype_tokens = TokenStream2::new();

let embedding_code = if cfg!(feature = "compression") {
// 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 = full_relative_path.to_string_lossy();
quote! {
rust_embed::flate!(static FILE: [u8] from #full_canonical_path);
rust_embed::flate!(static FILE: [u8] from #full_relative_path);
let bytes = &FILE[..];
}
} else {
Expand Down Expand Up @@ -249,34 +267,38 @@ fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
let folder_path = shellexpand::full(&folder_path).unwrap().to_string();

// Base relative paths on the Cargo.toml location
let folder_path = if Path::new(&folder_path).is_relative() {
Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap())
.join(folder_path)
let (relative_path, absolute_folder_path) = if Path::new(&folder_path).is_relative() {
let absolute_path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap())
.join(&folder_path)
.to_str()
.unwrap()
.to_owned()
.to_owned();
(Some(folder_path.clone()), absolute_path)
} else {
folder_path
if cfg!(feature = "compression") {
panic!("`folder` must be a relative path under `compression` feature.")
}
(None, folder_path)
};

if !Path::new(&folder_path).exists() {
if !Path::new(&absolute_folder_path).exists() {
let mut message = format!(
"#[derive(RustEmbed)] folder '{}' does not exist. cwd: '{}'",
folder_path,
absolute_folder_path,
std::env::current_dir().unwrap().to_str().unwrap()
);

// Add a message about the interpolate-folder-path feature if the path may
// include a variable
if folder_path.contains('$') && cfg!(not(feature = "interpolate-folder-path")) {
if absolute_folder_path.contains('$') && cfg!(not(feature = "interpolate-folder-path")) {
message += "\nA variable has been detected. RustEmbed can expand variables \
when the `interpolate-folder-path` feature is enabled.";
}

panic!("{}", message);
};

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

#[proc_macro_derive(RustEmbed, attributes(folder, prefix, include, exclude))]
Expand Down

0 comments on commit 1fb9245

Please sign in to comment.