bytemuck #
The bytemuck
crate is a Rust library that provides a safe and zero-cost way to transmute data between different types, which can be useful when working with low-level systems programming or interacting with libraries that expect data in a specific layout.
NOTE: Some of these examples require the
derive
cargo feature!
Casting Basics #
The crate offers five basic casting functions:
cast
: For casting values of typeT
.cast_ref
: For casting references&T
.cast_mut
: For casting mutable references&mut T
.cast_slice
: For casting slices&[T]
.cast_slice_mut
: For casting mutable slices&mut [T]
.
Using cast
to transmute a u32
to an f32
#
fn casting_example() {
use bytemuck::cast;
let x: u32 = 0x3f800000;
let y: f32 = cast(x); // y == 1.0
assert_eq!(y, 1.0);
println!("x: {x} y: {y}");
}
Casting a reference to a different type #
fn cast_ref_example() {
use bytemuck::{ cast_ref, Pod, Zeroable };
#[derive(Copy, Clone, Pod, Zeroable)]
#[repr(C)]
struct Point {
x: f32,
y: f32,
}
let point = Point { x: 1.0, y: 2.0 };
let point_ref: &Point = &point;
let raw_bytes: &[u8; std::mem::size_of::<Point>()] = cast_ref(point_ref);
assert_eq!(raw_bytes, &[0, 0, 128, 63, 0, 0, 0, 64]);
println!("Raw bytes: {raw_bytes:?}");
}
Casting a mutable slice #
fn cast_slice_mut_example() {
use bytemuck::{ cast_slice_mut, Pod, Zeroable };
#[derive(Copy, Clone, Pod, Zeroable, Debug, PartialEq)]
#[repr(C)]
struct Color {
r: u8,
g: u8,
b: u8,
a: u8,
}
let mut colors = [
Color { r: 255, g: 0, b: 0, a: 255 },
Color { r: 0, g: 255, b: 0, a: 255 },
];
println!("Original colors: {colors:?}");
let color_slice: &mut [Color] = &mut colors;
let bytes_slice: &mut [u8] = cast_slice_mut(color_slice);
// Modify the color values through the byte slice
bytes_slice[0] = 128; // Change the red component of the first color
assert_eq!(colors, [
Color { r: 128, g: 0, b: 0, a: 255 },
Color { r: 0, g: 255, b: 0, a: 255 },
]);
println!("Modified colors: {colors:?}");
}
Using try_cast
for fallible casting
#
fn try_cast_example() {
use bytemuck::{ try_cast, Pod, Zeroable };
#[derive(Copy, Clone, Pod, Zeroable, Debug)]
#[repr(C)]
struct Vertex {
position: [f32; 3],
tex_coords: [f32; 2],
}
let vertex_data = [0.0f32; 5]; // Some vertex data
match try_cast::<[f32; 5], Vertex>(vertex_data) {
Ok(vertex) => println!("Vertex: {vertex:?}"),
Err(e) => eprintln!("Failed to cast: {e:?}"),
}
}