rust-embed v8.11.0

#rust#proc-macro#http

git clone https://git.pyrossh.dev/rust-embed

rust macro which loads files into the rust binary at compile time during release and loads the file from the fs during dev.


6679d58pyrossh 2026-06-27T18:15:10+05:30
Fix rust-embed-utils is built twice when cross-compiling
Files changed (4) hide show
  1. Cargo.toml +1 -1
  2. impl/Cargo.toml +6 -1
  3. impl/src/lib.rs +24 -8
  4. utils/src/lib.rs +7 -24
Cargo.toml CHANGED
@@ -93,7 +93,7 @@ sha2 = "0.10"
93
93
  debug-embed = ["rust-embed-impl/debug-embed", "rust-embed-utils/debug-embed"]
94
94
  interpolate-folder-path = ["rust-embed-impl/interpolate-folder-path"]
95
95
  compression = ["rust-embed-impl/compression", "include-flate"]
96
- mime-guess = ["rust-embed-impl/mime-guess", "rust-embed-utils/mime-guess"]
96
+ mime-guess = ["rust-embed-utils/mime-guess"]
97
97
  include-exclude = [
98
98
  "rust-embed-impl/include-exclude",
99
99
  "rust-embed-utils/include-exclude",
impl/Cargo.toml CHANGED
@@ -17,6 +17,12 @@ proc-macro = true
17
17
  [dependencies]
18
18
  rust-embed-utils = { version = "8.11.0", path = "../utils" }
19
19
 
20
+ # Unconditional (host-only, this is a proc-macro crate) so that the `__mimetype_of`
21
+ # proc macro can always compute a mimetype regardless of how the `mime-guess`
22
+ # feature resolves for the host. Whether the result is actually used is decided
23
+ # target-side by the `__rust_embed_metadata!` macro in `rust-embed-utils`.
24
+ mime_guess = "2.0.4"
25
+
20
26
  syn = { version = "2", default-features = false, features = [
21
27
  "derive",
22
28
  "parsing",
@@ -35,6 +41,5 @@ optional = true
35
41
  debug-embed = []
36
42
  interpolate-folder-path = ["shellexpand"]
37
43
  compression = []
38
- mime-guess = ["rust-embed-utils/mime-guess"]
39
44
  include-exclude = ["rust-embed-utils/include-exclude"]
40
45
  deterministic-timestamps = []
impl/src/lib.rs CHANGED
@@ -276,13 +276,6 @@ fn embed_file(
276
276
  };
277
277
  (last_modified, created)
278
278
  };
279
- // Always compute and emit the mimetype, without branching on this crate's own
280
- // `mime-guess` feature. This crate is a proc-macro compiled for the host, so
281
- // its features are resolved independently of the target the generated code is
282
- // compiled into. The decision of whether to keep the mimetype is made
283
- // target-side by the `__rust_embed_metadata!` macro in `rust-embed-utils`.
284
- let mimetype = rust_embed_utils::_mimetype_of(Path::new(full_canonical_path));
285
-
286
279
  let embedding_code = if metadata_only {
287
280
  quote! {
288
281
  const BYTES: &'static [u8] = &[];
@@ -311,7 +304,12 @@ fn embed_file(
311
304
 
312
305
  #crate_path::EmbeddedFile {
313
306
  data: ::std::borrow::Cow::Borrowed(&BYTES),
307
+ // The mimetype is computed by a proc macro (so it does not depend
308
+ // on the host's `mime-guess` feature) and passed as the final
309
+ // argument. `__rust_embed_metadata!` is selected target-side: when
310
+ // the target lacks `mime-guess` it drops this argument without ever
311
+ // expanding the `__mimetype_of!` call.
314
- metadata: #crate_path::utils::__rust_embed_metadata!([#(#hash),*], #last_modified, #created, #mimetype)
312
+ metadata: #crate_path::utils::__rust_embed_metadata!([#(#hash),*], #last_modified, #created, #crate_path::__mimetype_of!(#full_canonical_path))
315
313
  }
316
314
  }
317
315
  })
@@ -449,3 +447,21 @@ pub fn derive_input_object(input: TokenStream) -> TokenStream {
449
447
  Err(e) => e.to_compile_error().into(),
450
448
  }
451
449
  }
