~repos /rust-embed

#rust#proc-macro#http

GIT_CONFIG_PARAMETERS="'http.version=HTTP/1.1'" git clone https://git.pyrossh.dev/rust-embed/.git rust-embed
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 +7 -8
  2. utils/src/lib.rs +48 -0
impl/src/lib.rs CHANGED
@@ -276,13 +276,12 @@ fn embed_file(
276
276
  };
277
277
  (last_modified, created)
278
278
  };
279
- #[cfg(feature = "mime-guess")]
279
+ // Always compute and emit the mimetype, without branching on this crate's own
280
- let mimetype_tokens = {
281
- let mt = file.metadata.mimetype();
282
- quote! { , #mt }
283
- };
284
- #[cfg(not(feature = "mime-guess"))]
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`.
285
- let mimetype_tokens = TokenStream2::new();
284
+ let mimetype = rust_embed_utils::_mimetype_of(Path::new(full_canonical_path));
286
285
 
287
286
  let embedding_code = if metadata_only {
288
287
  quote! {
@@ -312,7 +311,7 @@ fn embed_file(
312
311
 
313
312
  #crate_path::EmbeddedFile {
314
313
  data: ::std::borrow::Cow::Borrowed(&BYTES),
315
- metadata: #crate_path::Metadata::__rust_embed_new([#(#hash),*], #last_modified, #created #mimetype_tokens)
314
+ metadata: #crate_path::utils::__rust_embed_metadata!([#(#hash),*], #last_modified, #created, #mimetype)
316
315
  }
317
316
  }
318
317
  })
utils/src/lib.rs CHANGED
@@ -54,6 +54,54 @@ pub struct Metadata {
54
54
  mimetype: Cow<'static, str>,
55
55
  }
56
56
 
57
+ /// Constructs a [`Metadata`] from tokens emitted by the derive macro.
58
+ ///
59
+ /// The derive macro (`rust-embed-impl`) is a proc-macro and is therefore always
60
+ /// compiled for the *host*, where its `mime-guess` feature is resolved
61
+ /// independently of the *target* that the generated code is compiled into. It
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
64
+ /// all four arguments (including a mimetype string) and defers to this macro,
65
+ /// which *is* compiled for the target and so discards the mimetype when
66
+ /// `mime-guess` is disabled there.
67
+ #[cfg(feature = "mime-guess")]
68
+ #[doc(hidden)]
69
+ #[macro_export]
70
+ macro_rules! __rust_embed_metadata {
71
+ ($hash:expr, $last_modified:expr, $created:expr, $mimetype:expr $(,)?) => {
72
+ $crate::Metadata::__rust_embed_new($hash, $last_modified, $created, $mimetype)
73
+ };
74
+ }
75
+
76
+ /// See the `mime-guess` variant above. This variant drops the mimetype token.
77
+ #[cfg(not(feature = "mime-guess"))]
78
+ #[doc(hidden)]
79
+ #[macro_export]
80
+ macro_rules! __rust_embed_metadata {
81
+ ($hash:expr, $last_modified:expr, $created:expr, $mimetype:expr $(,)?) => {
82
+ $crate::Metadata::__rust_embed_new($hash, $last_modified, $created)
83
+ };
84
+ }
85
+
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
+
57
105
  impl Metadata {
58
106
  #[doc(hidden)]
59
107
  pub const fn __rust_embed_new(