~repos /rust-embed

#rust#proc-macro#http

git clone https://pyrossh.dev/repos/rust-embed.git

rust macro which loads files into the rust binary at compile time during release and loads the file from the fs during dev.


ddf29925 mbme

4 years ago
apply PR suggestions and address clippy warnings
Files changed (2) hide show
  1. impl/src/lib.rs +34 -22
  2. utils/src/lib.rs +7 -7
impl/src/lib.rs CHANGED
@@ -9,13 +9,15 @@ use proc_macro2::TokenStream as TokenStream2;
9
9
  use std::{env, path::Path};
10
10
  use syn::{Data, DeriveInput, Fields, Lit, Meta, MetaNameValue};
11
11
 
12
- fn embedded(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includes: Vec<String>, excludes: Vec<String>) -> TokenStream2 {
12
+ fn embedded(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includes: &[String], excludes: &[String]) -> TokenStream2 {
13
13
  extern crate rust_embed_utils;
14
14
 
15
15
  let mut match_values = Vec::<TokenStream2>::new();
16
16
  let mut list_values = Vec::<String>::new();
17
17
 
18
+ let includes: Vec<&str> = includes.iter().map(AsRef::as_ref).collect();
19
+ let excludes: Vec<&str> = excludes.iter().map(AsRef::as_ref).collect();
18
- for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(folder_path, includes, excludes) {
20
+ for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(folder_path, &includes, &excludes) {
19
21
  match_values.push(embed_file(&rel_path, &full_canonical_path));
20
22
 
21
23
  list_values.push(if let Some(prefix) = prefix {
@@ -78,7 +80,7 @@ fn embedded(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, inclu
78
80
  }
79
81
  }
80
82
 
81
- fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includes: Vec<String>, excludes: Vec<String>) -> TokenStream2 {
83
+ fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includes: &[String], excludes: &[String]) -> TokenStream2 {
82
84
  let (handle_prefix, map_iter) = if let Some(prefix) = prefix {
83
85
  (
84
86
  quote! { let file_path = file_path.strip_prefix(#prefix)?; },
@@ -88,12 +90,12 @@ fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includ
88
90
  (TokenStream2::new(), quote! { std::borrow::Cow::from(e.rel_path) })
89
91
  };
90
92
 
91
- let includes = quote! {
93
+ let declare_includes = quote! {
92
- vec![#(String::from(#includes)),*]
94
+ const includes: &[&str] = &[#(#includes),*];
93
95
  };
94
96
 
95
- let excludes = quote! {
97
+ let declare_excludes = quote! {
96
- vec![#(String::from(#excludes)),*]
98
+ const excludes: &[&str] = &[#(#excludes),*];
97
99
  };
98
100
 
99
101
  quote! {
@@ -103,12 +105,13 @@ fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includ
103
105
  pub fn get(file_path: &str) -> Option<rust_embed::EmbeddedFile> {
104
106
  #handle_prefix
105
107
 
106
- let file_path = std::path::Path::new(#folder_path).join(file_path.replace("\\", "/"));
107
- let rel_file_path = file_path.to_str()
108
+ #declare_includes
108
- .expect("Path does not have a string representation")
109
+ #declare_excludes
109
- .strip_prefix(#folder_path).expect("Failed to turn path to relative path");
110
110
 
111
+ let rel_file_path = file_path.replace("\\", "/");
112
+ let file_path = std::path::Path::new(#folder_path).join(&rel_file_path);
113
+
111
- if rust_embed::utils::is_path_included(rel_file_path, &#includes, &#excludes) {
114
+ if rust_embed::utils::is_path_included(&rel_file_path, includes, excludes) {
112
115
  rust_embed::utils::read_file_from_fs(&file_path).ok()
113
116
  } else {
114
117
  None
@@ -118,7 +121,11 @@ fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includ
118
121
  /// Iterates over the file paths in the folder.
119
122
  pub fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
120
123
  use std::path::Path;
124
+
125
+ #declare_includes
126
+ #declare_excludes
127
+
121
- rust_embed::utils::get_files(String::from(#folder_path), #includes, #excludes)
128
+ rust_embed::utils::get_files(String::from(#folder_path), includes, excludes)
122
129
  .map(|e| #map_iter)
123
130
  }
124
131
  }
@@ -137,12 +144,12 @@ fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includ
137
144
  }
138
145
 
139
146
  fn generate_assets(ident: &syn::Ident, folder_path: String, prefix: Option<String>, includes: Vec<String>, excludes: Vec<String>) -> TokenStream2 {
140
- let embedded_impl = embedded(ident, folder_path.clone(), prefix.as_deref(), includes.clone(), excludes.clone());
147
+ let embedded_impl = embedded(ident, folder_path.clone(), prefix.as_deref(), &includes, &excludes);
141
148
  if cfg!(feature = "debug-embed") {
142
149
  return embedded_impl;
143
150
  }
144
151
 
145
- let dynamic_impl = dynamic(ident, folder_path, prefix.as_deref(), includes, excludes);
152
+ let dynamic_impl = dynamic(ident, folder_path, prefix.as_deref(), &includes, &excludes);
146
153
 
147
154
  quote! {
148
155
  #embedded_impl
@@ -195,11 +202,6 @@ fn find_attribute_values(ast: &syn::DeriveInput, attr_name: &str) -> Vec<String>
195
202
  .collect()
196
203
  }
197
204
 
198
- /// Find a `name = "value"` attribute from the derive input
199
- fn find_attribute_value(ast: &syn::DeriveInput, attr_name: &str) -> Option<String> {
200
- find_attribute_values(ast, attr_name).into_iter().next()
201
- }
202
-
203
205
  fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
204
206
  match ast.data {
205
207
  Data::Struct(ref data) => match data.fields {
@@ -209,8 +211,18 @@ fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
209
211
  _ => panic!("RustEmbed can only be derived for unit structs"),
210
212
  };
211
213
 
214
+ let folder_path: String = {
215
+ let mut it = find_attribute_values(ast, "folder").into_iter();
216
+
217
+ match (it.next(), it.next()) {
218
+ (Some(folder_path), None) => folder_path,
219
+ _ => {
212
- let folder_path = find_attribute_value(ast, "folder").expect("#[derive(RustEmbed)] should contain one attribute like this #[folder = \"examples/public/\"]");
220
+ panic!("#[derive(RustEmbed)] must contain one attribute like this #[folder = \"examples/public/\"]");
221
+ }
222
+ }
223
+ };
224
+
213
- let prefix = find_attribute_value(ast, "prefix");
225
+ let prefix = find_attribute_values(ast, "prefix").into_iter().next();
214
226
  let includes = find_attribute_values(ast, "include");
215
227
  let excludes = find_attribute_values(ast, "exclude");
216
228
 
utils/src/lib.rs CHANGED
@@ -13,17 +13,17 @@ pub struct FileEntry {
13
13
  }
14
14
 
15
15
  #[cfg(not(feature = "include-exclude"))]
16
- pub fn is_path_included(_path: &str, _includes: &Vec<String>, _excludes: &Vec<String>) -> bool {
16
+ pub fn is_path_included(_path: &str, _includes: &[&str], _excludes: &[&str]) -> bool {
17
17
  return true;
18
18
  }
19
19
 
20
20
  #[cfg(feature = "include-exclude")]
21
- pub fn is_path_included(rel_path: &str, includes: &Vec<String>, excludes: &Vec<String>) -> bool {
21
+ pub fn is_path_included(rel_path: &str, includes: &[&str], excludes: &[&str]) -> bool {
22
22
  use glob::Pattern;
23
23
 
24
24
  // ignore path matched by exclusion pattern
25
25
  for exclude in excludes {
26
- let pattern = Pattern::new(exclude).expect(&format!("invalid exclude pattern '{}'", exclude));
26
+ let pattern = Pattern::new(exclude).unwrap_or_else(|_| panic!("invalid exclude pattern '{}'", exclude));
27
27
 
28
28
  if pattern.matches(rel_path) {
29
29
  return false;
@@ -37,18 +37,18 @@ pub fn is_path_included(rel_path: &str, includes: &Vec<String>, excludes: &Vec<S
37
37
 
38
38
  // accept path if matched by inclusion pattern
39
39
  for include in includes {
40
- let pattern = Pattern::new(include).expect(&format!("invalid include pattern '{}'", include));
40
+ let pattern = Pattern::new(include).unwrap_or_else(|_| panic!("invalid include pattern '{}'", include));
41
41
 
42
42
  if pattern.matches(rel_path) {
43
43
  return true;
44
44
  }
45
45
  }
46
46
 
47
- return false;
47
+ false
48
48
  }
49
49
 
50
50
  #[cfg_attr(all(debug_assertions, not(feature = "debug-embed")), allow(unused))]
51
- pub fn get_files(folder_path: String, includes: Vec<String>, excludes: Vec<String>) -> impl Iterator<Item = FileEntry> {
51
+ pub fn get_files<'patterns>(folder_path: String, includes: &'patterns [&str], excludes: &'patterns [&str]) -> impl Iterator<Item = FileEntry> + 'patterns {
52
52
  walkdir::WalkDir::new(&folder_path)
53
53
  .follow_links(true)
54
54
  .into_iter()
@@ -64,7 +64,7 @@ pub fn get_files(folder_path: String, includes: Vec<String>, excludes: Vec<Strin
64
64
  rel_path
65
65
  };
66
66
 
67
- if is_path_included(&rel_path, &includes, &excludes) {
67
+ if is_path_included(&rel_path, includes, excludes) {
68
68
  Some(FileEntry { rel_path, full_canonical_path })
69
69
  } else {
70
70
  None