Expand description
Load files into the Rust binary at compile time.
A custom derive macro that embeds files into the binary in release builds and reads them from the file system during development. Use it to bundle CSS, JS, and images into a single executable which can be deployed to your servers, and to build small container images.
The folder path given to #[folder] is resolved as follows:
- In
releasebuilds, or when thedebug-embedfeature is enabled, the files are embedded into the binary and the folder is resolved relative to the directory containingCargo.tomlat build time. - In
debugbuilds, and when thedebug-embedfeature is not enabled, the files are read from the file system at runtime. The folder captured at build time (relative to the directory containingCargo.toml) is used if it still exists; otherwise the folder is resolved relative to the directory the binary is run from. The fallback keeps debug builds working when the build directory is unavailable, for example when the binary was moved to another machine or runs in a sandbox such as WASI.
The folder must be a directory; deriving Embed on a path that does not
exist or is not a directory is a compile-time error.
Add the Embed derive to a struct with a folder attribute pointing at the
static folder:
use embed::Embed;
#[derive(Embed)]
#[folder = "examples/public/"]
struct Asset;The macro generates two associated functions:
get(file_path: &str) -> Option<embed::EmbeddedFile>returns the file at a path relative to the assets folder.iter()iterates over the relative paths of the files in the folder.
When the files are embedded (release builds, or with debug-embed), the
data is returned as a Cow::Borrowed(&'static [u8]) and the file list is a
static array. Otherwise the data is read from the file system on each call
and the file list is produced by walking the folder.
An EmbeddedFile holds the file data and its Metadata.
§Lookup paths
get accepts the same relative paths that iter yields: /-separated
paths with no empty, . or .. component and no backslash, for example
"index.html" or "images/llama.png". Any other input returns None
instead of being normalized, so get("./index.html"),
get("images/../index.html") and absolute paths always return None. This
guarantees that debug builds behave exactly like release builds: in both
cases the only accepted inputs are the exact paths listed by iter.
Paths are relative to the folder and never escape it, including through
symbolic links: a symlink whose target is outside the folder is ignored by
iter and returns None from get, in debug and release builds alike.
Symlinks that stay inside the folder are followed normally.
Files whose names are not valid UTF-8, or whose names contain a backslash,
are skipped when the folder is walked (they cannot be addressed by a &str
path). This matches the behaviour of Go’s embed package.
Two limits are worth knowing about:
- On case-insensitive file systems (for example the default macOS
configuration), a debug lookup may resolve a path whose casing differs
from the stored name, while embedded lookups are always case sensitive.
Pass names exactly as returned by
iter. - Debug lookups check the canonical path and then read it. A local attacker
able to modify the assets folder while the program runs could swap a path
between the check and the read; making this race-free requires
handle-relative APIs that are not available in safe
std. Release builds are unaffected, since the data is embedded.
§Attributes
§prefix
#[prefix = "my_prefix/"] prepends a prefix to every file path. The prefix
is required on get calls and is included in the paths returned by iter.
§metadata_only
#[metadata_only = true] excludes the file contents from the binary. Only
file paths and metadata are embedded.
§crate_path
#[crate_path = "some::path::Embed"] names the crate that provides the
EmbeddedFile, Metadata and RustEmbed items used by the generated code.
It defaults to embed and is meant for re-exporting scenarios.
§Features
debug-embed: always embed the files in the binary, even in debug builds.guess-media-type: addMetadata::mimetype()and guess each file’s media type from its path.
§Reproducible builds
When the SOURCE_DATE_EPOCH environment variable is set, its value (in
seconds since the UNIX epoch) is used for both
Metadata::last_modified and Metadata::created, so builds of the same
sources produce the same metadata. It is read at most once per process.
§Example
use embed::Embed;
#[derive(Embed)]
#[folder = "examples/public/"]
#[prefix = "prefix/"]
struct Asset;
fn main() {
let index_html = Asset::get("prefix/index.html").unwrap();
println!("{:?}", std::str::from_utf8(index_html.data.as_ref()));
for file in Asset::iter() {
println!("{}", file.as_ref());
}
}Structs§
- Embedded
File - A file embedded into the binary
- Metadata
- Metadata about an embedded file
Enums§
- Filenames
- An iterator over filenames.
Traits§
- Rust
Embed - A directory of binary assets.