~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 (2) hide show
  1. impl/src/lib.rs +37 -17
  2. utils/src/lib.rs +4 -2
impl/src/lib.rs CHANGED
@@ -7,6 +7,7 @@ extern crate proc_macro;
7
7
  use proc_macro::TokenStream;
8
8
  use proc_macro2::TokenStream as TokenStream2;
9
9
  use std::{
10
+ collections::BTreeMap,
10
11
  env,
11
12
  iter::FromIterator,
12
13
  path::{Path, PathBuf},
@@ -18,13 +19,13 @@ fn embedded(
18
19
  ) -> TokenStream2 {
19
20
  extern crate rust_embed_utils;
20
21
 
21
- let mut match_values = Vec::<TokenStream2>::new();
22
+ let mut match_values = BTreeMap::new();
22
23
  let mut list_values = Vec::<String>::new();
23
24
 
24
25
  let includes: Vec<&str> = includes.iter().map(AsRef::as_ref).collect();
25
26
  let excludes: Vec<&str> = excludes.iter().map(AsRef::as_ref).collect();
26
27
  for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(absolute_folder_path.clone(), &includes, &excludes) {
27
- match_values.push(embed_file(relative_folder_path.clone(), &rel_path, &full_canonical_path));
28
+ match_values.insert(rel_path.clone(), embed_file(relative_folder_path.clone(), &rel_path, &full_canonical_path));
28
29
 
29
30
  list_values.push(if let Some(prefix) = prefix {
30
31
  format!("{}{}", prefix, rel_path)
@@ -50,17 +51,33 @@ fn embedded(
50
51
  } else {
51
52
  TokenStream2::new()
52
53
  };
53
-
54
+ let match_values = match_values.into_iter().map(|(path, bytes)| {
55
+ quote! {
56
+ (#path, #bytes),
57
+ }
58
+ });
59
+ let value_type = if cfg!(feature = "compression") {
60
+ quote! { fn() -> rust_embed::EmbeddedFile }
61
+ } else {
62
+ quote! { rust_embed::EmbeddedFile }
63
+ };
64
+ let get_value = if cfg!(feature = "compression") {
65
+ quote! {|idx| (ENTRIES[idx].1)()}
66
+ } else {
67
+ quote! {|idx| ENTRIES[idx].1.clone()}
68
+ };
54
69
  quote! {
55
70
  #not_debug_attr
56
71
  impl #ident {
57
72
  /// Get an embedded file and its metadata.
58
73
  pub fn get(file_path: &str) -> Option<rust_embed::EmbeddedFile> {
59
74
  #handle_prefix
60
- match file_path.replace("\\", "/").as_str() {
75
+ let key = file_path.replace("\\", "/");
76
+ const ENTRIES: &'static [(&'static str, #value_type)] = &[
61
- #(#match_values)*
77
+ #(#match_values)*];
78
+ let position = ENTRIES.binary_search_by_key(&key.as_str(), |entry| entry.0);
62
- _ => None,
79
+ position.ok().map(#get_value)
63
- }
80
+
64
81
  }
65
82
 
66
83
  fn names() -> std::slice::Iter<'static, &'static str> {
@@ -202,23 +219,26 @@ fn embed_file(folder_path: Option<&str>, rel_path: &str, full_canonical_path: &s
202
219
  let full_relative_path = PathBuf::from_iter([folder_path.expect("folder_path must be provided under `compression` feature"), rel_path]);
203
220
  let full_relative_path = full_relative_path.to_string_lossy();
204
221
  quote! {
205
- rust_embed::flate!(static FILE: [u8] from #full_relative_path);
222
+ rust_embed::flate!(static BYTES: [u8] from #full_relative_path);
206
- let bytes = &FILE[..];
207
223
  }
208
224
  } else {
209
225
  quote! {
210
- let bytes = &include_bytes!(#full_canonical_path)[..];
226
+ const BYTES: &'static [u8] = include_bytes!(#full_canonical_path);
211
227
  }
212
228
  };
213
-
229
+ let closure_args = if cfg!(feature = "compression") {
230
+ quote! { || }
231
+ } else {
232
+ quote! {}
233
+ };
214
234
  quote! {
215
- #rel_path => {
235
+ #closure_args {
216
- #embedding_code
236
+ #embedding_code
217
237
 
218
- Some(rust_embed::EmbeddedFile {
238
+ rust_embed::EmbeddedFile {
219
- data: std::borrow::Cow::from(bytes),
239
+ data: std::borrow::Cow::Borrowed(&BYTES),
220
- metadata: rust_embed::Metadata::__rust_embed_new([#(#hash),*], #last_modified #mimetype_tokens)
240
+ metadata: rust_embed::Metadata::__rust_embed_new([#(#hash),*], #last_modified #mimetype_tokens)
221
- })
241
+ }
222
242
  }
223
243
  }
224
244
  }
utils/src/lib.rs CHANGED
@@ -78,12 +78,14 @@ pub fn get_files<'patterns>(folder_path: String, includes: &'patterns [&str], ex
78
78
  }
79
79
 
80
80
  /// A file embedded into the binary
81
+ #[derive(Clone)]
81
82
  pub struct EmbeddedFile {
82
83
  pub data: Cow<'static, [u8]>,
83
84
  pub metadata: Metadata,
84
85
  }
85
86
 
86
87
  /// Metadata about an embedded file
88
+ #[derive(Clone)]
87
89
  pub struct Metadata {
88
90
  hash: [u8; 32],
89
91
  last_modified: Option<u64>,
@@ -93,12 +95,12 @@ pub struct Metadata {
93
95
 
94
96
  impl Metadata {
95
97
  #[doc(hidden)]
96
- pub fn __rust_embed_new(hash: [u8; 32], last_modified: Option<u64>, #[cfg(feature = "mime-guess")] mimetype: &'static str) -> Self {
98
+ pub const fn __rust_embed_new(hash: [u8; 32], last_modified: Option<u64>, #[cfg(feature = "mime-guess")] mimetype: &'static str) -> Self {
97
99
  Self {
98
100
  hash,
99
101
  last_modified,
100
102
  #[cfg(feature = "mime-guess")]
101
- mimetype: mimetype.into(),
103
+ mimetype: Cow::Borrowed(mimetype),
102
104
  }
103
105
  }
104
106