Fix for this, please review and let me know.
From 91d0d219557c469fb2cbd65a3875b6ecd12cfa7d Mon Sep 17 00:00:00 2001
From: pyrossh <pyrossh>
Date: Mon, 15 Jun 2026 21:55:01 +0530
Subject: [PATCH] Fix mime guess host/target issue
---
impl/src/lib.rs | 15 +++++++--------
utils/src/lib.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/impl/src/lib.rs b/impl/src/lib.rs
index 927e3ea..861de76 100644
--- a/impl/src/lib.rs
+++ b/impl/src/lib.rs
@@ -276,13 +276,12 @@ fn embed_file(
};
(last_modified, created)
};
- #[cfg(feature = "mime-guess")]
- let mimetype_tokens = {
- let mt = file.metadata.mimetype();
- quote! { , #mt }
- };
- #[cfg(not(feature = "mime-guess"))]
- let mimetype_tokens = TokenStream2::new();
+ // Always compute and emit the mimetype, without branching on this crate's own
+ // `mime-guess` feature. This crate is a proc-macro compiled for the host, so
+ // its features are resolved independently of the target the generated code is
+ // compiled into. The decision of whether to keep the mimetype is made
+ // target-side by the `__rust_embed_metadata!` macro in `rust-embed-utils`.
+ let mimetype = rust_embed_utils::_mimetype_of(Path::new(full_canonical_path));
let embedding_code = if metadata_only {
quote! {
@@ -312,7 +311,7 @@ fn embed_file(
#crate_path::EmbeddedFile {
data: ::std::borrow::Cow::Borrowed(&BYTES),
- metadata: #crate_path::Metadata::__rust_embed_new([#(#hash),*], #last_modified, #created #mimetype_tokens)
+ metadata: #crate_path::utils::__rust_embed_metadata!([#(#hash),*], #last_modified, #created, #mimetype)
}
}
})
diff --git a/utils/src/lib.rs b/utils/src/lib.rs
index 2f3fefd..e638676 100644
--- a/utils/src/lib.rs
+++ b/utils/src/lib.rs
@@ -54,6 +54,54 @@ pub struct Metadata {
mimetype: Cow<'static, str>,
}
+/// Constructs a [`Metadata`] from tokens emitted by the derive macro.
+///
+/// The derive macro (`rust-embed-impl`) is a proc-macro and is therefore always
+/// compiled for the *host*, where its `mime-guess` feature is resolved
+/// independently of the *target* that the generated code is compiled into. It
+/// must not branch on its own `#[cfg(feature = "mime-guess")]`, since that
+/// reflects the host rather than the target. Instead it unconditionally emits
+/// all four arguments (including a mimetype string) and defers to this macro,
+/// which *is* compiled for the target and so discards the mimetype when
+/// `mime-guess` is disabled there.
+#[cfg(feature = "mime-guess")]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __rust_embed_metadata {
+ ($hash:expr, $last_modified:expr, $created:expr, $mimetype:expr $(,)?) => {
+ $crate::Metadata::__rust_embed_new($hash, $last_modified, $created, $mimetype)
+ };
+}
+
+/// See the `mime-guess` variant above. This variant drops the mimetype token.
+#[cfg(not(feature = "mime-guess"))]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __rust_embed_metadata {
+ ($hash:expr, $last_modified:expr, $created:expr, $mimetype:expr $(,)?) => {
+ $crate::Metadata::__rust_embed_new($hash, $last_modified, $created)
+ };
+}
+
+/// Computes the mimetype of a file at build time.
+///
+/// This is always available (regardless of the `mime-guess` feature) so that
+/// the derive macro can unconditionally produce a mimetype token without using
+/// `#[cfg(…)]`. The token is only ever used by [`__rust_embed_metadata`] when
+/// the target enables `mime-guess`; otherwise the empty string returned here is
+/// discarded by the macro.
+#[doc(hidden)]
+pub fn _mimetype_of(_path: &Path) -> String {
+ #[cfg(feature = "mime-guess")]
+ {
+ mime_guess::from_path(_path).first_or_octet_stream().to_string()
+ }
+ #[cfg(not(feature = "mime-guess"))]
+ {
+ String::new()
+ }
+}
+
impl Metadata {
#[doc(hidden)]
pub const fn __rust_embed_new(
--
2.54.0