~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.


c286171b Peter John

2 years ago
Merge pull request #217 from osiewicz/binary_search_by_path
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