pub struct Ref<B, T: ?Sized> { /* private fields */ }Expand description
A typed reference derived from a byte slice.
A Ref<B, T> is a reference to a T which is stored in a byte slice, B.
Unlike a native reference (&T or &mut T), Ref<B, T> has the same
mutability as the byte slice it was constructed from (B).
§Examples
Ref can be used to treat a sequence of bytes as a structured type, and
to read and write the fields of that type as if the byte slice reference
were simply a reference to that type.
use zerocopy::*;
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)]
#[repr(C)]
struct UdpHeader {
src_port: [u8; 2],
dst_port: [u8; 2],
length: [u8; 2],
checksum: [u8; 2],
}
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)]
#[repr(C, packed)]
struct UdpPacket {
header: UdpHeader,
body: [u8],
}
impl UdpPacket {
pub fn parse<B: ByteSlice>(bytes: B) -> Option<Ref<B, UdpPacket>> {
Ref::from_bytes(bytes).ok()
}
}Implementations§
Source§impl<B, T> Ref<B, T>
impl<B, T> Ref<B, T>
Sourcepub fn from_bytes(source: B) -> Result<Ref<B, T>, CastError<B, T>>
pub fn from_bytes(source: B) -> Result<Ref<B, T>, CastError<B, T>>
Constructs a Ref from a byte slice.
If the length of source is not a valid size of T, or
if source is not appropriately aligned for T, this returns Err. If
T: Unaligned, you can infallibly discard the alignment
error.
T may be a sized type, a slice, or a slice DST.
§Compile-Time Assertions
This method cannot yet be used on unsized types whose dynamically-sized component is zero-sized. Attempting to use this method on such types results in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: u16,
trailing_dst: [()],
}
let _ = Ref::<_, ZSTy>::from_bytes(&b"UU"[..]); // ⚠ Compile Error!§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Sized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_bytes_static_size(source: &[u8]) -> Option<Ref<&[u8], format::LocoPacket>> {
Ref::from_bytes(source).ok()
}
Assembly
bench_ref_type_from_bytes_static_size:
mov rax, rdi
cmp rdx, 6
setne cl
or cl, sil
test cl, 1
je .LBB5_2
xor esi, esi
mov qword ptr [rax], rsi
ret
.LBB5_2:
mov qword ptr [rax + 8], 6
mov qword ptr [rax + 16], 0
mov qword ptr [rax], rsi
ret
Machine Code Analysis
Iterations: 100
Instructions: 1300
Total Cycles: 404
Total uOps: 1300
Dispatch Width: 4
uOps Per Cycle: 3.22
IPC: 3.22
Block RThroughput: 4.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.33 cmp rdx, 6
1 1 0.50 setne cl
1 1 0.33 or cl, sil
1 1 0.33 test cl, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor esi, esi
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
1 1 1.00 * mov qword ptr [rax + 8], 6
1 1 1.00 * mov qword ptr [rax + 16], 0
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 2.55 2.34 4.00 3.11 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.81 0.18 - 0.01 - - mov rax, rdi
- - 0.56 0.43 - 0.01 - - cmp rdx, 6
- - 1.00 - - - - - setne cl
- - - 0.99 - 0.01 - - or cl, sil
- - 0.18 0.74 - 0.08 - - test cl, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor esi, esi
- - - - 1.00 - - 1.00 mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
- - - - 1.00 - 1.00 - mov qword ptr [rax + 8], 6
- - - - 1.00 - - 1.00 mov qword ptr [rax + 16], 0
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_bytes_dynamic_size(source: &[u8]) -> Option<Ref<&[u8], format::LocoPacket>> {
Ref::from_bytes(source).ok()
}
Assembly
bench_ref_type_from_bytes_dynamic_size:
mov rax, rdi
cmp rdx, 4
setae cl
mov edi, edx
or edi, esi
test dil, 1
sete dil
and dil, cl
cmp dil, 1
je .LBB5_2
xor esi, esi
mov qword ptr [rax], rsi
ret
.LBB5_2:
lea rcx, [rdx - 4]
shr rcx
mov qword ptr [rax + 8], rdx
mov qword ptr [rax + 16], rcx
mov qword ptr [rax], rsi
ret
Machine Code Analysis
Iterations: 100
Instructions: 1900
Total Cycles: 482
Total uOps: 1900
Dispatch Width: 4
uOps Per Cycle: 3.94
IPC: 3.94
Block RThroughput: 4.8
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.33 cmp rdx, 4
1 1 0.50 setae cl
1 1 0.33 mov edi, edx
1 1 0.33 or edi, esi
1 1 0.33 test dil, 1
1 1 0.50 sete dil
1 1 0.33 and dil, cl
1 1 0.33 cmp dil, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor esi, esi
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
1 1 0.50 lea rcx, [rdx - 4]
1 1 0.50 shr rcx
1 1 1.00 * mov qword ptr [rax + 8], rdx
1 1 1.00 * mov qword ptr [rax + 16], rcx
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 4.66 4.66 4.00 4.68 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.40 0.43 - 0.17 - - mov rax, rdi
- - 0.13 0.83 - 0.04 - - cmp rdx, 4
- - 0.67 - - 0.33 - - setae cl
- - 0.05 0.79 - 0.16 - - mov edi, edx
- - 0.36 0.52 - 0.12 - - or edi, esi
- - 0.39 0.52 - 0.09 - - test dil, 1
- - 0.98 - - 0.02 - - sete dil
- - 0.42 0.49 - 0.09 - - and dil, cl
- - 0.43 0.41 - 0.16 - - cmp dil, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor esi, esi
- - - - 1.00 - - 1.00 mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
- - 0.33 0.67 - - - - lea rcx, [rdx - 4]
- - 0.50 - - 0.50 - - shr rcx
- - - - 1.00 - 1.00 - mov qword ptr [rax + 8], rdx
- - - - 1.00 - - 1.00 mov qword ptr [rax + 16], rcx
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_bytes_dynamic_padding(
source: &[u8],
) -> Option<Ref<&[u8], format::LocoPacket>> {
Ref::from_bytes(source).ok()
}
Assembly
bench_ref_type_from_bytes_dynamic_padding:
cmp rdx, 12
setae al
mov ecx, edx
or ecx, esi
test cl, 3
sete cl
and cl, al
cmp cl, 1
je .LBB5_2
xor esi, esi
mov qword ptr [rdi], rsi
mov rax, rdi
ret
.LBB5_2:
lea rax, [rdx - 9]
movabs rcx, -6148914691236517205
mov r8, rdx
mul rcx
shr rdx
mov qword ptr [rdi + 8], r8
mov qword ptr [rdi + 16], rdx
mov qword ptr [rdi], rsi
mov rax, rdi
ret
Machine Code Analysis
Iterations: 100
Instructions: 2300
Total Cycles: 909
Total uOps: 2400
Dispatch Width: 4
uOps Per Cycle: 2.64
IPC: 2.53
Block RThroughput: 6.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 cmp rdx, 12
1 1 0.50 setae al
1 1 0.33 mov ecx, edx
1 1 0.33 or ecx, esi
1 1 0.33 test cl, 3
1 1 0.50 sete cl
1 1 0.33 and cl, al
1 1 0.33 cmp cl, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor esi, esi
1 1 1.00 * mov qword ptr [rdi], rsi
1 1 0.33 mov rax, rdi
1 1 1.00 U ret
1 1 0.50 lea rax, [rdx - 9]
1 1 0.33 movabs rcx, -6148914691236517205
1 1 0.33 mov r8, rdx
2 4 1.00 mul rcx
1 1 0.50 shr rdx
1 1 1.00 * mov qword ptr [rdi + 8], r8
1 1 1.00 * mov qword ptr [rdi + 16], rdx
1 1 1.00 * mov qword ptr [rdi], rsi
1 1 0.33 mov rax, rdi
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.49 5.99 4.00 6.52 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - 0.99 - 0.01 - - cmp rdx, 12
- - 0.53 - - 0.47 - - setae al
- - 0.52 0.01 - 0.47 - - mov ecx, edx
- - - 0.99 - 0.01 - - or ecx, esi
- - - 0.51 - 0.49 - - test cl, 3
- - 0.52 - - 0.48 - - sete cl
- - 0.47 0.48 - 0.05 - - and cl, al
- - 0.48 0.48 - 0.04 - - cmp cl, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor esi, esi
- - - - 1.00 - - 1.00 mov qword ptr [rdi], rsi
- - 0.03 0.48 - 0.49 - - mov rax, rdi
- - - - - 1.00 - - ret
- - 0.97 0.03 - - - - lea rax, [rdx - 9]
- - 0.49 0.51 - - - - movabs rcx, -6148914691236517205
- - 0.47 0.01 - 0.52 - - mov r8, rdx
- - 1.00 1.00 - - - - mul rcx
- - 1.00 - - - - - shr rdx
- - - - 1.00 - 1.00 - mov qword ptr [rdi + 8], r8
- - - - 1.00 - - 1.00 mov qword ptr [rdi + 16], rdx
- - - - 1.00 - 1.00 - mov qword ptr [rdi], rsi
- - 0.01 0.50 - 0.49 - - mov rax, rdi
- - - - - 1.00 - - ret
Source§impl<B, T> Ref<B, T>
impl<B, T> Ref<B, T>
Sourcepub fn from_prefix(source: B) -> Result<(Ref<B, T>, B), CastError<B, T>>
pub fn from_prefix(source: B) -> Result<(Ref<B, T>, B), CastError<B, T>>
Constructs a Ref from the prefix of a byte slice.
This method computes the largest possible size of T that
can fit in the leading bytes of source, then attempts to return both a
Ref to those bytes, and a reference to the remaining bytes. If there
are insufficient bytes, or if source is not appropriately aligned,
this returns Err. If T: Unaligned, you can
infallibly discard the alignment error.
T may be a sized type, a slice, or a slice DST.
§Compile-Time Assertions
This method cannot yet be used on unsized types whose dynamically-sized component is zero-sized. Attempting to use this method on such types results in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: u16,
trailing_dst: [()],
}
let _ = Ref::<_, ZSTy>::from_prefix(&b"UU"[..]); // ⚠ Compile Error!§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Sized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_prefix_static_size(source: &[u8]) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_prefix(source) {
Ok((packet, _rest)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_prefix_static_size:
mov rax, rdi
cmp rdx, 6
setb cl
or cl, sil
test cl, 1
je .LBB5_2
xor esi, esi
mov qword ptr [rax], rsi
ret
.LBB5_2:
mov qword ptr [rax + 8], 6
mov qword ptr [rax + 16], 0
mov qword ptr [rax], rsi
ret
Machine Code Analysis
Iterations: 100
Instructions: 1300
Total Cycles: 404
Total uOps: 1300
Dispatch Width: 4
uOps Per Cycle: 3.22
IPC: 3.22
Block RThroughput: 4.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.33 cmp rdx, 6
1 1 0.50 setb cl
1 1 0.33 or cl, sil
1 1 0.33 test cl, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor esi, esi
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
1 1 1.00 * mov qword ptr [rax + 8], 6
1 1 1.00 * mov qword ptr [rax + 16], 0
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 2.55 2.34 4.00 3.11 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.81 0.18 - 0.01 - - mov rax, rdi
- - 0.56 0.43 - 0.01 - - cmp rdx, 6
- - 1.00 - - - - - setb cl
- - - 0.99 - 0.01 - - or cl, sil
- - 0.18 0.74 - 0.08 - - test cl, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor esi, esi
- - - - 1.00 - - 1.00 mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
- - - - 1.00 - 1.00 - mov qword ptr [rax + 8], 6
- - - - 1.00 - - 1.00 mov qword ptr [rax + 16], 0
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_prefix_dynamic_size(
source: &[u8],
) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_prefix(source) {
Ok((packet, _rest)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_prefix_dynamic_size:
mov rax, rdi
cmp rdx, 4
setb cl
or cl, sil
test cl, 1
je .LBB5_2
xor esi, esi
mov qword ptr [rax], rsi
ret
.LBB5_2:
movabs rcx, 9223372036854775806
and rcx, rdx
add rdx, -4
shr rdx
mov qword ptr [rax + 8], rcx
mov qword ptr [rax + 16], rdx
mov qword ptr [rax], rsi
ret
Machine Code Analysis
Iterations: 100
Instructions: 1700
Total Cycles: 431
Total uOps: 1700
Dispatch Width: 4
uOps Per Cycle: 3.94
IPC: 3.94
Block RThroughput: 4.3
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.33 cmp rdx, 4
1 1 0.50 setb cl
1 1 0.33 or cl, sil
1 1 0.33 test cl, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor esi, esi
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
1 1 0.33 movabs rcx, 9223372036854775806
1 1 0.33 and rcx, rdx
1 1 0.33 add rdx, -4
1 1 0.50 shr rdx
1 1 1.00 * mov qword ptr [rax + 8], rcx
1 1 1.00 * mov qword ptr [rax + 16], rdx
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 3.99 3.75 4.00 4.26 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - 0.99 - 0.01 - - mov rax, rdi
- - 0.74 0.26 - - - - cmp rdx, 4
- - 1.00 - - - - - setb cl
- - 0.25 0.74 - 0.01 - - or cl, sil
- - 0.01 0.97 - 0.02 - - test cl, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor esi, esi
- - - - 1.00 - - 1.00 mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
- - 0.48 0.52 - - - - movabs rcx, 9223372036854775806
- - 0.73 0.27 - - - - and rcx, rdx
- - 0.02 - - 0.98 - - add rdx, -4
- - 0.76 - - 0.24 - - shr rdx
- - - - 1.00 - 1.00 - mov qword ptr [rax + 8], rcx
- - - - 1.00 - - 1.00 mov qword ptr [rax + 16], rdx
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_prefix_dynamic_padding(
source: &[u8],
) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_prefix(source) {
Ok((packet, _rest)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_prefix_dynamic_padding:
test sil, 3
sete al
cmp rdx, 12
setae cl
and cl, al
cmp cl, 1
je .LBB5_2
xor esi, esi
mov qword ptr [rdi], rsi
mov rax, rdi
ret
.LBB5_2:
movabs rcx, 9223372036854775804
and rcx, rdx
or rdx, 3
add rdx, -12
movabs r8, -6148914691236517205
mov rax, rdx
mul r8
shr rdx
mov qword ptr [rdi + 8], rcx
mov qword ptr [rdi + 16], rdx
mov qword ptr [rdi], rsi
mov rax, rdi
ret
Machine Code Analysis
Iterations: 100
Instructions: 2400
Total Cycles: 907
Total uOps: 2500
Dispatch Width: 4
uOps Per Cycle: 2.76
IPC: 2.65
Block RThroughput: 6.3
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 test sil, 3
1 1 0.50 sete al
1 1 0.33 cmp rdx, 12
1 1 0.50 setae cl
1 1 0.33 and cl, al
1 1 0.33 cmp cl, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor esi, esi
1 1 1.00 * mov qword ptr [rdi], rsi
1 1 0.33 mov rax, rdi
1 1 1.00 U ret
1 1 0.33 movabs rcx, 9223372036854775804
1 1 0.33 and rcx, rdx
1 1 0.33 or rdx, 3
1 1 0.33 add rdx, -12
1 1 0.33 movabs r8, -6148914691236517205
1 1 0.33 mov rax, rdx
2 4 1.00 mul r8
1 1 0.50 shr rdx
1 1 1.00 * mov qword ptr [rdi + 8], rcx
1 1 1.00 * mov qword ptr [rdi + 16], rdx
1 1 1.00 * mov qword ptr [rdi], rsi
1 1 0.33 mov rax, rdi
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.96 6.07 4.00 6.97 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.92 0.07 - 0.01 - - test sil, 3
- - 0.98 - - 0.02 - - sete al
- - 0.03 0.97 - - - - cmp rdx, 12
- - 0.99 - - 0.01 - - setae cl
- - 0.03 0.94 - 0.03 - - and cl, al
- - 0.06 0.94 - - - - cmp cl, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor esi, esi
- - - - 1.00 - - 1.00 mov qword ptr [rdi], rsi
- - 0.01 0.05 - 0.94 - - mov rax, rdi
- - - - - 1.00 - - ret
- - 0.92 0.08 - - - - movabs rcx, 9223372036854775804
- - 0.96 0.01 - 0.03 - - and rcx, rdx
- - - 0.03 - 0.97 - - or rdx, 3
- - 0.01 0.96 - 0.03 - - add rdx, -12
- - 0.03 0.06 - 0.91 - - movabs r8, -6148914691236517205
- - 0.94 0.03 - 0.03 - - mov rax, rdx
- - 1.00 1.00 - - - - mul r8
- - 0.05 - - 0.95 - - shr rdx
- - - - 1.00 - 1.00 - mov qword ptr [rdi + 8], rcx
- - - - 1.00 - - 1.00 mov qword ptr [rdi + 16], rdx
- - - - 1.00 - 1.00 - mov qword ptr [rdi], rsi
- - 0.03 0.93 - 0.04 - - mov rax, rdi
- - - - - 1.00 - - ret
Sourcepub fn from_suffix(source: B) -> Result<(B, Ref<B, T>), CastError<B, T>>
pub fn from_suffix(source: B) -> Result<(B, Ref<B, T>), CastError<B, T>>
Constructs a Ref from the suffix of a byte slice.
This method computes the largest possible size of T that
can fit in the trailing bytes of source, then attempts to return both
a Ref to those bytes, and a reference to the preceding bytes. If there
are insufficient bytes, or if that suffix of source is not
appropriately aligned, this returns Err. If T: Unaligned, you can infallibly discard the alignment
error.
T may be a sized type, a slice, or a slice DST.
§Compile-Time Assertions
This method cannot yet be used on unsized types whose dynamically-sized component is zero-sized. Attempting to use this method on such types results in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: u16,
trailing_dst: [()],
}
let _ = Ref::<_, ZSTy>::from_suffix(&b"UU"[..]); // ⚠ Compile Error!§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Sized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_suffix_static_size(source: &[u8]) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_suffix(source) {
Ok((_rest, packet)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_suffix_static_size:
mov rax, rdi
lea ecx, [rdx + rsi]
cmp rdx, 6
setb dil
or dil, cl
test dil, 1
je .LBB5_2
xor ecx, ecx
mov qword ptr [rax], rcx
ret
.LBB5_2:
lea rcx, [rsi + rdx]
add rcx, -6
mov qword ptr [rax + 8], 6
mov qword ptr [rax + 16], 0
mov qword ptr [rax], rcx
ret
Machine Code Analysis
Iterations: 100
Instructions: 1600
Total Cycles: 405
Total uOps: 1600
Dispatch Width: 4
uOps Per Cycle: 3.95
IPC: 3.95
Block RThroughput: 4.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.50 lea ecx, [rdx + rsi]
1 1 0.33 cmp rdx, 6
1 1 0.50 setb dil
1 1 0.33 or dil, cl
1 1 0.33 test dil, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor ecx, ecx
1 1 1.00 * mov qword ptr [rax], rcx
1 1 1.00 U ret
1 1 0.50 lea rcx, [rsi + rdx]
1 1 0.33 add rcx, -6
1 1 1.00 * mov qword ptr [rax + 8], 6
1 1 1.00 * mov qword ptr [rax + 16], 0
1 1 1.00 * mov qword ptr [rax], rcx
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 3.66 3.66 4.00 3.68 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.66 0.33 - 0.01 - - mov rax, rdi
- - 0.33 0.67 - - - - lea ecx, [rdx + rsi]
- - 0.34 0.33 - 0.33 - - cmp rdx, 6
- - 0.99 - - 0.01 - - setb dil
- - 0.33 0.67 - - - - or dil, cl
- - - 1.00 - - - - test dil, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor ecx, ecx
- - - - 1.00 - - 1.00 mov qword ptr [rax], rcx
- - - - - 1.00 - - ret
- - 0.34 0.66 - - - - lea rcx, [rsi + rdx]
- - 0.67 - - 0.33 - - add rcx, -6
- - - - 1.00 - 1.00 - mov qword ptr [rax + 8], 6
- - - - 1.00 - - 1.00 mov qword ptr [rax + 16], 0
- - - - 1.00 - 1.00 - mov qword ptr [rax], rcx
- - - - - 1.00 - - ret
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_suffix_dynamic_size(
source: &[u8],
) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_suffix(source) {
Ok((_rest, packet)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_suffix_dynamic_size:
mov rax, rdi
lea ecx, [rdx + rsi]
cmp rdx, 4
setb dil
or dil, cl
test dil, 1
je .LBB5_2
xor esi, esi
mov qword ptr [rax], rsi
ret
.LBB5_2:
lea rcx, [rdx - 4]
shr rcx
mov edi, edx
and edi, 1
movabs r8, 9223372036854775806
and r8, rdx
add rsi, rdi
mov qword ptr [rax + 8], r8
mov qword ptr [rax + 16], rcx
mov qword ptr [rax], rsi
ret
Machine Code Analysis
Iterations: 100
Instructions: 2100
Total Cycles: 540
Total uOps: 2100
Dispatch Width: 4
uOps Per Cycle: 3.89
IPC: 3.89
Block RThroughput: 5.3
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.50 lea ecx, [rdx + rsi]
1 1 0.33 cmp rdx, 4
1 1 0.50 setb dil
1 1 0.33 or dil, cl
1 1 0.33 test dil, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor esi, esi
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
1 1 0.50 lea rcx, [rdx - 4]
1 1 0.50 shr rcx
1 1 0.33 mov edi, edx
1 1 0.33 and edi, 1
1 1 0.33 movabs r8, 9223372036854775806
1 1 0.33 and r8, rdx
1 1 0.33 add rsi, rdi
1 1 1.00 * mov qword ptr [rax + 8], r8
1 1 1.00 * mov qword ptr [rax + 16], rcx
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 5.32 5.33 4.00 5.35 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.33 0.66 - 0.01 - - mov rax, rdi
- - 0.99 0.01 - - - - lea ecx, [rdx + rsi]
- - 0.01 0.98 - 0.01 - - cmp rdx, 4
- - 0.99 - - 0.01 - - setb dil
- - - 1.00 - - - - or dil, cl
- - - 1.00 - - - - test dil, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor esi, esi
- - - - 1.00 - - 1.00 mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
- - 0.65 0.35 - - - - lea rcx, [rdx - 4]
- - 0.68 - - 0.32 - - shr rcx
- - - 0.64 - 0.36 - - mov edi, edx
- - 0.66 0.01 - 0.33 - - and edi, 1
- - 0.34 - - 0.66 - - movabs r8, 9223372036854775806
- - 0.32 0.68 - - - - and r8, rdx
- - 0.35 - - 0.65 - - add rsi, rdi
- - - - 1.00 - 1.00 - mov qword ptr [rax + 8], r8
- - - - 1.00 - - 1.00 mov qword ptr [rax + 16], rcx
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - - 1.00 - - ret
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_suffix_dynamic_padding(
source: &[u8],
) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_suffix(source) {
Ok((_rest, packet)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_suffix_dynamic_padding:
lea eax, [rdx + rsi]
test al, 3
sete al
cmp rdx, 12
setae cl
and cl, al
cmp cl, 1
je .LBB5_2
xor esi, esi
mov qword ptr [rdi], rsi
mov rax, rdi
ret
.LBB5_2:
mov rax, rdx
or rax, 3
add rax, -12
movabs rcx, -6148914691236517205
mov r8, rdx
mul rcx
shr rdx
mov eax, r8d
and eax, 3
movabs rcx, 9223372036854775804
and rcx, r8
add rsi, rax
mov qword ptr [rdi + 8], rcx
mov qword ptr [rdi + 16], rdx
mov qword ptr [rdi], rsi
mov rax, rdi
ret
Machine Code Analysis
Iterations: 100
Instructions: 2900
Total Cycles: 942
Total uOps: 3000
Dispatch Width: 4
uOps Per Cycle: 3.18
IPC: 3.08
Block RThroughput: 7.5
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.50 lea eax, [rdx + rsi]
1 1 0.33 test al, 3
1 1 0.50 sete al
1 1 0.33 cmp rdx, 12
1 1 0.50 setae cl
1 1 0.33 and cl, al
1 1 0.33 cmp cl, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor esi, esi
1 1 1.00 * mov qword ptr [rdi], rsi
1 1 0.33 mov rax, rdi
1 1 1.00 U ret
1 1 0.33 mov rax, rdx
1 1 0.33 or rax, 3
1 1 0.33 add rax, -12
1 1 0.33 movabs rcx, -6148914691236517205
1 1 0.33 mov r8, rdx
2 4 1.00 mul rcx
1 1 0.50 shr rdx
1 1 0.33 mov eax, r8d
1 1 0.33 and eax, 3
1 1 0.33 movabs rcx, 9223372036854775804
1 1 0.33 and rcx, r8
1 1 0.33 add rsi, rax
1 1 1.00 * mov qword ptr [rdi + 8], rcx
1 1 1.00 * mov qword ptr [rdi + 16], rdx
1 1 1.00 * mov qword ptr [rdi], rsi
1 1 0.33 mov rax, rdi
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 8.34 8.01 4.00 8.65 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.36 0.64 - - - - lea eax, [rdx + rsi]
- - 0.32 0.36 - 0.32 - - test al, 3
- - 0.69 - - 0.31 - - sete al
- - 0.32 0.04 - 0.64 - - cmp rdx, 12
- - 0.68 - - 0.32 - - setae cl
- - 0.31 0.37 - 0.32 - - and cl, al
- - 0.31 0.37 - 0.32 - - cmp cl, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor esi, esi
- - - - 1.00 - - 1.00 mov qword ptr [rdi], rsi
- - 0.33 0.36 - 0.31 - - mov rax, rdi
- - - - - 1.00 - - ret
- - 0.32 0.32 - 0.36 - - mov rax, rdx
- - 0.01 0.63 - 0.36 - - or rax, 3
- - - 0.68 - 0.32 - - add rax, -12
- - 0.34 0.63 - 0.03 - - movabs rcx, -6148914691236517205
- - 0.32 0.32 - 0.36 - - mov r8, rdx
- - 1.00 1.00 - - - - mul rcx
- - 0.69 - - 0.31 - - shr rdx
- - 0.37 0.32 - 0.31 - - mov eax, r8d
- - 0.35 0.33 - 0.32 - - and eax, 3
- - 0.63 0.35 - 0.02 - - movabs rcx, 9223372036854775804
- - 0.32 0.32 - 0.36 - - and rcx, r8
- - 0.33 0.35 - 0.32 - - add rsi, rax
- - - - 1.00 - 1.00 - mov qword ptr [rdi + 8], rcx
- - - - 1.00 - - 1.00 mov qword ptr [rdi + 16], rdx
- - - - 1.00 - 1.00 - mov qword ptr [rdi], rsi
- - 0.34 0.62 - 0.04 - - mov rax, rdi
- - - - - 1.00 - - ret
Source§impl<B, T> Ref<B, T>
impl<B, T> Ref<B, T>
Sourcepub fn from_bytes_with_elems(
source: B,
count: usize,
) -> Result<Ref<B, T>, CastError<B, T>>
pub fn from_bytes_with_elems( source: B, count: usize, ) -> Result<Ref<B, T>, CastError<B, T>>
Constructs a Ref from the given bytes with DST length equal to count
without copying.
This method attempts to return a Ref to the prefix of source
interpreted as a T with count trailing elements, and a reference to
the remaining bytes. If the length of source is not equal to the size
of Self with count elements, or if source is not appropriately
aligned, this returns Err. If T: Unaligned, you can
infallibly discard the alignment error.
§Compile-Time Assertions
This method cannot yet be used on unsized types whose dynamically-sized component is zero-sized. Attempting to use this method on such types results in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: u16,
trailing_dst: [()],
}
let _ = Ref::<_, ZSTy>::from_bytes_with_elems(&b"UU"[..], 42); // ⚠ Compile Error!§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_bytes_with_elems_dynamic_size(
source: &[u8],
count: usize,
) -> Option<Ref<&[u8], format::LocoPacket>> {
Ref::from_bytes_with_elems(source, count).ok()
}
Assembly
bench_ref_type_from_bytes_with_elems_dynamic_size:
mov rax, rdi
lea rdi, [rcx + rcx]
test rcx, rcx
setns r8b
cmp rdi, -5
setb dil
and dil, r8b
lea r8, [2*rcx + 4]
cmp rdx, r8
sete r8b
movabs r9, 4611686018427387902
cmp rcx, r9
setb r9b
and r9b, r8b
and r9b, dil
cmp r9b, 1
je .LBB5_1
.LBB5_2:
mov qword ptr [rax], 0
ret
.LBB5_1:
test sil, 1
jne .LBB5_2
mov qword ptr [rax], rsi
mov qword ptr [rax + 8], rdx
mov qword ptr [rax + 16], rcx
ret
Machine Code Analysis
Iterations: 100
Instructions: 2500
Total Cycles: 706
Total uOps: 2500
Dispatch Width: 4
uOps Per Cycle: 3.54
IPC: 3.54
Block RThroughput: 6.3
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.50 lea rdi, [rcx + rcx]
1 1 0.33 test rcx, rcx
1 1 0.50 setns r8b
1 1 0.33 cmp rdi, -5
1 1 0.50 setb dil
1 1 0.33 and dil, r8b
1 1 0.50 lea r8, [2*rcx + 4]
1 1 0.33 cmp rdx, r8
1 1 0.50 sete r8b
1 1 0.33 movabs r9, 4611686018427387902
1 1 0.33 cmp rcx, r9
1 1 0.50 setb r9b
1 1 0.33 and r9b, r8b
1 1 0.33 and r9b, dil
1 1 0.33 cmp r9b, 1
1 1 1.00 je .LBB5_1
1 1 1.00 * mov qword ptr [rax], 0
1 1 1.00 U ret
1 1 0.33 test sil, 1
1 1 1.00 jne .LBB5_2
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 * mov qword ptr [rax + 8], rdx
1 1 1.00 * mov qword ptr [rax + 16], rcx
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.99 7.00 4.00 7.01 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.08 - - 0.92 - - mov rax, rdi
- - 0.99 0.01 - - - - lea rdi, [rcx + rcx]
- - 0.92 0.01 - 0.07 - - test rcx, rcx
- - 0.99 - - 0.01 - - setns r8b
- - 0.01 0.01 - 0.98 - - cmp rdi, -5
- - 0.98 - - 0.02 - - setb dil
- - - 0.99 - 0.01 - - and dil, r8b
- - 0.01 0.99 - - - - lea r8, [2*rcx + 4]
- - 0.99 0.01 - - - - cmp rdx, r8
- - 1.00 - - - - - sete r8b
- - 0.01 - - 0.99 - - movabs r9, 4611686018427387902
- - - 1.00 - - - - cmp rcx, r9
- - 0.99 - - 0.01 - - setb r9b
- - 0.01 0.99 - - - - and r9b, r8b
- - 0.01 0.99 - - - - and r9b, dil
- - - 1.00 - - - - cmp r9b, 1
- - - - - 1.00 - - je .LBB5_1
- - - - 1.00 - - 1.00 mov qword ptr [rax], 0
- - - - - 1.00 - - ret
- - - 1.00 - - - - test sil, 1
- - - - - 1.00 - - jne .LBB5_2
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - 1.00 - - 1.00 mov qword ptr [rax + 8], rdx
- - - - 1.00 - 1.00 - mov qword ptr [rax + 16], rcx
- - - - - 1.00 - - ret
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_bytes_with_elems_dynamic_padding(
source: &[u8],
count: usize,
) -> Option<Ref<&[u8], format::LocoPacket>> {
Ref::from_bytes_with_elems(source, count).ok()
}
Assembly
bench_ref_type_from_bytes_with_elems_dynamic_padding:
mov rax, rdi
movabs rdi, 6148914691236517201
cmp rcx, rdi
ja .LBB5_3
lea rdi, [rcx + 2*rcx]
or rdi, 3
add rdi, 9
cmp rdx, rdi
sete dil
movabs r8, 3074457345618258599
cmp rcx, r8
setb r8b
and r8b, dil
cmp r8b, 1
jne .LBB5_3
test sil, 3
je .LBB5_4
.LBB5_3:
mov qword ptr [rax], 0
ret
.LBB5_4:
mov qword ptr [rax], rsi
mov qword ptr [rax + 8], rdx
mov qword ptr [rax + 16], rcx
ret
Machine Code Analysis
Iterations: 100
Instructions: 2300
Total Cycles: 640
Total uOps: 2300
Dispatch Width: 4
uOps Per Cycle: 3.59
IPC: 3.59
Block RThroughput: 5.8
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.33 movabs rdi, 6148914691236517201
1 1 0.33 cmp rcx, rdi
1 1 1.00 ja .LBB5_3
1 1 0.50 lea rdi, [rcx + 2*rcx]
1 1 0.33 or rdi, 3
1 1 0.33 add rdi, 9
1 1 0.33 cmp rdx, rdi
1 1 0.50 sete dil
1 1 0.33 movabs r8, 3074457345618258599
1 1 0.33 cmp rcx, r8
1 1 0.50 setb r8b
1 1 0.33 and r8b, dil
1 1 0.33 cmp r8b, 1
1 1 1.00 jne .LBB5_3
1 1 0.33 test sil, 3
1 1 1.00 je .LBB5_4
1 1 1.00 * mov qword ptr [rax], 0
1 1 1.00 U ret
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 * mov qword ptr [rax + 8], rdx
1 1 1.00 * mov qword ptr [rax + 16], rcx
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.32 6.33 4.00 6.35 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.99 - - 0.01 - - mov rax, rdi
- - 0.66 0.34 - - - - movabs rdi, 6148914691236517201
- - 0.34 0.66 - - - - cmp rcx, rdi
- - - - - 1.00 - - ja .LBB5_3
- - 0.66 0.34 - - - - lea rdi, [rcx + 2*rcx]
- - 0.01 0.99 - - - - or rdi, 3
- - 0.01 0.99 - - - - add rdi, 9
- - 0.01 0.99 - - - - cmp rdx, rdi
- - 0.99 - - 0.01 - - sete dil
- - 0.35 0.01 - 0.64 - - movabs r8, 3074457345618258599
- - 0.99 - - 0.01 - - cmp rcx, r8
- - 0.99 - - 0.01 - - setb r8b
- - - 1.00 - - - - and r8b, dil
- - - 1.00 - - - - cmp r8b, 1
- - - - - 1.00 - - jne .LBB5_3
- - 0.32 0.01 - 0.67 - - test sil, 3
- - - - - 1.00 - - je .LBB5_4
- - - - 1.00 - - 1.00 mov qword ptr [rax], 0
- - - - - 1.00 - - ret
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - 1.00 - - 1.00 mov qword ptr [rax + 8], rdx
- - - - 1.00 - 1.00 - mov qword ptr [rax + 16], rcx
- - - - - 1.00 - - ret
Source§impl<B, T> Ref<B, T>
impl<B, T> Ref<B, T>
Sourcepub fn from_prefix_with_elems(
source: B,
count: usize,
) -> Result<(Ref<B, T>, B), CastError<B, T>>
pub fn from_prefix_with_elems( source: B, count: usize, ) -> Result<(Ref<B, T>, B), CastError<B, T>>
Constructs a Ref from the prefix of the given bytes with DST
length equal to count without copying.
This method attempts to return a Ref to the prefix of source
interpreted as a T with count trailing elements, and a reference to
the remaining bytes. If there are insufficient bytes, or if source is
not appropriately aligned, this returns Err. If T: Unaligned, you can infallibly discard the alignment
error.
§Compile-Time Assertions
This method cannot yet be used on unsized types whose dynamically-sized component is zero-sized. Attempting to use this method on such types results in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: u16,
trailing_dst: [()],
}
let _ = Ref::<_, ZSTy>::from_prefix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error!§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_prefix_with_elems_dynamic_size(
source: &[u8],
count: usize,
) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_prefix_with_elems(source, count) {
Ok((packet, _rest)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_prefix_with_elems_dynamic_size:
mov rax, rdi
lea rdi, [rcx + rcx]
test rcx, rcx
sets r8b
cmp rdi, -5
setae r9b
or r9b, r8b
jne .LBB5_3
add rdi, 4
cmp rdi, rdx
ja .LBB5_3
movabs rdx, 4611686018427387902
cmp rcx, rdx
setb dl
test sil, 1
sete r8b
test dl, r8b
jne .LBB5_4
.LBB5_3:
mov qword ptr [rax], 0
ret
.LBB5_4:
mov qword ptr [rax], rsi
mov qword ptr [rax + 8], rdi
mov qword ptr [rax + 16], rcx
ret
Machine Code Analysis
Iterations: 100
Instructions: 2400
Total Cycles: 672
Total uOps: 2400
Dispatch Width: 4
uOps Per Cycle: 3.57
IPC: 3.57
Block RThroughput: 6.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.50 lea rdi, [rcx + rcx]
1 1 0.33 test rcx, rcx
1 1 0.50 sets r8b
1 1 0.33 cmp rdi, -5
1 1 0.50 setae r9b
1 1 0.33 or r9b, r8b
1 1 1.00 jne .LBB5_3
1 1 0.33 add rdi, 4
1 1 0.33 cmp rdi, rdx
1 1 1.00 ja .LBB5_3
1 1 0.33 movabs rdx, 4611686018427387902
1 1 0.33 cmp rcx, rdx
1 1 0.50 setb dl
1 1 0.33 test sil, 1
1 1 0.50 sete r8b
1 1 0.33 test dl, r8b
1 1 1.00 jne .LBB5_4
1 1 1.00 * mov qword ptr [rax], 0
1 1 1.00 U ret
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 * mov qword ptr [rax + 8], rdi
1 1 1.00 * mov qword ptr [rax + 16], rcx
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.66 6.65 4.00 6.69 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.03 0.96 - 0.01 - - mov rax, rdi
- - 0.64 0.36 - - - - lea rdi, [rcx + rcx]
- - 0.34 0.66 - - - - test rcx, rcx
- - 0.99 - - 0.01 - - sets r8b
- - 0.66 0.34 - - - - cmp rdi, -5
- - 0.67 - - 0.33 - - setae r9b
- - 0.01 0.99 - - - - or r9b, r8b
- - - - - 1.00 - - jne .LBB5_3
- - - 0.99 - 0.01 - - add rdi, 4
- - 0.66 0.33 - 0.01 - - cmp rdi, rdx
- - - - - 1.00 - - ja .LBB5_3
- - - 0.01 - 0.99 - - movabs rdx, 4611686018427387902
- - 0.33 0.34 - 0.33 - - cmp rcx, rdx
- - 1.00 - - - - - setb dl
- - 0.33 0.67 - - - - test sil, 1
- - 1.00 - - - - - sete r8b
- - - 1.00 - - - - test dl, r8b
- - - - - 1.00 - - jne .LBB5_4
- - - - 1.00 - - 1.00 mov qword ptr [rax], 0
- - - - - 1.00 - - ret
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - 1.00 - - 1.00 mov qword ptr [rax + 8], rdi
- - - - 1.00 - 1.00 - mov qword ptr [rax + 16], rcx
- - - - - 1.00 - - ret
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_prefix_with_elems_dynamic_padding(
source: &[u8],
count: usize,
) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_prefix_with_elems(source, count) {
Ok((packet, _rest)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_prefix_with_elems_dynamic_padding:
mov rax, rdi
movabs rdi, 6148914691236517201
cmp rcx, rdi
ja .LBB5_4
lea rdi, [rcx + 2*rcx]
or rdi, 3
add rdi, 9
cmp rdi, rdx
setbe dl
movabs r8, 3074457345618258599
cmp rcx, r8
setb r8b
and r8b, dl
cmp r8b, 1
jne .LBB5_4
test sil, 3
je .LBB5_3
.LBB5_4:
mov qword ptr [rax], 0
ret
.LBB5_3:
mov qword ptr [rax], rsi
mov qword ptr [rax + 8], rdi
mov qword ptr [rax + 16], rcx
ret
Machine Code Analysis
Iterations: 100
Instructions: 2300
Total Cycles: 674
Total uOps: 2400
Dispatch Width: 4
uOps Per Cycle: 3.56
IPC: 3.41
Block RThroughput: 6.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.33 movabs rdi, 6148914691236517201
1 1 0.33 cmp rcx, rdi
1 1 1.00 ja .LBB5_4
1 1 0.50 lea rdi, [rcx + 2*rcx]
1 1 0.33 or rdi, 3
1 1 0.33 add rdi, 9
1 1 0.33 cmp rdi, rdx
2 2 1.00 setbe dl
1 1 0.33 movabs r8, 3074457345618258599
1 1 0.33 cmp rcx, r8
1 1 0.50 setb r8b
1 1 0.33 and r8b, dl
1 1 0.33 cmp r8b, 1
1 1 1.00 jne .LBB5_4
1 1 0.33 test sil, 3
1 1 1.00 je .LBB5_3
1 1 1.00 * mov qword ptr [rax], 0
1 1 1.00 U ret
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 * mov qword ptr [rax + 8], rdi
1 1 1.00 * mov qword ptr [rax + 16], rcx
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.66 6.65 4.00 6.69 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.01 0.98 - 0.01 - - mov rax, rdi
- - 0.01 0.99 - - - - movabs rdi, 6148914691236517201
- - 0.02 0.98 - - - - cmp rcx, rdi
- - - - - 1.00 - - ja .LBB5_4
- - 0.02 0.98 - - - - lea rdi, [rcx + 2*rcx]
- - 0.68 0.32 - - - - or rdi, 3
- - 0.98 0.02 - - - - add rdi, 9
- - 0.97 0.03 - - - - cmp rdi, rdx
- - 1.96 - - 0.04 - - setbe dl
- - 0.02 0.98 - - - - movabs r8, 3074457345618258599
- - 0.02 0.34 - 0.64 - - cmp rcx, r8
- - 0.02 - - 0.98 - - setb r8b
- - 0.97 0.02 - 0.01 - - and r8b, dl
- - 0.97 0.02 - 0.01 - - cmp r8b, 1
- - - - - 1.00 - - jne .LBB5_4
- - 0.01 0.99 - - - - test sil, 3
- - - - - 1.00 - - je .LBB5_3
- - - - 1.00 - - 1.00 mov qword ptr [rax], 0
- - - - - 1.00 - - ret
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - 1.00 - - 1.00 mov qword ptr [rax + 8], rdi
- - - - 1.00 - 1.00 - mov qword ptr [rax + 16], rcx
- - - - - 1.00 - - ret
Sourcepub fn from_suffix_with_elems(
source: B,
count: usize,
) -> Result<(B, Ref<B, T>), CastError<B, T>>
pub fn from_suffix_with_elems( source: B, count: usize, ) -> Result<(B, Ref<B, T>), CastError<B, T>>
Constructs a Ref from the suffix of the given bytes with DST length
equal to count without copying.
This method attempts to return a Ref to the suffix of source
interpreted as a T with count trailing elements, and a reference to
the preceding bytes. If there are insufficient bytes, or if that suffix
of source is not appropriately aligned, this returns Err. If T: Unaligned, you can infallibly discard the alignment
error.
§Compile-Time Assertions
This method cannot yet be used on unsized types whose dynamically-sized component is zero-sized. Attempting to use this method on such types results in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: u16,
trailing_dst: [()],
}
let _ = Ref::<_, ZSTy>::from_suffix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error!§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_suffix_with_elems_dynamic_size(
source: &[u8],
count: usize,
) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_suffix_with_elems(source, count) {
Ok((_rest, packet)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_suffix_with_elems_dynamic_size:
mov rax, rdi
lea rdi, [rcx + rcx]
test rcx, rcx
sets r8b
cmp rdi, -5
setae r9b
or r9b, r8b
jne .LBB5_4
add rdi, 4
sub rdx, rdi
jb .LBB5_4
movabs r8, 4611686018427387901
cmp rcx, r8
ja .LBB5_4
add rsi, rdx
mov edx, esi
and edx, 1
je .LBB5_5
.LBB5_4:
mov qword ptr [rax], 0
ret
.LBB5_5:
mov qword ptr [rax], rsi
mov qword ptr [rax + 8], rdi
mov qword ptr [rax + 16], rcx
ret
Machine Code Analysis
Iterations: 100
Instructions: 2400
Total Cycles: 673
Total uOps: 2400
Dispatch Width: 4
uOps Per Cycle: 3.57
IPC: 3.57
Block RThroughput: 6.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.50 lea rdi, [rcx + rcx]
1 1 0.33 test rcx, rcx
1 1 0.50 sets r8b
1 1 0.33 cmp rdi, -5
1 1 0.50 setae r9b
1 1 0.33 or r9b, r8b
1 1 1.00 jne .LBB5_4
1 1 0.33 add rdi, 4
1 1 0.33 sub rdx, rdi
1 1 1.00 jb .LBB5_4
1 1 0.33 movabs r8, 4611686018427387901
1 1 0.33 cmp rcx, r8
1 1 1.00 ja .LBB5_4
1 1 0.33 add rsi, rdx
1 1 0.33 mov edx, esi
1 1 0.33 and edx, 1
1 1 1.00 je .LBB5_5
1 1 1.00 * mov qword ptr [rax], 0
1 1 1.00 U ret
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 * mov qword ptr [rax + 8], rdi
1 1 1.00 * mov qword ptr [rax + 16], rcx
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.65 6.65 4.00 6.70 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - 0.99 - 0.01 - - mov rax, rdi
- - 0.01 0.99 - - - - lea rdi, [rcx + rcx]
- - 0.67 0.33 - - - - test rcx, rcx
- - 0.99 - - 0.01 - - sets r8b
- - - 1.00 - - - - cmp rdi, -5
- - 1.00 - - - - - setae r9b
- - 1.00 - - - - - or r9b, r8b
- - - - - 1.00 - - jne .LBB5_4
- - - 0.99 - 0.01 - - add rdi, 4
- - - 0.33 - 0.67 - - sub rdx, rdi
- - - - - 1.00 - - jb .LBB5_4
- - - 1.00 - - - - movabs r8, 4611686018427387901
- - 0.66 0.34 - - - - cmp rcx, r8
- - - - - 1.00 - - ja .LBB5_4
- - 0.34 0.66 - - - - add rsi, rdx
- - 0.98 0.02 - - - - mov edx, esi
- - 1.00 - - - - - and edx, 1
- - - - - 1.00 - - je .LBB5_5
- - - - 1.00 - - 1.00 mov qword ptr [rax], 0
- - - - - 1.00 - - ret
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - 1.00 - - 1.00 mov qword ptr [rax + 8], rdi
- - - - 1.00 - 1.00 - mov qword ptr [rax + 16], rcx
- - - - - 1.00 - - ret
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_from_suffix_with_elems_dynamic_padding(
source: &[u8],
count: usize,
) -> Option<Ref<&[u8], format::LocoPacket>> {
match Ref::from_suffix_with_elems(source, count) {
Ok((_rest, packet)) => Some(packet),
_ => None,
}
}
Assembly
bench_ref_type_from_suffix_with_elems_dynamic_padding:
mov rax, rdi
movabs rdi, 6148914691236517201
cmp rcx, rdi
ja .LBB5_3
lea rdi, [rcx + 2*rcx]
or rdi, 3
add rdi, 9
sub rdx, rdi
setae r8b
movabs r9, 3074457345618258599
cmp rcx, r9
setb r9b
and r9b, r8b
cmp r9b, 1
jne .LBB5_3
add rsi, rdx
test sil, 3
je .LBB5_4
.LBB5_3:
mov qword ptr [rax], 0
ret
.LBB5_4:
mov qword ptr [rax], rsi
mov qword ptr [rax + 8], rdi
mov qword ptr [rax + 16], rcx
ret
Machine Code Analysis
Iterations: 100
Instructions: 2400
Total Cycles: 673
Total uOps: 2400
Dispatch Width: 4
uOps Per Cycle: 3.57
IPC: 3.57
Block RThroughput: 6.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 1 0.33 mov rax, rdi
1 1 0.33 movabs rdi, 6148914691236517201
1 1 0.33 cmp rcx, rdi
1 1 1.00 ja .LBB5_3
1 1 0.50 lea rdi, [rcx + 2*rcx]
1 1 0.33 or rdi, 3
1 1 0.33 add rdi, 9
1 1 0.33 sub rdx, rdi
1 1 0.50 setae r8b
1 1 0.33 movabs r9, 3074457345618258599
1 1 0.33 cmp rcx, r9
1 1 0.50 setb r9b
1 1 0.33 and r9b, r8b
1 1 0.33 cmp r9b, 1
1 1 1.00 jne .LBB5_3
1 1 0.33 add rsi, rdx
1 1 0.33 test sil, 3
1 1 1.00 je .LBB5_4
1 1 1.00 * mov qword ptr [rax], 0
1 1 1.00 U ret
1 1 1.00 * mov qword ptr [rax], rsi
1 1 1.00 * mov qword ptr [rax + 8], rdi
1 1 1.00 * mov qword ptr [rax + 16], rcx
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.66 6.66 4.00 6.68 2.00 2.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.33 0.01 - 0.66 - - mov rax, rdi
- - 0.34 0.02 - 0.64 - - movabs rdi, 6148914691236517201
- - 0.34 0.34 - 0.32 - - cmp rcx, rdi
- - - - - 1.00 - - ja .LBB5_3
- - 0.66 0.34 - - - - lea rdi, [rcx + 2*rcx]
- - 0.02 0.97 - 0.01 - - or rdi, 3
- - 0.02 0.98 - - - - add rdi, 9
- - 0.01 0.99 - - - - sub rdx, rdi
- - 1.00 - - - - - setae r8b
- - 0.97 0.02 - 0.01 - - movabs r9, 3074457345618258599
- - 0.98 0.01 - 0.01 - - cmp rcx, r9
- - 0.98 - - 0.02 - - setb r9b
- - 0.01 0.98 - 0.01 - - and r9b, r8b
- - 0.02 0.98 - - - - cmp r9b, 1
- - - - - 1.00 - - jne .LBB5_3
- - - 1.00 - - - - add rsi, rdx
- - 0.98 0.02 - - - - test sil, 3
- - - - - 1.00 - - je .LBB5_4
- - - - 1.00 - - 1.00 mov qword ptr [rax], 0
- - - - - 1.00 - - ret
- - - - 1.00 - 1.00 - mov qword ptr [rax], rsi
- - - - 1.00 - - 1.00 mov qword ptr [rax + 8], rdi
- - - - 1.00 - 1.00 - mov qword ptr [rax + 16], rcx
- - - - - 1.00 - - ret
Source§impl<'a, B, T> Ref<B, T>
impl<'a, B, T> Ref<B, T>
Sourcepub fn into_ref(r: Self) -> &'a T
pub fn into_ref(r: Self) -> &'a T
Converts this Ref into a reference.
into_ref consumes the Ref, and returns a reference to T.
Note: this is an associated function, which means that you have to call
it as Ref::into_ref(r) instead of r.into_ref(). This is so that
there is no conflict with a method on the inner type.
§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Sized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_into_ref_static_size(
source: Ref<&[u8], format::LocoPacket>,
) -> &format::LocoPacket {
Ref::into_ref(source)
}
Assembly
bench_ref_type_into_ref_static_size:
mov rax, qword ptr [rdi]
ret
Machine Code Analysis
Iterations: 100
Instructions: 200
Total Cycles: 103
Total uOps: 200
Dispatch Width: 4
uOps Per Cycle: 1.94
IPC: 1.94
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 0.50 0.50
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.50 0.50 mov rax, qword ptr [rdi]
- - - - - 1.00 - - ret
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_into_ref_dynamic_size(
source: Ref<&[u8], format::LocoPacket>,
) -> &format::LocoPacket {
Ref::into_ref(source)
}
Assembly
bench_ref_type_into_ref_dynamic_size:
mov rdx, qword ptr [rdi + 16]
mov rax, qword ptr [rdi]
mov rcx, qword ptr [rdi + 8]
mov esi, 1
movabs rdi, 4611686018427387902
cmp rdx, rdi
jae .LBB8_3
test al, 1
jne .LBB8_2
lea rdi, [2*rdx + 4]
cmp rcx, rdi
jne .LBB8_3
ret
.LBB8_2:
xor esi, esi
.LBB8_3:
sub rsp, 24
mov qword ptr [rsp], rsi
mov qword ptr [rsp + 8], rax
mov qword ptr [rsp + 16], rcx
lea rdi, [rip + .Lanon.HASH.2]
lea rcx, [rip + .Lanon.HASH.1]
lea r8, [rip + .Lanon.HASH.4]
mov rdx, rsp
mov esi, 54
call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Machine Code Analysis
Iterations: 100
Instructions: 2400
Total Cycles: 1647
Total uOps: 2700
Dispatch Width: 4
uOps Per Cycle: 1.64
IPC: 1.46
Block RThroughput: 6.8
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rdx, qword ptr [rdi + 16]
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rcx, qword ptr [rdi + 8]
1 1 0.33 mov esi, 1
1 1 0.33 movabs rdi, 4611686018427387902
1 1 0.33 cmp rdx, rdi
1 1 1.00 jae .LBB8_3
1 1 0.33 test al, 1
1 1 1.00 jne .LBB8_2
1 1 0.50 lea rdi, [2*rdx + 4]
1 1 0.33 cmp rcx, rdi
1 1 1.00 jne .LBB8_3
1 1 1.00 U ret
1 0 0.25 xor esi, esi
1 1 0.33 sub rsp, 24
1 1 1.00 * mov qword ptr [rsp], rsi
1 1 1.00 * mov qword ptr [rsp + 8], rax
1 1 1.00 * mov qword ptr [rsp + 16], rcx
1 1 0.50 lea rdi, [rip + .Lanon.HASH.2]
1 1 0.50 lea rcx, [rip + .Lanon.HASH.1]
1 1 0.50 lea r8, [rip + .Lanon.HASH.4]
1 1 0.33 mov rdx, rsp
1 1 0.33 mov esi, 54
4 7 1.00 * call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 5.15 5.74 4.00 6.11 3.98 4.02
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.71 0.29 mov rdx, qword ptr [rdi + 16]
- - - - - - 0.72 0.28 mov rax, qword ptr [rdi]
- - - - - - 0.29 0.71 mov rcx, qword ptr [rdi + 8]
- - 0.83 0.16 - 0.01 - - mov esi, 1
- - 0.16 0.84 - - - - movabs rdi, 4611686018427387902
- - 0.80 0.04 - 0.16 - - cmp rdx, rdi
- - - - - 1.00 - - jae .LBB8_3
- - 0.13 0.74 - 0.13 - - test al, 1
- - - - - 1.00 - - jne .LBB8_2
- - 0.10 0.90 - - - - lea rdi, [2*rdx + 4]
- - 0.09 0.91 - - - - cmp rcx, rdi
- - - - - 1.00 - - jne .LBB8_3
- - - - - 1.00 - - ret
- - - - - - - - xor esi, esi
- - 0.29 0.13 - 0.58 - - sub rsp, 24
- - - - 1.00 - 0.72 0.28 mov qword ptr [rsp], rsi
- - - - 1.00 - 0.28 0.72 mov qword ptr [rsp + 8], rax
- - - - 1.00 - 0.72 0.28 mov qword ptr [rsp + 16], rcx
- - 0.76 0.24 - - - - lea rdi, [rip + .Lanon.HASH.2]
- - 0.82 0.18 - - - - lea rcx, [rip + .Lanon.HASH.1]
- - 0.92 0.08 - - - - lea r8, [rip + .Lanon.HASH.4]
- - 0.09 0.68 - 0.23 - - mov rdx, rsp
- - 0.16 0.84 - - - - mov esi, 54
- - - - 1.00 1.00 0.54 1.46 call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_into_ref_dynamic_padding(
source: Ref<&[u8], format::LocoPacket>,
) -> &format::LocoPacket {
Ref::into_ref(source)
}
Assembly
bench_ref_type_into_ref_dynamic_padding:
mov rdx, qword ptr [rdi + 16]
mov rax, qword ptr [rdi]
mov rcx, qword ptr [rdi + 8]
mov esi, 1
movabs rdi, 3074457345618258599
cmp rdx, rdi
jae .LBB8_3
test al, 3
jne .LBB8_2
lea rdi, [rdx + 2*rdx]
or rdi, 3
add rdi, 9
cmp rcx, rdi
jne .LBB8_3
ret
.LBB8_2:
xor esi, esi
.LBB8_3:
sub rsp, 24
mov qword ptr [rsp], rsi
mov qword ptr [rsp + 8], rax
mov qword ptr [rsp + 16], rcx
lea rdi, [rip + .Lanon.HASH.2]
lea rcx, [rip + .Lanon.HASH.1]
lea r8, [rip + .Lanon.HASH.4]
mov rdx, rsp
mov esi, 54
call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Machine Code Analysis
Iterations: 100
Instructions: 2600
Total Cycles: 1812
Total uOps: 2900
Dispatch Width: 4
uOps Per Cycle: 1.60
IPC: 1.43
Block RThroughput: 7.3
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rdx, qword ptr [rdi + 16]
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rcx, qword ptr [rdi + 8]
1 1 0.33 mov esi, 1
1 1 0.33 movabs rdi, 3074457345618258599
1 1 0.33 cmp rdx, rdi
1 1 1.00 jae .LBB8_3
1 1 0.33 test al, 3
1 1 1.00 jne .LBB8_2
1 1 0.50 lea rdi, [rdx + 2*rdx]
1 1 0.33 or rdi, 3
1 1 0.33 add rdi, 9
1 1 0.33 cmp rcx, rdi
1 1 1.00 jne .LBB8_3
1 1 1.00 U ret
1 0 0.25 xor esi, esi
1 1 0.33 sub rsp, 24
1 1 1.00 * mov qword ptr [rsp], rsi
1 1 1.00 * mov qword ptr [rsp + 8], rax
1 1 1.00 * mov qword ptr [rsp + 16], rcx
1 1 0.50 lea rdi, [rip + .Lanon.HASH.2]
1 1 0.50 lea rcx, [rip + .Lanon.HASH.1]
1 1 0.50 lea r8, [rip + .Lanon.HASH.4]
1 1 0.33 mov rdx, rsp
1 1 0.33 mov esi, 54
4 7 1.00 * call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.41 6.42 4.00 6.17 3.99 4.01
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.54 0.46 mov rdx, qword ptr [rdi + 16]
- - - - - - 0.50 0.50 mov rax, qword ptr [rdi]
- - - - - - 0.49 0.51 mov rcx, qword ptr [rdi + 8]
- - 0.52 0.47 - 0.01 - - mov esi, 1
- - 0.47 0.53 - - - - movabs rdi, 3074457345618258599
- - 0.47 0.53 - - - - cmp rdx, rdi
- - - - - 1.00 - - jae .LBB8_3
- - 0.54 0.44 - 0.02 - - test al, 3
- - - - - 1.00 - - jne .LBB8_2
- - 0.44 0.56 - - - - lea rdi, [rdx + 2*rdx]
- - 0.48 0.52 - - - - or rdi, 3
- - 0.48 0.48 - 0.04 - - add rdi, 9
- - 0.51 0.39 - 0.10 - - cmp rcx, rdi
- - - - - 1.00 - - jne .LBB8_3
- - - - - 1.00 - - ret
- - - - - - - - xor esi, esi
- - 0.53 0.47 - - - - sub rsp, 24
- - - - 1.00 - 0.52 0.48 mov qword ptr [rsp], rsi
- - - - 1.00 - 0.48 0.52 mov qword ptr [rsp + 8], rax
- - - - 1.00 - 0.52 0.48 mov qword ptr [rsp + 16], rcx
- - 0.49 0.51 - - - - lea rdi, [rip + .Lanon.HASH.2]
- - 0.46 0.54 - - - - lea rcx, [rip + .Lanon.HASH.1]
- - 0.54 0.46 - - - - lea r8, [rip + .Lanon.HASH.4]
- - 0.04 0.06 - 0.90 - - mov rdx, rsp
- - 0.44 0.46 - 0.10 - - mov esi, 54
- - - - 1.00 1.00 0.94 1.06 call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Source§impl<'a, B, T> Ref<B, T>
impl<'a, B, T> Ref<B, T>
Sourcepub fn into_mut(r: Self) -> &'a mut T
pub fn into_mut(r: Self) -> &'a mut T
Converts this Ref into a mutable reference.
into_mut consumes the Ref, and returns a mutable reference to T.
Note: this is an associated function, which means that you have to call
it as Ref::into_mut(r) instead of r.into_mut(). This is so that
there is no conflict with a method on the inner type.
§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Sized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_into_mut_static_size(
source: Ref<&mut [u8], format::LocoPacket>,
) -> &mut format::LocoPacket {
Ref::into_mut(source)
}
Assembly
bench_ref_type_into_mut_static_size:
mov rax, qword ptr [rdi]
ret
Machine Code Analysis
Iterations: 100
Instructions: 200
Total Cycles: 103
Total uOps: 200
Dispatch Width: 4
uOps Per Cycle: 1.94
IPC: 1.94
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 0.50 0.50
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.50 0.50 mov rax, qword ptr [rdi]
- - - - - 1.00 - - ret
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_into_mut_dynamic_size(
source: Ref<&mut [u8], format::LocoPacket>,
) -> &mut format::LocoPacket {
Ref::into_mut(source)
}
Assembly
bench_ref_type_into_mut_dynamic_size:
mov rdx, qword ptr [rdi + 16]
mov rax, qword ptr [rdi]
mov rcx, qword ptr [rdi + 8]
mov esi, 1
movabs rdi, 4611686018427387902
cmp rdx, rdi
jae .LBB8_3
test al, 1
jne .LBB8_2
lea rdi, [2*rdx + 4]
cmp rcx, rdi
jne .LBB8_3
ret
.LBB8_2:
xor esi, esi
.LBB8_3:
sub rsp, 24
mov qword ptr [rsp], rsi
mov qword ptr [rsp + 8], rax
mov qword ptr [rsp + 16], rcx
lea rdi, [rip + .Lanon.HASH.2]
lea rcx, [rip + .Lanon.HASH.1]
lea r8, [rip + .Lanon.HASH.4]
mov rdx, rsp
mov esi, 54
call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Machine Code Analysis
Iterations: 100
Instructions: 2400
Total Cycles: 1647
Total uOps: 2700
Dispatch Width: 4
uOps Per Cycle: 1.64
IPC: 1.46
Block RThroughput: 6.8
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rdx, qword ptr [rdi + 16]
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rcx, qword ptr [rdi + 8]
1 1 0.33 mov esi, 1
1 1 0.33 movabs rdi, 4611686018427387902
1 1 0.33 cmp rdx, rdi
1 1 1.00 jae .LBB8_3
1 1 0.33 test al, 1
1 1 1.00 jne .LBB8_2
1 1 0.50 lea rdi, [2*rdx + 4]
1 1 0.33 cmp rcx, rdi
1 1 1.00 jne .LBB8_3
1 1 1.00 U ret
1 0 0.25 xor esi, esi
1 1 0.33 sub rsp, 24
1 1 1.00 * mov qword ptr [rsp], rsi
1 1 1.00 * mov qword ptr [rsp + 8], rax
1 1 1.00 * mov qword ptr [rsp + 16], rcx
1 1 0.50 lea rdi, [rip + .Lanon.HASH.2]
1 1 0.50 lea rcx, [rip + .Lanon.HASH.1]
1 1 0.50 lea r8, [rip + .Lanon.HASH.4]
1 1 0.33 mov rdx, rsp
1 1 0.33 mov esi, 54
4 7 1.00 * call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 5.15 5.74 4.00 6.11 3.98 4.02
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.71 0.29 mov rdx, qword ptr [rdi + 16]
- - - - - - 0.72 0.28 mov rax, qword ptr [rdi]
- - - - - - 0.29 0.71 mov rcx, qword ptr [rdi + 8]
- - 0.83 0.16 - 0.01 - - mov esi, 1
- - 0.16 0.84 - - - - movabs rdi, 4611686018427387902
- - 0.80 0.04 - 0.16 - - cmp rdx, rdi
- - - - - 1.00 - - jae .LBB8_3
- - 0.13 0.74 - 0.13 - - test al, 1
- - - - - 1.00 - - jne .LBB8_2
- - 0.10 0.90 - - - - lea rdi, [2*rdx + 4]
- - 0.09 0.91 - - - - cmp rcx, rdi
- - - - - 1.00 - - jne .LBB8_3
- - - - - 1.00 - - ret
- - - - - - - - xor esi, esi
- - 0.29 0.13 - 0.58 - - sub rsp, 24
- - - - 1.00 - 0.72 0.28 mov qword ptr [rsp], rsi
- - - - 1.00 - 0.28 0.72 mov qword ptr [rsp + 8], rax
- - - - 1.00 - 0.72 0.28 mov qword ptr [rsp + 16], rcx
- - 0.76 0.24 - - - - lea rdi, [rip + .Lanon.HASH.2]
- - 0.82 0.18 - - - - lea rcx, [rip + .Lanon.HASH.1]
- - 0.92 0.08 - - - - lea r8, [rip + .Lanon.HASH.4]
- - 0.09 0.68 - 0.23 - - mov rdx, rsp
- - 0.16 0.84 - - - - mov esi, 54
- - - - 1.00 1.00 0.54 1.46 call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Source§impl<B, T> Ref<B, T>
impl<B, T> Ref<B, T>
Sourcepub fn bytes(r: &Self) -> &[u8]
pub fn bytes(r: &Self) -> &[u8]
Gets the underlying bytes.
Note: this is an associated function, which means that you have to call
it as Ref::bytes(r) instead of r.bytes(). This is so that there is
no conflict with a method on the inner type.
§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Sized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_bytes_static_size<'a>(source: &'a Ref<&[u8], format::LocoPacket>) -> &'a [u8] {
Ref::bytes(source)
}
Assembly
bench_ref_type_bytes_static_size:
mov rax, qword ptr [rdi]
mov rdx, qword ptr [rdi + 8]
ret
Machine Code Analysis
Iterations: 100
Instructions: 300
Total Cycles: 107
Total uOps: 300
Dispatch Width: 4
uOps Per Cycle: 2.80
IPC: 2.80
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rdx, qword ptr [rdi + 8]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 1.00 1.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - - 1.00 mov rax, qword ptr [rdi]
- - - - - - 1.00 - mov rdx, qword ptr [rdi + 8]
- - - - - 1.00 - - ret
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_bytes_dynamic_size<'a>(source: &'a Ref<&[u8], format::LocoPacket>) -> &'a [u8] {
Ref::bytes(source)
}
Assembly
bench_ref_type_bytes_dynamic_size:
mov rax, qword ptr [rdi]
mov rdx, qword ptr [rdi + 8]
ret
Machine Code Analysis
Iterations: 100
Instructions: 300
Total Cycles: 107
Total uOps: 300
Dispatch Width: 4
uOps Per Cycle: 2.80
IPC: 2.80
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rdx, qword ptr [rdi + 8]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 1.00 1.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - - 1.00 mov rax, qword ptr [rdi]
- - - - - - 1.00 - mov rdx, qword ptr [rdi + 8]
- - - - - 1.00 - - ret
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_bytes_dynamic_padding<'a>(
source: &'a Ref<&[u8], format::LocoPacket>,
) -> &'a [u8] {
Ref::bytes(source)
}
Assembly
bench_ref_type_bytes_dynamic_padding:
mov rax, qword ptr [rdi]
mov rdx, qword ptr [rdi + 8]
ret
Machine Code Analysis
Iterations: 100
Instructions: 300
Total Cycles: 107
Total uOps: 300
Dispatch Width: 4
uOps Per Cycle: 2.80
IPC: 2.80
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rdx, qword ptr [rdi + 8]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 1.00 1.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - - 1.00 mov rax, qword ptr [rdi]
- - - - - - 1.00 - mov rdx, qword ptr [rdi + 8]
- - - - - 1.00 - - ret
Source§impl<B, T> Ref<B, T>where
B: ByteSliceMut,
T: ?Sized,
impl<B, T> Ref<B, T>where
B: ByteSliceMut,
T: ?Sized,
Sourcepub fn bytes_mut(r: &mut Self) -> &mut [u8] ⓘ
pub fn bytes_mut(r: &mut Self) -> &mut [u8] ⓘ
Gets the underlying bytes mutably.
Note: this is an associated function, which means that you have to call
it as Ref::bytes_mut(r) instead of r.bytes_mut(). This is so that
there is no conflict with a method on the inner type.
§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Sized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_bytes_mut_static_size<'a>(
source: &'a mut Ref<&mut [u8], format::LocoPacket>,
) -> &'a mut [u8] {
Ref::bytes_mut(source)
}
Assembly
bench_ref_type_bytes_mut_static_size:
mov rax, qword ptr [rdi]
mov rdx, qword ptr [rdi + 8]
ret
Machine Code Analysis
Iterations: 100
Instructions: 300
Total Cycles: 107
Total uOps: 300
Dispatch Width: 4
uOps Per Cycle: 2.80
IPC: 2.80
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rdx, qword ptr [rdi + 8]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 1.00 1.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - - 1.00 mov rax, qword ptr [rdi]
- - - - - - 1.00 - mov rdx, qword ptr [rdi + 8]
- - - - - 1.00 - - ret
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_bytes_mut_dynamic_size<'a>(
source: &'a mut Ref<&mut [u8], format::LocoPacket>,
) -> &'a mut [u8] {
Ref::bytes_mut(source)
}
Assembly
bench_ref_type_bytes_mut_dynamic_size:
mov rax, qword ptr [rdi]
mov rdx, qword ptr [rdi + 8]
ret
Machine Code Analysis
Iterations: 100
Instructions: 300
Total Cycles: 107
Total uOps: 300
Dispatch Width: 4
uOps Per Cycle: 2.80
IPC: 2.80
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rdx, qword ptr [rdi + 8]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 1.00 1.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - - 1.00 mov rax, qword ptr [rdi]
- - - - - - 1.00 - mov rdx, qword ptr [rdi + 8]
- - - - - 1.00 - - ret
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_bytes_mut_dynamic_padding<'a>(
source: &'a mut Ref<&mut [u8], format::LocoPacket>,
) -> &'a mut [u8] {
Ref::bytes_mut(source)
}
Assembly
bench_ref_type_bytes_mut_dynamic_padding:
mov rax, qword ptr [rdi]
mov rdx, qword ptr [rdi + 8]
ret
Machine Code Analysis
Iterations: 100
Instructions: 300
Total Cycles: 107
Total uOps: 300
Dispatch Width: 4
uOps Per Cycle: 2.80
IPC: 2.80
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rdx, qword ptr [rdi + 8]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 1.00 1.00
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - - 1.00 mov rax, qword ptr [rdi]
- - - - - - 1.00 - mov rdx, qword ptr [rdi + 8]
- - - - - 1.00 - - ret
Source§impl<B, T> Ref<B, T>
impl<B, T> Ref<B, T>
Sourcepub fn read(r: &Self) -> T
pub fn read(r: &Self) -> T
Reads a copy of T.
Note: this is an associated function, which means that you have to call
it as Ref::read(r) instead of r.read(). This is so that there is no
conflict with a method on the inner type.
§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_read_static_size(source: &Ref<&[u8], format::LocoPacket>) -> format::LocoPacket {
Ref::read(source)
}
Assembly
bench_ref_type_read_static_size:
mov rax, qword ptr [rdi]
mov ecx, dword ptr [rax]
movzx eax, word ptr [rax + 4]
shl rax, 32
or rax, rcx
ret
Machine Code Analysis
Iterations: 100
Instructions: 600
Total Cycles: 169
Total uOps: 600
Dispatch Width: 4
uOps Per Cycle: 3.55
IPC: 3.55
Block RThroughput: 1.5
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov ecx, dword ptr [rax]
1 5 0.50 * movzx eax, word ptr [rax + 4]
1 1 0.50 shl rax, 32
1 1 0.33 or rax, rcx
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 0.91 0.90 - 1.19 1.50 1.50
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.50 0.50 mov rax, qword ptr [rdi]
- - - - - - 0.31 0.69 mov ecx, dword ptr [rax]
- - - - - - 0.69 0.31 movzx eax, word ptr [rax + 4]
- - 0.91 - - 0.09 - - shl rax, 32
- - - 0.90 - 0.10 - - or rax, rcx
- - - - - 1.00 - - ret
Source§impl<B, T> Ref<B, T>where
B: ByteSliceMut,
T: IntoBytes,
impl<B, T> Ref<B, T>where
B: ByteSliceMut,
T: IntoBytes,
Sourcepub fn write(r: &mut Self, t: T)
pub fn write(r: &mut Self, t: T)
Writes the bytes of t and then forgets t.
Note: this is an associated function, which means that you have to call
it as Ref::write(r, t) instead of r.write(t). This is so that there
is no conflict with a method on the inner type.
§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_write_static_size(
destination: &mut Ref<&mut [u8], format::LocoPacket>,
value: format::LocoPacket,
) {
Ref::write(destination, value)
}
Assembly
bench_ref_type_write_static_size:
mov rax, qword ptr [rdi]
mov dword ptr [rax], esi
shr rsi, 32
mov word ptr [rax + 4], si
ret
Machine Code Analysis
Iterations: 100
Instructions: 500
Total Cycles: 208
Total uOps: 500
Dispatch Width: 4
uOps Per Cycle: 2.40
IPC: 2.40
Block RThroughput: 2.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 1 1.00 * mov dword ptr [rax], esi
1 1 0.50 shr rsi, 32
1 1 1.00 * mov word ptr [rax + 4], si
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 0.99 - 2.00 1.01 1.50 1.50
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.50 0.50 mov rax, qword ptr [rdi]
- - - - 1.00 - 0.33 0.67 mov dword ptr [rax], esi
- - 0.99 - - 0.01 - - shr rsi, 32
- - - - 1.00 - 0.67 0.33 mov word ptr [rax + 4], si
- - - - - 1.00 - - ret
Trait Implementations§
impl<B: CopyableByteSlice + Copy, T: ?Sized> Copy for Ref<B, T>
Source§impl<B, T> Deref for Ref<B, T>
impl<B, T> Deref for Ref<B, T>
Source§fn deref(&self) -> &T
fn deref(&self) -> &T
Dereferences the value.
§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Sized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_deref_static_size<'a>(
source: &'a Ref<&[u8], format::LocoPacket>,
) -> &'a format::LocoPacket {
core::ops::Deref::deref(source)
}
Assembly
bench_ref_type_deref_static_size:
mov rax, qword ptr [rdi]
ret
Machine Code Analysis
Iterations: 100
Instructions: 200
Total Cycles: 103
Total uOps: 200
Dispatch Width: 4
uOps Per Cycle: 1.94
IPC: 1.94
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 0.50 0.50
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.50 0.50 mov rax, qword ptr [rdi]
- - - - - 1.00 - - ret
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_deref_dynamic_size<'a>(
source: &'a Ref<&[u8], format::LocoPacket>,
) -> &'a format::LocoPacket {
core::ops::Deref::deref(source)
}
Assembly
bench_ref_type_deref_dynamic_size:
mov rdx, qword ptr [rdi + 16]
mov rax, qword ptr [rdi]
mov rcx, qword ptr [rdi + 8]
mov esi, 1
movabs rdi, 4611686018427387902
cmp rdx, rdi
jae .LBB8_3
test al, 1
jne .LBB8_2
lea rdi, [2*rdx + 4]
cmp rcx, rdi
jne .LBB8_3
ret
.LBB8_2:
xor esi, esi
.LBB8_3:
sub rsp, 24
mov qword ptr [rsp], rsi
mov qword ptr [rsp + 8], rax
mov qword ptr [rsp + 16], rcx
lea rdi, [rip + .Lanon.HASH.7]
lea rcx, [rip + .Lanon.HASH.1]
lea r8, [rip + .Lanon.HASH.9]
mov rdx, rsp
mov esi, 58
call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Machine Code Analysis
Iterations: 100
Instructions: 2400
Total Cycles: 1647
Total uOps: 2700
Dispatch Width: 4
uOps Per Cycle: 1.64
IPC: 1.46
Block RThroughput: 6.8
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rdx, qword ptr [rdi + 16]
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rcx, qword ptr [rdi + 8]
1 1 0.33 mov esi, 1
1 1 0.33 movabs rdi, 4611686018427387902
1 1 0.33 cmp rdx, rdi
1 1 1.00 jae .LBB8_3
1 1 0.33 test al, 1
1 1 1.00 jne .LBB8_2
1 1 0.50 lea rdi, [2*rdx + 4]
1 1 0.33 cmp rcx, rdi
1 1 1.00 jne .LBB8_3
1 1 1.00 U ret
1 0 0.25 xor esi, esi
1 1 0.33 sub rsp, 24
1 1 1.00 * mov qword ptr [rsp], rsi
1 1 1.00 * mov qword ptr [rsp + 8], rax
1 1 1.00 * mov qword ptr [rsp + 16], rcx
1 1 0.50 lea rdi, [rip + .Lanon.HASH.7]
1 1 0.50 lea rcx, [rip + .Lanon.HASH.1]
1 1 0.50 lea r8, [rip + .Lanon.HASH.9]
1 1 0.33 mov rdx, rsp
1 1 0.33 mov esi, 58
4 7 1.00 * call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 5.15 5.74 4.00 6.11 3.98 4.02
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.71 0.29 mov rdx, qword ptr [rdi + 16]
- - - - - - 0.72 0.28 mov rax, qword ptr [rdi]
- - - - - - 0.29 0.71 mov rcx, qword ptr [rdi + 8]
- - 0.83 0.16 - 0.01 - - mov esi, 1
- - 0.16 0.84 - - - - movabs rdi, 4611686018427387902
- - 0.80 0.04 - 0.16 - - cmp rdx, rdi
- - - - - 1.00 - - jae .LBB8_3
- - 0.13 0.74 - 0.13 - - test al, 1
- - - - - 1.00 - - jne .LBB8_2
- - 0.10 0.90 - - - - lea rdi, [2*rdx + 4]
- - 0.09 0.91 - - - - cmp rcx, rdi
- - - - - 1.00 - - jne .LBB8_3
- - - - - 1.00 - - ret
- - - - - - - - xor esi, esi
- - 0.29 0.13 - 0.58 - - sub rsp, 24
- - - - 1.00 - 0.72 0.28 mov qword ptr [rsp], rsi
- - - - 1.00 - 0.28 0.72 mov qword ptr [rsp + 8], rax
- - - - 1.00 - 0.72 0.28 mov qword ptr [rsp + 16], rcx
- - 0.76 0.24 - - - - lea rdi, [rip + .Lanon.HASH.7]
- - 0.82 0.18 - - - - lea rcx, [rip + .Lanon.HASH.1]
- - 0.92 0.08 - - - - lea r8, [rip + .Lanon.HASH.9]
- - 0.09 0.68 - 0.23 - - mov rdx, rsp
- - 0.16 0.84 - - - - mov esi, 58
- - - - 1.00 1.00 0.54 1.46 call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Dynamically Padded
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable, SplitAt)]
#[repr(C, align(4))]
pub struct Packet<Magic> {
magic_number: Magic,
milk: u8,
mug_size: u8,
temperature: [u8; 5],
marshmallows: [[u8; 3]],
}
/// A packet begining with the magic number `0xC0C0`.
pub type CocoPacket = Packet<C0C0>;
/// A packet beginning with any two initialized bytes.
pub type LocoPacket = Packet<[u8; 2]>;
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_padding.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_deref_dynamic_padding<'a>(
source: &'a Ref<&[u8], format::LocoPacket>,
) -> &'a format::LocoPacket {
core::ops::Deref::deref(source)
}
Assembly
bench_ref_type_deref_dynamic_padding:
mov rdx, qword ptr [rdi + 16]
mov rax, qword ptr [rdi]
mov rcx, qword ptr [rdi + 8]
mov esi, 1
movabs rdi, 3074457345618258599
cmp rdx, rdi
jae .LBB8_3
test al, 3
jne .LBB8_2
lea rdi, [rdx + 2*rdx]
or rdi, 3
add rdi, 9
cmp rcx, rdi
jne .LBB8_3
ret
.LBB8_2:
xor esi, esi
.LBB8_3:
sub rsp, 24
mov qword ptr [rsp], rsi
mov qword ptr [rsp + 8], rax
mov qword ptr [rsp + 16], rcx
lea rdi, [rip + .Lanon.HASH.7]
lea rcx, [rip + .Lanon.HASH.1]
lea r8, [rip + .Lanon.HASH.9]
mov rdx, rsp
mov esi, 58
call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Machine Code Analysis
Iterations: 100
Instructions: 2600
Total Cycles: 1812
Total uOps: 2900
Dispatch Width: 4
uOps Per Cycle: 1.60
IPC: 1.43
Block RThroughput: 7.3
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rdx, qword ptr [rdi + 16]
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rcx, qword ptr [rdi + 8]
1 1 0.33 mov esi, 1
1 1 0.33 movabs rdi, 3074457345618258599
1 1 0.33 cmp rdx, rdi
1 1 1.00 jae .LBB8_3
1 1 0.33 test al, 3
1 1 1.00 jne .LBB8_2
1 1 0.50 lea rdi, [rdx + 2*rdx]
1 1 0.33 or rdi, 3
1 1 0.33 add rdi, 9
1 1 0.33 cmp rcx, rdi
1 1 1.00 jne .LBB8_3
1 1 1.00 U ret
1 0 0.25 xor esi, esi
1 1 0.33 sub rsp, 24
1 1 1.00 * mov qword ptr [rsp], rsi
1 1 1.00 * mov qword ptr [rsp + 8], rax
1 1 1.00 * mov qword ptr [rsp + 16], rcx
1 1 0.50 lea rdi, [rip + .Lanon.HASH.7]
1 1 0.50 lea rcx, [rip + .Lanon.HASH.1]
1 1 0.50 lea r8, [rip + .Lanon.HASH.9]
1 1 0.33 mov rdx, rsp
1 1 0.33 mov esi, 58
4 7 1.00 * call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 6.41 6.42 4.00 6.17 3.99 4.01
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.54 0.46 mov rdx, qword ptr [rdi + 16]
- - - - - - 0.50 0.50 mov rax, qword ptr [rdi]
- - - - - - 0.49 0.51 mov rcx, qword ptr [rdi + 8]
- - 0.52 0.47 - 0.01 - - mov esi, 1
- - 0.47 0.53 - - - - movabs rdi, 3074457345618258599
- - 0.47 0.53 - - - - cmp rdx, rdi
- - - - - 1.00 - - jae .LBB8_3
- - 0.54 0.44 - 0.02 - - test al, 3
- - - - - 1.00 - - jne .LBB8_2
- - 0.44 0.56 - - - - lea rdi, [rdx + 2*rdx]
- - 0.48 0.52 - - - - or rdi, 3
- - 0.48 0.48 - 0.04 - - add rdi, 9
- - 0.51 0.39 - 0.10 - - cmp rcx, rdi
- - - - - 1.00 - - jne .LBB8_3
- - - - - 1.00 - - ret
- - - - - - - - xor esi, esi
- - 0.53 0.47 - - - - sub rsp, 24
- - - - 1.00 - 0.52 0.48 mov qword ptr [rsp], rsi
- - - - 1.00 - 0.48 0.52 mov qword ptr [rsp + 8], rax
- - - - 1.00 - 0.52 0.48 mov qword ptr [rsp + 16], rcx
- - 0.49 0.51 - - - - lea rdi, [rip + .Lanon.HASH.7]
- - 0.46 0.54 - - - - lea rcx, [rip + .Lanon.HASH.1]
- - 0.54 0.46 - - - - lea r8, [rip + .Lanon.HASH.9]
- - 0.04 0.06 - 0.90 - - mov rdx, rsp
- - 0.44 0.46 - 0.10 - - mov esi, 58
- - - - 1.00 1.00 0.94 1.06 call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Source§impl<B, T> DerefMut for Ref<B, T>
impl<B, T> DerefMut for Ref<B, T>
Source§fn deref_mut(&mut self) -> &mut T
fn deref_mut(&mut self) -> &mut T
Mutably dereferences the value.
§ Code Generation
This abstraction is safe and cheap, but does not necessarily have zero runtime cost. The codegen you experience in practice will depend on optimization level, the layout of the destination type, and what the compiler can prove about the source.
The below examples illustrate typical codegen for increasingly complex types:
Sized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [u8; 2],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_static_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_deref_mut_static_size<'a>(
source: &'a mut Ref<&mut [u8], format::LocoPacket>,
) -> &'a mut format::LocoPacket {
core::ops::DerefMut::deref_mut(source)
}
Assembly
bench_ref_type_deref_mut_static_size:
mov rax, qword ptr [rdi]
ret
Machine Code Analysis
Iterations: 100
Instructions: 200
Total Cycles: 103
Total uOps: 200
Dispatch Width: 4
uOps Per Cycle: 1.94
IPC: 1.94
Block RThroughput: 1.0
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rax, qword ptr [rdi]
1 1 1.00 U ret
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - - - - 1.00 0.50 0.50
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.50 0.50 mov rax, qword ptr [rdi]
- - - - - 1.00 - - ret
Unsized
Format
use zerocopy_derive::*;
// The only valid value of this type are the bytes `0xC0C0`.
#[derive(TryFromBytes, KnownLayout, Immutable, IntoBytes)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
macro_rules! define_packet {
($name: ident, $trait: ident, $leading_field: ty) => {
#[derive($trait, KnownLayout, Immutable, IntoBytes, SplitAt)]
#[repr(C, align(2))]
pub struct $name {
magic_number: $leading_field,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
};
}
/// Packet begins with bytes 0xC0C0.
define_packet!(CocoPacket, TryFromBytes, C0C0);
/// Packet begins with any two bytes.
define_packet!(LocoPacket, FromBytes, [u8; 2]);
Benchmark
// Copyright 2026 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use zerocopy::Ref;
#[path = "formats/coco_dynamic_size.rs"]
mod format;
#[unsafe(no_mangle)]
fn bench_ref_type_deref_mut_dynamic_size<'a>(
source: &'a mut Ref<&mut [u8], format::LocoPacket>,
) -> &'a mut format::LocoPacket {
core::ops::DerefMut::deref_mut(source)
}
Assembly
bench_ref_type_deref_mut_dynamic_size:
mov rdx, qword ptr [rdi + 16]
mov rax, qword ptr [rdi]
mov rcx, qword ptr [rdi + 8]
mov esi, 1
movabs rdi, 4611686018427387902
cmp rdx, rdi
jae .LBB8_3
test al, 1
jne .LBB8_2
lea rdi, [2*rdx + 4]
cmp rcx, rdi
jne .LBB8_3
ret
.LBB8_2:
xor esi, esi
.LBB8_3:
sub rsp, 24
mov qword ptr [rsp], rsi
mov qword ptr [rsp + 8], rax
mov qword ptr [rsp + 16], rcx
lea rdi, [rip + .Lanon.HASH.7]
lea rcx, [rip + .Lanon.HASH.1]
lea r8, [rip + .Lanon.HASH.9]
mov rdx, rsp
mov esi, 65
call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Machine Code Analysis
Iterations: 100
Instructions: 2400
Total Cycles: 1647
Total uOps: 2700
Dispatch Width: 4
uOps Per Cycle: 1.64
IPC: 1.46
Block RThroughput: 6.8
Instruction Info:
[1]: #uOps
[2]: Latency
[3]: RThroughput
[4]: MayLoad
[5]: MayStore
[6]: HasSideEffects (U)
[1] [2] [3] [4] [5] [6] Instructions:
1 5 0.50 * mov rdx, qword ptr [rdi + 16]
1 5 0.50 * mov rax, qword ptr [rdi]
1 5 0.50 * mov rcx, qword ptr [rdi + 8]
1 1 0.33 mov esi, 1
1 1 0.33 movabs rdi, 4611686018427387902
1 1 0.33 cmp rdx, rdi
1 1 1.00 jae .LBB8_3
1 1 0.33 test al, 1
1 1 1.00 jne .LBB8_2
1 1 0.50 lea rdi, [2*rdx + 4]
1 1 0.33 cmp rcx, rdi
1 1 1.00 jne .LBB8_3
1 1 1.00 U ret
1 0 0.25 xor esi, esi
1 1 0.33 sub rsp, 24
1 1 1.00 * mov qword ptr [rsp], rsi
1 1 1.00 * mov qword ptr [rsp + 8], rax
1 1 1.00 * mov qword ptr [rsp + 16], rcx
1 1 0.50 lea rdi, [rip + .Lanon.HASH.7]
1 1 0.50 lea rcx, [rip + .Lanon.HASH.1]
1 1 0.50 lea r8, [rip + .Lanon.HASH.9]
1 1 0.33 mov rdx, rsp
1 1 0.33 mov esi, 65
4 7 1.00 * call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]
Resources:
[0] - SBDivider
[1] - SBFPDivider
[2] - SBPort0
[3] - SBPort1
[4] - SBPort4
[5] - SBPort5
[6.0] - SBPort23
[6.1] - SBPort23
Resource pressure per iteration:
[0] [1] [2] [3] [4] [5] [6.0] [6.1]
- - 5.15 5.74 4.00 6.11 3.98 4.02
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - 0.71 0.29 mov rdx, qword ptr [rdi + 16]
- - - - - - 0.72 0.28 mov rax, qword ptr [rdi]
- - - - - - 0.29 0.71 mov rcx, qword ptr [rdi + 8]
- - 0.83 0.16 - 0.01 - - mov esi, 1
- - 0.16 0.84 - - - - movabs rdi, 4611686018427387902
- - 0.80 0.04 - 0.16 - - cmp rdx, rdi
- - - - - 1.00 - - jae .LBB8_3
- - 0.13 0.74 - 0.13 - - test al, 1
- - - - - 1.00 - - jne .LBB8_2
- - 0.10 0.90 - - - - lea rdi, [2*rdx + 4]
- - 0.09 0.91 - - - - cmp rcx, rdi
- - - - - 1.00 - - jne .LBB8_3
- - - - - 1.00 - - ret
- - - - - - - - xor esi, esi
- - 0.29 0.13 - 0.58 - - sub rsp, 24
- - - - 1.00 - 0.72 0.28 mov qword ptr [rsp], rsi
- - - - 1.00 - 0.28 0.72 mov qword ptr [rsp + 8], rax
- - - - 1.00 - 0.72 0.28 mov qword ptr [rsp + 16], rcx
- - 0.76 0.24 - - - - lea rdi, [rip + .Lanon.HASH.7]
- - 0.82 0.18 - - - - lea rcx, [rip + .Lanon.HASH.1]
- - 0.92 0.08 - - - - lea r8, [rip + .Lanon.HASH.9]
- - 0.09 0.68 - 0.23 - - mov rdx, rsp
- - 0.16 0.84 - - - - mov esi, 65
- - - - 1.00 1.00 0.54 1.46 call qword ptr [rip + core::result::unwrap_failed@GOTPCREL]