Skip to main content

Ref

Struct Ref 

Source
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>

Source

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>

Source

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
Source

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>
where B: ByteSlice, T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized,

Source

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>
where B: SplitByteSlice, T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized,

Source

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
Source

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>
where B: 'a + IntoByteSlice<'a>, T: FromBytes + KnownLayout + Immutable + ?Sized,

Source

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>
where B: 'a + IntoByteSliceMut<'a>, T: FromBytes + IntoBytes + KnownLayout + ?Sized,

Source

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>
where B: ByteSlice, T: ?Sized,

Source

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,

Source

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>
where B: ByteSlice, T: FromBytes,

Source

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,

Source

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§

Source§

impl<B: CloneableByteSlice + Clone, T: ?Sized> Clone for Ref<B, T>

Source§

fn clone(&self) -> Ref<B, T>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<B: CopyableByteSlice + Copy, T: ?Sized> Copy for Ref<B, T>

Source§

impl<T, B> Debug for Ref<B, T>

Source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<B, T> Deref for Ref<B, T>

Source§

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§

type Target = T

The resulting type after dereferencing.
Source§

impl<B, T> DerefMut for Ref<B, T>

Source§

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]
Source§

impl<T, B> Display for Ref<B, T>

Source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T, B> Eq for Ref<B, T>

Source§

impl<T, B> Ord for Ref<B, T>

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

fn clamp_to<R>(self, range: R) -> Self
where Self: Sized, R: ClampBounds<Self>,

🔬This is a nightly-only experimental API. (clamp_to)
Restrict a value to a certain range. Read more
Source§

impl<T, B> PartialEq for Ref<B, T>

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl<T, B> PartialOrd for Ref<B, T>

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more

Auto Trait Implementations§

§

impl<B, T> Freeze for Ref<B, T>
where B: Freeze, PhantomData<T>: Freeze, T: ?Sized,

§

impl<B, T> RefUnwindSafe for Ref<B, T>

§

impl<B, T> Send for Ref<B, T>
where B: Send, PhantomData<T>: Send, T: ?Sized,

§

impl<B, T> Sync for Ref<B, T>
where B: Sync, PhantomData<T>: Sync, T: ?Sized,

§

impl<B, T> Unpin for Ref<B, T>
where B: Unpin, PhantomData<T>: Unpin, T: ?Sized,

§

impl<B, T> UnsafeUnpin for Ref<B, T>

§

impl<B, T> UnwindSafe for Ref<B, T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.