~repos /rust-embed
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.
7c0fc42f
—
Mark Drobnak 2 years ago
Merge pull request #203 from BBaoVanC/static-mime-guess
- .github/workflows/test.yml +2 -0
- Cargo.toml +6 -0
- impl/Cargo.toml +1 -0
- impl/src/lib.rs +8 -1
- tests/mime_guess.rs +35 -0
- utils/Cargo.toml +2 -0
- utils/src/lib.rs +20 -2
.github/workflows/test.yml
CHANGED
|
@@ -33,6 +33,8 @@ jobs:
|
|
|
33
33
|
cargo test --test lib
|
|
34
34
|
cargo test --test lib --features "debug-embed"
|
|
35
35
|
cargo test --test lib --features "compression" --release
|
|
36
|
+
cargo test --test mime_guess --features "mime-guess"
|
|
37
|
+
cargo test --test mime_guess --features "mime-guess" --release
|
|
36
38
|
cargo test --test interpolated_path --features "interpolate-folder-path"
|
|
37
39
|
cargo test --test interpolated_path --features "interpolate-folder-path" --release
|
|
38
40
|
cargo build --example basic
|
Cargo.toml
CHANGED
|
@@ -56,6 +56,11 @@ name = "include_exclude"
|
|
|
56
56
|
path = "tests/include_exclude.rs"
|
|
57
57
|
required-features = ["include-exclude"]
|
|
58
58
|
|
|
59
|
+
[[test]]
|
|
60
|
+
name = "mime_guess"
|
|
61
|
+
path = "tests/mime_guess.rs"
|
|
62
|
+
required-features = ["mime-guess"]
|
|
63
|
+
|
|
59
64
|
[dependencies]
|
|
60
65
|
walkdir = "2.3.1"
|
|
61
66
|
rust-embed-impl = { version = "6.3.1", path = "impl"}
|
|
@@ -79,6 +84,7 @@ sha2 = "0.10"
|
|
|
79
84
|
debug-embed = ["rust-embed-impl/debug-embed", "rust-embed-utils/debug-embed"]
|
|
80
85
|
interpolate-folder-path = ["rust-embed-impl/interpolate-folder-path"]
|
|
81
86
|
compression = ["rust-embed-impl/compression", "include-flate"]
|
|
87
|
+
mime-guess = ["rust-embed-impl/mime-guess"]
|
|
82
88
|
include-exclude = ["rust-embed-impl/include-exclude", "rust-embed-utils/include-exclude"]
|
|
83
89
|
actix = ["actix-web", "mime_guess"]
|
|
84
90
|
warp-ex = ["warp", "tokio", "mime_guess"]
|
impl/Cargo.toml
CHANGED
|
@@ -30,4 +30,5 @@ optional = true
|
|
|
30
30
|
debug-embed = []
|
|
31
31
|
interpolate-folder-path = ["shellexpand"]
|
|
32
32
|
compression = []
|
|
33
|
+
mime-guess = ["rust-embed-utils/mime-guess"]
|
|
33
34
|
include-exclude = ["rust-embed-utils/include-exclude"]
|
impl/src/lib.rs
CHANGED
|
@@ -174,6 +174,13 @@ fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
|
|
|
174
174
|
Some(last_modified) => quote! { Some(#last_modified) },
|
|
175
175
|
None => quote! { None },
|
|
176
176
|
};
|
|
177
|
+
#[cfg(feature = "mime-guess")]
|
|
178
|
+
let mimetype_tokens = {
|
|
179
|
+
let mt = file.metadata.mimetype();
|
|
180
|
+
quote! { , #mt }
|
|
181
|
+
};
|
|
182
|
+
#[cfg(not(feature = "mime-guess"))]
|
|
183
|
+
let mimetype_tokens = TokenStream2::new();
|
|
177
184
|
|
|
178
185
|
let embedding_code = if cfg!(feature = "compression") {
|
|
179
186
|
quote! {
|
|
@@ -192,7 +199,7 @@ fn embed_file(rel_path: &str, full_canonical_path: &str) -> TokenStream2 {
|
|
|
192
199
|
|
|
193
200
|
Some(rust_embed::EmbeddedFile {
|
|
194
201
|
data: std::borrow::Cow::from(bytes),
|
|
195
|
-
metadata: rust_embed::Metadata::__rust_embed_new([#(#hash),*], #last_modified)
|
|
202
|
+
metadata: rust_embed::Metadata::__rust_embed_new([#(#hash),*], #last_modified #mimetype_tokens)
|
|
196
203
|
})
|
|
197
204
|
}
|
|
198
205
|
}
|
tests/mime_guess.rs
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
use rust_embed::{EmbeddedFile, RustEmbed};
|
|
2
|
+
|
|
3
|
+
#[derive(RustEmbed)]
|
|
4
|
+
#[folder = "examples/public/"]
|
|
5
|
+
struct Asset;
|
|
6
|
+
|
|
7
|
+
#[test]
|
|
8
|
+
fn html_mime_is_correct() {
|
|
9
|
+
let html_file: EmbeddedFile = Asset::get("index.html").expect("index.html exists");
|
|
10
|
+
assert_eq!(html_file.metadata.mimetype(), "text/html");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
#[test]
|
|
14
|
+
fn css_mime_is_correct() {
|
|
15
|
+
let css_file: EmbeddedFile = Asset::get("main.css").expect("main.css exists");
|
|
16
|
+
assert_eq!(css_file.metadata.mimetype(), "text/css");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#[test]
|
|
20
|
+
fn js_mime_is_correct() {
|
|
21
|
+
let js_file: EmbeddedFile = Asset::get("main.js").expect("main.js exists");
|
|
22
|
+
assert_eq!(js_file.metadata.mimetype(), "application/javascript");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#[test]
|
|
26
|
+
fn jpg_mime_is_correct() {
|
|
27
|
+
let jpg_file: EmbeddedFile = Asset::get("images/flower.jpg").expect("flower.jpg exists");
|
|
28
|
+
assert_eq!(jpg_file.metadata.mimetype(), "image/jpeg");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#[test]
|
|
32
|
+
fn png_mime_is_correct() {
|
|
33
|
+
let png_file: EmbeddedFile = Asset::get("images/llama.png").expect("llama.png exists");
|
|
34
|
+
assert_eq!(png_file.metadata.mimetype(), "image/png");
|
|
35
|
+
}
|
utils/Cargo.toml
CHANGED
|
@@ -14,6 +14,7 @@ edition = "2018"
|
|
|
14
14
|
[dependencies]
|
|
15
15
|
walkdir = "2.3.1"
|
|
16
16
|
sha2 = "0.10.5"
|
|
17
|
+
mime_guess = { version = "2.0.4", optional = true }
|
|
17
18
|
|
|
18
19
|
[dependencies.globset]
|
|
19
20
|
version = "0.4.8"
|
|
@@ -21,4 +22,5 @@ optional = true
|
|
|
21
22
|
|
|
22
23
|
[features]
|
|
23
24
|
debug-embed = []
|
|
25
|
+
mime-guess = ["mime_guess"]
|
|
24
26
|
include-exclude = ["globset"]
|
utils/src/lib.rs
CHANGED
|
@@ -87,12 +87,19 @@ pub struct EmbeddedFile {
|
|
|
87
87
|
pub struct Metadata {
|
|
88
88
|
hash: [u8; 32],
|
|
89
89
|
last_modified: Option<u64>,
|
|
90
|
+
#[cfg(feature = "mime-guess")]
|
|
91
|
+
mimetype: Cow<'static, str>,
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
impl Metadata {
|
|
93
95
|
#[doc(hidden)]
|
|
94
|
-
pub fn __rust_embed_new(hash: [u8; 32], last_modified: Option<u64>) -> Self {
|
|
96
|
+
pub fn __rust_embed_new(hash: [u8; 32], last_modified: Option<u64>, #[cfg(feature = "mime-guess")] mimetype: &'static str) -> Self {
|
|
97
|
+
Self {
|
|
98
|
+
hash,
|
|
95
|
-
|
|
99
|
+
last_modified,
|
|
100
|
+
#[cfg(feature = "mime-guess")]
|
|
101
|
+
mimetype: mimetype.into(),
|
|
102
|
+
}
|
|
96
103
|
}
|
|
97
104
|
|
|
98
105
|
/// The SHA256 hash of the file
|
|
@@ -105,6 +112,12 @@ impl Metadata {
|
|
|
105
112
|
pub fn last_modified(&self) -> Option<u64> {
|
|
106
113
|
self.last_modified
|
|
107
114
|
}
|
|
115
|
+
|
|
116
|
+
/// The mime type of the file
|
|
117
|
+
#[cfg(feature = "mime-guess")]
|
|
118
|
+
pub fn mimetype(&self) -> &str {
|
|
119
|
+
&self.mimetype
|
|
120
|
+
}
|
|
108
121
|
}
|
|
109
122
|
|
|
110
123
|
pub fn read_file_from_fs(file_path: &Path) -> io::Result<EmbeddedFile> {
|
|
@@ -127,11 +140,16 @@ pub fn read_file_from_fs(file_path: &Path) -> io::Result<EmbeddedFile> {
|
|
|
127
140
|
.as_secs()
|
|
128
141
|
});
|
|
129
142
|
|
|
143
|
+
#[cfg(feature = "mime-guess")]
|
|
144
|
+
let mimetype = mime_guess::from_path(file_path).first_or_octet_stream().to_string();
|
|
145
|
+
|
|
130
146
|
Ok(EmbeddedFile {
|
|
131
147
|
data,
|
|
132
148
|
metadata: Metadata {
|
|
133
149
|
hash,
|
|
134
150
|
last_modified: source_date_epoch.or(last_modified),
|
|
151
|
+
#[cfg(feature = "mime-guess")]
|
|
152
|
+
mimetype: mimetype.into(),
|
|
135
153
|
},
|
|
136
154
|
})
|
|
137
155
|
}
|