include-packed
include-packed
is a Rust crate that provides an efficient replacement for
std::include_bytes!
. It is designed for projects that need to embed large
binary files without suffering from slow compile times and large executable sizes.
It combines the fast-compile approach of include-blob
with zstd
compression,
inspired by include-bytes-zstd
.
How It Works
Instead of embedding file contents directly into your source code, this crate processes files in a build script.
- Build Script: You use the
include_packed::Config
builder in yourbuild.rs
script. For native targets, it reads your asset files, compresses them withzstd
, and creates linkable object files. - Macro Expansion: The
include_packed!
macro in your code expands to an expression that links to the compressed data (on native) or embeds the compressed data directly (on Wasm). - Runtime: At runtime, the expression decompresses the data and returns it
as a
Vec<u8>
.
This method significantly reduces compile times for projects with large binary assets and keeps the final executable size smaller.
Usage
-
Add
include_packed
to yourCargo.toml
. Thebuild
feature is required for build-dependencies.[] = "0.1.0" # be sure to use the latest version [] = { = "0.1.0", = ["build"] } # be sure to use the latest version
-
Create a
build.rs
file in your project root to prepare your assets.// build.rs
-
Use the macro in your code to include an asset. The path must be relative to the crate root.
// src/main.rs use include_packed;
Runtime Performance & Caching
Unlike std::include_bytes!
, which returns a &'static [u8]
, the include_packed!
macro returns a Vec<u8>
.
This is because the asset data is stored compressed within your binary. When you call the macro, the data must be decompressed at runtime into a newly allocated Vec<u8>
on the heap. This decompression has a small but non-zero CPU and memory cost each time it's called.
If you need to access an asset multiple times, it's recommended to decompress it only once and cache the result. The standard library's std::sync::LazyLock
is perfect for this.
Example with LazyLock
This example shows how to decompress an asset only on its first use. All subsequent accesses will be nearly zero-cost.
use LazyLock;
use include_packed;
// The asset is only decompressed the very first time `LARGE_ASSET` is accessed.
// All subsequent accesses will just return a reference to the cached `Vec<u8>`.
static LARGE_ASSET: = new;
License
This project is licensed under the MIT License.
Acknowledgements
This crate is a combination of ideas from:
include-blob
by SludgePhD, licensed under 0BSD.include-bytes-zstd
by Koichi Akabe, licensed under MIT/Apache-2.0.