bytemuck
A zero-cost, no_std Rust crate for safely casting between plain data types and reinterpreting slices as bytes.
Repository Health
Technical Analysis
bytemuck lets Rust code perform “bit cast” operations between data types safely, without reaching for unsafe transmutes at every call site. A family of marker traits (Pod, Zeroable, NoUninit, AnyBitPattern, CheckedBitPattern, TransparentWrapper) express exactly which safety guarantees a type upholds, and the crate’s cast/cast_slice functions use those guarantees to reinterpret values and slices as different types without copying.
It is especially popular in Rust’s graphics and game-engine community, where cast_slice is the standard way to turn a slice of vertex/color structs into the raw &[u8] a GPU buffer upload expects. The crate is #![no_std], has effectively no runtime cost, and ships an optional derive feature so consumers can implement the marker traits on their own types with a single attribute instead of writing unsafe impls by hand.
What You Get
- Five core casting functions —
cast,cast_ref,cast_mut,cast_slice,cast_slice_mut— covering owned values, references, and slices - A layered trait system (
Zeroable,Pod,NoUninit,AnyBitPattern,CheckedBitPattern,TransparentWrapper,Contiguous) so you only claim the safety guarantees your type actually has - Fallible
try_cast*variants that return aPodCastErrorinstead of panicking on alignment or size mismatches - An optional
derivefeature (via the siblingbytemuck_deriveproc-macro crate) that implements the marker traits for your structs and enums with compile-time validation - Opt-in feature flags for
alloc/stdintegration, SIMD types (wasm, aarch64, avx512), const-context casting, and more, so the no_std/MSRV-1.34 core stays minimal by default
Common Use Cases
- Casting a slice of vertex or color structs into
&[u8]to upload directly to a GPU buffer - Reinterpreting network or file bytes as a fixed-layout struct without manual field-by-field parsing
- Zero-copy conversion between numeric types and their raw byte representation (e.g.
f32to/from bits) - Deriving
Pod/Zeroableon#[repr(C)]structs so they can flow through APIs that require plain-old-data types
Under The Hood
Architecture — bytemuck splits its public surface across one file per marker trait: pod.rs defines Pod (the strongest guarantee, valid for any bit pattern and safe under mutable aliasing), zeroable.rs defines the weaker Zeroable, no_uninit.rs and anybitpattern.rs define NoUninit/AnyBitPattern for types that only support a subset of casts, checked.rs layers CheckedBitPattern on top with a runtime validity check (used for C-style enums and similar), transparent.rs defines TransparentWrapper for repr(transparent) newtypes, and contiguous.rs defines Contiguous for enum-to-integer conversions. lib.rs re-exports all of these and implements the actual cast/cast_ref/cast_mut/cast_slice/cast_slice_mut functions on top of core::mem::transmute, guarded by size/alignment assertions in internal.rs. A separate proc-macro crate (derive/, published as bytemuck_derive) implements the #[derive(...)] macros consumed via the optional derive feature, keeping the compile-time-only proc-macro dependency out of the core crate’s default build.
Tech Stack — the core crate is #![no_std] with zero required dependencies, targeting an MSRV of Rust 1.34 for the default feature set. Cargo.toml gates over 30 additional features (derive, extern_crate_alloc/std, zeroable_maybe_uninit, min_const_generics, wasm_simd, aarch64_simd, avx512_simd, const_zeroed, must_cast, and more), each documented with the specific MSRV it requires, so users opt into exactly the surface (and compiler-version cost) they need. The optional derive feature pulls in bytemuck_derive (syn 2, quote, proc-macro2) as a separate proc-macro crate, and nightly_portable_simd optionally depends on rustversion for nightly-only std::simd support.
Code Quality — the tests/ directory has nine dedicated integration test files (cast_slice_tests.rs, checked_tests.rs, array_tests.rs, offset_of_tests.rs, std_tests.rs, transparent.rs, wrapper_forgets.rs, doc_tests.rs, derive.rs) exercising both success and failure paths, including explicit PodCastError variants for misalignment and slop-byte cases. Every unsafe trait (Pod, Zeroable, NoUninit, AnyBitPattern, CheckedBitPattern, TransparentWrapper) carries an extensive doc comment enumerating the exact safety invariants implementers must uphold, and CI is wired through .github/workflows/rust.yml. rustfmt.toml enforces consistent formatting, and the crate’s naming convention (cast_, try_cast_, must_cast_ prefixes) makes fallibility and compile-time-checked variants discoverable from the function name alone.
API Design — the five core functions (cast, cast_ref, cast_mut, cast_slice, cast_slice_mut) map directly onto Rust’s five basic ownership/borrowing forms (T, &T, &mut T, &[T], &mut [T]), which lib.rs’s module-level doc comment states explicitly as the mental model for the whole crate. The derive feature removes almost all boilerplate for common cases — a single #[derive(Pod, Zeroable)] replaces a hand-written unsafe impl block. The trade-off is discoverability: the crate exposes more than 30 Cargo features with subtly different MSRV and safety implications, so newcomers need to read the feature-flag section of lib.rs’s docs closely to pick the right combination for their use case.