450
+
451
+ /// Expands to a string literal containing the mimetype of the file at the given
452
+ /// path, guessed from its extension.
453
+ ///
454
+ /// This lives in the proc-macro crate (which depends on `mime_guess`
455
+ /// unconditionally) rather than being computed inside the derive's host-side
456
+ /// logic: the derive must emit tokens that do not depend on the *host*'s
457
+ /// `mime-guess` feature, and this proc macro is invoked only from the
458
+ /// target-side `__rust_embed_metadata!` macro. When the target has `mime-guess`
459
+ /// disabled, the invocation generated by the derive is discarded by that macro
460
+ /// without ever being expanded.
461
+ #[doc(hidden)]
462
+ #[proc_macro]
463
+ pub fn __mimetype_of(input: TokenStream) -> TokenStream {
464
+ let path = parse_macro_input!(input as syn::LitStr).value();
465
+ let mimetype = mime_guess::from_path(&path).first_or_octet_stream().to_string();
466
+ quote! { #mimetype }.into()
467
+ }
utils/src/lib.rs CHANGED
@@ -60,10 +60,10 @@ pub struct Metadata {
60
60
  /// compiled for the *host*, where its `mime-guess` feature is resolved
61
61
  /// independently of the *target* that the generated code is compiled into. It
62
62
  /// must not branch on its own `#[cfg(feature = "mime-guess")]`, since that
63
- /// reflects the host rather than the target. Instead it unconditionally emits
63
+ /// reflects the host rather than the target. Instead it unconditionally emits a
64
- /// all four arguments (including a mimetype string) and defers to this macro,
64
+ /// `__mimetype_of!(...)` call as the final argument and defers to this macro,
65
- /// which *is* compiled for the target and so discards the mimetype when
65
+ /// which *is* compiled for the target. This variant (target has `mime-guess`)
66
- /// `mime-guess` is disabled there.
66
+ /// forwards the argument, expanding the proc macro to the real mimetype.
67
67
  #[cfg(feature = "mime-guess")]
68
68
  #[doc(hidden)]
69
69
  #[macro_export]
@@ -73,7 +73,9 @@ macro_rules! __rust_embed_metadata {
73
73
  };
74
74
  }
75
75
 
76
- /// See the `mime-guess` variant above. This variant drops the mimetype token.
76
+ /// See the `mime-guess` variant above. This variant (target lacks `mime-guess`)
77
+ /// drops the final argument, so the `__mimetype_of!` call it contains is never
78
+ /// expanded.
77
79
  #[cfg(not(feature = "mime-guess"))]
78
80
  #[doc(hidden)]
79
81
  #[macro_export]
@@ -83,25 +85,6 @@ macro_rules! __rust_embed_metadata {
83
85
  };
84
86
  }
85
87
 
86
- /// Computes the mimetype of a file at build time.
87
- ///
88
- /// This is always available (regardless of the `mime-guess` feature) so that
89
- /// the derive macro can unconditionally produce a mimetype token without using
90
- /// `#[cfg(…)]`. The token is only ever used by [`__rust_embed_metadata`] when
91
- /// the target enables `mime-guess`; otherwise the empty string returned here is
92
- /// discarded by the macro.
93
- #[doc(hidden)]
94
- pub fn _mimetype_of(_path: &Path) -> String {
95
- #[cfg(feature = "mime-guess")]
96
- {
97
- mime_guess::from_path(_path).first_or_octet_stream().to_string()
98
- }
99
- #[cfg(not(feature = "mime-guess"))]
100
- {
101
- String::new()
102
- }
103
- }
104
-
105
88
  impl Metadata {
106
89
  #[doc(hidden)]
107
90
  pub const fn __rust_embed_new(