rust_embed/lib.rs
1#![forbid(unsafe_code)]
2#[cfg(feature = "compression")]
3#[cfg_attr(feature = "compression", doc(hidden))]
4pub use include_flate::flate;
5
6#[cfg(feature = "compression")]
7pub use include_flate;
8
9extern crate rust_embed_impl;
10pub use rust_embed_impl::*;
11
12#[cfg(feature = "compression")]
13pub use rust_embed_utils::EmbeddedCompressedFile;
14pub use rust_embed_utils::{EmbeddedFile, Metadata};
15
16#[doc(hidden)]
17pub extern crate rust_embed_utils as utils;
18
19/// A directory of binary assets.
20///
21/// The files in the specified folder will be embedded into the executable in
22/// release builds. Debug builds will read the data from the file system at
23/// runtime.
24///
25/// This trait is meant to be derived like so:
26/// ```
27/// use rust_embed::Embed;
28///
29/// #[derive(Embed)]
30/// #[folder = "examples/public/"]
31/// struct Asset;
32///
33/// fn main() {}
34/// ```
35pub trait RustEmbed {
36 /// Get file compressed
37 #[cfg(feature = "compression")]
38 fn compressed(file_path: &str) -> Option<EmbeddedCompressedFile>;
39
40 /// Get an embedded file and its metadata.
41 ///
42 /// If the feature `debug-embed` is enabled or the binary was compiled in
43 /// release mode, the file information is embedded in the binary and the file
44 /// data is returned as a `Cow::Borrowed(&'static [u8])`.
45 ///
46 /// Otherwise, the information is read from the file system on each call and
47 /// the file data is returned as a `Cow::Owned(Vec<u8>)`.
48 fn get(file_path: &str) -> Option<EmbeddedFile>;
49
50 /// Iterates over the file paths in the folder.
51 ///
52 /// If the feature `debug-embed` is enabled or the binary is compiled in
53 /// release mode, a static array containing the list of relative file paths
54 /// is used.
55 ///
56 /// Otherwise, the files are listed from the file system on each call.
57 fn iter() -> impl Iterator<Item = std::borrow::Cow<'static, str>> + 'static;
58}
59
60pub use RustEmbed as Embed;
61
62/// A dyn-compatible ("object safe") counterpart to [`RustEmbed`].
63///
64/// `RustEmbed` cannot be used as `dyn RustEmbed` because its methods have no
65/// `self` parameter (they are associated functions on a marker type). This
66/// trait exists for callers who need to store or pass around an embedded
67/// directory as a trait object, e.g. `Box<dyn DynRustEmbed>`.
68///
69/// It is blanket-implemented for every type that implements `RustEmbed`, so
70/// there is nothing to derive or implement manually:
71///
72/// ```
73/// use rust_embed::{DynRustEmbed, Embed};
74///
75/// #[derive(Embed)]
76/// #[folder = "examples/public/"]
77/// struct Asset;
78///
79/// fn main() {
80/// let embed: Box<dyn DynRustEmbed> = Box::new(Asset);
81/// let _ = embed.get("index.html");
82/// }
83/// ```
84pub trait DynRustEmbed {
85 /// Get file compressed. See [`RustEmbed::compressed`].
86 #[cfg(feature = "compression")]
87 fn compressed(&self, file_path: &str) -> Option<EmbeddedCompressedFile>;
88
89 /// Get an embedded file and its metadata. See [`RustEmbed::get`].
90 fn get(&self, file_path: &str) -> Option<EmbeddedFile>;
91
92 /// Returns the file paths in the folder. See [`RustEmbed::iter`].
93 fn names(&self) -> Vec<std::borrow::Cow<'static, str>>;
94}
95
96impl<T: RustEmbed> DynRustEmbed for T {
97 #[cfg(feature = "compression")]
98 fn compressed(&self, file_path: &str) -> Option<EmbeddedCompressedFile> {
99 T::compressed(file_path)
100 }
101
102 fn get(&self, file_path: &str) -> Option<EmbeddedFile> {
103 T::get(file_path)
104 }
105
106 fn names(&self) -> Vec<std::borrow::Cow<'static, str>> {
107 T::iter().collect()
108 }
109}
110
111/// An iterator over filenames.
112///
113/// This enum exists for optimization purposes, to avoid boxing the iterator in
114/// some cases. Do not try and match on it, as different variants will exist
115/// depending on the compilation context.
116pub enum Filenames {
117 /// Release builds use a named iterator type, which can be stack-allocated.
118 #[cfg(any(not(debug_assertions), feature = "debug-embed"))]
119 Embedded(std::slice::Iter<'static, &'static str>),
120
121 /// The debug iterator type is currently unnameable and still needs to be
122 /// boxed.
123 #[cfg(all(debug_assertions, not(feature = "debug-embed")))]
124 Dynamic(Box<dyn Iterator<Item = std::borrow::Cow<'static, str>>>),
125}
126
127impl Iterator for Filenames {
128 type Item = std::borrow::Cow<'static, str>;
129 fn next(&mut self) -> Option<Self::Item> {
130 match self {
131 #[cfg(any(not(debug_assertions), feature = "debug-embed"))]
132 Filenames::Embedded(names) => names.next().map(|x| std::borrow::Cow::from(*x)),
133
134 #[cfg(all(debug_assertions, not(feature = "debug-embed")))]
135 Filenames::Dynamic(boxed) => boxed.next(),
136 }
137 }
138}