| Crates.io | rust-silos |
| lib.rs | rust-silos |
| version | 0.2.6 |
| created_at | 2025-07-19 08:40:06.328563+00 |
| updated_at | 2025-07-30 03:00:58.635796+00 |
| description | Minimal, robust file embedding for Rust. Efficient, allocation-free, and reliable. |
| homepage | |
| repository | https://github.com/vivsh/rust-silos |
| max_upload_size | |
| id | 1760009 |
| size | 42,743 |
Minimal, robust file embedding for Rust. Efficient and reliable.
include_bytes!.use rust_silos::Silo;
// Embed the "assets" directory at compile time
static ASSETS: Silo = rust_silos::embed_silo!("assets");
fn main() {
// Access embedded files by relative path
if let Some(file) = ASSETS.get_file("logo.png") {
let bytes = file.read_bytes().unwrap();
// ... use bytes ...
}
}
The embed_silo! macro can be used as:
static ASSETS: Silo = rust_silos::embed_silo!("assets");
By default, in debug mode, files are read from disk for hot-reload; in release mode, files are embedded in the binary. This can be overridden:
force = true — always embed files, even in debug mode.force = false — always use disk, even in release mode.crate = path — use a custom crate path for the runtime (needed if you re-export or rename the crate).Example with options:
static ASSETS: Silo = rust_silos::embed_silo!("assets", force = true, crate = my_runtime_crate);
crate argument?If you re-export or rename the rust-silos crate in your project, set crate = my_runtime_crate to ensure the macro-generated code uses the correct path to the runtime API.
After creating a Silo with the macro, you can control whether it uses embedded files or reads from disk at runtime:
into_dynamic(): Always use disk (dynamic) mode, even in release builds. Useful for tests, hot-reload, or CLI tools.auto_dynamic(): Use disk in debug mode, embedded in release mode. This is the default for development–production parity. Should be used only on an embedded silo; for other modes it is a no-op.Example:
let dir = ASSETS.auto_dynamic(); // disk in debug, embedded in release
let dir = ASSETS.into_dynamic(); // always disk
force argument in the macro to control this behavior explicitly.You can compose multiple silos using SiloSet to support overlays and override semantics. Later silos in the set override files from earlier ones with the same relative path.
use rust_silos::{Silo, SiloSet};
static BASE: Silo = rust_silos::embed_silo!("base");
static THEME: Silo = rust_silos::embed_silo!("theme");
let set = SiloSet::new(vec![BASE, THEME]);
if let Some(file) = set.get_file("index.html") {
// File from THEME if it exists, otherwise BASE
}
Overlay precedence is left-to-right. Only the highest-precedence file for each path is returned by iter_override().
The Silo struct provides a simple API for accessing embedded files:
new(path: &str) -> Self: Creates a new dynamic Silo from the given path.
get_file(path: &str) -> Option<File>: Retrieve a file by its relative path.
iter() -> Box<dyn Iterator<Item = File>>: Iterate over all files in the silo.
is_embedded() -> bool: Returns true if the silo is embedded in the binary.
is_dynamic() -> bool: Returns true if the silo is dynamic (filesystem-backed).
auto_dynamic(self) -> Self: Converts the silo to dynamic mode in debug builds; no-op in release builds. Should be used only on an embedded silo; for other modes it is a no-op.
into_dynamic(self) -> Self: Converts the silo to dynamic mode if it is embedded; no-op otherwise.
The SiloSet struct allows composing multiple Silo instances to support overlays and override semantics:
new(silos: Vec<Silo>) -> SiloSet: Create a new SiloSet from a list of Silo instances.get_file(path: &str) -> Option<File>: Retrieve the highest-precedence file for a given path.iter() -> impl Iterator<Item = File>: Iterate over all files in the SiloSet.iter_override() -> impl Iterator<Item = File>: Iterate over files with override precedence.Example:
use rust_silos::{Silo, SiloSet};
static BASE: Silo = rust_silos::embed_silo!("base");
static THEME: Silo = rust_silos::embed_silo!("theme");
let set = SiloSet::new(vec![BASE, THEME]);
if let Some(file) = set.get_file("index.html") {
// File from THEME if it exists, otherwise BASE
}
If you need overlays, dynamic/disk mode, or a virtual filesystem abstraction, see fs-embed.
This crate includes comprehensive tests for all public API. To run tests:
cargo test -p rust-silos
This crate is dual-licensed under either the MIT or Apache-2.0 license, at your option. See LICENSE-MIT and LICENSE-APACHE for details.