fs-embed
Embed directories into your binary at compile time with zero runtime config β supporting both embedded and live (dynamic) modes through a single API.
π Philosophy
fs-embed
is built for frictionless file access across environments:
- β
Always embedded:
fs_embed!("dir")
embeds directories at compile time, even in debug builds. - π Switch to live mode (e.g. for hot-reloading): Call
.into_dynamic()
or.auto_dynamic()
β no need to change your file access logic. - π Overlay support: Compose multiple embedded or dynamic directories using
DirSet
, with override precedence. - π© One macro, one API: No cargo features, no env vars, no conditional compilation.
This enables:
- Reproducible builds: Assets are fully embedded in release binaries.
- Fast iteration in development: Read live files with a one-line change β no config, no rebuild.
- Clean architecture: Keep templates, config, and assets in sync with source and override them per environment.
π Quick Start
use fs_embed;
// Embed the "static" folder β always at compile time, even in debug builds.
static STATIC: Dir = fs_embed!;
π
fs_embed!("static")
expects a literal relative path inside your crate, resolved viaCARGO_MANIFEST_DIR
.
π Embedded vs Dynamic
Two methods let you switch modes at runtime:
-
.into_dynamic()
- Always reads from disk.
- Useful for tests, hot-reload, or CLI tools.
let dir = fs_embed!.into_dynamic;
-
.auto_dynamic()
- Reads from disk in debug, embedded in release.
- Best for developmentβproduction parity.
let dir = fs_embed!.auto_dynamic;
π Core API
Method | Description |
---|---|
Dir::get_file(path) |
Get a file by relative path |
Dir::read_str() / read_bytes() |
Read file contents |
Dir::walk() |
Recursively yield all files |
Dir::walk_override() |
Recursively yield highest-precedence files (for overlays) |
Dir::is_embedded() |
Returns true if directory is embedded |
Dir::into_dynamic() |
Convert to dynamic (disk-backed) mode |
Dir::auto_dynamic() |
Use disk in debug, embedded in release |
π₯ Override Behavior
You can compose multiple directories using DirSet
:
let dir = new;
let file = dir.get_file; // From theme if it exists, otherwise base
- Overlay precedence is left-to-right.
- Only the first match for each path is returned.
walk_override()
yields exactly one file per unique relative path.
β οΈ Notes
DirSet::walk()
traversal order is not guaranteed (OS-dependent).Dir::entries()
preserves insertion order of embedded files and folders, but disk-backed order may vary.- All embedded files are resolved at compile time. Dynamic mode reads directly from disk at runtime.
π¦ Installation
[]
= "0.1"
π Docs
Full API documentation: docs.rs/fs-embed
β€οΈ Inspired by
fs-embed
unifies compile-time embedding with runtime overrides in a zero-config, ergonomic interface β ideal for CLI tools, embedded apps, web frameworks, and static-site generators.