Publishing to crates.io
Publishing to crates.io packages your crate's source files into a compressed .crate tarball and uploads it to the public Rust package registry so anyone can depend on it via cargo add <crate> or install its binaries via cargo install <crate>.
Publishing Workflow:
1. Verify metadata & include/exclude rules (`cargo package --list`)
2. Dry-run full verification build (`cargo publish --dry-run`)
3. Authenticate (`cargo login` or CI Trusted Publishing / `CARGO_REGISTRY_TOKEN`)
4. Upload permanent release (`cargo publish`)
Required Cargo.toml Metadata for crates.io
Before crates.io accepts a package, the [package] section of Cargo.toml must include a clear description and license, and all dependencies must come from a registry (pure path or git dependencies without a version are rejected):
[package]
name = "fast_varint"
version = "0.1.0"
edition = "2024"
rust-version = "1.85"
description = "Zero-allocation LEB128 variable-length integer encoding and decoding"
license = "MIT OR Apache-2.0"
repository = "https://github.com/example/fast_varint"
homepage = "https://github.com/example/fast_varint"
documentation = "https://docs.rs/fast_varint"
readme = "README.md"
keywords = ["varint", "leb128", "encoding", "no-std"]
categories = ["encoding", "no-std"]
# Exclude large test fixtures or CI configs to keep the .crate download small (<10 MiB limit)
exclude = [
"fuzz/",
"testdata/*.bin",
".github/",
]
Note that crates.io enforces a maximum of 5 keywords and 5 categories (chosen from the official crates.io category slugs).
Inspecting and Dry-Running Before Publishing
Published versions on crates.io are permanent and immutable—once 0.1.0 is uploaded, its contents can never be overwritten or deleted. Always inspect the packaged file list and perform a dry run before publishing:
# 1. Inspect every file that will be bundled into the .crate archive
cargo package --list
# 2. Unpack the .crate archive into target/package/ and compile it from scratch
# to verify no untracked local files were accidentally required
cargo publish --dry-run
# 3. Publish for real once the dry run succeeds
cargo publish
Handling Defective Releases with cargo yank
Although a published version cannot be deleted or overwritten (so existing Cargo.lock files across the world never break), you can yank a broken or vulnerable version:
# Prevent new projects from resolving version 0.1.0 during `cargo add` or `cargo update`
cargo yank --version 0.1.0
# Undo a yank if it was done by mistake
cargo yank --version 0.1.0 --undo
| Action | Existing Projects with 0.1.0 in Cargo.lock |
New Projects Running cargo add / cargo update |
|---|---|---|
Normal Version (0.1.0) |
Downloads and builds 0.1.0 normally |
Can select 0.1.0 |
Yanked Version (cargo yank --version 0.1.0) |
Continues to download and build 0.1.0 (Cargo.lock is never broken!) |
Never selects 0.1.0 (resolver skips yanked versions) |
pub fn encode_u64_leb128(mut value: u64, out: &mut [u8; 10]) -> &[u8] {
let mut i = 0;
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
out[i] = byte;
i += 1;
if value == 0 {
break;
}
}
&out[..i]
}
fn main() {
let mut buf = [0u8; 10];
let encoded = encode_u64_leb128(300, &mut buf);
println!("300 encoded as LEB128: {encoded:02x?}");
}
300 encoded as LEB128: [ac, 02]