Skip to main content

Crate embed

Crate embed 

Source
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 release builds, or when the debug-embed feature is enabled, the files are embedded into the binary and the folder is resolved relative to the directory containing Cargo.toml at build time.
  • In debug builds, and when the debug-embed feature is not enabled, the files are read from the file system at runtime. The folder captured at build time (relative to the directory containing Cargo.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: add Metadata::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§

EmbeddedFile
A file embedded into the binary
Metadata
Metadata about an embedded file

Enums§

Filenames
An iterator over filenames.

Traits§

RustEmbed
A directory of binary assets.

Derive Macros§

Embed