pub unsafe trait FromBytes: FromZeros {
Show 16 methods
// Provided methods
fn ref_from_bytes(source: &[u8]) -> Result<&Self, CastError<&[u8], Self>>
where Self: KnownLayout + Immutable { ... }
fn ref_from_prefix(
source: &[u8],
) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>
where Self: KnownLayout + Immutable { ... }
fn ref_from_suffix(
source: &[u8],
) -> Result<(&[u8], &Self), CastError<&[u8], Self>>
where Self: Immutable + KnownLayout { ... }
fn mut_from_bytes(
source: &mut [u8],
) -> Result<&mut Self, CastError<&mut [u8], Self>>
where Self: IntoBytes + KnownLayout { ... }
fn mut_from_prefix(
source: &mut [u8],
) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>
where Self: IntoBytes + KnownLayout { ... }
fn mut_from_suffix(
source: &mut [u8],
) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>
where Self: IntoBytes + KnownLayout { ... }
fn ref_from_bytes_with_elems(
source: &[u8],
count: usize,
) -> Result<&Self, CastError<&[u8], Self>>
where Self: KnownLayout<PointerMetadata = usize> + Immutable { ... }
fn ref_from_prefix_with_elems(
source: &[u8],
count: usize,
) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>
where Self: KnownLayout<PointerMetadata = usize> + Immutable { ... }
fn ref_from_suffix_with_elems(
source: &[u8],
count: usize,
) -> Result<(&[u8], &Self), CastError<&[u8], Self>>
where Self: KnownLayout<PointerMetadata = usize> + Immutable { ... }
fn mut_from_bytes_with_elems(
source: &mut [u8],
count: usize,
) -> Result<&mut Self, CastError<&mut [u8], Self>>
where Self: IntoBytes + KnownLayout<PointerMetadata = usize> + Immutable { ... }
fn mut_from_prefix_with_elems(
source: &mut [u8],
count: usize,
) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>
where Self: IntoBytes + KnownLayout<PointerMetadata = usize> { ... }
fn mut_from_suffix_with_elems(
source: &mut [u8],
count: usize,
) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>
where Self: IntoBytes + KnownLayout<PointerMetadata = usize> { ... }
fn read_from_bytes(source: &[u8]) -> Result<Self, SizeError<&[u8], Self>>
where Self: Sized { ... }
fn read_from_prefix(
source: &[u8],
) -> Result<(Self, &[u8]), SizeError<&[u8], Self>>
where Self: Sized { ... }
fn read_from_suffix(
source: &[u8],
) -> Result<(&[u8], Self), SizeError<&[u8], Self>>
where Self: Sized { ... }
fn read_from_io<R>(src: R) -> Result<Self>
where Self: Sized,
R: Read { ... }
}Expand description
Types for which any bit pattern is valid.
Any memory region of the appropriate length which contains initialized bytes
can be viewed as any FromBytes type with no runtime overhead. This is
useful for efficiently parsing bytes as structured data.
§Warning: Padding bytes
Note that, when a value is moved or copied, only the non-padding bytes of that value are guaranteed to be preserved. It is unsound to assume that values written to padding bytes are preserved after a move or copy. For example, the following is unsound:
use core::mem::{size_of, transmute};
use zerocopy::FromZeros;
// Assume `Foo` is a type with padding bytes.
#[derive(FromZeros, Default)]
struct Foo {
...
}
let mut foo: Foo = Foo::default();
FromZeros::zero(&mut foo);
// UNSOUND: Although `FromZeros::zero` writes zeros to all bytes of `foo`,
// those writes are not guaranteed to be preserved in padding bytes when
// `foo` is moved, so this may expose padding bytes as `u8`s.
let foo_bytes: [u8; size_of::<Foo>()] = unsafe { transmute(foo) };§Implementation
Do not implement this trait yourself! Instead, use
#[derive(FromBytes)]; e.g.:
#[derive(FromBytes)]
struct MyStruct {
...
}
#[derive(FromBytes)]
#[repr(u8)]
enum MyEnum {
...
}
#[derive(FromBytes, Immutable)]
union MyUnion {
...
}This derive performs a sophisticated, compile-time safety analysis to
determine whether a type is FromBytes.
§Safety
This section describes what is required in order for T: FromBytes, and
what unsafe code may assume of such types. If you don’t plan on implementing
FromBytes manually, and you don’t plan on writing unsafe code that
operates on FromBytes types, then you don’t need to read this section.
If T: FromBytes, then unsafe code may assume that it is sound to produce a
T whose bytes are initialized to any sequence of valid u8s (in other
words, any byte value which is not uninitialized). If a type is marked as
FromBytes which violates this contract, it may cause undefined behavior.
#[derive(FromBytes)] only permits types which satisfy these
requirements.
Provided Methods§
Sourcefn ref_from_bytes(source: &[u8]) -> Result<&Self, CastError<&[u8], Self>>where
Self: KnownLayout + Immutable,
fn ref_from_bytes(source: &[u8]) -> Result<&Self, CastError<&[u8], Self>>where
Self: KnownLayout + Immutable,
Interprets the given source as a &Self.
This method attempts to return a reference to source interpreted as a
Self. If the length of source is not a valid size of
Self, or if source is not appropriately aligned, this
returns Err. If Self: Unaligned, you can
infallibly discard the alignment error.
Self 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(FromBytes, Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: u16,
trailing_dst: [()],
}
let _ = ZSTy::ref_from_bytes(0u16.as_bytes()); // ⚠ Compile Error!§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C)]
struct PacketHeader {
src_port: [u8; 2],
dst_port: [u8; 2],
length: [u8; 2],
checksum: [u8; 2],
}
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C)]
struct Packet {
header: PacketHeader,
body: [u8],
}
// These bytes encode a `Packet`.
let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11][..];
let packet = Packet::ref_from_bytes(bytes).unwrap();
assert_eq!(packet.header.src_port, [0, 1]);
assert_eq!(packet.header.dst_port, [2, 3]);
assert_eq!(packet.header.length, [4, 5]);
assert_eq!(packet.header.checksum, [6, 7]);
assert_eq!(packet.body, [8, 9, 10, 11]);§ Code Generation
This abstraction for reinterpreting a buffer of bytes as a structured type is safe and cheap, but does not necessarily have zero runtime cost. The below code generation benchmark exercises this routine on a destination type whose complex layout places complex requirements on the source:
- the source must begin an even memory address
- the source has a minimum length of 4 bytes
- the source has a total length divisible by 2
These conditions must all be checked at runtime in this example, but 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)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C, align(2))]
pub struct Packet<Magic> {
magic_number: Magic,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
/// 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
#[path = "formats/coco.rs"]
mod format;
#[unsafe(no_mangle)]
fn codegen_test(source: &[u8]) -> Option<&format::LocoPacket> {
zerocopy::FromBytes::ref_from_bytes(source).ok()
}
Machine Code Analysis
§Replication
You may replicate this analysis on your device with cargo-show-asm by running:
cargo asm --bench ref_from_bytes codegen_test --mca§Results
Iterations: 100
Instructions: 1800
Total Cycles: 704
Total uOps: 2000
Dispatch Width: 4
uOps Per Cycle: 2.84
IPC: 2.56
Block RThroughput: 5.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 rdx, rsi
1 1 0.33 cmp rsi, 4
1 1 0.50 setb al
1 1 0.33 or al, dil
1 1 0.33 test al, 1
1 1 1.00 je .LBB5_2
1 0 0.25 xor eax, eax
1 1 1.00 U ret
1 1 0.50 lea rcx, [rdx - 4]
1 1 0.33 mov rsi, rcx
1 1 0.33 and rsi, -2
1 1 0.33 add rsi, 4
1 1 0.50 shr rcx
1 0 0.25 xor eax, eax
1 1 0.33 cmp rdx, rsi
2 2 0.67 cmove rdx, rcx
2 2 0.67 cmove 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]
- - 5.97 5.98 - 6.05 - -
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.97 0.01 - 0.02 - - mov rdx, rsi
- - 0.01 0.02 - 0.97 - - cmp rsi, 4
- - 0.03 - - 0.97 - - setb al
- - 0.01 0.02 - 0.97 - - or al, dil
- - - 0.98 - 0.02 - - test al, 1
- - - - - 1.00 - - je .LBB5_2
- - - - - - - - xor eax, eax
- - - - - 1.00 - - ret
- - 0.98 0.02 - - - - lea rcx, [rdx - 4]
- - 0.01 0.99 - - - - mov rsi, rcx
- - - 0.98 - 0.02 - - and rsi, -2
- - 0.98 0.01 - 0.01 - - add rsi, 4
- - 0.99 - - 0.01 - - shr rcx
- - - - - - - - xor eax, eax
- - 0.02 0.97 - 0.01 - - cmp rdx, rsi
- - 0.99 0.99 - 0.02 - - cmove rdx, rcx
- - 0.98 0.99 - 0.03 - - cmove rax, rdi
- - - - - 1.00 - - retSourcefn ref_from_prefix(
source: &[u8],
) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>where
Self: KnownLayout + Immutable,
fn ref_from_prefix(
source: &[u8],
) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>where
Self: KnownLayout + Immutable,
Interprets the prefix of the given source as a &Self without
copying.
This method computes the largest possible size of Self
that can fit in the leading bytes of source, then attempts to return
both a reference to those bytes interpreted as a Self, and a reference
to the remaining bytes. If there are insufficient bytes, or if source
is not appropriately aligned, this returns Err. If Self: Unaligned, you can infallibly discard the alignment
error.
Self 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. See ref_from_prefix_with_elems, which does
support such types. Attempting to use this method on such types results
in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(FromBytes, Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: u16,
trailing_dst: [()],
}
let _ = ZSTy::ref_from_prefix(0u16.as_bytes()); // ⚠ Compile Error!§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C)]
struct PacketHeader {
src_port: [u8; 2],
dst_port: [u8; 2],
length: [u8; 2],
checksum: [u8; 2],
}
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C)]
struct Packet {
header: PacketHeader,
body: [[u8; 2]],
}
// These are more bytes than are needed to encode a `Packet`.
let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14][..];
let (packet, suffix) = Packet::ref_from_prefix(bytes).unwrap();
assert_eq!(packet.header.src_port, [0, 1]);
assert_eq!(packet.header.dst_port, [2, 3]);
assert_eq!(packet.header.length, [4, 5]);
assert_eq!(packet.header.checksum, [6, 7]);
assert_eq!(packet.body, [[8, 9], [10, 11], [12, 13]]);
assert_eq!(suffix, &[14u8][..]);§ Code Generation
This abstraction for reinterpreting a buffer of bytes as a structured type is safe and cheap, but does not necessarily have zero runtime cost. The below code generation benchmark exercises this routine on a destination type whose complex layout places complex requirements on the source:
- the source must begin an even memory address
- the source has a minimum length of 4 bytes
These conditions must all be checked at runtime in this example, but 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)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C, align(2))]
pub struct Packet<Magic> {
magic_number: Magic,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
/// 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
#[path = "formats/coco.rs"]
mod format;
#[unsafe(no_mangle)]
fn codegen_test(source: &[u8]) -> Option<&format::LocoPacket> {
match zerocopy::FromBytes::ref_from_prefix(source) {
Ok((packet, _rest)) => Some(packet),
_ => None,
}
}
Machine Code Analysis
§Replication
You may replicate this analysis on your device with cargo-show-asm by running:
cargo asm --bench ref_from_prefix codegen_test --mca§Results
Iterations: 100
Instructions: 1400
Total Cycles: 405
Total uOps: 1400
Dispatch Width: 4
uOps Per Cycle: 3.46
IPC: 3.46
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 0 0.25 xor edx, edx
1 1 0.33 mov eax, 0
1 1 0.33 test dil, 1
1 1 1.00 jne .LBB5_4
1 1 0.33 cmp rsi, 4
1 1 1.00 jae .LBB5_3
1 1 0.33 mov edx, 1
1 0 0.25 xor eax, eax
1 1 1.00 U ret
1 1 0.33 add rsi, -4
1 1 0.50 shr rsi
1 1 0.33 mov rdx, 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]
- - 3.99 3.99 - 4.02 - -
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - - - - - - xor edx, edx
- - 0.01 0.98 - 0.01 - - mov eax, 0
- - 0.98 0.02 - - - - test dil, 1
- - - - - 1.00 - - jne .LBB5_4
- - 0.02 0.98 - - - - cmp rsi, 4
- - - - - 1.00 - - jae .LBB5_3
- - 0.98 0.01 - 0.01 - - mov edx, 1
- - - - - - - - xor eax, eax
- - - - - 1.00 - - ret
- - 0.01 0.99 - - - - add rsi, -4
- - 1.00 - - - - - shr rsi
- - - 1.00 - - - - mov rdx, rsi
- - 0.99 0.01 - - - - mov rax, rdi
- - - - - 1.00 - - retSourcefn ref_from_suffix(
source: &[u8],
) -> Result<(&[u8], &Self), CastError<&[u8], Self>>where
Self: Immutable + KnownLayout,
fn ref_from_suffix(
source: &[u8],
) -> Result<(&[u8], &Self), CastError<&[u8], Self>>where
Self: Immutable + KnownLayout,
Interprets the suffix of the given bytes as a &Self.
This method computes the largest possible size of Self
that can fit in the trailing bytes of source, then attempts to return
both a reference to those bytes interpreted as a Self, 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
Self: Unaligned, you can infallibly discard the
alignment error.
Self 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. See ref_from_suffix_with_elems, which does
support such types. Attempting to use this method on such types results
in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(FromBytes, Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: u16,
trailing_dst: [()],
}
let _ = ZSTy::ref_from_suffix(0u16.as_bytes()); // ⚠ Compile Error!§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, Immutable, KnownLayout)]
#[repr(C)]
struct PacketTrailer {
frame_check_sequence: [u8; 4],
}
// These are more bytes than are needed to encode a `PacketTrailer`.
let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
let (prefix, trailer) = PacketTrailer::ref_from_suffix(bytes).unwrap();
assert_eq!(prefix, &[0, 1, 2, 3, 4, 5][..]);
assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);§ Code Generation
This abstraction for reinterpreting a buffer of bytes as a structured
type is safe and cheap, but does not necessarily have zero runtime cost.
The below code generation benchmark exercises this routine on a
destination type whose complex layout places complex requirements on the
source’s largest valid-size suffix for Self, which must:
- begin at an even memory address
- have a minimum length of 4 bytes
These conditions must all be checked at runtime in this example, but 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)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C, align(2))]
pub struct Packet<Magic> {
magic_number: Magic,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
/// 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
#[path = "formats/coco.rs"]
mod format;
#[unsafe(no_mangle)]
fn codegen_test(source: &[u8]) -> Option<&format::LocoPacket> {
match zerocopy::FromBytes::ref_from_suffix(source) {
Ok((_rest, packet)) => Some(packet),
_ => None,
}
}
Machine Code Analysis
§Replication
You may replicate this analysis on your device with cargo-show-asm by running:
cargo asm --bench ref_from_suffix codegen_test --mca§Results
Iterations: 100
Instructions: 1200
Total Cycles: 439
Total uOps: 1400
Dispatch Width: 4
uOps Per Cycle: 3.19
IPC: 2.73
Block RThroughput: 3.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.33 mov rdx, rsi
1 1 0.50 lea ecx, [rsi + rdi]
1 1 0.33 mov eax, edx
1 1 0.33 and eax, 1
1 1 0.33 add rax, rdi
1 0 0.25 xor esi, esi
1 1 0.33 sub rdx, 4
2 2 0.67 cmovb rax, rsi
1 1 0.50 shr rdx
1 1 0.33 test cl, 1
2 2 0.67 cmovne 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.33 4.33 - 4.34 - -
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.02 0.32 - 0.66 - - mov rdx, rsi
- - 0.32 0.68 - - - - lea ecx, [rsi + rdi]
- - 0.66 - - 0.34 - - mov eax, edx
- - 0.02 0.33 - 0.65 - - and eax, 1
- - - 0.99 - 0.01 - - add rax, rdi
- - - - - - - - xor esi, esi
- - 0.65 - - 0.35 - - sub rdx, 4
- - 1.00 1.00 - - - - cmovb rax, rsi
- - 0.66 - - 0.34 - - shr rdx
- - - 0.01 - 0.99 - - test cl, 1
- - 1.00 1.00 - - - - cmovne rax, rsi
- - - - - 1.00 - - retSourcefn mut_from_bytes(
source: &mut [u8],
) -> Result<&mut Self, CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
fn mut_from_bytes(
source: &mut [u8],
) -> Result<&mut Self, CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
Interprets the given source as a &mut Self.
This method attempts to return a reference to source interpreted as a
Self. If the length of source is not a valid size of
Self, or if source is not appropriately aligned, this
returns Err. If Self: Unaligned, you can
infallibly discard the alignment error.
Self 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. See mut_from_prefix_with_elems, which does
support such types. Attempting to use this method on such types results
in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
#[repr(C, packed)]
struct ZSTy {
leading_sized: [u8; 2],
trailing_dst: [()],
}
let mut source = [85, 85];
let _ = ZSTy::mut_from_bytes(&mut source[..]); // ⚠ Compile Error!§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C)]
struct PacketHeader {
src_port: [u8; 2],
dst_port: [u8; 2],
length: [u8; 2],
checksum: [u8; 2],
}
// These bytes encode a `PacketHeader`.
let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..];
let header = PacketHeader::mut_from_bytes(bytes).unwrap();
assert_eq!(header.src_port, [0, 1]);
assert_eq!(header.dst_port, [2, 3]);
assert_eq!(header.length, [4, 5]);
assert_eq!(header.checksum, [6, 7]);
header.checksum = [0, 0];
assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0]);
§ Code Generation
Sourcefn mut_from_prefix(
source: &mut [u8],
) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
fn mut_from_prefix(
source: &mut [u8],
) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
Interprets the prefix of the given source as a &mut Self without
copying.
This method computes the largest possible size of Self
that can fit in the leading bytes of source, then attempts to return
both a reference to those bytes interpreted as a Self, and a reference
to the remaining bytes. If there are insufficient bytes, or if source
is not appropriately aligned, this returns Err. If Self: Unaligned, you can infallibly discard the alignment
error.
Self 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. See mut_from_suffix_with_elems, which does
support such types. Attempting to use this method on such types results
in a compile-time assertion error; e.g.:
use zerocopy::*;
#[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
#[repr(C, packed)]
struct ZSTy {
leading_sized: [u8; 2],
trailing_dst: [()],
}
let mut source = [85, 85];
let _ = ZSTy::mut_from_prefix(&mut source[..]); // ⚠ Compile Error!§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C)]
struct PacketHeader {
src_port: [u8; 2],
dst_port: [u8; 2],
length: [u8; 2],
checksum: [u8; 2],
}
// These are more bytes than are needed to encode a `PacketHeader`.
let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
let (header, body) = PacketHeader::mut_from_prefix(bytes).unwrap();
assert_eq!(header.src_port, [0, 1]);
assert_eq!(header.dst_port, [2, 3]);
assert_eq!(header.length, [4, 5]);
assert_eq!(header.checksum, [6, 7]);
assert_eq!(body, &[8, 9][..]);
header.checksum = [0, 0];
body.fill(1);
assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 1, 1]);§ Code Generation
Sourcefn mut_from_suffix(
source: &mut [u8],
) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
fn mut_from_suffix(
source: &mut [u8],
) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>where
Self: IntoBytes + KnownLayout,
Interprets the suffix of the given source as a &mut Self without
copying.
This method computes the largest possible size of Self
that can fit in the trailing bytes of source, then attempts to return
both a reference to those bytes interpreted as a Self, 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
Self: Unaligned, you can infallibly discard the
alignment error.
Self 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(FromBytes, Immutable, IntoBytes, KnownLayout)]
#[repr(C, packed)]
struct ZSTy {
leading_sized: [u8; 2],
trailing_dst: [()],
}
let mut source = [85, 85];
let _ = ZSTy::mut_from_suffix(&mut source[..]); // ⚠ Compile Error!§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
#[repr(C)]
struct PacketTrailer {
frame_check_sequence: [u8; 4],
}
// These are more bytes than are needed to encode a `PacketTrailer`.
let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
let (prefix, trailer) = PacketTrailer::mut_from_suffix(bytes).unwrap();
assert_eq!(prefix, &[0u8, 1, 2, 3, 4, 5][..]);
assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
prefix.fill(0);
trailer.frame_check_sequence.fill(1);
assert_eq!(bytes, [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]);§ Code Generation
Sourcefn ref_from_bytes_with_elems(
source: &[u8],
count: usize,
) -> Result<&Self, CastError<&[u8], Self>>
fn ref_from_bytes_with_elems( source: &[u8], count: usize, ) -> Result<&Self, CastError<&[u8], Self>>
Interprets the given source as a &Self with a DST length equal to
count.
This method attempts to return a reference to source interpreted as a
Self with count trailing elements. 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 Self: Unaligned, you can infallibly discard the alignment
error.
§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, Immutable)]
#[repr(C)]
struct Pixel {
r: u8,
g: u8,
b: u8,
a: u8,
}
let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..];
let pixels = <[Pixel]>::ref_from_bytes_with_elems(bytes, 2).unwrap();
assert_eq!(pixels, &[
Pixel { r: 0, g: 1, b: 2, a: 3 },
Pixel { r: 4, g: 5, b: 6, a: 7 },
]);
Since an explicit count is provided, this method supports types with
zero-sized trailing slice elements. Methods such as ref_from_bytes
which do not take an explicit count do not support such types.
use zerocopy::*;
#[derive(FromBytes, Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: [u8; 2],
trailing_dst: [()],
}
let src = &[85, 85][..];
let zsty = ZSTy::ref_from_bytes_with_elems(src, 42).unwrap();
assert_eq!(zsty.trailing_dst.len(), 42);§ Code Generation
This abstraction for reinterpreting a buffer of bytes as a structured type is safe and cheap, but does not necessarily have zero runtime cost. The below code generation benchmark exercises this routine on a destination type whose complex layout places complex requirements on the source:
- the source must begin an even memory address
- the source has a total length that exactly fits a
Selfwith a trailing slice length ofelems
These conditions must all be checked at runtime in this example, but 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)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C, align(2))]
pub struct Packet<Magic> {
magic_number: Magic,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
/// 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
#[path = "formats/coco.rs"]
mod format;
#[unsafe(no_mangle)]
fn codegen_test(source: &[u8], count: usize) -> Option<&format::LocoPacket> {
zerocopy::FromBytes::ref_from_bytes_with_elems(source, count).ok()
}
Machine Code Analysis
§Replication
You may replicate this analysis on your device with cargo-show-asm by running:
cargo asm --bench ref_from_bytes_with_elems codegen_test --mca§Results
Iterations: 100
Instructions: 1300
Total Cycles: 439
Total uOps: 1400
Dispatch Width: 4
uOps Per Cycle: 3.19
IPC: 2.96
Block RThroughput: 3.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.33 movabs rax, 9223372036854775805
1 1 0.33 cmp rdx, rax
2 2 1.00 seta cl
1 1 0.33 mov rax, rdi
1 1 0.33 or dil, cl
1 1 0.33 test dil, 1
1 1 1.00 jne .LBB5_2
1 1 0.50 lea rcx, [2*rdx + 4]
1 1 0.33 cmp rsi, rcx
1 1 1.00 je .LBB5_3
1 0 0.25 xor eax, eax
1 1 0.33 mov rdx, 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.32 4.33 - 4.35 - -
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - 0.99 - 0.01 - - movabs rax, 9223372036854775805
- - 0.33 0.67 - - - - cmp rdx, rax
- - 1.98 - - 0.02 - - seta cl
- - 0.01 0.99 - - - - mov rax, rdi
- - 1.00 - - - - - or dil, cl
- - 0.99 0.01 - - - - test dil, 1
- - - - - 1.00 - - jne .LBB5_2
- - - 1.00 - - - - lea rcx, [2*rdx + 4]
- - 0.01 - - 0.99 - - cmp rsi, rcx
- - - - - 1.00 - - je .LBB5_3
- - - - - - - - xor eax, eax
- - - 0.67 - 0.33 - - mov rdx, rsi
- - - - - 1.00 - - retSourcefn ref_from_prefix_with_elems(
source: &[u8],
count: usize,
) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>
fn ref_from_prefix_with_elems( source: &[u8], count: usize, ) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>
Interprets the prefix of the given source as a DST &Self with length
equal to count.
This method attempts to return a reference to the prefix of source
interpreted as a Self 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 Self: Unaligned, you can infallibly discard the alignment
error.
§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, Immutable)]
#[repr(C)]
struct Pixel {
r: u8,
g: u8,
b: u8,
a: u8,
}
// These are more bytes than are needed to encode two `Pixel`s.
let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
let (pixels, suffix) = <[Pixel]>::ref_from_prefix_with_elems(bytes, 2).unwrap();
assert_eq!(pixels, &[
Pixel { r: 0, g: 1, b: 2, a: 3 },
Pixel { r: 4, g: 5, b: 6, a: 7 },
]);
assert_eq!(suffix, &[8, 9]);Since an explicit count is provided, this method supports types with
zero-sized trailing slice elements. Methods such as ref_from_prefix
which do not take an explicit count do not support such types.
use zerocopy::*;
#[derive(FromBytes, Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: [u8; 2],
trailing_dst: [()],
}
let src = &[85, 85][..];
let (zsty, _) = ZSTy::ref_from_prefix_with_elems(src, 42).unwrap();
assert_eq!(zsty.trailing_dst.len(), 42);§ Code Generation
This abstraction for reinterpreting a buffer of bytes as a structured type is safe and cheap, but does not necessarily have zero runtime cost. The below code generation benchmark exercises this routine on a destination type whose complex layout places complex requirements on the source:
- the source must begin an even memory address
- the source has a prefix that fits a
Selfwith a trailing slice length ofcount
These conditions must all be checked at runtime in this example, but 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)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C, align(2))]
pub struct Packet<Magic> {
magic_number: Magic,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
/// 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
#[path = "formats/coco.rs"]
mod format;
#[unsafe(no_mangle)]
fn codegen_test(source: &[u8], count: usize) -> Option<&format::LocoPacket> {
match zerocopy::FromBytes::ref_from_prefix_with_elems(source, count) {
Ok((packet, _rest)) => Some(packet),
_ => None,
}
}
Machine Code Analysis
§Replication
You may replicate this analysis on your device with cargo-show-asm by running:
cargo asm --bench ref_from_prefix_with_elems codegen_test --mca§Results
Iterations: 100
Instructions: 1900
Total Cycles: 672
Total uOps: 2300
Dispatch Width: 4
uOps Per Cycle: 3.42
IPC: 2.83
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 movabs rax, 9223372036854775805
1 1 0.33 cmp rdx, rax
1 1 1.00 ja .LBB5_1
1 1 0.33 mov rcx, rdx
1 0 0.25 xor edx, edx
1 1 0.33 mov eax, 0
1 1 0.33 test dil, 1
1 1 1.00 jne .LBB5_4
1 1 0.50 lea rax, [2*rcx + 4]
1 0 0.25 xor r8d, r8d
1 1 0.33 cmp rax, rsi
1 1 0.33 mov edx, 1
3 3 1.00 cmovbe rdx, rcx
3 3 1.00 cmova rdi, r8
1 1 0.33 mov rax, rdi
1 1 1.00 U ret
1 1 0.33 mov edx, 1
1 0 0.25 xor eax, eax
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 - 6.68 - -
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - - 0.99 - 0.01 - - movabs rax, 9223372036854775805
- - 0.37 0.63 - - - - cmp rdx, rax
- - - - - 1.00 - - ja .LBB5_1
- - 0.63 0.37 - - - - mov rcx, rdx
- - - - - - - - xor edx, edx
- - 0.01 0.98 - 0.01 - - mov eax, 0
- - 0.98 0.02 - - - - test dil, 1
- - - - - 1.00 - - jne .LBB5_4
- - 0.01 0.99 - - - - lea rax, [2*rcx + 4]
- - - - - - - - xor r8d, r8d
- - 1.00 - - - - - cmp rax, rsi
- - - 0.67 - 0.33 - - mov edx, 1
- - 0.73 0.98 - 1.29 - - cmovbe rdx, rcx
- - 1.60 0.36 - 1.04 - - cmova rdi, r8
- - 0.99 0.01 - - - - mov rax, rdi
- - - - - 1.00 - - ret
- - 0.34 0.66 - - - - mov edx, 1
- - - - - - - - xor eax, eax
- - - - - 1.00 - - retSourcefn ref_from_suffix_with_elems(
source: &[u8],
count: usize,
) -> Result<(&[u8], &Self), CastError<&[u8], Self>>
fn ref_from_suffix_with_elems( source: &[u8], count: usize, ) -> Result<(&[u8], &Self), CastError<&[u8], Self>>
Interprets the suffix of the given source as a DST &Self with length
equal to count.
This method attempts to return a reference to the suffix of source
interpreted as a Self 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
Self: Unaligned, you can infallibly discard the
alignment error.
§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, Immutable)]
#[repr(C)]
struct Pixel {
r: u8,
g: u8,
b: u8,
a: u8,
}
// These are more bytes than are needed to encode two `Pixel`s.
let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
let (prefix, pixels) = <[Pixel]>::ref_from_suffix_with_elems(bytes, 2).unwrap();
assert_eq!(prefix, &[0, 1]);
assert_eq!(pixels, &[
Pixel { r: 2, g: 3, b: 4, a: 5 },
Pixel { r: 6, g: 7, b: 8, a: 9 },
]);Since an explicit count is provided, this method supports types with
zero-sized trailing slice elements. Methods such as ref_from_suffix
which do not take an explicit count do not support such types.
use zerocopy::*;
#[derive(FromBytes, Immutable, KnownLayout)]
#[repr(C)]
struct ZSTy {
leading_sized: [u8; 2],
trailing_dst: [()],
}
let src = &[85, 85][..];
let (_, zsty) = ZSTy::ref_from_suffix_with_elems(src, 42).unwrap();
assert_eq!(zsty.trailing_dst.len(), 42);§ Code Generation
This abstraction for reinterpreting a buffer of bytes as a structured
type is safe and cheap, but does not necessarily have zero runtime cost.
The below code generation benchmark exercises this routine on a
destination type whose complex layout places complex requirements on the
valid-size suffix for a Self of trailing slice length count, which
must:
- begin at an even memory address
- have a minimum length of 4 bytes
These conditions must all be checked at runtime in this example, but 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)]
#[repr(u16)]
pub enum C0C0 {
_XC0C0 = 0xC0C0,
}
#[derive(FromBytes, KnownLayout, Immutable)]
#[repr(C, align(2))]
pub struct Packet<Magic> {
magic_number: Magic,
mug_size: u8,
temperature: u8,
marshmallows: [[u8; 2]],
}
/// 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
#[path = "formats/coco.rs"]
mod format;
#[unsafe(no_mangle)]
fn codegen_test(source: &[u8], count: usize) -> Option<&format::LocoPacket> {
match zerocopy::FromBytes::ref_from_suffix_with_elems(source, count) {
Ok((_rest, packet)) => Some(packet),
_ => None,
}
}
Machine Code Analysis
§Replication
You may replicate this analysis on your device with cargo-show-asm by running:
cargo asm --bench ref_from_suffix_with_elems codegen_test --mca§Results
Iterations: 100
Instructions: 1900
Total Cycles: 571
Total uOps: 1900
Dispatch Width: 4
uOps Per Cycle: 3.33
IPC: 3.33
Block RThroughput: 5.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 movabs rax, 9223372036854775805
1 1 0.33 cmp rdx, rax
1 1 1.00 ja .LBB5_1
1 1 0.50 lea r8d, [rsi + rdi]
1 0 0.25 xor ecx, ecx
1 1 0.33 mov eax, 0
1 1 0.33 test r8b, 1
1 1 1.00 jne .LBB5_5
1 1 0.50 lea rax, [2*rdx + 4]
1 1 0.33 sub rsi, rax
1 1 1.00 jae .LBB5_4
1 0 0.25 xor eax, eax
1 1 0.33 mov edx, 1
1 1 1.00 U ret
1 1 0.33 add rdi, rsi
1 1 0.33 mov rcx, rdx
1 1 0.33 mov rax, rdi
1 1 0.33 mov rdx, 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]
- - 5.66 5.66 - 5.68 - -
Resource pressure by instruction:
[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions:
- - 0.66 0.33 - 0.01 - - movabs rax, 9223372036854775805
- - 0.01 0.99 - - - - cmp rdx, rax
- - - - - 1.00 - - ja .LBB5_1
- - 0.99 0.01 - - - - lea r8d, [rsi + rdi]
- - - - - - - - xor ecx, ecx
- - 0.33 0.33 - 0.34 - - mov eax, 0
- - 0.33 0.34 - 0.33 - - test r8b, 1
- - - - - 1.00 - - jne .LBB5_5
- - 0.34 0.66 - - - - lea rax, [2*rdx + 4]
- - - 1.00 - - - - sub rsi, rax
- - - - - 1.00 - - jae .LBB5_4
- - - - - - - - xor eax, eax
- - 1.00 - - - - - mov edx, 1
- - - - - 1.00 - - ret
- - - 1.00 - - - - add rdi, rsi
- - 1.00 - - - - - mov rcx, rdx
- - 0.32 0.68 - - - - mov rax, rdi
- - 0.68 0.32 - - - - mov rdx, rcx
- - - - - 1.00 - - retSourcefn mut_from_bytes_with_elems(
source: &mut [u8],
count: usize,
) -> Result<&mut Self, CastError<&mut [u8], Self>>
fn mut_from_bytes_with_elems( source: &mut [u8], count: usize, ) -> Result<&mut Self, CastError<&mut [u8], Self>>
Interprets the given source as a &mut Self with a DST length equal
to count.
This method attempts to return a reference to source interpreted as a
Self with count trailing elements. 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 Self: Unaligned, you can infallibly discard the alignment
error.
§Examples
use zerocopy::FromBytes;
#[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
#[repr(C)]
struct Pixel {
r: u8,
g: u8,
b: u8,
a: u8,
}
let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..];
let pixels = <[Pixel]>::mut_from_bytes_with_elems(bytes, 2).unwrap();
assert_eq!(pixels, &[
Pixel { r: 0, g: 1, b: 2, a: 3 },
Pixel { r: 4, g: 5, b: 6, a: 7 },
]);
pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0]);Since an explicit count is provided, this method supports types with
zero-sized trailing slice elements. Methods such as mut_from_bytes
which do not take an explicit count do not support such types.
use zerocopy::*;
#[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
#[repr(C, packed)]
struct ZSTy {
leading_sized: [u8; 2],
trailing_dst: [()],
}
let src = &mut [85, 85][..];
let zsty = ZSTy::mut_from_bytes_with_elems(src, 42).unwrap();
assert_eq!(zsty.trailing_dst.len(), 42);§ Code Generation
Sourcefn mut_from_prefix_with_elems(
source: &mut [u8],
count: usize,
) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>
fn mut_from_prefix_with_elems( source: &mut [u8], count: usize, ) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>
Interprets the prefix of the given source as a &mut Self with DST
length equal to count.
This method attempts to return a reference to the prefix of source
interpreted as a Self with count trailing elements, and a reference
to the preceding bytes. If there are insufficient bytes, or if source
is not appropriately aligned, this returns Err. If Self: Unaligned, you can infallibly discard the alignment
error.
§Examples
use zerocopy::FromBytes;
#[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
#[repr(C)]
struct Pixel {
r: u8,
g: u8,
b: u8,
a: u8,
}
// These are more bytes than are needed to encode two `Pixel`s.
let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
let (pixels, suffix) = <[Pixel]>::mut_from_prefix_with_elems(bytes, 2).unwrap();
assert_eq!(pixels, &[
Pixel { r: 0, g: 1, b: 2, a: 3 },
Pixel { r: 4, g: 5, b: 6, a: 7 },
]);
assert_eq!(suffix, &[8, 9]);
pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
suffix.fill(1);
assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0, 1, 1]);Since an explicit count is provided, this method supports types with
zero-sized trailing slice elements. Methods such as mut_from_prefix
which do not take an explicit count do not support such types.
use zerocopy::*;
#[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
#[repr(C, packed)]
struct ZSTy {
leading_sized: [u8; 2],
trailing_dst: [()],
}
let src = &mut [85, 85][..];
let (zsty, _) = ZSTy::mut_from_prefix_with_elems(src, 42).unwrap();
assert_eq!(zsty.trailing_dst.len(), 42);§ Code Generation
Sourcefn mut_from_suffix_with_elems(
source: &mut [u8],
count: usize,
) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>
fn mut_from_suffix_with_elems( source: &mut [u8], count: usize, ) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>
Interprets the suffix of the given source as a &mut Self with DST
length equal to count.
This method attempts to return a reference to the suffix of source
interpreted as a Self with count trailing elements, and a reference
to the remaining bytes. If there are insufficient bytes, or if that
suffix of source is not appropriately aligned, this returns Err. If
Self: Unaligned, you can infallibly discard the
alignment error.
§Examples
use zerocopy::FromBytes;
#[derive(FromBytes, IntoBytes, Immutable)]
#[repr(C)]
struct Pixel {
r: u8,
g: u8,
b: u8,
a: u8,
}
// These are more bytes than are needed to encode two `Pixel`s.
let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
let (prefix, pixels) = <[Pixel]>::mut_from_suffix_with_elems(bytes, 2).unwrap();
assert_eq!(prefix, &[0, 1]);
assert_eq!(pixels, &[
Pixel { r: 2, g: 3, b: 4, a: 5 },
Pixel { r: 6, g: 7, b: 8, a: 9 },
]);
prefix.fill(9);
pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
assert_eq!(bytes, [9, 9, 2, 3, 4, 5, 0, 0, 0, 0]);Since an explicit count is provided, this method supports types with
zero-sized trailing slice elements. Methods such as mut_from_suffix
which do not take an explicit count do not support such types.
use zerocopy::*;
#[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
#[repr(C, packed)]
struct ZSTy {
leading_sized: [u8; 2],
trailing_dst: [()],
}
let src = &mut [85, 85][..];
let (_, zsty) = ZSTy::mut_from_suffix_with_elems(src, 42).unwrap();
assert_eq!(zsty.trailing_dst.len(), 42);§ Code Generation
Sourcefn read_from_bytes(source: &[u8]) -> Result<Self, SizeError<&[u8], Self>>where
Self: Sized,
fn read_from_bytes(source: &[u8]) -> Result<Self, SizeError<&[u8], Self>>where
Self: Sized,
Reads a copy of Self from the given source.
If source.len() != size_of::<Self>(), read_from_bytes returns Err.
§Examples
use zerocopy::FromBytes;
#[derive(FromBytes)]
#[repr(C)]
struct PacketHeader {
src_port: [u8; 2],
dst_port: [u8; 2],
length: [u8; 2],
checksum: [u8; 2],
}
// These bytes encode a `PacketHeader`.
let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..];
let header = PacketHeader::read_from_bytes(bytes).unwrap();
assert_eq!(header.src_port, [0, 1]);
assert_eq!(header.dst_port, [2, 3]);
assert_eq!(header.length, [4, 5]);
assert_eq!(header.checksum, [6, 7]);Sourcefn read_from_prefix(
source: &[u8],
) -> Result<(Self, &[u8]), SizeError<&[u8], Self>>where
Self: Sized,
fn read_from_prefix(
source: &[u8],
) -> Result<(Self, &[u8]), SizeError<&[u8], Self>>where
Self: Sized,
Reads a copy of Self from the prefix of the given source.
This attempts to read a Self from the first size_of::<Self>() bytes
of source, returning that Self and any remaining bytes. If
source.len() < size_of::<Self>(), it returns Err.
§Examples
use zerocopy::FromBytes;
#[derive(FromBytes)]
#[repr(C)]
struct PacketHeader {
src_port: [u8; 2],
dst_port: [u8; 2],
length: [u8; 2],
checksum: [u8; 2],
}
// These are more bytes than are needed to encode a `PacketHeader`.
let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
let (header, body) = PacketHeader::read_from_prefix(bytes).unwrap();
assert_eq!(header.src_port, [0, 1]);
assert_eq!(header.dst_port, [2, 3]);
assert_eq!(header.length, [4, 5]);
assert_eq!(header.checksum, [6, 7]);
assert_eq!(body, [8, 9]);Sourcefn read_from_suffix(
source: &[u8],
) -> Result<(&[u8], Self), SizeError<&[u8], Self>>where
Self: Sized,
fn read_from_suffix(
source: &[u8],
) -> Result<(&[u8], Self), SizeError<&[u8], Self>>where
Self: Sized,
Reads a copy of Self from the suffix of the given source.
This attempts to read a Self from the last size_of::<Self>() bytes
of source, returning that Self and any preceding bytes. If
source.len() < size_of::<Self>(), it returns Err.
§Examples
use zerocopy::FromBytes;
#[derive(FromBytes)]
#[repr(C)]
struct PacketTrailer {
frame_check_sequence: [u8; 4],
}
// These are more bytes than are needed to encode a `PacketTrailer`.
let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
let (prefix, trailer) = PacketTrailer::read_from_suffix(bytes).unwrap();
assert_eq!(prefix, [0, 1, 2, 3, 4, 5]);
assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);Sourcefn read_from_io<R>(src: R) -> Result<Self>
Available on crate feature std only.
fn read_from_io<R>(src: R) -> Result<Self>
std only.Reads a copy of self from an io::Read.
This is useful for interfacing with operating system byte sinks (files, sockets, etc.).
§Examples
use zerocopy::{byteorder::big_endian::*, FromBytes};
use std::fs::File;
#[derive(FromBytes)]
#[repr(C)]
struct BitmapFileHeader {
signature: [u8; 2],
size: U32,
reserved: U64,
offset: U64,
}
let mut file = File::open("image.bin").unwrap();
let header = BitmapFileHeader::read_from_io(&mut file).unwrap();Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementations on Foreign Types§
impl FromBytes for Option<NonZeroI8>
impl FromBytes for Option<NonZeroI16>
impl FromBytes for Option<NonZeroI32>
impl FromBytes for Option<NonZeroI64>
impl FromBytes for Option<NonZeroI128>
impl FromBytes for Option<NonZeroIsize>
impl FromBytes for Option<NonZeroU8>
impl FromBytes for Option<NonZeroU16>
impl FromBytes for Option<NonZeroU32>
impl FromBytes for Option<NonZeroU64>
impl FromBytes for Option<NonZeroU128>
impl FromBytes for Option<NonZeroUsize>
impl FromBytes for f16
float-nightly only.impl FromBytes for f32
impl FromBytes for f64
impl FromBytes for f128
float-nightly only.impl FromBytes for i8
impl FromBytes for i16
impl FromBytes for i32
impl FromBytes for i64
impl FromBytes for i128
impl FromBytes for isize
impl FromBytes for u8
impl FromBytes for u16
impl FromBytes for u32
impl FromBytes for u64
impl FromBytes for u128
impl FromBytes for ()
impl FromBytes for usize
impl FromBytes for float64x1_t
rust=1.59.0 and crate feature simd only.impl FromBytes for float64x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for float32x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for float32x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int8x8_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int8x8x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int8x8x3_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int8x8x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int8x16_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int8x16x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int8x16x3_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int8x16x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int16x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int16x8_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int32x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int32x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int64x1_t
rust=1.59.0 and crate feature simd only.impl FromBytes for int64x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly8x8_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly8x8x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly8x8x3_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly8x8x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly8x16_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly8x16x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly8x16x3_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly8x16x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly16x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly16x8_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly64x1_t
rust=1.59.0 and crate feature simd only.impl FromBytes for poly64x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint8x8_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint8x8x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint8x8x3_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint8x8x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint8x16_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint8x16x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint8x16x3_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint8x16x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint16x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint16x4x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint16x4x3_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint16x4x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint16x8_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint32x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint32x4_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint64x1_t
rust=1.59.0 and crate feature simd only.impl FromBytes for uint64x2_t
rust=1.59.0 and crate feature simd only.impl FromBytes for AtomicI8
target_has_atomic=8 and rust=1.60.0 only.impl FromBytes for AtomicI16
target_has_atomic=16 and rust=1.60.0 only.impl FromBytes for AtomicI32
target_has_atomic=32 and rust=1.60.0 only.impl FromBytes for AtomicI64
target_has_atomic=64 and rust=1.60.0 only.impl FromBytes for AtomicIsize
target_has_atomic=ptr and rust=1.60.0 only.impl FromBytes for AtomicU8
target_has_atomic=8 and rust=1.60.0 only.impl FromBytes for AtomicU16
target_has_atomic=16 and rust=1.60.0 only.impl FromBytes for AtomicU32
target_has_atomic=32 and rust=1.60.0 only.impl FromBytes for AtomicU64
target_has_atomic=64 and rust=1.60.0 only.impl FromBytes for AtomicUsize
target_has_atomic=ptr and rust=1.60.0 only.