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


ce93f7e5 Piotr Osiewicz

2 years ago
feat: Store file contents statically and use binary search for lookup.
Files changed (2) hide show
  1. impl/src/lib.rs +22 -15
  2. utils/src/lib.rs +3 -1
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,23 @@ 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
+ });
54
59
  quote! {
55
60
  #not_debug_attr
56
61
  impl #ident {
57
62
  /// Get an embedded file and its metadata.
58
63
  pub fn get(file_path: &str) -> Option<rust_embed::EmbeddedFile> {
59
64
  #handle_prefix
60
- match file_path.replace("\\", "/").as_str() {
65
+ let key = file_path.replace("\\", "/");
66
+ const ENTRIES: &'static [(&'static str, rust_embed::EmbeddedFile)] = &[
61
- #(#match_values)*
67
+ #(#match_values)*];
68
+ let position = ENTRIES.binary_search_by_key(&key.as_str(), |entry| entry.0);
62
- _ => None,
69
+ position.ok().map(|index| ENTRIES[index].1.clone())
63
- }
70
+
64
71
  }
65
72
 
66
73
  fn names() -> std::slice::Iter<'static, &'static str> {
@@ -203,22 +210,22 @@ fn embed_file(folder_path: Option<&str>, rel_path: &str, full_canonical_path: &s
203
210
  let full_relative_path = full_relative_path.to_string_lossy();
204
211
  quote! {
205
212
  rust_embed::flate!(static FILE: [u8] from #full_relative_path);
206
- let bytes = &FILE[..];
213
+ const BYTES: &'static [u8] = FILE;
207
214
  }
208
215
  } else {
209
216
  quote! {
210
- let bytes = &include_bytes!(#full_canonical_path)[..];
217
+ const BYTES: &'static [u8] = include_bytes!(#full_canonical_path);
211
218
  }
212
219
  };
213
220
 
214
221
  quote! {
215
- #rel_path => {
222
+ {
216
- #embedding_code
223
+ #embedding_code
217
224
 
218
- Some(rust_embed::EmbeddedFile {
225
+ rust_embed::EmbeddedFile {
219
- data: std::borrow::Cow::from(bytes),
226
+ data: std::borrow::Cow::Borrowed(BYTES),
220
- metadata: rust_embed::Metadata::__rust_embed_new([#(#hash),*], #last_modified #mimetype_tokens)
227
+ metadata: rust_embed::Metadata::__rust_embed_new([#(#hash),*], #last_modified #mimetype_tokens)
221
- })
228
+ }
222
229
  }
223
230
  }
224
231
  }
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,7 +95,7 @@ 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,