~repos /rust-embed

#rust#proc-macro#http

git clone https://pyrossh.dev/repos/rust-embed.git
Discussions: https://groups.google.com/g/rust-embed-devs

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


Files changed (1) hide show
  1. impl/src/lib.rs +38 -5
impl/src/lib.rs CHANGED
@@ -16,6 +16,7 @@ use syn::{parse_macro_input, Data, DeriveInput, Expr, ExprLit, Fields, Lit, Meta
16
16
 
17
17
  fn embedded(
18
18
  ident: &syn::Ident, relative_folder_path: Option<&str>, absolute_folder_path: String, prefix: Option<&str>, includes: &[String], excludes: &[String],
19
+ metadata_only: bool,
19
20
  ) -> syn::Result<TokenStream2> {
20
21
  extern crate rust_embed_utils;
21
22
 
@@ -25,7 +26,10 @@ fn embedded(
25
26
  let includes: Vec<&str> = includes.iter().map(AsRef::as_ref).collect();
26
27
  let excludes: Vec<&str> = excludes.iter().map(AsRef::as_ref).collect();
27
28
  for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(absolute_folder_path.clone(), &includes, &excludes) {
29
+ match_values.insert(
30
+ rel_path.clone(),
28
- match_values.insert(rel_path.clone(), embed_file(relative_folder_path, ident, &rel_path, &full_canonical_path)?);
31
+ embed_file(relative_folder_path, ident, &rel_path, &full_canonical_path, metadata_only)?,
32
+ );
29
33
 
30
34
  list_values.push(if let Some(prefix) = prefix {
31
35
  format!("{}{}", prefix, rel_path)
@@ -187,6 +191,7 @@ fn dynamic(ident: &syn::Ident, folder_path: String, prefix: Option<&str>, includ
187
191
 
188
192
  fn generate_assets(
189
193
  ident: &syn::Ident, relative_folder_path: Option<&str>, absolute_folder_path: String, prefix: Option<String>, includes: Vec<String>, excludes: Vec<String>,
194
+ metadata_only: bool,
190
195
  ) -> syn::Result<TokenStream2> {
191
196
  let embedded_impl = embedded(
192
197
  ident,
@@ -195,6 +200,7 @@ fn generate_assets(
195
200
  prefix.as_deref(),
196
201
  &includes,
197
202
  &excludes,
203
+ metadata_only,
198
204
  );
199
205
  if cfg!(feature = "debug-embed") {
200
206
  return embedded_impl;
@@ -208,7 +214,7 @@ fn generate_assets(
208
214
  })
209
215
  }
210
216
 
211
- fn embed_file(folder_path: Option<&str>, ident: &syn::Ident, rel_path: &str, full_canonical_path: &str) -> syn::Result<TokenStream2> {
217
+ fn embed_file(folder_path: Option<&str>, ident: &syn::Ident, rel_path: &str, full_canonical_path: &str, metadata_only: bool) -> syn::Result<TokenStream2> {
212
218
  let file = rust_embed_utils::read_file_from_fs(Path::new(full_canonical_path)).expect("File should be readable");
213
219
  let hash = file.metadata.sha256_hash();
214
220
  let last_modified = match file.metadata.last_modified() {
@@ -227,7 +233,11 @@ fn embed_file(folder_path: Option<&str>, ident: &syn::Ident, rel_path: &str, ful
227
233
  #[cfg(not(feature = "mime-guess"))]
228
234
  let mimetype_tokens = TokenStream2::new();
229
235
 
236
+ let embedding_code = if metadata_only {
237
+ quote! {
238
+ const BYTES: &'static [u8] = &[];
239
+ }
230
- let embedding_code = if cfg!(feature = "compression") {
240
+ } else if cfg!(feature = "compression") {
231
241
  let folder_path = folder_path.ok_or(syn::Error::new(ident.span(), "`folder` must be provided under `compression` feature."))?;
232
242
  // Print some debugging information
233
243
  let full_relative_path = PathBuf::from_iter([folder_path, rel_path]);
@@ -273,6 +283,20 @@ fn find_attribute_values(ast: &syn::DeriveInput, attr_name: &str) -> Vec<String>
273
283
  .collect()
274
284
  }
275
285
 
286
+ fn find_bool_attribute(ast: &syn::DeriveInput, attr_name: &str) -> Option<bool> {
287
+ ast
288
+ .attrs
289
+ .iter()
290
+ .find(|value| value.path().is_ident(attr_name))
291
+ .and_then(|attr| match &attr.meta {
292
+ Meta::NameValue(MetaNameValue {
293
+ value: Expr::Lit(ExprLit { lit: Lit::Bool(val), .. }),
294
+ ..
295
+ }) => Some(val.value()),
296
+ _ => None,
297
+ })
298
+ }
299
+
276
300
  fn impl_rust_embed(ast: &syn::DeriveInput) -> syn::Result<TokenStream2> {
277
301
  match ast.data {
278
302
  Data::Struct(ref data) => match data.fields {
@@ -294,6 +318,7 @@ fn impl_rust_embed(ast: &syn::DeriveInput) -> syn::Result<TokenStream2> {
294
318
  let prefix = find_attribute_values(ast, "prefix").into_iter().next();
295
319
  let includes = find_attribute_values(ast, "include");
296
320
  let excludes = find_attribute_values(ast, "exclude");
321
+ let metadata_only = find_bool_attribute(ast, "metadata_only").unwrap_or(false);
297
322
 
298
323
  #[cfg(not(feature = "include-exclude"))]
299
324
  if !includes.is_empty() || !excludes.is_empty() {
@@ -340,10 +365,18 @@ fn impl_rust_embed(ast: &syn::DeriveInput) -> syn::Result<TokenStream2> {
340
365
  return Err(syn::Error::new_spanned(ast, message));
341
366
  };
342
367
 
368
+ generate_assets(
369
+ &ast.ident,
343
- generate_assets(&ast.ident, relative_path.as_deref(), absolute_folder_path, prefix, includes, excludes)
370
+ relative_path.as_deref(),
371
+ absolute_folder_path,
372
+ prefix,
373
+ includes,
374
+ excludes,
375
+ metadata_only,
376
+ )
344
377
  }
345
378
 
346
- #[proc_macro_derive(RustEmbed, attributes(folder, prefix, include, exclude))]
379
+ #[proc_macro_derive(RustEmbed, attributes(folder, prefix, include, exclude, metadata_only))]
347
380
  pub fn derive_input_object(input: TokenStream) -> TokenStream {
348
381
  let ast = parse_macro_input!(input as DeriveInput);
349
382
  match impl_rust_embed(&ast) {