~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 +73 -46
  2. utils/src/lib.rs +1 -0
impl/src/lib.rs CHANGED
@@ -7,9 +7,62 @@ use proc_macro::TokenStream;
7
7
  use std::{env, path::Path};
8
8
  use syn::{export::TokenStream2, Data, DeriveInput, Fields, Lit, Meta};
9
9
 
10
- #[cfg(all(debug_assertions, not(feature = "debug-embed")))]
11
- fn generate_assets(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
10
+ fn embedded(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
11
+ extern crate rust_embed_utils;
12
+
13
+ let mut match_values = Vec::<TokenStream2>::new();
14
+ let mut list_values = Vec::<String>::new();
15
+
16
+ for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(folder_path) {
17
+ match_values.push(embed_file(&rel_path, &full_canonical_path));
18
+ list_values.push(rel_path);
19
+ }
20
+
21
+ let array_len = list_values.len();
22
+
23
+ // If debug-embed is on, unconditionally include the code below. Otherwise,
24
+ // make it conditional on cfg(not(debug_assertions)).
25
+ let not_debug_attr = if cfg!(feature = "debug-embed") {
26
+ quote! {}
27
+ } else {
28
+ quote! { #[cfg(not(debug_assertions))]}
29
+ };
30
+
12
31
  quote! {
32
+ #not_debug_attr
33
+ impl #ident {
34
+ pub fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
35
+ match file_path.replace("\\", "/").as_str() {
36
+ #(#match_values)*
37
+ _ => None,
38
+ }
39
+ }
40
+
41
+ fn names() -> std::slice::Iter<'static, &'static str> {
42
+ const items: [&str; #array_len] = [#(#list_values),*];
43
+ items.iter()
44
+ }
45
+
46
+ pub fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
47
+ Self::names().map(|x| std::borrow::Cow::from(*x))
48
+ }
49
+ }
50
+
51
+ #not_debug_attr
52
+ impl rust_embed::RustEmbed for #ident {
53
+ fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
54
+ #ident::get(file_path)
55
+ }
56
+ fn iter() -> rust_embed::Filenames {
57
+ rust_embed::Filenames::Embedded(#ident::names())
58
+ }
59
+ }
60
+ }
61
+ }
62
+
63
+ fn dynamic(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
64
+ quote! {
65
+ #[cfg(debug_assertions)]
13
66
  impl #ident {
14
67
  pub fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
15
68
  use std::fs;
@@ -29,6 +82,8 @@ fn generate_assets(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
29
82
  rust_embed::utils::get_files(String::from(#folder_path)).map(|e| std::borrow::Cow::from(e.rel_path))
30
83
  }
31
84
  }
85
+
86
+ #[cfg(debug_assertions)]
32
87
  impl rust_embed::RustEmbed for #ident {
33
88
  fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
34
89
  #ident::get(file_path)
@@ -41,7 +96,21 @@ fn generate_assets(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
41
96
  }
42
97
  }
43
98
 
99
+ fn generate_assets(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
100
+ let embedded_impl = embedded(ident, folder_path.clone());
101
+ if cfg!(feature = "debug-embed") {
102
+ return embedded_impl;
103
+ }
104
+
105
+ let dynamic_impl = dynamic(ident, folder_path);
106
+
107
+ quote! {
108
+ #embedded_impl
109
+ #dynamic_impl
110
+ }
111
+ }
112
+
44
- #[cfg(all(not(feature = "compression"), any(not(debug_assertions), feature = "debug-embed")))]
113
+ #[cfg(not(feature = "compression"))]
45
114
  fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
46
115
  quote! {
47
116
  #rel_path => {
@@ -51,7 +120,7 @@ fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
51
120
  }
52
121
  }
53
122
 
54
- #[cfg(all(feature = "compression", any(not(debug_assertions), feature = "debug-embed")))]
123
+ #[cfg(feature = "compression")]
55
124
  fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
56
125
  quote! {
57
126
  #rel_path => {
@@ -63,48 +132,6 @@ fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
63
132
  }
64
133
  }
65
134
 
66
- #[cfg(any(not(debug_assertions), feature = "debug-embed"))]
67
- fn generate_assets(ident: &syn::Ident, folder_path: String) -> TokenStream2 {
68
- extern crate rust_embed_utils;
69
-
70
- let mut match_values = Vec::<TokenStream2>::new();
71
- let mut list_values = Vec::<String>::new();
72
-
73
- for rust_embed_utils::FileEntry { rel_path, full_canonical_path } in rust_embed_utils::get_files(folder_path) {
74
- match_values.push(embed_file(&rel_path, &full_canonical_path));
75
- list_values.push(rel_path);
76
- }
77
-
78
- let array_len = list_values.len();
79
-
80
- quote! {
81
- impl #ident {
82
- pub fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
83
- match file_path.replace("\\", "/").as_str() {
84
- #(#match_values)*
85
- _ => None,
86
- }
87
- }
88
-
89
- fn names() -> std::slice::Iter<'static, &'static str> {
90
- const items: [&str; #array_len] = [#(#list_values),*];
91
- items.iter()
92
- }
93
- pub fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> {
94
- Self::names().map(|x| std::borrow::Cow::from(*x))
95
- }
96
- }
97
- impl rust_embed::RustEmbed for #ident {
98
- fn get(file_path: &str) -> Option<std::borrow::Cow<'static, [u8]>> {
99
- #ident::get(file_path)
100
- }
101
- fn iter() -> rust_embed::Filenames {
102
- rust_embed::Filenames::Embedded(#ident::names())
103
- }
104
- }
105
- }
106
- }
107
-
108
135
  fn impl_rust_embed(ast: &syn::DeriveInput) -> TokenStream2 {
109
136
  match ast.data {
110
137
  Data::Struct(ref data) => match data.fields {
utils/src/lib.rs CHANGED
@@ -7,6 +7,7 @@ pub struct FileEntry {
7
7
  #[cfg_attr(all(debug_assertions, not(feature = "debug-embed")), allow(unused))]
8
8
  pub fn get_files(folder_path: String) -> impl Iterator<Item = FileEntry> {
9
9
  walkdir::WalkDir::new(&folder_path)
10
+ .follow_links(true)
10
11
  .into_iter()
11
12
  .filter_map(|e| e.ok())
12
13
  .filter(|e| e.file_type().is_file())