zerocopy/lib.rs
1// Copyright 2018 The Fuchsia Authors
2//
3// Licensed under the 2-Clause BSD License <LICENSE-BSD or
4// https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0
5// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
6// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
7// This file may not be copied, modified, or distributed except according to
8// those terms.
9
10// After updating the following doc comment, make sure to run the following
11// command to update `README.md` based on its contents:
12//
13// cargo -q run --manifest-path tools/Cargo.toml -p generate-readme > README.md
14
15//! *<span style="font-size: 100%; color:grey;">Need more out of zerocopy?
16//! Submit a [customer request issue][customer-request-issue]!</span>*
17//!
18//! ***<span style="font-size: 140%">Fast, safe, <span
19//! style="color:red;">compile error</span>. Pick two.</span>***
20//!
21//! Zerocopy makes zero-cost memory manipulation effortless. We write `unsafe`
22//! so you don't have to.
23//!
24//! *Thanks for using zerocopy 0.8! For an overview of what changes from 0.7,
25//! check out our [release notes][release-notes], which include a step-by-step
26//! guide for upgrading from 0.7.*
27//!
28//! *Have questions? Need help? Ask the maintainers on [GitHub][github-q-a] or
29//! on [Discord][discord]!*
30//!
31//! [customer-request-issue]: https://github.com/google/zerocopy/issues/new/choose
32//! [release-notes]: https://github.com/google/zerocopy/discussions/1680
33//! [github-q-a]: https://github.com/google/zerocopy/discussions/categories/q-a
34//! [discord]: https://discord.gg/MAvWH2R6zk
35//!
36//! # Overview
37//!
38//! ##### Conversion Traits
39//!
40//! Zerocopy provides four derivable traits for zero-cost conversions:
41//! - [`TryFromBytes`] indicates that a type may safely be converted from
42//! certain byte sequences (conditional on runtime checks)
43//! - [`FromZeros`] indicates that a sequence of zero bytes represents a valid
44//! instance of a type
45//! - [`FromBytes`] indicates that a type may safely be converted from an
46//! arbitrary byte sequence
47//! - [`IntoBytes`] indicates that a type may safely be converted *to* a byte
48//! sequence
49//!
50//! These traits support sized types, slices, and [slice DSTs][slice-dsts].
51//!
52//! [slice-dsts]: KnownLayout#dynamically-sized-types
53//!
54//! ##### Marker Traits
55//!
56//! Zerocopy provides three derivable marker traits that do not provide any
57//! functionality themselves, but are required to call certain methods provided
58//! by the conversion traits:
59//! - [`KnownLayout`] indicates that zerocopy can reason about certain layout
60//! qualities of a type
61//! - [`Immutable`] indicates that a type is free from interior mutability,
62//! except by ownership or an exclusive (`&mut`) borrow
63//! - [`Unaligned`] indicates that a type's alignment requirement is 1
64//!
65//! You should generally derive these marker traits whenever possible.
66//!
67//! ##### Conversion Macros
68//!
69//! Zerocopy provides six macros for safe casting between types:
70//!
71//! - ([`try_`][try_transmute])[`transmute`] (conditionally) converts a value of
72//! one type to a value of another type of the same size
73//! - ([`try_`][try_transmute_mut])[`transmute_mut`] (conditionally) converts a
74//! mutable reference of one type to a mutable reference of another type of
75//! the same size
76//! - ([`try_`][try_transmute_ref])[`transmute_ref`] (conditionally) converts a
77//! mutable or immutable reference of one type to an immutable reference of
78//! another type of the same size
79//!
80//! These macros perform *compile-time* size and alignment checks, meaning that
81//! unconditional casts have zero cost at runtime. Conditional casts do not need
82//! to validate size or alignment runtime, but do need to validate contents.
83//!
84//! These macros cannot be used in generic contexts. For generic conversions,
85//! use the methods defined by the [conversion traits](#conversion-traits).
86//!
87//! ##### Byteorder-Aware Numerics
88//!
89//! Zerocopy provides byte-order aware integer types that support these
90//! conversions; see the [`byteorder`] module. These types are especially useful
91//! for network parsing.
92//!
93//! # Cargo Features
94//!
95//! - **`alloc`**
96//! By default, `zerocopy` is `no_std`. When the `alloc` feature is enabled,
97//! the `alloc` crate is added as a dependency, and some allocation-related
98//! functionality is added.
99//!
100//! - **`std`**
101//! By default, `zerocopy` is `no_std`. When the `std` feature is enabled, the
102//! `std` crate is added as a dependency (ie, `no_std` is disabled), and
103//! support for some `std` types is added. `std` implies `alloc`.
104//!
105//! - **`derive`**
106//! Provides derives for the core marker traits via the `zerocopy-derive`
107//! crate. These derives are re-exported from `zerocopy`, so it is not
108//! necessary to depend on `zerocopy-derive` directly.
109//!
110//! However, you may experience better compile times if you instead directly
111//! depend on both `zerocopy` and `zerocopy-derive` in your `Cargo.toml`,
112//! since doing so will allow Rust to compile these crates in parallel. To do
113//! so, do *not* enable the `derive` feature, and list both dependencies in
114//! your `Cargo.toml` with the same leading non-zero version number; e.g:
115//!
116//! ```toml
117//! [dependencies]
118//! zerocopy = "0.X"
119//! zerocopy-derive = "0.X"
120//! ```
121//!
122//! To avoid the risk of [duplicate import errors][duplicate-import-errors] if
123//! one of your dependencies enables zerocopy's `derive` feature, import
124//! derives as `use zerocopy_derive::*` rather than by name (e.g., `use
125//! zerocopy_derive::FromBytes`).
126//!
127//! - **`simd`**
128//! When the `simd` feature is enabled, `FromZeros`, `FromBytes`, and
129//! `IntoBytes` impls are emitted for all stable SIMD types which exist on the
130//! target platform. Note that the layout of SIMD types is not yet stabilized,
131//! so these impls may be removed in the future if layout changes make them
132//! invalid. For more information, see the Unsafe Code Guidelines Reference
133//! page on the [layout of packed SIMD vectors][simd-layout].
134//!
135//! - **`simd-nightly`**
136//! Enables the `simd` feature and adds support for SIMD types which are only
137//! available on nightly. Since these types are unstable, support for any type
138//! may be removed at any point in the future.
139//!
140//! - **`float-nightly`**
141//! Adds support for the unstable `f16` and `f128` types. These types are
142//! not yet fully implemented and may not be supported on all platforms.
143//!
144//! [duplicate-import-errors]: https://github.com/google/zerocopy/issues/1587
145//! [simd-layout]: https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html
146//!
147//! # Security Ethos
148//!
149//! Zerocopy is expressly designed for use in security-critical contexts. We
150//! strive to ensure that that zerocopy code is sound under Rust's current
151//! memory model, and *any future memory model*. We ensure this by:
152//! - **...not 'guessing' about Rust's semantics.**
153//! We annotate `unsafe` code with a precise rationale for its soundness that
154//! cites a relevant section of Rust's official documentation. When Rust's
155//! documented semantics are unclear, we work with the Rust Operational
156//! Semantics Team to clarify Rust's documentation.
157//! - **...rigorously testing our implementation.**
158//! We run tests using [Miri], ensuring that zerocopy is sound across a wide
159//! array of supported target platforms of varying endianness and pointer
160//! width, and across both current and experimental memory models of Rust.
161//! - **...formally proving the correctness of our implementation.**
162//! We apply formal verification tools like [Kani][kani] to prove zerocopy's
163//! correctness.
164//!
165//! For more information, see our full [soundness policy].
166//!
167//! [Miri]: https://github.com/rust-lang/miri
168//! [Kani]: https://github.com/model-checking/kani
169//! [soundness policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#soundness
170//!
171//! # Relationship to Project Safe Transmute
172//!
173//! [Project Safe Transmute] is an official initiative of the Rust Project to
174//! develop language-level support for safer transmutation. The Project consults
175//! with crates like zerocopy to identify aspects of safer transmutation that
176//! would benefit from compiler support, and has developed an [experimental,
177//! compiler-supported analysis][mcp-transmutability] which determines whether,
178//! for a given type, any value of that type may be soundly transmuted into
179//! another type. Once this functionality is sufficiently mature, zerocopy
180//! intends to replace its internal transmutability analysis (implemented by our
181//! custom derives) with the compiler-supported one. This change will likely be
182//! an implementation detail that is invisible to zerocopy's users.
183//!
184//! Project Safe Transmute will not replace the need for most of zerocopy's
185//! higher-level abstractions. The experimental compiler analysis is a tool for
186//! checking the soundness of `unsafe` code, not a tool to avoid writing
187//! `unsafe` code altogether. For the foreseeable future, crates like zerocopy
188//! will still be required in order to provide higher-level abstractions on top
189//! of the building block provided by Project Safe Transmute.
190//!
191//! [Project Safe Transmute]: https://rust-lang.github.io/rfcs/2835-project-safe-transmute.html
192//! [mcp-transmutability]: https://github.com/rust-lang/compiler-team/issues/411
193//!
194//! # MSRV
195//!
196//! See our [MSRV policy].
197//!
198//! [MSRV policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#msrv
199//!
200//! # Changelog
201//!
202//! Zerocopy uses [GitHub Releases].
203//!
204//! [GitHub Releases]: https://github.com/google/zerocopy/releases
205
206// Sometimes we want to use lints which were added after our MSRV.
207// `unknown_lints` is `warn` by default and we deny warnings in CI, so without
208// this attribute, any unknown lint would cause a CI failure when testing with
209// our MSRV.
210#![allow(unknown_lints, non_local_definitions, unreachable_patterns)]
211#![deny(renamed_and_removed_lints)]
212#![deny(
213 anonymous_parameters,
214 deprecated_in_future,
215 late_bound_lifetime_arguments,
216 missing_copy_implementations,
217 missing_debug_implementations,
218 missing_docs,
219 path_statements,
220 patterns_in_fns_without_body,
221 rust_2018_idioms,
222 trivial_numeric_casts,
223 unreachable_pub,
224 unsafe_op_in_unsafe_fn,
225 unused_extern_crates,
226 // We intentionally choose not to deny `unused_qualifications`. When items
227 // are added to the prelude (e.g., `core::mem::size_of`), this has the
228 // consequence of making some uses trigger this lint on the latest toolchain
229 // (e.g., `mem::size_of`), but fixing it (e.g. by replacing with `size_of`)
230 // does not work on older toolchains.
231 //
232 // We tested a more complicated fix in #1413, but ultimately decided that,
233 // since this lint is just a minor style lint, the complexity isn't worth it
234 // - it's fine to occasionally have unused qualifications slip through,
235 // especially since these do not affect our user-facing API in any way.
236 variant_size_differences
237)]
238#![cfg_attr(
239 __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS,
240 deny(fuzzy_provenance_casts, lossy_provenance_casts)
241)]
242#![deny(
243 clippy::all,
244 clippy::alloc_instead_of_core,
245 clippy::arithmetic_side_effects,
246 clippy::as_underscore,
247 clippy::assertions_on_result_states,
248 clippy::as_conversions,
249 clippy::correctness,
250 clippy::dbg_macro,
251 clippy::decimal_literal_representation,
252 clippy::double_must_use,
253 clippy::get_unwrap,
254 clippy::indexing_slicing,
255 clippy::missing_inline_in_public_items,
256 clippy::missing_safety_doc,
257 clippy::must_use_candidate,
258 clippy::must_use_unit,
259 clippy::obfuscated_if_else,
260 clippy::perf,
261 clippy::print_stdout,
262 clippy::return_self_not_must_use,
263 clippy::std_instead_of_core,
264 clippy::style,
265 clippy::suspicious,
266 clippy::todo,
267 clippy::undocumented_unsafe_blocks,
268 clippy::unimplemented,
269 clippy::unnested_or_patterns,
270 clippy::unwrap_used,
271 clippy::use_debug
272)]
273#![allow(clippy::type_complexity)]
274#![deny(
275 rustdoc::bare_urls,
276 rustdoc::broken_intra_doc_links,
277 rustdoc::invalid_codeblock_attributes,
278 rustdoc::invalid_html_tags,
279 rustdoc::invalid_rust_codeblocks,
280 rustdoc::missing_crate_level_docs,
281 rustdoc::private_intra_doc_links
282)]
283// In test code, it makes sense to weight more heavily towards concise, readable
284// code over correct or debuggable code.
285#![cfg_attr(any(test, kani), allow(
286 // In tests, you get line numbers and have access to source code, so panic
287 // messages are less important. You also often unwrap a lot, which would
288 // make expect'ing instead very verbose.
289 clippy::unwrap_used,
290 // In tests, there's no harm to "panic risks" - the worst that can happen is
291 // that your test will fail, and you'll fix it. By contrast, panic risks in
292 // production code introduce the possibly of code panicking unexpectedly "in
293 // the field".
294 clippy::arithmetic_side_effects,
295 clippy::indexing_slicing,
296))]
297#![cfg_attr(not(any(test, feature = "std")), no_std)]
298#![cfg_attr(
299 all(feature = "simd-nightly", any(target_arch = "x86", target_arch = "x86_64")),
300 feature(stdarch_x86_avx512)
301)]
302#![cfg_attr(
303 all(feature = "simd-nightly", target_arch = "arm"),
304 feature(stdarch_arm_dsp, stdarch_arm_neon_intrinsics)
305)]
306#![cfg_attr(
307 all(feature = "simd-nightly", any(target_arch = "powerpc", target_arch = "powerpc64")),
308 feature(stdarch_powerpc)
309)]
310#![cfg_attr(feature = "float-nightly", feature(f16, f128))]
311#![cfg_attr(doc_cfg, feature(doc_cfg))]
312#![cfg_attr(
313 __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS,
314 feature(layout_for_ptr, coverage_attribute)
315)]
316
317// This is a hack to allow zerocopy-derive derives to work in this crate. They
318// assume that zerocopy is linked as an extern crate, so they access items from
319// it as `zerocopy::Xxx`. This makes that still work.
320#[cfg(any(feature = "derive", test))]
321extern crate self as zerocopy;
322
323#[doc(hidden)]
324#[macro_use]
325pub mod util;
326
327pub mod byte_slice;
328pub mod byteorder;
329mod deprecated;
330// This module is `pub` so that zerocopy's error types and error handling
331// documentation is grouped together in a cohesive module. In practice, we
332// expect most users to use the re-export of `error`'s items to avoid identifier
333// stuttering.
334pub mod error;
335mod impls;
336#[doc(hidden)]
337pub mod layout;
338mod macros;
339#[doc(hidden)]
340pub mod pointer;
341mod r#ref;
342// TODO(#252): If we make this pub, come up with a better name.
343mod wrappers;
344
345pub use crate::byte_slice::*;
346pub use crate::byteorder::*;
347pub use crate::error::*;
348pub use crate::r#ref::*;
349pub use crate::wrappers::*;
350
351use core::{
352 cell::UnsafeCell,
353 cmp::Ordering,
354 fmt::{self, Debug, Display, Formatter},
355 hash::Hasher,
356 marker::PhantomData,
357 mem::{self, ManuallyDrop, MaybeUninit as CoreMaybeUninit},
358 num::{
359 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
360 NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping,
361 },
362 ops::{Deref, DerefMut},
363 ptr::{self, NonNull},
364 slice,
365};
366
367#[cfg(feature = "std")]
368use std::io;
369
370use crate::pointer::{invariant, BecauseExclusive};
371
372#[cfg(any(feature = "alloc", test))]
373extern crate alloc;
374#[cfg(any(feature = "alloc", test))]
375use alloc::{boxed::Box, vec::Vec};
376
377#[cfg(any(feature = "alloc", test, kani))]
378use core::alloc::Layout;
379
380// Used by `TryFromBytes::is_bit_valid`.
381#[doc(hidden)]
382pub use crate::pointer::{BecauseImmutable, Maybe, MaybeAligned, Ptr};
383// Used by `KnownLayout`.
384#[doc(hidden)]
385pub use crate::layout::*;
386
387// For each trait polyfill, as soon as the corresponding feature is stable, the
388// polyfill import will be unused because method/function resolution will prefer
389// the inherent method/function over a trait method/function. Thus, we suppress
390// the `unused_imports` warning.
391//
392// See the documentation on `util::polyfills` for more information.
393#[allow(unused_imports)]
394use crate::util::polyfills::{self, NonNullExt as _, NumExt as _};
395
396#[rustversion::nightly]
397#[cfg(all(test, not(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)))]
398const _: () = {
399 #[deprecated = "some tests may be skipped due to missing RUSTFLAGS=\"--cfg __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS\""]
400 const _WARNING: () = ();
401 #[warn(deprecated)]
402 _WARNING
403};
404
405// These exist so that code which was written against the old names will get
406// less confusing error messages when they upgrade to a more recent version of
407// zerocopy. On our MSRV toolchain, the error messages read, for example:
408//
409// error[E0603]: trait `FromZeroes` is private
410// --> examples/deprecated.rs:1:15
411// |
412// 1 | use zerocopy::FromZeroes;
413// | ^^^^^^^^^^ private trait
414// |
415// note: the trait `FromZeroes` is defined here
416// --> /Users/josh/workspace/zerocopy/src/lib.rs:1845:5
417// |
418// 1845 | use FromZeros as FromZeroes;
419// | ^^^^^^^^^^^^^^^^^^^^^^^
420//
421// The "note" provides enough context to make it easy to figure out how to fix
422// the error.
423#[allow(unused)]
424use {FromZeros as FromZeroes, IntoBytes as AsBytes, Ref as LayoutVerified};
425
426/// Implements [`KnownLayout`].
427///
428/// This derive analyzes various aspects of a type's layout that are needed for
429/// some of zerocopy's APIs. It can be applied to structs, enums, and unions;
430/// e.g.:
431///
432/// ```
433/// # use zerocopy_derive::KnownLayout;
434/// #[derive(KnownLayout)]
435/// struct MyStruct {
436/// # /*
437/// ...
438/// # */
439/// }
440///
441/// #[derive(KnownLayout)]
442/// enum MyEnum {
443/// # V00,
444/// # /*
445/// ...
446/// # */
447/// }
448///
449/// #[derive(KnownLayout)]
450/// union MyUnion {
451/// # variant: u8,
452/// # /*
453/// ...
454/// # */
455/// }
456/// ```
457///
458/// # Limitations
459///
460/// This derive cannot currently be applied to unsized structs without an
461/// explicit `repr` attribute.
462///
463/// Some invocations of this derive run afoul of a [known bug] in Rust's type
464/// privacy checker. For example, this code:
465///
466/// ```compile_fail,E0446
467/// use zerocopy::*;
468/// # use zerocopy_derive::*;
469///
470/// #[derive(KnownLayout)]
471/// #[repr(C)]
472/// pub struct PublicType {
473/// leading: Foo,
474/// trailing: Bar,
475/// }
476///
477/// #[derive(KnownLayout)]
478/// struct Foo;
479///
480/// #[derive(KnownLayout)]
481/// struct Bar;
482/// ```
483///
484/// ...results in a compilation error:
485///
486/// ```text
487/// error[E0446]: private type `Bar` in public interface
488/// --> examples/bug.rs:3:10
489/// |
490/// 3 | #[derive(KnownLayout)]
491/// | ^^^^^^^^^^^ can't leak private type
492/// ...
493/// 14 | struct Bar;
494/// | ---------- `Bar` declared as private
495/// |
496/// = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
497/// ```
498///
499/// This issue arises when `#[derive(KnownLayout)]` is applied to `repr(C)`
500/// structs whose trailing field type is less public than the enclosing struct.
501///
502/// To work around this, mark the trailing field type `pub` and annotate it with
503/// `#[doc(hidden)]`; e.g.:
504///
505/// ```no_run
506/// use zerocopy::*;
507/// # use zerocopy_derive::*;
508///
509/// #[derive(KnownLayout)]
510/// #[repr(C)]
511/// pub struct PublicType {
512/// leading: Foo,
513/// trailing: Bar,
514/// }
515///
516/// #[derive(KnownLayout)]
517/// struct Foo;
518///
519/// #[doc(hidden)]
520/// #[derive(KnownLayout)]
521/// pub struct Bar; // <- `Bar` is now also `pub`
522/// ```
523///
524/// [known bug]: https://github.com/rust-lang/rust/issues/45713
525#[cfg(any(feature = "derive", test))]
526#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
527pub use zerocopy_derive::KnownLayout;
528
529/// Indicates that zerocopy can reason about certain aspects of a type's layout.
530///
531/// This trait is required by many of zerocopy's APIs. It supports sized types,
532/// slices, and [slice DSTs](#dynamically-sized-types).
533///
534/// # Implementation
535///
536/// **Do not implement this trait yourself!** Instead, use
537/// [`#[derive(KnownLayout)]`][derive]; e.g.:
538///
539/// ```
540/// # use zerocopy_derive::KnownLayout;
541/// #[derive(KnownLayout)]
542/// struct MyStruct {
543/// # /*
544/// ...
545/// # */
546/// }
547///
548/// #[derive(KnownLayout)]
549/// enum MyEnum {
550/// # /*
551/// ...
552/// # */
553/// }
554///
555/// #[derive(KnownLayout)]
556/// union MyUnion {
557/// # variant: u8,
558/// # /*
559/// ...
560/// # */
561/// }
562/// ```
563///
564/// This derive performs a sophisticated analysis to deduce the layout
565/// characteristics of types. You **must** implement this trait via the derive.
566///
567/// # Dynamically-sized types
568///
569/// `KnownLayout` supports slice-based dynamically sized types ("slice DSTs").
570///
571/// A slice DST is a type whose trailing field is either a slice or another
572/// slice DST, rather than a type with fixed size. For example:
573///
574/// ```
575/// #[repr(C)]
576/// struct PacketHeader {
577/// # /*
578/// ...
579/// # */
580/// }
581///
582/// #[repr(C)]
583/// struct Packet {
584/// header: PacketHeader,
585/// body: [u8],
586/// }
587/// ```
588///
589/// It can be useful to think of slice DSTs as a generalization of slices - in
590/// other words, a normal slice is just the special case of a slice DST with
591/// zero leading fields. In particular:
592/// - Like slices, slice DSTs can have different lengths at runtime
593/// - Like slices, slice DSTs cannot be passed by-value, but only by reference
594/// or via other indirection such as `Box`
595/// - Like slices, a reference (or `Box`, or other pointer type) to a slice DST
596/// encodes the number of elements in the trailing slice field
597///
598/// ## Slice DST layout
599///
600/// Just like other composite Rust types, the layout of a slice DST is not
601/// well-defined unless it is specified using an explicit `#[repr(...)]`
602/// attribute such as `#[repr(C)]`. [Other representations are
603/// supported][reprs], but in this section, we'll use `#[repr(C)]` as our
604/// example.
605///
606/// A `#[repr(C)]` slice DST is laid out [just like sized `#[repr(C)]`
607/// types][repr-c-structs], but the presenence of a variable-length field
608/// introduces the possibility of *dynamic padding*. In particular, it may be
609/// necessary to add trailing padding *after* the trailing slice field in order
610/// to satisfy the outer type's alignment, and the amount of padding required
611/// may be a function of the length of the trailing slice field. This is just a
612/// natural consequence of the normal `#[repr(C)]` rules applied to slice DSTs,
613/// but it can result in surprising behavior. For example, consider the
614/// following type:
615///
616/// ```
617/// #[repr(C)]
618/// struct Foo {
619/// a: u32,
620/// b: u8,
621/// z: [u16],
622/// }
623/// ```
624///
625/// Assuming that `u32` has alignment 4 (this is not true on all platforms),
626/// then `Foo` has alignment 4 as well. Here is the smallest possible value for
627/// `Foo`:
628///
629/// ```text
630/// byte offset | 01234567
631/// field | aaaab---
632/// ><
633/// ```
634///
635/// In this value, `z` has length 0. Abiding by `#[repr(C)]`, the lowest offset
636/// that we can place `z` at is 5, but since `z` has alignment 2, we need to
637/// round up to offset 6. This means that there is one byte of padding between
638/// `b` and `z`, then 0 bytes of `z` itself (denoted `><` in this diagram), and
639/// then two bytes of padding after `z` in order to satisfy the overall
640/// alignment of `Foo`. The size of this instance is 8 bytes.
641///
642/// What about if `z` has length 1?
643///
644/// ```text
645/// byte offset | 01234567
646/// field | aaaab-zz
647/// ```
648///
649/// In this instance, `z` has length 1, and thus takes up 2 bytes. That means
650/// that we no longer need padding after `z` in order to satisfy `Foo`'s
651/// alignment. We've now seen two different values of `Foo` with two different
652/// lengths of `z`, but they both have the same size - 8 bytes.
653///
654/// What about if `z` has length 2?
655///
656/// ```text
657/// byte offset | 012345678901
658/// field | aaaab-zzzz--
659/// ```
660///
661/// Now `z` has length 2, and thus takes up 4 bytes. This brings our un-padded
662/// size to 10, and so we now need another 2 bytes of padding after `z` to
663/// satisfy `Foo`'s alignment.
664///
665/// Again, all of this is just a logical consequence of the `#[repr(C)]` rules
666/// applied to slice DSTs, but it can be surprising that the amount of trailing
667/// padding becomes a function of the trailing slice field's length, and thus
668/// can only be computed at runtime.
669///
670/// [reprs]: https://doc.rust-lang.org/reference/type-layout.html#representations
671/// [repr-c-structs]: https://doc.rust-lang.org/reference/type-layout.html#reprc-structs
672///
673/// ## What is a valid size?
674///
675/// There are two places in zerocopy's API that we refer to "a valid size" of a
676/// type. In normal casts or conversions, where the source is a byte slice, we
677/// need to know whether the source byte slice is a valid size of the
678/// destination type. In prefix or suffix casts, we need to know whether *there
679/// exists* a valid size of the destination type which fits in the source byte
680/// slice and, if so, what the largest such size is.
681///
682/// As outlined above, a slice DST's size is defined by the number of elements
683/// in its trailing slice field. However, there is not necessarily a 1-to-1
684/// mapping between trailing slice field length and overall size. As we saw in
685/// the previous section with the type `Foo`, instances with both 0 and 1
686/// elements in the trailing `z` field result in a `Foo` whose size is 8 bytes.
687///
688/// When we say "x is a valid size of `T`", we mean one of two things:
689/// - If `T: Sized`, then we mean that `x == size_of::<T>()`
690/// - If `T` is a slice DST, then we mean that there exists a `len` such that the instance of
691/// `T` with `len` trailing slice elements has size `x`
692///
693/// When we say "largest possible size of `T` that fits in a byte slice", we
694/// mean one of two things:
695/// - If `T: Sized`, then we mean `size_of::<T>()` if the byte slice is at least
696/// `size_of::<T>()` bytes long
697/// - If `T` is a slice DST, then we mean to consider all values, `len`, such
698/// that the instance of `T` with `len` trailing slice elements fits in the
699/// byte slice, and to choose the largest such `len`, if any
700///
701///
702/// # Safety
703///
704/// This trait does not convey any safety guarantees to code outside this crate.
705///
706/// You must not rely on the `#[doc(hidden)]` internals of `KnownLayout`. Future
707/// releases of zerocopy may make backwards-breaking changes to these items,
708/// including changes that only affect soundness, which may cause code which
709/// uses those items to silently become unsound.
710///
711#[cfg_attr(feature = "derive", doc = "[derive]: zerocopy_derive::KnownLayout")]
712#[cfg_attr(
713 not(feature = "derive"),
714 doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.KnownLayout.html"),
715)]
716#[cfg_attr(
717 zerocopy_diagnostic_on_unimplemented_1_78_0,
718 diagnostic::on_unimplemented(note = "Consider adding `#[derive(KnownLayout)]` to `{Self}`")
719)]
720pub unsafe trait KnownLayout {
721 // The `Self: Sized` bound makes it so that `KnownLayout` can still be
722 // object safe. It's not currently object safe thanks to `const LAYOUT`, and
723 // it likely won't be in the future, but there's no reason not to be
724 // forwards-compatible with object safety.
725 #[doc(hidden)]
726 fn only_derive_is_allowed_to_implement_this_trait()
727 where
728 Self: Sized;
729
730 /// The type of metadata stored in a pointer to `Self`.
731 ///
732 /// This is `()` for sized types and `usize` for slice DSTs.
733 type PointerMetadata: PointerMetadata;
734
735 /// A maybe-uninitialized analog of `Self`
736 ///
737 /// # Safety
738 ///
739 /// `Self::LAYOUT` and `Self::MaybeUninit::LAYOUT` are identical.
740 /// `Self::MaybeUninit` admits uninitialized bytes in all positions.
741 #[doc(hidden)]
742 type MaybeUninit: ?Sized + KnownLayout<PointerMetadata = Self::PointerMetadata>;
743
744 /// The layout of `Self`.
745 ///
746 /// # Safety
747 ///
748 /// Callers may assume that `LAYOUT` accurately reflects the layout of
749 /// `Self`. In particular:
750 /// - `LAYOUT.align` is equal to `Self`'s alignment
751 /// - If `Self: Sized`, then `LAYOUT.size_info == SizeInfo::Sized { size }`
752 /// where `size == size_of::<Self>()`
753 /// - If `Self` is a slice DST, then `LAYOUT.size_info ==
754 /// SizeInfo::SliceDst(slice_layout)` where:
755 /// - The size, `size`, of an instance of `Self` with `elems` trailing
756 /// slice elements is equal to `slice_layout.offset +
757 /// slice_layout.elem_size * elems` rounded up to the nearest multiple
758 /// of `LAYOUT.align`
759 /// - For such an instance, any bytes in the range `[slice_layout.offset +
760 /// slice_layout.elem_size * elems, size)` are padding and must not be
761 /// assumed to be initialized
762 #[doc(hidden)]
763 const LAYOUT: DstLayout;
764
765 /// SAFETY: The returned pointer has the same address and provenance as
766 /// `bytes`. If `Self` is a DST, the returned pointer's referent has `elems`
767 /// elements in its trailing slice.
768 #[doc(hidden)]
769 fn raw_from_ptr_len(bytes: NonNull<u8>, meta: Self::PointerMetadata) -> NonNull<Self>;
770
771 /// Extracts the metadata from a pointer to `Self`.
772 ///
773 /// # Safety
774 ///
775 /// `pointer_to_metadata` always returns the correct metadata stored in
776 /// `ptr`.
777 #[doc(hidden)]
778 fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata;
779
780 /// Computes the length of the byte range addressed by `ptr`.
781 ///
782 /// Returns `None` if the resulting length would not fit in an `usize`.
783 ///
784 /// # Safety
785 ///
786 /// Callers may assume that `size_of_val_raw` always returns the correct
787 /// size.
788 ///
789 /// Callers may assume that, if `ptr` addresses a byte range whose length
790 /// fits in an `usize`, this will return `Some`.
791 #[doc(hidden)]
792 #[must_use]
793 #[inline(always)]
794 fn size_of_val_raw(ptr: NonNull<Self>) -> Option<usize> {
795 let meta = Self::pointer_to_metadata(ptr.as_ptr());
796 // SAFETY: `size_for_metadata` promises to only return `None` if the
797 // resulting size would not fit in a `usize`.
798 meta.size_for_metadata(Self::LAYOUT)
799 }
800}
801
802/// The metadata associated with a [`KnownLayout`] type.
803#[doc(hidden)]
804pub trait PointerMetadata: Copy + Eq + Debug {
805 /// Constructs a `Self` from an element count.
806 ///
807 /// If `Self = ()`, this returns `()`. If `Self = usize`, this returns
808 /// `elems`. No other types are currently supported.
809 fn from_elem_count(elems: usize) -> Self;
810
811 /// Computes the size of the object with the given layout and pointer
812 /// metadata.
813 ///
814 /// # Panics
815 ///
816 /// If `Self = ()`, `layout` must describe a sized type. If `Self = usize`,
817 /// `layout` must describe a slice DST. Otherwise, `size_for_metadata` may
818 /// panic.
819 ///
820 /// # Safety
821 ///
822 /// `size_for_metadata` promises to only return `None` if the resulting size
823 /// would not fit in a `usize`.
824 fn size_for_metadata(&self, layout: DstLayout) -> Option<usize>;
825}
826
827impl PointerMetadata for () {
828 #[inline]
829 #[allow(clippy::unused_unit)]
830 fn from_elem_count(_elems: usize) -> () {}
831
832 #[inline]
833 fn size_for_metadata(&self, layout: DstLayout) -> Option<usize> {
834 match layout.size_info {
835 SizeInfo::Sized { size } => Some(size),
836 // NOTE: This branch is unreachable, but we return `None` rather
837 // than `unreachable!()` to avoid generating panic paths.
838 SizeInfo::SliceDst(_) => None,
839 }
840 }
841}
842
843impl PointerMetadata for usize {
844 #[inline]
845 fn from_elem_count(elems: usize) -> usize {
846 elems
847 }
848
849 #[inline]
850 fn size_for_metadata(&self, layout: DstLayout) -> Option<usize> {
851 match layout.size_info {
852 SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) => {
853 let slice_len = elem_size.checked_mul(*self)?;
854 let without_padding = offset.checked_add(slice_len)?;
855 without_padding.checked_add(util::padding_needed_for(without_padding, layout.align))
856 }
857 // NOTE: This branch is unreachable, but we return `None` rather
858 // than `unreachable!()` to avoid generating panic paths.
859 SizeInfo::Sized { .. } => None,
860 }
861 }
862}
863
864// SAFETY: Delegates safety to `DstLayout::for_slice`.
865unsafe impl<T> KnownLayout for [T] {
866 #[allow(clippy::missing_inline_in_public_items)]
867 #[cfg_attr(
868 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
869 coverage(off)
870 )]
871 fn only_derive_is_allowed_to_implement_this_trait()
872 where
873 Self: Sized,
874 {
875 }
876
877 type PointerMetadata = usize;
878
879 // SAFETY: `CoreMaybeUninit<T>::LAYOUT` and `T::LAYOUT` are identical
880 // because `CoreMaybeUninit<T>` has the same size and alignment as `T` [1].
881 // Consequently, `[CoreMaybeUninit<T>]::LAYOUT` and `[T]::LAYOUT` are
882 // identical, because they both lack a fixed-sized prefix and because they
883 // inherit the alignments of their inner element type (which are identical)
884 // [2][3].
885 //
886 // `[CoreMaybeUninit<T>]` admits uninitialized bytes at all positions
887 // because `CoreMaybeUninit<T>` admits uninitialized bytes at all positions
888 // and because the inner elements of `[CoreMaybeUninit<T>]` are laid out
889 // back-to-back [2][3].
890 //
891 // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1:
892 //
893 // `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as
894 // `T`
895 //
896 // [2] Per https://doc.rust-lang.org/1.82.0/reference/type-layout.html#slice-layout:
897 //
898 // Slices have the same layout as the section of the array they slice.
899 //
900 // [3] Per https://doc.rust-lang.org/1.82.0/reference/type-layout.html#array-layout:
901 //
902 // An array of `[T; N]` has a size of `size_of::<T>() * N` and the same
903 // alignment of `T`. Arrays are laid out so that the zero-based `nth`
904 // element of the array is offset from the start of the array by `n *
905 // size_of::<T>()` bytes.
906 type MaybeUninit = [CoreMaybeUninit<T>];
907
908 const LAYOUT: DstLayout = DstLayout::for_slice::<T>();
909
910 // SAFETY: `.cast` preserves address and provenance. The returned pointer
911 // refers to an object with `elems` elements by construction.
912 #[inline(always)]
913 fn raw_from_ptr_len(data: NonNull<u8>, elems: usize) -> NonNull<Self> {
914 // TODO(#67): Remove this allow. See NonNullExt for more details.
915 #[allow(unstable_name_collisions)]
916 NonNull::slice_from_raw_parts(data.cast::<T>(), elems)
917 }
918
919 #[inline(always)]
920 fn pointer_to_metadata(ptr: *mut [T]) -> usize {
921 #[allow(clippy::as_conversions)]
922 let slc = ptr as *const [()];
923
924 // SAFETY:
925 // - `()` has alignment 1, so `slc` is trivially aligned.
926 // - `slc` was derived from a non-null pointer.
927 // - The size is 0 regardless of the length, so it is sound to
928 // materialize a reference regardless of location.
929 // - By invariant, `self.ptr` has valid provenance.
930 let slc = unsafe { &*slc };
931
932 // This is correct because the preceding `as` cast preserves the number
933 // of slice elements. [1]
934 //
935 // [1] Per https://doc.rust-lang.org/reference/expressions/operator-expr.html#pointer-to-pointer-cast:
936 //
937 // For slice types like `[T]` and `[U]`, the raw pointer types `*const
938 // [T]`, `*mut [T]`, `*const [U]`, and `*mut [U]` encode the number of
939 // elements in this slice. Casts between these raw pointer types
940 // preserve the number of elements. ... The same holds for `str` and
941 // any compound type whose unsized tail is a slice type, such as
942 // struct `Foo(i32, [u8])` or `(u64, Foo)`.
943 slc.len()
944 }
945}
946
947#[rustfmt::skip]
948impl_known_layout!(
949 (),
950 u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64,
951 bool, char,
952 NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32,
953 NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize
954);
955#[rustfmt::skip]
956#[cfg(feature = "float-nightly")]
957impl_known_layout!(
958 #[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))]
959 f16,
960 #[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))]
961 f128
962);
963#[rustfmt::skip]
964impl_known_layout!(
965 T => Option<T>,
966 T: ?Sized => PhantomData<T>,
967 T => Wrapping<T>,
968 T => CoreMaybeUninit<T>,
969 T: ?Sized => *const T,
970 T: ?Sized => *mut T,
971 T: ?Sized => &'_ T,
972 T: ?Sized => &'_ mut T,
973);
974impl_known_layout!(const N: usize, T => [T; N]);
975
976safety_comment! {
977 /// SAFETY:
978 /// `str`, `ManuallyDrop<[T]>` [1], and `UnsafeCell<T>` [2] have the same
979 /// representations as `[u8]`, `[T]`, and `T` repsectively. `str` has
980 /// different bit validity than `[u8]`, but that doesn't affect the
981 /// soundness of this impl.
982 ///
983 /// [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html:
984 ///
985 /// `ManuallyDrop<T>` is guaranteed to have the same layout and bit
986 /// validity as `T`
987 ///
988 /// [2] Per https://doc.rust-lang.org/core/cell/struct.UnsafeCell.html#memory-layout:
989 ///
990 /// `UnsafeCell<T>` has the same in-memory representation as its inner
991 /// type `T`.
992 ///
993 /// TODO(#429):
994 /// - Add quotes from docs.
995 /// - Once [1] (added in
996 /// https://github.com/rust-lang/rust/pull/115522) is available on stable,
997 /// quote the stable docs instead of the nightly docs.
998 unsafe_impl_known_layout!(#[repr([u8])] str);
999 unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] ManuallyDrop<T>);
1000 unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] UnsafeCell<T>);
1001}
1002
1003safety_comment! {
1004 /// SAFETY:
1005 /// - By consequence of the invariant on `T::MaybeUninit` that `T::LAYOUT`
1006 /// and `T::MaybeUninit::LAYOUT` are equal, `T` and `T::MaybeUninit`
1007 /// have the same:
1008 /// - Fixed prefix size
1009 /// - Alignment
1010 /// - (For DSTs) trailing slice element size
1011 /// - By consequence of the above, referents `T::MaybeUninit` and `T` have
1012 /// the require the same kind of pointer metadata, and thus it is valid to
1013 /// perform an `as` cast from `*mut T` and `*mut T::MaybeUninit`, and this
1014 /// operation preserves referent size (ie, `size_of_val_raw`).
1015 unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T::MaybeUninit)] MaybeUninit<T>);
1016}
1017
1018/// Analyzes whether a type is [`FromZeros`].
1019///
1020/// This derive analyzes, at compile time, whether the annotated type satisfies
1021/// the [safety conditions] of `FromZeros` and implements `FromZeros` and its
1022/// supertraits if it is sound to do so. This derive can be applied to structs,
1023/// enums, and unions; e.g.:
1024///
1025/// ```
1026/// # use zerocopy_derive::{FromZeros, Immutable};
1027/// #[derive(FromZeros)]
1028/// struct MyStruct {
1029/// # /*
1030/// ...
1031/// # */
1032/// }
1033///
1034/// #[derive(FromZeros)]
1035/// #[repr(u8)]
1036/// enum MyEnum {
1037/// # Variant0,
1038/// # /*
1039/// ...
1040/// # */
1041/// }
1042///
1043/// #[derive(FromZeros, Immutable)]
1044/// union MyUnion {
1045/// # variant: u8,
1046/// # /*
1047/// ...
1048/// # */
1049/// }
1050/// ```
1051///
1052/// [safety conditions]: trait@FromZeros#safety
1053///
1054/// # Analysis
1055///
1056/// *This section describes, roughly, the analysis performed by this derive to
1057/// determine whether it is sound to implement `FromZeros` for a given type.
1058/// Unless you are modifying the implementation of this derive, or attempting to
1059/// manually implement `FromZeros` for a type yourself, you don't need to read
1060/// this section.*
1061///
1062/// If a type has the following properties, then this derive can implement
1063/// `FromZeros` for that type:
1064///
1065/// - If the type is a struct, all of its fields must be `FromZeros`.
1066/// - If the type is an enum:
1067/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`,
1068/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`).
1069/// - It must have a variant with a discriminant/tag of `0`, and its fields
1070/// must be `FromZeros`. See [the reference] for a description of
1071/// discriminant values are specified.
1072/// - The fields of that variant must be `FromZeros`.
1073///
1074/// This analysis is subject to change. Unsafe code may *only* rely on the
1075/// documented [safety conditions] of `FromZeros`, and must *not* rely on the
1076/// implementation details of this derive.
1077///
1078/// [the reference]: https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations
1079///
1080/// ## Why isn't an explicit representation required for structs?
1081///
1082/// Neither this derive, nor the [safety conditions] of `FromZeros`, requires
1083/// that structs are marked with `#[repr(C)]`.
1084///
1085/// Per the [Rust reference](reference),
1086///
1087/// > The representation of a type can change the padding between fields, but
1088/// > does not change the layout of the fields themselves.
1089///
1090/// [reference]: https://doc.rust-lang.org/reference/type-layout.html#representations
1091///
1092/// Since the layout of structs only consists of padding bytes and field bytes,
1093/// a struct is soundly `FromZeros` if:
1094/// 1. its padding is soundly `FromZeros`, and
1095/// 2. its fields are soundly `FromZeros`.
1096///
1097/// The answer to the first question is always yes: padding bytes do not have
1098/// any validity constraints. A [discussion] of this question in the Unsafe Code
1099/// Guidelines Working Group concluded that it would be virtually unimaginable
1100/// for future versions of rustc to add validity constraints to padding bytes.
1101///
1102/// [discussion]: https://github.com/rust-lang/unsafe-code-guidelines/issues/174
1103///
1104/// Whether a struct is soundly `FromZeros` therefore solely depends on whether
1105/// its fields are `FromZeros`.
1106// TODO(#146): Document why we don't require an enum to have an explicit `repr`
1107// attribute.
1108#[cfg(any(feature = "derive", test))]
1109#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
1110pub use zerocopy_derive::FromZeros;
1111
1112/// Analyzes whether a type is [`Immutable`].
1113///
1114/// This derive analyzes, at compile time, whether the annotated type satisfies
1115/// the [safety conditions] of `Immutable` and implements `Immutable` if it is
1116/// sound to do so. This derive can be applied to structs, enums, and unions;
1117/// e.g.:
1118///
1119/// ```
1120/// # use zerocopy_derive::Immutable;
1121/// #[derive(Immutable)]
1122/// struct MyStruct {
1123/// # /*
1124/// ...
1125/// # */
1126/// }
1127///
1128/// #[derive(Immutable)]
1129/// enum MyEnum {
1130/// # Variant0,
1131/// # /*
1132/// ...
1133/// # */
1134/// }
1135///
1136/// #[derive(Immutable)]
1137/// union MyUnion {
1138/// # variant: u8,
1139/// # /*
1140/// ...
1141/// # */
1142/// }
1143/// ```
1144///
1145/// # Analysis
1146///
1147/// *This section describes, roughly, the analysis performed by this derive to
1148/// determine whether it is sound to implement `Immutable` for a given type.
1149/// Unless you are modifying the implementation of this derive, you don't need
1150/// to read this section.*
1151///
1152/// If a type has the following properties, then this derive can implement
1153/// `Immutable` for that type:
1154///
1155/// - All fields must be `Immutable`.
1156///
1157/// This analysis is subject to change. Unsafe code may *only* rely on the
1158/// documented [safety conditions] of `Immutable`, and must *not* rely on the
1159/// implementation details of this derive.
1160///
1161/// [safety conditions]: trait@Immutable#safety
1162#[cfg(any(feature = "derive", test))]
1163#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
1164pub use zerocopy_derive::Immutable;
1165
1166/// Types which are free from interior mutability.
1167///
1168/// `T: Immutable` indicates that `T` does not permit interior mutation, except
1169/// by ownership or an exclusive (`&mut`) borrow.
1170///
1171/// # Implementation
1172///
1173/// **Do not implement this trait yourself!** Instead, use
1174/// [`#[derive(Immutable)]`][derive] (requires the `derive` Cargo feature);
1175/// e.g.:
1176///
1177/// ```
1178/// # use zerocopy_derive::Immutable;
1179/// #[derive(Immutable)]
1180/// struct MyStruct {
1181/// # /*
1182/// ...
1183/// # */
1184/// }
1185///
1186/// #[derive(Immutable)]
1187/// enum MyEnum {
1188/// # /*
1189/// ...
1190/// # */
1191/// }
1192///
1193/// #[derive(Immutable)]
1194/// union MyUnion {
1195/// # variant: u8,
1196/// # /*
1197/// ...
1198/// # */
1199/// }
1200/// ```
1201///
1202/// This derive performs a sophisticated, compile-time safety analysis to
1203/// determine whether a type is `Immutable`.
1204///
1205/// # Safety
1206///
1207/// Unsafe code outside of this crate must not make any assumptions about `T`
1208/// based on `T: Immutable`. We reserve the right to relax the requirements for
1209/// `Immutable` in the future, and if unsafe code outside of this crate makes
1210/// assumptions based on `T: Immutable`, future relaxations may cause that code
1211/// to become unsound.
1212///
1213// # Safety (Internal)
1214//
1215// If `T: Immutable`, unsafe code *inside of this crate* may assume that, given
1216// `t: &T`, `t` does not contain any [`UnsafeCell`]s at any byte location
1217// within the byte range addressed by `t`. This includes ranges of length 0
1218// (e.g., `UnsafeCell<()>` and `[UnsafeCell<u8>; 0]`). If a type implements
1219// `Immutable` which violates this assumptions, it may cause this crate to
1220// exhibit [undefined behavior].
1221//
1222// [`UnsafeCell`]: core::cell::UnsafeCell
1223// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html
1224#[cfg_attr(
1225 feature = "derive",
1226 doc = "[derive]: zerocopy_derive::Immutable",
1227 doc = "[derive-analysis]: zerocopy_derive::Immutable#analysis"
1228)]
1229#[cfg_attr(
1230 not(feature = "derive"),
1231 doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Immutable.html"),
1232 doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Immutable.html#analysis"),
1233)]
1234#[cfg_attr(
1235 zerocopy_diagnostic_on_unimplemented_1_78_0,
1236 diagnostic::on_unimplemented(note = "Consider adding `#[derive(Immutable)]` to `{Self}`")
1237)]
1238pub unsafe trait Immutable {
1239 // The `Self: Sized` bound makes it so that `Immutable` is still object
1240 // safe.
1241 #[doc(hidden)]
1242 fn only_derive_is_allowed_to_implement_this_trait()
1243 where
1244 Self: Sized;
1245}
1246
1247/// Implements [`TryFromBytes`].
1248///
1249/// This derive synthesizes the runtime checks required to check whether a
1250/// sequence of initialized bytes corresponds to a valid instance of a type.
1251/// This derive can be applied to structs, enums, and unions; e.g.:
1252///
1253/// ```
1254/// # use zerocopy_derive::{TryFromBytes, Immutable};
1255/// #[derive(TryFromBytes)]
1256/// struct MyStruct {
1257/// # /*
1258/// ...
1259/// # */
1260/// }
1261///
1262/// #[derive(TryFromBytes)]
1263/// #[repr(u8)]
1264/// enum MyEnum {
1265/// # V00,
1266/// # /*
1267/// ...
1268/// # */
1269/// }
1270///
1271/// #[derive(TryFromBytes, Immutable)]
1272/// union MyUnion {
1273/// # variant: u8,
1274/// # /*
1275/// ...
1276/// # */
1277/// }
1278/// ```
1279///
1280/// [safety conditions]: trait@TryFromBytes#safety
1281#[cfg(any(feature = "derive", test))]
1282#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
1283pub use zerocopy_derive::TryFromBytes;
1284
1285/// Types for which some bit patterns are valid.
1286///
1287/// A memory region of the appropriate length which contains initialized bytes
1288/// can be viewed as a `TryFromBytes` type so long as the runtime value of those
1289/// bytes corresponds to a [*valid instance*] of that type. For example,
1290/// [`bool`] is `TryFromBytes`, so zerocopy can transmute a [`u8`] into a
1291/// [`bool`] so long as it first checks that the value of the [`u8`] is `0` or
1292/// `1`.
1293///
1294/// # Implementation
1295///
1296/// **Do not implement this trait yourself!** Instead, use
1297/// [`#[derive(TryFromBytes)]`][derive]; e.g.:
1298///
1299/// ```
1300/// # use zerocopy_derive::{TryFromBytes, Immutable};
1301/// #[derive(TryFromBytes)]
1302/// struct MyStruct {
1303/// # /*
1304/// ...
1305/// # */
1306/// }
1307///
1308/// #[derive(TryFromBytes)]
1309/// #[repr(u8)]
1310/// enum MyEnum {
1311/// # V00,
1312/// # /*
1313/// ...
1314/// # */
1315/// }
1316///
1317/// #[derive(TryFromBytes, Immutable)]
1318/// union MyUnion {
1319/// # variant: u8,
1320/// # /*
1321/// ...
1322/// # */
1323/// }
1324/// ```
1325///
1326/// This derive ensures that the runtime check of whether bytes correspond to a
1327/// valid instance is sound. You **must** implement this trait via the derive.
1328///
1329/// # What is a "valid instance"?
1330///
1331/// In Rust, each type has *bit validity*, which refers to the set of bit
1332/// patterns which may appear in an instance of that type. It is impossible for
1333/// safe Rust code to produce values which violate bit validity (ie, values
1334/// outside of the "valid" set of bit patterns). If `unsafe` code produces an
1335/// invalid value, this is considered [undefined behavior].
1336///
1337/// Rust's bit validity rules are currently being decided, which means that some
1338/// types have three classes of bit patterns: those which are definitely valid,
1339/// and whose validity is documented in the language; those which may or may not
1340/// be considered valid at some point in the future; and those which are
1341/// definitely invalid.
1342///
1343/// Zerocopy takes a conservative approach, and only considers a bit pattern to
1344/// be valid if its validity is a documenteed guarantee provided by the
1345/// language.
1346///
1347/// For most use cases, Rust's current guarantees align with programmers'
1348/// intuitions about what ought to be valid. As a result, zerocopy's
1349/// conservatism should not affect most users.
1350///
1351/// If you are negatively affected by lack of support for a particular type,
1352/// we encourage you to let us know by [filing an issue][github-repo].
1353///
1354/// # `TryFromBytes` is not symmetrical with [`IntoBytes`]
1355///
1356/// There are some types which implement both `TryFromBytes` and [`IntoBytes`],
1357/// but for which `TryFromBytes` is not guaranteed to accept all byte sequences
1358/// produced by `IntoBytes`. In other words, for some `T: TryFromBytes +
1359/// IntoBytes`, there exist values of `t: T` such that
1360/// `TryFromBytes::try_ref_from_bytes(t.as_bytes()) == None`. Code should not
1361/// generally assume that values produced by `IntoBytes` will necessarily be
1362/// accepted as valid by `TryFromBytes`.
1363///
1364/// # Safety
1365///
1366/// On its own, `T: TryFromBytes` does not make any guarantees about the layout
1367/// or representation of `T`. It merely provides the ability to perform a
1368/// validity check at runtime via methods like [`try_ref_from_bytes`].
1369///
1370/// You must not rely on the `#[doc(hidden)]` internals of `TryFromBytes`.
1371/// Future releases of zerocopy may make backwards-breaking changes to these
1372/// items, including changes that only affect soundness, which may cause code
1373/// which uses those items to silently become unsound.
1374///
1375/// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html
1376/// [github-repo]: https://github.com/google/zerocopy
1377/// [`try_ref_from_bytes`]: TryFromBytes::try_ref_from_bytes
1378/// [*valid instance*]: #what-is-a-valid-instance
1379#[cfg_attr(feature = "derive", doc = "[derive]: zerocopy_derive::TryFromBytes")]
1380#[cfg_attr(
1381 not(feature = "derive"),
1382 doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.TryFromBytes.html"),
1383)]
1384#[cfg_attr(
1385 zerocopy_diagnostic_on_unimplemented_1_78_0,
1386 diagnostic::on_unimplemented(note = "Consider adding `#[derive(TryFromBytes)]` to `{Self}`")
1387)]
1388pub unsafe trait TryFromBytes {
1389 // The `Self: Sized` bound makes it so that `TryFromBytes` is still object
1390 // safe.
1391 #[doc(hidden)]
1392 fn only_derive_is_allowed_to_implement_this_trait()
1393 where
1394 Self: Sized;
1395
1396 /// Does a given memory range contain a valid instance of `Self`?
1397 ///
1398 /// # Safety
1399 ///
1400 /// Unsafe code may assume that, if `is_bit_valid(candidate)` returns true,
1401 /// `*candidate` contains a valid `Self`.
1402 ///
1403 /// # Panics
1404 ///
1405 /// `is_bit_valid` may panic. Callers are responsible for ensuring that any
1406 /// `unsafe` code remains sound even in the face of `is_bit_valid`
1407 /// panicking. (We support user-defined validation routines; so long as
1408 /// these routines are not required to be `unsafe`, there is no way to
1409 /// ensure that these do not generate panics.)
1410 ///
1411 /// Besides user-defined validation routines panicking, `is_bit_valid` will
1412 /// either panic or fail to compile if called on a pointer with [`Shared`]
1413 /// aliasing when `Self: !Immutable`.
1414 ///
1415 /// [`UnsafeCell`]: core::cell::UnsafeCell
1416 /// [`Shared`]: invariant::Shared
1417 #[doc(hidden)]
1418 fn is_bit_valid<A: invariant::Aliasing + invariant::AtLeast<invariant::Shared>>(
1419 candidate: Maybe<'_, Self, A>,
1420 ) -> bool;
1421
1422 /// Attempts to interpret the given `source` as a `&Self`.
1423 ///
1424 /// If the bytes of `source` are a valid instance of `Self`, this method
1425 /// returns a reference to those bytes interpreted as a `Self`. If the
1426 /// length of `source` is not a [valid size of `Self`][valid-size], or if
1427 /// `source` is not appropriately aligned, or if `source` is not a valid
1428 /// instance of `Self`, this returns `Err`. If [`Self:
1429 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
1430 /// error][ConvertError::from].
1431 ///
1432 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
1433 ///
1434 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
1435 /// [self-unaligned]: Unaligned
1436 /// [slice-dst]: KnownLayout#dynamically-sized-types
1437 ///
1438 /// # Compile-Time Assertions
1439 ///
1440 /// This method cannot yet be used on unsized types whose dynamically-sized
1441 /// component is zero-sized. Attempting to use this method on such types
1442 /// results in a compile-time assertion error; e.g.:
1443 ///
1444 /// ```compile_fail,E0080
1445 /// use zerocopy::*;
1446 /// # use zerocopy_derive::*;
1447 ///
1448 /// #[derive(TryFromBytes, Immutable, KnownLayout)]
1449 /// #[repr(C)]
1450 /// struct ZSTy {
1451 /// leading_sized: u16,
1452 /// trailing_dst: [()],
1453 /// }
1454 ///
1455 /// let _ = ZSTy::try_ref_from_bytes(0u16.as_bytes()); // âš Compile Error!
1456 /// ```
1457 ///
1458 /// # Examples
1459 ///
1460 /// ```
1461 /// use zerocopy::TryFromBytes;
1462 /// # use zerocopy_derive::*;
1463 ///
1464 /// // The only valid value of this type is the byte `0xC0`
1465 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1466 /// #[repr(u8)]
1467 /// enum C0 { xC0 = 0xC0 }
1468 ///
1469 /// // The only valid value of this type is the byte sequence `0xC0C0`.
1470 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1471 /// #[repr(C)]
1472 /// struct C0C0(C0, C0);
1473 ///
1474 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1475 /// #[repr(C)]
1476 /// struct Packet {
1477 /// magic_number: C0C0,
1478 /// mug_size: u8,
1479 /// temperature: u8,
1480 /// marshmallows: [[u8; 2]],
1481 /// }
1482 ///
1483 /// let bytes = &[0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5][..];
1484 ///
1485 /// let packet = Packet::try_ref_from_bytes(bytes).unwrap();
1486 ///
1487 /// assert_eq!(packet.mug_size, 240);
1488 /// assert_eq!(packet.temperature, 77);
1489 /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]);
1490 ///
1491 /// // These bytes are not valid instance of `Packet`.
1492 /// let bytes = &[0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5][..];
1493 /// assert!(Packet::try_ref_from_bytes(bytes).is_err());
1494 /// ```
1495 #[must_use = "has no side effects"]
1496 #[inline]
1497 fn try_ref_from_bytes(source: &[u8]) -> Result<&Self, TryCastError<&[u8], Self>>
1498 where
1499 Self: KnownLayout + Immutable,
1500 {
1501 static_assert_dst_is_not_zst!(Self);
1502 match Ptr::from_ref(source).try_cast_into_no_leftover::<Self, BecauseImmutable>(None) {
1503 Ok(source) => {
1504 // This call may panic. If that happens, it doesn't cause any soundness
1505 // issues, as we have not generated any invalid state which we need to
1506 // fix before returning.
1507 //
1508 // Note that one panic or post-monomorphization error condition is
1509 // calling `try_into_valid` (and thus `is_bit_valid`) with a shared
1510 // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
1511 // condition will not happen.
1512 match source.try_into_valid() {
1513 Ok(valid) => Ok(valid.as_ref()),
1514 Err(e) => {
1515 Err(e.map_src(|src| src.as_bytes::<BecauseImmutable>().as_ref()).into())
1516 }
1517 }
1518 }
1519 Err(e) => Err(e.map_src(Ptr::as_ref).into()),
1520 }
1521 }
1522
1523 /// Attempts to interpret the prefix of the given `source` as a `&Self`.
1524 ///
1525 /// This method computes the [largest possible size of `Self`][valid-size]
1526 /// that can fit in the leading bytes of `source`. If that prefix is a valid
1527 /// instance of `Self`, this method returns a reference to those bytes
1528 /// interpreted as `Self`, and a reference to the remaining bytes. If there
1529 /// are insufficient bytes, or if `source` is not appropriately aligned, or
1530 /// if those bytes are not a valid instance of `Self`, this returns `Err`.
1531 /// If [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
1532 /// alignment error][ConvertError::from].
1533 ///
1534 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
1535 ///
1536 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
1537 /// [self-unaligned]: Unaligned
1538 /// [slice-dst]: KnownLayout#dynamically-sized-types
1539 ///
1540 /// # Compile-Time Assertions
1541 ///
1542 /// This method cannot yet be used on unsized types whose dynamically-sized
1543 /// component is zero-sized. Attempting to use this method on such types
1544 /// results in a compile-time assertion error; e.g.:
1545 ///
1546 /// ```compile_fail,E0080
1547 /// use zerocopy::*;
1548 /// # use zerocopy_derive::*;
1549 ///
1550 /// #[derive(TryFromBytes, Immutable, KnownLayout)]
1551 /// #[repr(C)]
1552 /// struct ZSTy {
1553 /// leading_sized: u16,
1554 /// trailing_dst: [()],
1555 /// }
1556 ///
1557 /// let _ = ZSTy::try_ref_from_prefix(0u16.as_bytes()); // âš Compile Error!
1558 /// ```
1559 ///
1560 /// # Examples
1561 ///
1562 /// ```
1563 /// use zerocopy::TryFromBytes;
1564 /// # use zerocopy_derive::*;
1565 ///
1566 /// // The only valid value of this type is the byte `0xC0`
1567 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1568 /// #[repr(u8)]
1569 /// enum C0 { xC0 = 0xC0 }
1570 ///
1571 /// // The only valid value of this type is the bytes `0xC0C0`.
1572 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1573 /// #[repr(C)]
1574 /// struct C0C0(C0, C0);
1575 ///
1576 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1577 /// #[repr(C)]
1578 /// struct Packet {
1579 /// magic_number: C0C0,
1580 /// mug_size: u8,
1581 /// temperature: u8,
1582 /// marshmallows: [[u8; 2]],
1583 /// }
1584 ///
1585 /// // These are more bytes than are needed to encode a `Packet`.
1586 /// let bytes = &[0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
1587 ///
1588 /// let (packet, suffix) = Packet::try_ref_from_prefix(bytes).unwrap();
1589 ///
1590 /// assert_eq!(packet.mug_size, 240);
1591 /// assert_eq!(packet.temperature, 77);
1592 /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]);
1593 /// assert_eq!(suffix, &[6u8][..]);
1594 ///
1595 /// // These bytes are not valid instance of `Packet`.
1596 /// let bytes = &[0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
1597 /// assert!(Packet::try_ref_from_prefix(bytes).is_err());
1598 /// ```
1599 #[must_use = "has no side effects"]
1600 #[inline]
1601 fn try_ref_from_prefix(source: &[u8]) -> Result<(&Self, &[u8]), TryCastError<&[u8], Self>>
1602 where
1603 Self: KnownLayout + Immutable,
1604 {
1605 static_assert_dst_is_not_zst!(Self);
1606 try_ref_from_prefix_suffix(source, CastType::Prefix, None)
1607 }
1608
1609 /// Attempts to interpret the suffix of the given `source` as a `&Self`.
1610 ///
1611 /// This method computes the [largest possible size of `Self`][valid-size]
1612 /// that can fit in the trailing bytes of `source`. If that suffix is a
1613 /// valid instance of `Self`, this method returns a reference to those bytes
1614 /// interpreted as `Self`, and a reference to the preceding bytes. If there
1615 /// are insufficient bytes, or if the suffix of `source` would not be
1616 /// appropriately aligned, or if the suffix is not a valid instance of
1617 /// `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], you
1618 /// can [infallibly discard the alignment error][ConvertError::from].
1619 ///
1620 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
1621 ///
1622 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
1623 /// [self-unaligned]: Unaligned
1624 /// [slice-dst]: KnownLayout#dynamically-sized-types
1625 ///
1626 /// # Compile-Time Assertions
1627 ///
1628 /// This method cannot yet be used on unsized types whose dynamically-sized
1629 /// component is zero-sized. Attempting to use this method on such types
1630 /// results in a compile-time assertion error; e.g.:
1631 ///
1632 /// ```compile_fail,E0080
1633 /// use zerocopy::*;
1634 /// # use zerocopy_derive::*;
1635 ///
1636 /// #[derive(TryFromBytes, Immutable, KnownLayout)]
1637 /// #[repr(C)]
1638 /// struct ZSTy {
1639 /// leading_sized: u16,
1640 /// trailing_dst: [()],
1641 /// }
1642 ///
1643 /// let _ = ZSTy::try_ref_from_suffix(0u16.as_bytes()); // âš Compile Error!
1644 /// ```
1645 ///
1646 /// # Examples
1647 ///
1648 /// ```
1649 /// use zerocopy::TryFromBytes;
1650 /// # use zerocopy_derive::*;
1651 ///
1652 /// // The only valid value of this type is the byte `0xC0`
1653 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1654 /// #[repr(u8)]
1655 /// enum C0 { xC0 = 0xC0 }
1656 ///
1657 /// // The only valid value of this type is the bytes `0xC0C0`.
1658 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1659 /// #[repr(C)]
1660 /// struct C0C0(C0, C0);
1661 ///
1662 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1663 /// #[repr(C)]
1664 /// struct Packet {
1665 /// magic_number: C0C0,
1666 /// mug_size: u8,
1667 /// temperature: u8,
1668 /// marshmallows: [[u8; 2]],
1669 /// }
1670 ///
1671 /// // These are more bytes than are needed to encode a `Packet`.
1672 /// let bytes = &[0, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
1673 ///
1674 /// let (prefix, packet) = Packet::try_ref_from_suffix(bytes).unwrap();
1675 ///
1676 /// assert_eq!(packet.mug_size, 240);
1677 /// assert_eq!(packet.temperature, 77);
1678 /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
1679 /// assert_eq!(prefix, &[0u8][..]);
1680 ///
1681 /// // These bytes are not valid instance of `Packet`.
1682 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0x10][..];
1683 /// assert!(Packet::try_ref_from_suffix(bytes).is_err());
1684 /// ```
1685 #[must_use = "has no side effects"]
1686 #[inline]
1687 fn try_ref_from_suffix(source: &[u8]) -> Result<(&[u8], &Self), TryCastError<&[u8], Self>>
1688 where
1689 Self: KnownLayout + Immutable,
1690 {
1691 static_assert_dst_is_not_zst!(Self);
1692 try_ref_from_prefix_suffix(source, CastType::Suffix, None).map(swap)
1693 }
1694
1695 /// Attempts to interpret the given `source` as a `&mut Self` without
1696 /// copying.
1697 ///
1698 /// If the bytes of `source` are a valid instance of `Self`, this method
1699 /// returns a reference to those bytes interpreted as a `Self`. If the
1700 /// length of `source` is not a [valid size of `Self`][valid-size], or if
1701 /// `source` is not appropriately aligned, or if `source` is not a valid
1702 /// instance of `Self`, this returns `Err`. If [`Self:
1703 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
1704 /// error][ConvertError::from].
1705 ///
1706 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
1707 ///
1708 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
1709 /// [self-unaligned]: Unaligned
1710 /// [slice-dst]: KnownLayout#dynamically-sized-types
1711 ///
1712 /// # Compile-Time Assertions
1713 ///
1714 /// This method cannot yet be used on unsized types whose dynamically-sized
1715 /// component is zero-sized. Attempting to use this method on such types
1716 /// results in a compile-time assertion error; e.g.:
1717 ///
1718 /// ```compile_fail,E0080
1719 /// use zerocopy::*;
1720 /// # use zerocopy_derive::*;
1721 ///
1722 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1723 /// #[repr(C, packed)]
1724 /// struct ZSTy {
1725 /// leading_sized: [u8; 2],
1726 /// trailing_dst: [()],
1727 /// }
1728 ///
1729 /// let mut source = [85, 85];
1730 /// let _ = ZSTy::try_mut_from_bytes(&mut source[..]); // âš Compile Error!
1731 /// ```
1732 ///
1733 /// # Examples
1734 ///
1735 /// ```
1736 /// use zerocopy::TryFromBytes;
1737 /// # use zerocopy_derive::*;
1738 ///
1739 /// // The only valid value of this type is the byte `0xC0`
1740 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1741 /// #[repr(u8)]
1742 /// enum C0 { xC0 = 0xC0 }
1743 ///
1744 /// // The only valid value of this type is the bytes `0xC0C0`.
1745 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1746 /// #[repr(C)]
1747 /// struct C0C0(C0, C0);
1748 ///
1749 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1750 /// #[repr(C, packed)]
1751 /// struct Packet {
1752 /// magic_number: C0C0,
1753 /// mug_size: u8,
1754 /// temperature: u8,
1755 /// marshmallows: [[u8; 2]],
1756 /// }
1757 ///
1758 /// let bytes = &mut [0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5][..];
1759 ///
1760 /// let packet = Packet::try_mut_from_bytes(bytes).unwrap();
1761 ///
1762 /// assert_eq!(packet.mug_size, 240);
1763 /// assert_eq!(packet.temperature, 77);
1764 /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]);
1765 ///
1766 /// packet.temperature = 111;
1767 ///
1768 /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 0, 1, 2, 3, 4, 5]);
1769 ///
1770 /// // These bytes are not valid instance of `Packet`.
1771 /// let bytes = &mut [0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
1772 /// assert!(Packet::try_mut_from_bytes(bytes).is_err());
1773 /// ```
1774 #[must_use = "has no side effects"]
1775 #[inline]
1776 fn try_mut_from_bytes(bytes: &mut [u8]) -> Result<&mut Self, TryCastError<&mut [u8], Self>>
1777 where
1778 Self: KnownLayout + IntoBytes,
1779 {
1780 static_assert_dst_is_not_zst!(Self);
1781 match Ptr::from_mut(bytes).try_cast_into_no_leftover::<Self, BecauseExclusive>(None) {
1782 Ok(source) => {
1783 // This call may panic. If that happens, it doesn't cause any soundness
1784 // issues, as we have not generated any invalid state which we need to
1785 // fix before returning.
1786 //
1787 // Note that one panic or post-monomorphization error condition is
1788 // calling `try_into_valid` (and thus `is_bit_valid`) with a shared
1789 // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
1790 // condition will not happen.
1791 match source.try_into_valid() {
1792 Ok(source) => Ok(source.as_mut()),
1793 Err(e) => {
1794 Err(e.map_src(|src| src.as_bytes::<BecauseExclusive>().as_mut()).into())
1795 }
1796 }
1797 }
1798 Err(e) => Err(e.map_src(Ptr::as_mut).into()),
1799 }
1800 }
1801
1802 /// Attempts to interpret the prefix of the given `source` as a `&mut
1803 /// Self`.
1804 ///
1805 /// This method computes the [largest possible size of `Self`][valid-size]
1806 /// that can fit in the leading bytes of `source`. If that prefix is a valid
1807 /// instance of `Self`, this method returns a reference to those bytes
1808 /// interpreted as `Self`, and a reference to the remaining bytes. If there
1809 /// are insufficient bytes, or if `source` is not appropriately aligned, or
1810 /// if the bytes are not a valid instance of `Self`, this returns `Err`. If
1811 /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
1812 /// alignment error][ConvertError::from].
1813 ///
1814 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
1815 ///
1816 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
1817 /// [self-unaligned]: Unaligned
1818 /// [slice-dst]: KnownLayout#dynamically-sized-types
1819 ///
1820 /// # Compile-Time Assertions
1821 ///
1822 /// This method cannot yet be used on unsized types whose dynamically-sized
1823 /// component is zero-sized. Attempting to use this method on such types
1824 /// results in a compile-time assertion error; e.g.:
1825 ///
1826 /// ```compile_fail,E0080
1827 /// use zerocopy::*;
1828 /// # use zerocopy_derive::*;
1829 ///
1830 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1831 /// #[repr(C, packed)]
1832 /// struct ZSTy {
1833 /// leading_sized: [u8; 2],
1834 /// trailing_dst: [()],
1835 /// }
1836 ///
1837 /// let mut source = [85, 85];
1838 /// let _ = ZSTy::try_mut_from_prefix(&mut source[..]); // âš Compile Error!
1839 /// ```
1840 ///
1841 /// # Examples
1842 ///
1843 /// ```
1844 /// use zerocopy::TryFromBytes;
1845 /// # use zerocopy_derive::*;
1846 ///
1847 /// // The only valid value of this type is the byte `0xC0`
1848 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1849 /// #[repr(u8)]
1850 /// enum C0 { xC0 = 0xC0 }
1851 ///
1852 /// // The only valid value of this type is the bytes `0xC0C0`.
1853 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1854 /// #[repr(C)]
1855 /// struct C0C0(C0, C0);
1856 ///
1857 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1858 /// #[repr(C, packed)]
1859 /// struct Packet {
1860 /// magic_number: C0C0,
1861 /// mug_size: u8,
1862 /// temperature: u8,
1863 /// marshmallows: [[u8; 2]],
1864 /// }
1865 ///
1866 /// // These are more bytes than are needed to encode a `Packet`.
1867 /// let bytes = &mut [0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
1868 ///
1869 /// let (packet, suffix) = Packet::try_mut_from_prefix(bytes).unwrap();
1870 ///
1871 /// assert_eq!(packet.mug_size, 240);
1872 /// assert_eq!(packet.temperature, 77);
1873 /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]);
1874 /// assert_eq!(suffix, &[6u8][..]);
1875 ///
1876 /// packet.temperature = 111;
1877 /// suffix[0] = 222;
1878 ///
1879 /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 0, 1, 2, 3, 4, 5, 222]);
1880 ///
1881 /// // These bytes are not valid instance of `Packet`.
1882 /// let bytes = &mut [0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
1883 /// assert!(Packet::try_mut_from_prefix(bytes).is_err());
1884 /// ```
1885 #[must_use = "has no side effects"]
1886 #[inline]
1887 fn try_mut_from_prefix(
1888 source: &mut [u8],
1889 ) -> Result<(&mut Self, &mut [u8]), TryCastError<&mut [u8], Self>>
1890 where
1891 Self: KnownLayout + IntoBytes,
1892 {
1893 static_assert_dst_is_not_zst!(Self);
1894 try_mut_from_prefix_suffix(source, CastType::Prefix, None)
1895 }
1896
1897 /// Attempts to interpret the suffix of the given `source` as a `&mut
1898 /// Self`.
1899 ///
1900 /// This method computes the [largest possible size of `Self`][valid-size]
1901 /// that can fit in the trailing bytes of `source`. If that suffix is a
1902 /// valid instance of `Self`, this method returns a reference to those bytes
1903 /// interpreted as `Self`, and a reference to the preceding bytes. If there
1904 /// are insufficient bytes, or if the suffix of `source` would not be
1905 /// appropriately aligned, or if the suffix is not a valid instance of
1906 /// `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], you
1907 /// can [infallibly discard the alignment error][ConvertError::from].
1908 ///
1909 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
1910 ///
1911 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
1912 /// [self-unaligned]: Unaligned
1913 /// [slice-dst]: KnownLayout#dynamically-sized-types
1914 ///
1915 /// # Compile-Time Assertions
1916 ///
1917 /// This method cannot yet be used on unsized types whose dynamically-sized
1918 /// component is zero-sized. Attempting to use this method on such types
1919 /// results in a compile-time assertion error; e.g.:
1920 ///
1921 /// ```compile_fail,E0080
1922 /// use zerocopy::*;
1923 /// # use zerocopy_derive::*;
1924 ///
1925 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1926 /// #[repr(C, packed)]
1927 /// struct ZSTy {
1928 /// leading_sized: u16,
1929 /// trailing_dst: [()],
1930 /// }
1931 ///
1932 /// let mut source = [85, 85];
1933 /// let _ = ZSTy::try_mut_from_suffix(&mut source[..]); // âš Compile Error!
1934 /// ```
1935 ///
1936 /// # Examples
1937 ///
1938 /// ```
1939 /// use zerocopy::TryFromBytes;
1940 /// # use zerocopy_derive::*;
1941 ///
1942 /// // The only valid value of this type is the byte `0xC0`
1943 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1944 /// #[repr(u8)]
1945 /// enum C0 { xC0 = 0xC0 }
1946 ///
1947 /// // The only valid value of this type is the bytes `0xC0C0`.
1948 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1949 /// #[repr(C)]
1950 /// struct C0C0(C0, C0);
1951 ///
1952 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
1953 /// #[repr(C, packed)]
1954 /// struct Packet {
1955 /// magic_number: C0C0,
1956 /// mug_size: u8,
1957 /// temperature: u8,
1958 /// marshmallows: [[u8; 2]],
1959 /// }
1960 ///
1961 /// // These are more bytes than are needed to encode a `Packet`.
1962 /// let bytes = &mut [0, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
1963 ///
1964 /// let (prefix, packet) = Packet::try_mut_from_suffix(bytes).unwrap();
1965 ///
1966 /// assert_eq!(packet.mug_size, 240);
1967 /// assert_eq!(packet.temperature, 77);
1968 /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
1969 /// assert_eq!(prefix, &[0u8][..]);
1970 ///
1971 /// prefix[0] = 111;
1972 /// packet.temperature = 222;
1973 ///
1974 /// assert_eq!(bytes, [111, 0xC0, 0xC0, 240, 222, 2, 3, 4, 5, 6, 7]);
1975 ///
1976 /// // These bytes are not valid instance of `Packet`.
1977 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0x10][..];
1978 /// assert!(Packet::try_mut_from_suffix(bytes).is_err());
1979 /// ```
1980 #[must_use = "has no side effects"]
1981 #[inline]
1982 fn try_mut_from_suffix(
1983 source: &mut [u8],
1984 ) -> Result<(&mut [u8], &mut Self), TryCastError<&mut [u8], Self>>
1985 where
1986 Self: KnownLayout + IntoBytes,
1987 {
1988 static_assert_dst_is_not_zst!(Self);
1989 try_mut_from_prefix_suffix(source, CastType::Suffix, None).map(swap)
1990 }
1991
1992 /// Attempts to interpret the given `source` as a `&Self` with a DST length
1993 /// equal to `count`.
1994 ///
1995 /// This method attempts to return a reference to `source` interpreted as a
1996 /// `Self` with `count` trailing elements. If the length of `source` is not
1997 /// equal to the size of `Self` with `count` elements, if `source` is not
1998 /// appropriately aligned, or if `source` does not contain a valid instance
1999 /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned],
2000 /// you can [infallibly discard the alignment error][ConvertError::from].
2001 ///
2002 /// [self-unaligned]: Unaligned
2003 /// [slice-dst]: KnownLayout#dynamically-sized-types
2004 ///
2005 /// # Examples
2006 ///
2007 /// ```
2008 /// # #![allow(non_camel_case_types)] // For C0::xC0
2009 /// use zerocopy::TryFromBytes;
2010 /// # use zerocopy_derive::*;
2011 ///
2012 /// // The only valid value of this type is the byte `0xC0`
2013 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2014 /// #[repr(u8)]
2015 /// enum C0 { xC0 = 0xC0 }
2016 ///
2017 /// // The only valid value of this type is the bytes `0xC0C0`.
2018 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2019 /// #[repr(C)]
2020 /// struct C0C0(C0, C0);
2021 ///
2022 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2023 /// #[repr(C)]
2024 /// struct Packet {
2025 /// magic_number: C0C0,
2026 /// mug_size: u8,
2027 /// temperature: u8,
2028 /// marshmallows: [[u8; 2]],
2029 /// }
2030 ///
2031 /// let bytes = &[0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
2032 ///
2033 /// let packet = Packet::try_ref_from_bytes_with_elems(bytes, 3).unwrap();
2034 ///
2035 /// assert_eq!(packet.mug_size, 240);
2036 /// assert_eq!(packet.temperature, 77);
2037 /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2038 ///
2039 /// // These bytes are not valid instance of `Packet`.
2040 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0xC0][..];
2041 /// assert!(Packet::try_ref_from_bytes_with_elems(bytes, 3).is_err());
2042 /// ```
2043 ///
2044 /// Since an explicit `count` is provided, this method supports types with
2045 /// zero-sized trailing slice elements. Methods such as [`try_ref_from_bytes`]
2046 /// which do not take an explicit count do not support such types.
2047 ///
2048 /// ```
2049 /// use core::num::NonZeroU16;
2050 /// use zerocopy::*;
2051 /// # use zerocopy_derive::*;
2052 ///
2053 /// #[derive(TryFromBytes, Immutable, KnownLayout)]
2054 /// #[repr(C)]
2055 /// struct ZSTy {
2056 /// leading_sized: NonZeroU16,
2057 /// trailing_dst: [()],
2058 /// }
2059 ///
2060 /// let src = 0xCAFEu16.as_bytes();
2061 /// let zsty = ZSTy::try_ref_from_bytes_with_elems(src, 42).unwrap();
2062 /// assert_eq!(zsty.trailing_dst.len(), 42);
2063 /// ```
2064 ///
2065 /// [`try_ref_from_bytes`]: TryFromBytes::try_ref_from_bytes
2066 #[must_use = "has no side effects"]
2067 #[inline]
2068 fn try_ref_from_bytes_with_elems(
2069 source: &[u8],
2070 count: usize,
2071 ) -> Result<&Self, TryCastError<&[u8], Self>>
2072 where
2073 Self: KnownLayout<PointerMetadata = usize> + Immutable,
2074 {
2075 match Ptr::from_ref(source).try_cast_into_no_leftover::<Self, BecauseImmutable>(Some(count))
2076 {
2077 Ok(source) => {
2078 // This call may panic. If that happens, it doesn't cause any soundness
2079 // issues, as we have not generated any invalid state which we need to
2080 // fix before returning.
2081 //
2082 // Note that one panic or post-monomorphization error condition is
2083 // calling `try_into_valid` (and thus `is_bit_valid`) with a shared
2084 // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
2085 // condition will not happen.
2086 match source.try_into_valid() {
2087 Ok(source) => Ok(source.as_ref()),
2088 Err(e) => {
2089 Err(e.map_src(|src| src.as_bytes::<BecauseImmutable>().as_ref()).into())
2090 }
2091 }
2092 }
2093 Err(e) => Err(e.map_src(Ptr::as_ref).into()),
2094 }
2095 }
2096
2097 /// Attempts to interpret the prefix of the given `source` as a `&Self` with
2098 /// a DST length equal to `count`.
2099 ///
2100 /// This method attempts to return a reference to the prefix of `source`
2101 /// interpreted as a `Self` with `count` trailing elements, and a reference
2102 /// to the remaining bytes. If the length of `source` is less than the size
2103 /// of `Self` with `count` elements, if `source` is not appropriately
2104 /// aligned, or if the prefix of `source` does not contain a valid instance
2105 /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned],
2106 /// you can [infallibly discard the alignment error][ConvertError::from].
2107 ///
2108 /// [self-unaligned]: Unaligned
2109 /// [slice-dst]: KnownLayout#dynamically-sized-types
2110 ///
2111 /// # Examples
2112 ///
2113 /// ```
2114 /// # #![allow(non_camel_case_types)] // For C0::xC0
2115 /// use zerocopy::TryFromBytes;
2116 /// # use zerocopy_derive::*;
2117 ///
2118 /// // The only valid value of this type is the byte `0xC0`
2119 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2120 /// #[repr(u8)]
2121 /// enum C0 { xC0 = 0xC0 }
2122 ///
2123 /// // The only valid value of this type is the bytes `0xC0C0`.
2124 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2125 /// #[repr(C)]
2126 /// struct C0C0(C0, C0);
2127 ///
2128 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2129 /// #[repr(C)]
2130 /// struct Packet {
2131 /// magic_number: C0C0,
2132 /// mug_size: u8,
2133 /// temperature: u8,
2134 /// marshmallows: [[u8; 2]],
2135 /// }
2136 ///
2137 /// let bytes = &[0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7, 8][..];
2138 ///
2139 /// let (packet, suffix) = Packet::try_ref_from_prefix_with_elems(bytes, 3).unwrap();
2140 ///
2141 /// assert_eq!(packet.mug_size, 240);
2142 /// assert_eq!(packet.temperature, 77);
2143 /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2144 /// assert_eq!(suffix, &[8u8][..]);
2145 ///
2146 /// // These bytes are not valid instance of `Packet`.
2147 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..];
2148 /// assert!(Packet::try_ref_from_prefix_with_elems(bytes, 3).is_err());
2149 /// ```
2150 ///
2151 /// Since an explicit `count` is provided, this method supports types with
2152 /// zero-sized trailing slice elements. Methods such as [`try_ref_from_prefix`]
2153 /// which do not take an explicit count do not support such types.
2154 ///
2155 /// ```
2156 /// use core::num::NonZeroU16;
2157 /// use zerocopy::*;
2158 /// # use zerocopy_derive::*;
2159 ///
2160 /// #[derive(TryFromBytes, Immutable, KnownLayout)]
2161 /// #[repr(C)]
2162 /// struct ZSTy {
2163 /// leading_sized: NonZeroU16,
2164 /// trailing_dst: [()],
2165 /// }
2166 ///
2167 /// let src = 0xCAFEu16.as_bytes();
2168 /// let (zsty, _) = ZSTy::try_ref_from_prefix_with_elems(src, 42).unwrap();
2169 /// assert_eq!(zsty.trailing_dst.len(), 42);
2170 /// ```
2171 ///
2172 /// [`try_ref_from_prefix`]: TryFromBytes::try_ref_from_prefix
2173 #[must_use = "has no side effects"]
2174 #[inline]
2175 fn try_ref_from_prefix_with_elems(
2176 source: &[u8],
2177 count: usize,
2178 ) -> Result<(&Self, &[u8]), TryCastError<&[u8], Self>>
2179 where
2180 Self: KnownLayout<PointerMetadata = usize> + Immutable,
2181 {
2182 try_ref_from_prefix_suffix(source, CastType::Prefix, Some(count))
2183 }
2184
2185 /// Attempts to interpret the suffix of the given `source` as a `&Self` with
2186 /// a DST length equal to `count`.
2187 ///
2188 /// This method attempts to return a reference to the suffix of `source`
2189 /// interpreted as a `Self` with `count` trailing elements, and a reference
2190 /// to the preceding bytes. If the length of `source` is less than the size
2191 /// of `Self` with `count` elements, if the suffix of `source` is not
2192 /// appropriately aligned, or if the suffix of `source` does not contain a
2193 /// valid instance of `Self`, this returns `Err`. If [`Self:
2194 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
2195 /// error][ConvertError::from].
2196 ///
2197 /// [self-unaligned]: Unaligned
2198 /// [slice-dst]: KnownLayout#dynamically-sized-types
2199 ///
2200 /// # Examples
2201 ///
2202 /// ```
2203 /// # #![allow(non_camel_case_types)] // For C0::xC0
2204 /// use zerocopy::TryFromBytes;
2205 /// # use zerocopy_derive::*;
2206 ///
2207 /// // The only valid value of this type is the byte `0xC0`
2208 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2209 /// #[repr(u8)]
2210 /// enum C0 { xC0 = 0xC0 }
2211 ///
2212 /// // The only valid value of this type is the bytes `0xC0C0`.
2213 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2214 /// #[repr(C)]
2215 /// struct C0C0(C0, C0);
2216 ///
2217 /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2218 /// #[repr(C)]
2219 /// struct Packet {
2220 /// magic_number: C0C0,
2221 /// mug_size: u8,
2222 /// temperature: u8,
2223 /// marshmallows: [[u8; 2]],
2224 /// }
2225 ///
2226 /// let bytes = &[123, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
2227 ///
2228 /// let (prefix, packet) = Packet::try_ref_from_suffix_with_elems(bytes, 3).unwrap();
2229 ///
2230 /// assert_eq!(packet.mug_size, 240);
2231 /// assert_eq!(packet.temperature, 77);
2232 /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2233 /// assert_eq!(prefix, &[123u8][..]);
2234 ///
2235 /// // These bytes are not valid instance of `Packet`.
2236 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..];
2237 /// assert!(Packet::try_ref_from_suffix_with_elems(bytes, 3).is_err());
2238 /// ```
2239 ///
2240 /// Since an explicit `count` is provided, this method supports types with
2241 /// zero-sized trailing slice elements. Methods such as [`try_ref_from_prefix`]
2242 /// which do not take an explicit count do not support such types.
2243 ///
2244 /// ```
2245 /// use core::num::NonZeroU16;
2246 /// use zerocopy::*;
2247 /// # use zerocopy_derive::*;
2248 ///
2249 /// #[derive(TryFromBytes, Immutable, KnownLayout)]
2250 /// #[repr(C)]
2251 /// struct ZSTy {
2252 /// leading_sized: NonZeroU16,
2253 /// trailing_dst: [()],
2254 /// }
2255 ///
2256 /// let src = 0xCAFEu16.as_bytes();
2257 /// let (_, zsty) = ZSTy::try_ref_from_suffix_with_elems(src, 42).unwrap();
2258 /// assert_eq!(zsty.trailing_dst.len(), 42);
2259 /// ```
2260 ///
2261 /// [`try_ref_from_prefix`]: TryFromBytes::try_ref_from_prefix
2262 #[must_use = "has no side effects"]
2263 #[inline]
2264 fn try_ref_from_suffix_with_elems(
2265 source: &[u8],
2266 count: usize,
2267 ) -> Result<(&[u8], &Self), TryCastError<&[u8], Self>>
2268 where
2269 Self: KnownLayout<PointerMetadata = usize> + Immutable,
2270 {
2271 try_ref_from_prefix_suffix(source, CastType::Suffix, Some(count)).map(swap)
2272 }
2273
2274 /// Attempts to interpret the given `source` as a `&mut Self` with a DST
2275 /// length equal to `count`.
2276 ///
2277 /// This method attempts to return a reference to `source` interpreted as a
2278 /// `Self` with `count` trailing elements. If the length of `source` is not
2279 /// equal to the size of `Self` with `count` elements, if `source` is not
2280 /// appropriately aligned, or if `source` does not contain a valid instance
2281 /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned],
2282 /// you can [infallibly discard the alignment error][ConvertError::from].
2283 ///
2284 /// [self-unaligned]: Unaligned
2285 /// [slice-dst]: KnownLayout#dynamically-sized-types
2286 ///
2287 /// # Examples
2288 ///
2289 /// ```
2290 /// # #![allow(non_camel_case_types)] // For C0::xC0
2291 /// use zerocopy::TryFromBytes;
2292 /// # use zerocopy_derive::*;
2293 ///
2294 /// // The only valid value of this type is the byte `0xC0`
2295 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2296 /// #[repr(u8)]
2297 /// enum C0 { xC0 = 0xC0 }
2298 ///
2299 /// // The only valid value of this type is the bytes `0xC0C0`.
2300 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2301 /// #[repr(C)]
2302 /// struct C0C0(C0, C0);
2303 ///
2304 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2305 /// #[repr(C, packed)]
2306 /// struct Packet {
2307 /// magic_number: C0C0,
2308 /// mug_size: u8,
2309 /// temperature: u8,
2310 /// marshmallows: [[u8; 2]],
2311 /// }
2312 ///
2313 /// let bytes = &mut [0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
2314 ///
2315 /// let packet = Packet::try_mut_from_bytes_with_elems(bytes, 3).unwrap();
2316 ///
2317 /// assert_eq!(packet.mug_size, 240);
2318 /// assert_eq!(packet.temperature, 77);
2319 /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2320 ///
2321 /// packet.temperature = 111;
2322 ///
2323 /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 2, 3, 4, 5, 6, 7]);
2324 ///
2325 /// // These bytes are not valid instance of `Packet`.
2326 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0xC0][..];
2327 /// assert!(Packet::try_mut_from_bytes_with_elems(bytes, 3).is_err());
2328 /// ```
2329 ///
2330 /// Since an explicit `count` is provided, this method supports types with
2331 /// zero-sized trailing slice elements. Methods such as [`try_mut_from_bytes`]
2332 /// which do not take an explicit count do not support such types.
2333 ///
2334 /// ```
2335 /// use core::num::NonZeroU16;
2336 /// use zerocopy::*;
2337 /// # use zerocopy_derive::*;
2338 ///
2339 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2340 /// #[repr(C, packed)]
2341 /// struct ZSTy {
2342 /// leading_sized: NonZeroU16,
2343 /// trailing_dst: [()],
2344 /// }
2345 ///
2346 /// let mut src = 0xCAFEu16;
2347 /// let src = src.as_mut_bytes();
2348 /// let zsty = ZSTy::try_mut_from_bytes_with_elems(src, 42).unwrap();
2349 /// assert_eq!(zsty.trailing_dst.len(), 42);
2350 /// ```
2351 ///
2352 /// [`try_mut_from_bytes`]: TryFromBytes::try_mut_from_bytes
2353 #[must_use = "has no side effects"]
2354 #[inline]
2355 fn try_mut_from_bytes_with_elems(
2356 source: &mut [u8],
2357 count: usize,
2358 ) -> Result<&mut Self, TryCastError<&mut [u8], Self>>
2359 where
2360 Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
2361 {
2362 match Ptr::from_mut(source).try_cast_into_no_leftover::<Self, BecauseExclusive>(Some(count))
2363 {
2364 Ok(source) => {
2365 // This call may panic. If that happens, it doesn't cause any soundness
2366 // issues, as we have not generated any invalid state which we need to
2367 // fix before returning.
2368 //
2369 // Note that one panic or post-monomorphization error condition is
2370 // calling `try_into_valid` (and thus `is_bit_valid`) with a shared
2371 // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
2372 // condition will not happen.
2373 match source.try_into_valid() {
2374 Ok(source) => Ok(source.as_mut()),
2375 Err(e) => {
2376 Err(e.map_src(|src| src.as_bytes::<BecauseExclusive>().as_mut()).into())
2377 }
2378 }
2379 }
2380 Err(e) => Err(e.map_src(Ptr::as_mut).into()),
2381 }
2382 }
2383
2384 /// Attempts to interpret the prefix of the given `source` as a `&mut Self`
2385 /// with a DST length equal to `count`.
2386 ///
2387 /// This method attempts to return a reference to the prefix of `source`
2388 /// interpreted as a `Self` with `count` trailing elements, and a reference
2389 /// to the remaining bytes. If the length of `source` is less than the size
2390 /// of `Self` with `count` elements, if `source` is not appropriately
2391 /// aligned, or if the prefix of `source` does not contain a valid instance
2392 /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned],
2393 /// you can [infallibly discard the alignment error][ConvertError::from].
2394 ///
2395 /// [self-unaligned]: Unaligned
2396 /// [slice-dst]: KnownLayout#dynamically-sized-types
2397 ///
2398 /// # Examples
2399 ///
2400 /// ```
2401 /// # #![allow(non_camel_case_types)] // For C0::xC0
2402 /// use zerocopy::TryFromBytes;
2403 /// # use zerocopy_derive::*;
2404 ///
2405 /// // The only valid value of this type is the byte `0xC0`
2406 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2407 /// #[repr(u8)]
2408 /// enum C0 { xC0 = 0xC0 }
2409 ///
2410 /// // The only valid value of this type is the bytes `0xC0C0`.
2411 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2412 /// #[repr(C)]
2413 /// struct C0C0(C0, C0);
2414 ///
2415 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2416 /// #[repr(C, packed)]
2417 /// struct Packet {
2418 /// magic_number: C0C0,
2419 /// mug_size: u8,
2420 /// temperature: u8,
2421 /// marshmallows: [[u8; 2]],
2422 /// }
2423 ///
2424 /// let bytes = &mut [0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7, 8][..];
2425 ///
2426 /// let (packet, suffix) = Packet::try_mut_from_prefix_with_elems(bytes, 3).unwrap();
2427 ///
2428 /// assert_eq!(packet.mug_size, 240);
2429 /// assert_eq!(packet.temperature, 77);
2430 /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2431 /// assert_eq!(suffix, &[8u8][..]);
2432 ///
2433 /// packet.temperature = 111;
2434 /// suffix[0] = 222;
2435 ///
2436 /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 2, 3, 4, 5, 6, 7, 222]);
2437 ///
2438 /// // These bytes are not valid instance of `Packet`.
2439 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..];
2440 /// assert!(Packet::try_mut_from_prefix_with_elems(bytes, 3).is_err());
2441 /// ```
2442 ///
2443 /// Since an explicit `count` is provided, this method supports types with
2444 /// zero-sized trailing slice elements. Methods such as [`try_mut_from_prefix`]
2445 /// which do not take an explicit count do not support such types.
2446 ///
2447 /// ```
2448 /// use core::num::NonZeroU16;
2449 /// use zerocopy::*;
2450 /// # use zerocopy_derive::*;
2451 ///
2452 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2453 /// #[repr(C, packed)]
2454 /// struct ZSTy {
2455 /// leading_sized: NonZeroU16,
2456 /// trailing_dst: [()],
2457 /// }
2458 ///
2459 /// let mut src = 0xCAFEu16;
2460 /// let src = src.as_mut_bytes();
2461 /// let (zsty, _) = ZSTy::try_mut_from_prefix_with_elems(src, 42).unwrap();
2462 /// assert_eq!(zsty.trailing_dst.len(), 42);
2463 /// ```
2464 ///
2465 /// [`try_mut_from_prefix`]: TryFromBytes::try_mut_from_prefix
2466 #[must_use = "has no side effects"]
2467 #[inline]
2468 fn try_mut_from_prefix_with_elems(
2469 source: &mut [u8],
2470 count: usize,
2471 ) -> Result<(&mut Self, &mut [u8]), TryCastError<&mut [u8], Self>>
2472 where
2473 Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
2474 {
2475 try_mut_from_prefix_suffix(source, CastType::Prefix, Some(count))
2476 }
2477
2478 /// Attempts to interpret the suffix of the given `source` as a `&mut Self`
2479 /// with a DST length equal to `count`.
2480 ///
2481 /// This method attempts to return a reference to the suffix of `source`
2482 /// interpreted as a `Self` with `count` trailing elements, and a reference
2483 /// to the preceding bytes. If the length of `source` is less than the size
2484 /// of `Self` with `count` elements, if the suffix of `source` is not
2485 /// appropriately aligned, or if the suffix of `source` does not contain a
2486 /// valid instance of `Self`, this returns `Err`. If [`Self:
2487 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
2488 /// error][ConvertError::from].
2489 ///
2490 /// [self-unaligned]: Unaligned
2491 /// [slice-dst]: KnownLayout#dynamically-sized-types
2492 ///
2493 /// # Examples
2494 ///
2495 /// ```
2496 /// # #![allow(non_camel_case_types)] // For C0::xC0
2497 /// use zerocopy::TryFromBytes;
2498 /// # use zerocopy_derive::*;
2499 ///
2500 /// // The only valid value of this type is the byte `0xC0`
2501 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2502 /// #[repr(u8)]
2503 /// enum C0 { xC0 = 0xC0 }
2504 ///
2505 /// // The only valid value of this type is the bytes `0xC0C0`.
2506 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2507 /// #[repr(C)]
2508 /// struct C0C0(C0, C0);
2509 ///
2510 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2511 /// #[repr(C, packed)]
2512 /// struct Packet {
2513 /// magic_number: C0C0,
2514 /// mug_size: u8,
2515 /// temperature: u8,
2516 /// marshmallows: [[u8; 2]],
2517 /// }
2518 ///
2519 /// let bytes = &mut [123, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
2520 ///
2521 /// let (prefix, packet) = Packet::try_mut_from_suffix_with_elems(bytes, 3).unwrap();
2522 ///
2523 /// assert_eq!(packet.mug_size, 240);
2524 /// assert_eq!(packet.temperature, 77);
2525 /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2526 /// assert_eq!(prefix, &[123u8][..]);
2527 ///
2528 /// prefix[0] = 111;
2529 /// packet.temperature = 222;
2530 ///
2531 /// assert_eq!(bytes, [111, 0xC0, 0xC0, 240, 222, 2, 3, 4, 5, 6, 7]);
2532 ///
2533 /// // These bytes are not valid instance of `Packet`.
2534 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..];
2535 /// assert!(Packet::try_mut_from_suffix_with_elems(bytes, 3).is_err());
2536 /// ```
2537 ///
2538 /// Since an explicit `count` is provided, this method supports types with
2539 /// zero-sized trailing slice elements. Methods such as [`try_mut_from_prefix`]
2540 /// which do not take an explicit count do not support such types.
2541 ///
2542 /// ```
2543 /// use core::num::NonZeroU16;
2544 /// use zerocopy::*;
2545 /// # use zerocopy_derive::*;
2546 ///
2547 /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2548 /// #[repr(C, packed)]
2549 /// struct ZSTy {
2550 /// leading_sized: NonZeroU16,
2551 /// trailing_dst: [()],
2552 /// }
2553 ///
2554 /// let mut src = 0xCAFEu16;
2555 /// let src = src.as_mut_bytes();
2556 /// let (_, zsty) = ZSTy::try_mut_from_suffix_with_elems(src, 42).unwrap();
2557 /// assert_eq!(zsty.trailing_dst.len(), 42);
2558 /// ```
2559 ///
2560 /// [`try_mut_from_prefix`]: TryFromBytes::try_mut_from_prefix
2561 #[must_use = "has no side effects"]
2562 #[inline]
2563 fn try_mut_from_suffix_with_elems(
2564 source: &mut [u8],
2565 count: usize,
2566 ) -> Result<(&mut [u8], &mut Self), TryCastError<&mut [u8], Self>>
2567 where
2568 Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
2569 {
2570 try_mut_from_prefix_suffix(source, CastType::Suffix, Some(count)).map(swap)
2571 }
2572
2573 /// Attempts to read the given `source` as a `Self`.
2574 ///
2575 /// If `source.len() != size_of::<Self>()` or the bytes are not a valid
2576 /// instance of `Self`, this returns `Err`.
2577 ///
2578 /// # Examples
2579 ///
2580 /// ```
2581 /// use zerocopy::TryFromBytes;
2582 /// # use zerocopy_derive::*;
2583 ///
2584 /// // The only valid value of this type is the byte `0xC0`
2585 /// #[derive(TryFromBytes)]
2586 /// #[repr(u8)]
2587 /// enum C0 { xC0 = 0xC0 }
2588 ///
2589 /// // The only valid value of this type is the bytes `0xC0C0`.
2590 /// #[derive(TryFromBytes)]
2591 /// #[repr(C)]
2592 /// struct C0C0(C0, C0);
2593 ///
2594 /// #[derive(TryFromBytes)]
2595 /// #[repr(C)]
2596 /// struct Packet {
2597 /// magic_number: C0C0,
2598 /// mug_size: u8,
2599 /// temperature: u8,
2600 /// }
2601 ///
2602 /// let bytes = &[0xC0, 0xC0, 240, 77][..];
2603 ///
2604 /// let packet = Packet::try_read_from_bytes(bytes).unwrap();
2605 ///
2606 /// assert_eq!(packet.mug_size, 240);
2607 /// assert_eq!(packet.temperature, 77);
2608 ///
2609 /// // These bytes are not valid instance of `Packet`.
2610 /// let bytes = &mut [0x10, 0xC0, 240, 77][..];
2611 /// assert!(Packet::try_read_from_bytes(bytes).is_err());
2612 /// ```
2613 #[must_use = "has no side effects"]
2614 #[inline]
2615 fn try_read_from_bytes(source: &[u8]) -> Result<Self, TryReadError<&[u8], Self>>
2616 where
2617 Self: Sized,
2618 {
2619 let candidate = match CoreMaybeUninit::<Self>::read_from_bytes(source) {
2620 Ok(candidate) => candidate,
2621 Err(e) => {
2622 return Err(TryReadError::Size(e.with_dst()));
2623 }
2624 };
2625 // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
2626 // its bytes are initialized.
2627 unsafe { try_read_from(source, candidate) }
2628 }
2629
2630 /// Attempts to read a `Self` from the prefix of the given `source`.
2631 ///
2632 /// This attempts to read a `Self` from the first `size_of::<Self>()` bytes
2633 /// of `source`, returning that `Self` and any remaining bytes. If
2634 /// `source.len() < size_of::<Self>()` or the bytes are not a valid instance
2635 /// of `Self`, it returns `Err`.
2636 ///
2637 /// # Examples
2638 ///
2639 /// ```
2640 /// use zerocopy::TryFromBytes;
2641 /// # use zerocopy_derive::*;
2642 ///
2643 /// // The only valid value of this type is the byte `0xC0`
2644 /// #[derive(TryFromBytes)]
2645 /// #[repr(u8)]
2646 /// enum C0 { xC0 = 0xC0 }
2647 ///
2648 /// // The only valid value of this type is the bytes `0xC0C0`.
2649 /// #[derive(TryFromBytes)]
2650 /// #[repr(C)]
2651 /// struct C0C0(C0, C0);
2652 ///
2653 /// #[derive(TryFromBytes)]
2654 /// #[repr(C)]
2655 /// struct Packet {
2656 /// magic_number: C0C0,
2657 /// mug_size: u8,
2658 /// temperature: u8,
2659 /// }
2660 ///
2661 /// // These are more bytes than are needed to encode a `Packet`.
2662 /// let bytes = &[0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
2663 ///
2664 /// let (packet, suffix) = Packet::try_read_from_prefix(bytes).unwrap();
2665 ///
2666 /// assert_eq!(packet.mug_size, 240);
2667 /// assert_eq!(packet.temperature, 77);
2668 /// assert_eq!(suffix, &[0u8, 1, 2, 3, 4, 5, 6][..]);
2669 ///
2670 /// // These bytes are not valid instance of `Packet`.
2671 /// let bytes = &[0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
2672 /// assert!(Packet::try_read_from_prefix(bytes).is_err());
2673 /// ```
2674 #[must_use = "has no side effects"]
2675 #[inline]
2676 fn try_read_from_prefix(source: &[u8]) -> Result<(Self, &[u8]), TryReadError<&[u8], Self>>
2677 where
2678 Self: Sized,
2679 {
2680 let (candidate, suffix) = match CoreMaybeUninit::<Self>::read_from_prefix(source) {
2681 Ok(candidate) => candidate,
2682 Err(e) => {
2683 return Err(TryReadError::Size(e.with_dst()));
2684 }
2685 };
2686 // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
2687 // its bytes are initialized.
2688 unsafe { try_read_from(source, candidate).map(|slf| (slf, suffix)) }
2689 }
2690
2691 /// Attempts to read a `Self` from the suffix of the given `source`.
2692 ///
2693 /// This attempts to read a `Self` from the last `size_of::<Self>()` bytes
2694 /// of `source`, returning that `Self` and any preceding bytes. If
2695 /// `source.len() < size_of::<Self>()` or the bytes are not a valid instance
2696 /// of `Self`, it returns `Err`.
2697 ///
2698 /// # Examples
2699 ///
2700 /// ```
2701 /// # #![allow(non_camel_case_types)] // For C0::xC0
2702 /// use zerocopy::TryFromBytes;
2703 /// # use zerocopy_derive::*;
2704 ///
2705 /// // The only valid value of this type is the byte `0xC0`
2706 /// #[derive(TryFromBytes)]
2707 /// #[repr(u8)]
2708 /// enum C0 { xC0 = 0xC0 }
2709 ///
2710 /// // The only valid value of this type is the bytes `0xC0C0`.
2711 /// #[derive(TryFromBytes)]
2712 /// #[repr(C)]
2713 /// struct C0C0(C0, C0);
2714 ///
2715 /// #[derive(TryFromBytes)]
2716 /// #[repr(C)]
2717 /// struct Packet {
2718 /// magic_number: C0C0,
2719 /// mug_size: u8,
2720 /// temperature: u8,
2721 /// }
2722 ///
2723 /// // These are more bytes than are needed to encode a `Packet`.
2724 /// let bytes = &[0, 1, 2, 3, 4, 5, 0xC0, 0xC0, 240, 77][..];
2725 ///
2726 /// let (prefix, packet) = Packet::try_read_from_suffix(bytes).unwrap();
2727 ///
2728 /// assert_eq!(packet.mug_size, 240);
2729 /// assert_eq!(packet.temperature, 77);
2730 /// assert_eq!(prefix, &[0u8, 1, 2, 3, 4, 5][..]);
2731 ///
2732 /// // These bytes are not valid instance of `Packet`.
2733 /// let bytes = &[0, 1, 2, 3, 4, 5, 0x10, 0xC0, 240, 77][..];
2734 /// assert!(Packet::try_read_from_suffix(bytes).is_err());
2735 /// ```
2736 #[must_use = "has no side effects"]
2737 #[inline]
2738 fn try_read_from_suffix(source: &[u8]) -> Result<(&[u8], Self), TryReadError<&[u8], Self>>
2739 where
2740 Self: Sized,
2741 {
2742 let (prefix, candidate) = match CoreMaybeUninit::<Self>::read_from_suffix(source) {
2743 Ok(candidate) => candidate,
2744 Err(e) => {
2745 return Err(TryReadError::Size(e.with_dst()));
2746 }
2747 };
2748 // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
2749 // its bytes are initialized.
2750 unsafe { try_read_from(source, candidate).map(|slf| (prefix, slf)) }
2751 }
2752}
2753
2754#[inline(always)]
2755fn try_ref_from_prefix_suffix<T: TryFromBytes + KnownLayout + Immutable + ?Sized>(
2756 source: &[u8],
2757 cast_type: CastType,
2758 meta: Option<T::PointerMetadata>,
2759) -> Result<(&T, &[u8]), TryCastError<&[u8], T>> {
2760 match Ptr::from_ref(source).try_cast_into::<T, BecauseImmutable>(cast_type, meta) {
2761 Ok((source, prefix_suffix)) => {
2762 // This call may panic. If that happens, it doesn't cause any soundness
2763 // issues, as we have not generated any invalid state which we need to
2764 // fix before returning.
2765 //
2766 // Note that one panic or post-monomorphization error condition is
2767 // calling `try_into_valid` (and thus `is_bit_valid`) with a shared
2768 // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
2769 // condition will not happen.
2770 match source.try_into_valid() {
2771 Ok(valid) => Ok((valid.as_ref(), prefix_suffix.as_ref())),
2772 Err(e) => Err(e.map_src(|src| src.as_bytes::<BecauseImmutable>().as_ref()).into()),
2773 }
2774 }
2775 Err(e) => Err(e.map_src(Ptr::as_ref).into()),
2776 }
2777}
2778
2779#[inline(always)]
2780fn try_mut_from_prefix_suffix<T: IntoBytes + TryFromBytes + KnownLayout + ?Sized>(
2781 candidate: &mut [u8],
2782 cast_type: CastType,
2783 meta: Option<T::PointerMetadata>,
2784) -> Result<(&mut T, &mut [u8]), TryCastError<&mut [u8], T>> {
2785 match Ptr::from_mut(candidate).try_cast_into::<T, BecauseExclusive>(cast_type, meta) {
2786 Ok((candidate, prefix_suffix)) => {
2787 // This call may panic. If that happens, it doesn't cause any soundness
2788 // issues, as we have not generated any invalid state which we need to
2789 // fix before returning.
2790 //
2791 // Note that one panic or post-monomorphization error condition is
2792 // calling `try_into_valid` (and thus `is_bit_valid`) with a shared
2793 // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
2794 // condition will not happen.
2795 match candidate.try_into_valid() {
2796 Ok(valid) => Ok((valid.as_mut(), prefix_suffix.as_mut())),
2797 Err(e) => Err(e.map_src(|src| src.as_bytes::<BecauseExclusive>().as_mut()).into()),
2798 }
2799 }
2800 Err(e) => Err(e.map_src(Ptr::as_mut).into()),
2801 }
2802}
2803
2804#[inline(always)]
2805fn swap<T, U>((t, u): (T, U)) -> (U, T) {
2806 (u, t)
2807}
2808
2809/// # Safety
2810///
2811/// All bytes of `candidate` must be initialized.
2812#[inline(always)]
2813unsafe fn try_read_from<S, T: TryFromBytes>(
2814 source: S,
2815 mut candidate: CoreMaybeUninit<T>,
2816) -> Result<T, TryReadError<S, T>> {
2817 // We use `from_mut` despite not mutating via `c_ptr` so that we don't need
2818 // to add a `T: Immutable` bound.
2819 let c_ptr = Ptr::from_mut(&mut candidate);
2820 let c_ptr = c_ptr.transparent_wrapper_into_inner();
2821 // SAFETY: `c_ptr` has no uninitialized sub-ranges because it derived from
2822 // `candidate`, which the caller promises is entirely initialized.
2823 let c_ptr = unsafe { c_ptr.assume_validity::<invariant::Initialized>() };
2824
2825 // This call may panic. If that happens, it doesn't cause any soundness
2826 // issues, as we have not generated any invalid state which we need to
2827 // fix before returning.
2828 //
2829 // Note that one panic or post-monomorphization error condition is
2830 // calling `try_into_valid` (and thus `is_bit_valid`) with a shared
2831 // pointer when `Self: !Immutable`. Since `Self: Immutable`, this panic
2832 // condition will not happen.
2833 if !T::is_bit_valid(c_ptr.forget_aligned()) {
2834 return Err(ValidityError::new(source).into());
2835 }
2836
2837 // SAFETY: We just validated that `candidate` contains a valid `T`.
2838 Ok(unsafe { candidate.assume_init() })
2839}
2840
2841/// Types for which a sequence of bytes all set to zero represents a valid
2842/// instance of the type.
2843///
2844/// Any memory region of the appropriate length which is guaranteed to contain
2845/// only zero bytes can be viewed as any `FromZeros` type with no runtime
2846/// overhead. This is useful whenever memory is known to be in a zeroed state,
2847/// such memory returned from some allocation routines.
2848///
2849/// # Warning: Padding bytes
2850///
2851/// Note that, when a value is moved or copied, only the non-padding bytes of
2852/// that value are guaranteed to be preserved. It is unsound to assume that
2853/// values written to padding bytes are preserved after a move or copy. For more
2854/// details, see the [`FromBytes` docs][frombytes-warning-padding-bytes].
2855///
2856/// [frombytes-warning-padding-bytes]: FromBytes#warning-padding-bytes
2857///
2858/// # Implementation
2859///
2860/// **Do not implement this trait yourself!** Instead, use
2861/// [`#[derive(FromZeros)]`][derive]; e.g.:
2862///
2863/// ```
2864/// # use zerocopy_derive::{FromZeros, Immutable};
2865/// #[derive(FromZeros)]
2866/// struct MyStruct {
2867/// # /*
2868/// ...
2869/// # */
2870/// }
2871///
2872/// #[derive(FromZeros)]
2873/// #[repr(u8)]
2874/// enum MyEnum {
2875/// # Variant0,
2876/// # /*
2877/// ...
2878/// # */
2879/// }
2880///
2881/// #[derive(FromZeros, Immutable)]
2882/// union MyUnion {
2883/// # variant: u8,
2884/// # /*
2885/// ...
2886/// # */
2887/// }
2888/// ```
2889///
2890/// This derive performs a sophisticated, compile-time safety analysis to
2891/// determine whether a type is `FromZeros`.
2892///
2893/// # Safety
2894///
2895/// *This section describes what is required in order for `T: FromZeros`, and
2896/// what unsafe code may assume of such types. If you don't plan on implementing
2897/// `FromZeros` manually, and you don't plan on writing unsafe code that
2898/// operates on `FromZeros` types, then you don't need to read this section.*
2899///
2900/// If `T: FromZeros`, then unsafe code may assume that it is sound to produce a
2901/// `T` whose bytes are all initialized to zero. If a type is marked as
2902/// `FromZeros` which violates this contract, it may cause undefined behavior.
2903///
2904/// `#[derive(FromZeros)]` only permits [types which satisfy these
2905/// requirements][derive-analysis].
2906///
2907#[cfg_attr(
2908 feature = "derive",
2909 doc = "[derive]: zerocopy_derive::FromZeros",
2910 doc = "[derive-analysis]: zerocopy_derive::FromZeros#analysis"
2911)]
2912#[cfg_attr(
2913 not(feature = "derive"),
2914 doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromZeros.html"),
2915 doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromZeros.html#analysis"),
2916)]
2917#[cfg_attr(
2918 zerocopy_diagnostic_on_unimplemented_1_78_0,
2919 diagnostic::on_unimplemented(note = "Consider adding `#[derive(FromZeros)]` to `{Self}`")
2920)]
2921pub unsafe trait FromZeros: TryFromBytes {
2922 // The `Self: Sized` bound makes it so that `FromZeros` is still object
2923 // safe.
2924 #[doc(hidden)]
2925 fn only_derive_is_allowed_to_implement_this_trait()
2926 where
2927 Self: Sized;
2928
2929 /// Overwrites `self` with zeros.
2930 ///
2931 /// Sets every byte in `self` to 0. While this is similar to doing `*self =
2932 /// Self::new_zeroed()`, it differs in that `zero` does not semantically
2933 /// drop the current value and replace it with a new one — it simply
2934 /// modifies the bytes of the existing value.
2935 ///
2936 /// # Examples
2937 ///
2938 /// ```
2939 /// # use zerocopy::FromZeros;
2940 /// # use zerocopy_derive::*;
2941 /// #
2942 /// #[derive(FromZeros)]
2943 /// #[repr(C)]
2944 /// struct PacketHeader {
2945 /// src_port: [u8; 2],
2946 /// dst_port: [u8; 2],
2947 /// length: [u8; 2],
2948 /// checksum: [u8; 2],
2949 /// }
2950 ///
2951 /// let mut header = PacketHeader {
2952 /// src_port: 100u16.to_be_bytes(),
2953 /// dst_port: 200u16.to_be_bytes(),
2954 /// length: 300u16.to_be_bytes(),
2955 /// checksum: 400u16.to_be_bytes(),
2956 /// };
2957 ///
2958 /// header.zero();
2959 ///
2960 /// assert_eq!(header.src_port, [0, 0]);
2961 /// assert_eq!(header.dst_port, [0, 0]);
2962 /// assert_eq!(header.length, [0, 0]);
2963 /// assert_eq!(header.checksum, [0, 0]);
2964 /// ```
2965 #[inline(always)]
2966 fn zero(&mut self) {
2967 let slf: *mut Self = self;
2968 let len = mem::size_of_val(self);
2969 // SAFETY:
2970 // - `self` is guaranteed by the type system to be valid for writes of
2971 // size `size_of_val(self)`.
2972 // - `u8`'s alignment is 1, and thus `self` is guaranteed to be aligned
2973 // as required by `u8`.
2974 // - Since `Self: FromZeros`, the all-zeros instance is a valid instance
2975 // of `Self.`
2976 //
2977 // TODO(#429): Add references to docs and quotes.
2978 unsafe { ptr::write_bytes(slf.cast::<u8>(), 0, len) };
2979 }
2980
2981 /// Creates an instance of `Self` from zeroed bytes.
2982 ///
2983 /// # Examples
2984 ///
2985 /// ```
2986 /// # use zerocopy::FromZeros;
2987 /// # use zerocopy_derive::*;
2988 /// #
2989 /// #[derive(FromZeros)]
2990 /// #[repr(C)]
2991 /// struct PacketHeader {
2992 /// src_port: [u8; 2],
2993 /// dst_port: [u8; 2],
2994 /// length: [u8; 2],
2995 /// checksum: [u8; 2],
2996 /// }
2997 ///
2998 /// let header: PacketHeader = FromZeros::new_zeroed();
2999 ///
3000 /// assert_eq!(header.src_port, [0, 0]);
3001 /// assert_eq!(header.dst_port, [0, 0]);
3002 /// assert_eq!(header.length, [0, 0]);
3003 /// assert_eq!(header.checksum, [0, 0]);
3004 /// ```
3005 #[must_use = "has no side effects"]
3006 #[inline(always)]
3007 fn new_zeroed() -> Self
3008 where
3009 Self: Sized,
3010 {
3011 // SAFETY: `FromZeros` says that the all-zeros bit pattern is legal.
3012 unsafe { mem::zeroed() }
3013 }
3014
3015 /// Creates a `Box<Self>` from zeroed bytes.
3016 ///
3017 /// This function is useful for allocating large values on the heap and
3018 /// zero-initializing them, without ever creating a temporary instance of
3019 /// `Self` on the stack. For example, `<[u8; 1048576]>::new_box_zeroed()`
3020 /// will allocate `[u8; 1048576]` directly on the heap; it does not require
3021 /// storing `[u8; 1048576]` in a temporary variable on the stack.
3022 ///
3023 /// On systems that use a heap implementation that supports allocating from
3024 /// pre-zeroed memory, using `new_box_zeroed` (or related functions) may
3025 /// have performance benefits.
3026 ///
3027 /// # Errors
3028 ///
3029 /// Returns an error on allocation failure. Allocation failure is guaranteed
3030 /// never to cause a panic or an abort.
3031 #[must_use = "has no side effects (other than allocation)"]
3032 #[cfg(any(feature = "alloc", test))]
3033 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
3034 #[inline]
3035 fn new_box_zeroed() -> Result<Box<Self>, AllocError>
3036 where
3037 Self: Sized,
3038 {
3039 // If `T` is a ZST, then return a proper boxed instance of it. There is
3040 // no allocation, but `Box` does require a correct dangling pointer.
3041 let layout = Layout::new::<Self>();
3042 if layout.size() == 0 {
3043 // Construct the `Box` from a dangling pointer to avoid calling
3044 // `Self::new_zeroed`. This ensures that stack space is never
3045 // allocated for `Self` even on lower opt-levels where this branch
3046 // might not get optimized out.
3047
3048 // SAFETY: Per [1], when `T` is a ZST, `Box<T>`'s only validity
3049 // requirements are that the pointer is non-null and sufficiently
3050 // aligned. Per [2], `NonNull::dangling` produces a pointer which
3051 // is sufficiently aligned. Since the produced pointer is a
3052 // `NonNull`, it is non-null.
3053 //
3054 // [1] Per https://doc.rust-lang.org/nightly/std/boxed/index.html#memory-layout:
3055 //
3056 // For zero-sized values, the `Box` pointer has to be non-null and sufficiently aligned.
3057 //
3058 // [2] Per https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.dangling:
3059 //
3060 // Creates a new `NonNull` that is dangling, but well-aligned.
3061 return Ok(unsafe { Box::from_raw(NonNull::dangling().as_ptr()) });
3062 }
3063
3064 // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
3065 #[allow(clippy::undocumented_unsafe_blocks)]
3066 let ptr = unsafe { alloc::alloc::alloc_zeroed(layout).cast::<Self>() };
3067 if ptr.is_null() {
3068 return Err(AllocError);
3069 }
3070 // TODO(#429): Add a "SAFETY" comment and remove this `allow`.
3071 #[allow(clippy::undocumented_unsafe_blocks)]
3072 Ok(unsafe { Box::from_raw(ptr) })
3073 }
3074
3075 /// Creates a `Box<[Self]>` (a boxed slice) from zeroed bytes.
3076 ///
3077 /// This function is useful for allocating large values of `[Self]` on the
3078 /// heap and zero-initializing them, without ever creating a temporary
3079 /// instance of `[Self; _]` on the stack. For example,
3080 /// `u8::new_box_slice_zeroed(1048576)` will allocate the slice directly on
3081 /// the heap; it does not require storing the slice on the stack.
3082 ///
3083 /// On systems that use a heap implementation that supports allocating from
3084 /// pre-zeroed memory, using `new_box_slice_zeroed` may have performance
3085 /// benefits.
3086 ///
3087 /// If `Self` is a zero-sized type, then this function will return a
3088 /// `Box<[Self]>` that has the correct `len`. Such a box cannot contain any
3089 /// actual information, but its `len()` property will report the correct
3090 /// value.
3091 ///
3092 /// # Errors
3093 ///
3094 /// Returns an error on allocation failure. Allocation failure is
3095 /// guaranteed never to cause a panic or an abort.
3096 #[must_use = "has no side effects (other than allocation)"]
3097 #[cfg(feature = "alloc")]
3098 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
3099 #[inline]
3100 fn new_box_zeroed_with_elems(count: usize) -> Result<Box<Self>, AllocError>
3101 where
3102 Self: KnownLayout<PointerMetadata = usize>,
3103 {
3104 // SAFETY: `alloc::alloc::alloc_zeroed` is a valid argument of
3105 // `new_box`. The referent of the pointer returned by `alloc_zeroed`
3106 // (and, consequently, the `Box` derived from it) is a valid instance of
3107 // `Self`, because `Self` is `FromZeros`.
3108 unsafe { crate::util::new_box(count, alloc::alloc::alloc_zeroed) }
3109 }
3110
3111 #[deprecated(since = "0.8.0", note = "renamed to `FromZeros::new_box_zeroed_with_elems`")]
3112 #[doc(hidden)]
3113 #[cfg(feature = "alloc")]
3114 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
3115 #[must_use = "has no side effects (other than allocation)"]
3116 #[inline(always)]
3117 fn new_box_slice_zeroed(len: usize) -> Result<Box<[Self]>, AllocError>
3118 where
3119 Self: Sized,
3120 {
3121 <[Self]>::new_box_zeroed_with_elems(len)
3122 }
3123
3124 /// Creates a `Vec<Self>` from zeroed bytes.
3125 ///
3126 /// This function is useful for allocating large values of `Vec`s and
3127 /// zero-initializing them, without ever creating a temporary instance of
3128 /// `[Self; _]` (or many temporary instances of `Self`) on the stack. For
3129 /// example, `u8::new_vec_zeroed(1048576)` will allocate directly on the
3130 /// heap; it does not require storing intermediate values on the stack.
3131 ///
3132 /// On systems that use a heap implementation that supports allocating from
3133 /// pre-zeroed memory, using `new_vec_zeroed` may have performance benefits.
3134 ///
3135 /// If `Self` is a zero-sized type, then this function will return a
3136 /// `Vec<Self>` that has the correct `len`. Such a `Vec` cannot contain any
3137 /// actual information, but its `len()` property will report the correct
3138 /// value.
3139 ///
3140 /// # Errors
3141 ///
3142 /// Returns an error on allocation failure. Allocation failure is
3143 /// guaranteed never to cause a panic or an abort.
3144 #[must_use = "has no side effects (other than allocation)"]
3145 #[cfg(feature = "alloc")]
3146 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
3147 #[inline(always)]
3148 fn new_vec_zeroed(len: usize) -> Result<Vec<Self>, AllocError>
3149 where
3150 Self: Sized,
3151 {
3152 <[Self]>::new_box_zeroed_with_elems(len).map(Into::into)
3153 }
3154
3155 /// Extends a `Vec<Self>` by pushing `additional` new items onto the end of
3156 /// the vector. The new items are initialized with zeros.
3157 #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
3158 #[cfg(feature = "alloc")]
3159 #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.57.0", feature = "alloc"))))]
3160 #[inline(always)]
3161 fn extend_vec_zeroed(v: &mut Vec<Self>, additional: usize) -> Result<(), AllocError>
3162 where
3163 Self: Sized,
3164 {
3165 // PANICS: We pass `v.len()` for `position`, so the `position > v.len()`
3166 // panic condition is not satisfied.
3167 <Self as FromZeros>::insert_vec_zeroed(v, v.len(), additional)
3168 }
3169
3170 /// Inserts `additional` new items into `Vec<Self>` at `position`. The new
3171 /// items are initialized with zeros.
3172 ///
3173 /// # Panics
3174 ///
3175 /// Panics if `position > v.len()`.
3176 #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
3177 #[cfg(feature = "alloc")]
3178 #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.57.0", feature = "alloc"))))]
3179 #[inline]
3180 fn insert_vec_zeroed(
3181 v: &mut Vec<Self>,
3182 position: usize,
3183 additional: usize,
3184 ) -> Result<(), AllocError>
3185 where
3186 Self: Sized,
3187 {
3188 assert!(position <= v.len());
3189 // We only conditionally compile on versions on which `try_reserve` is
3190 // stable; the Clippy lint is a false positive.
3191 #[allow(clippy::incompatible_msrv)]
3192 v.try_reserve(additional).map_err(|_| AllocError)?;
3193 // SAFETY: The `try_reserve` call guarantees that these cannot overflow:
3194 // * `ptr.add(position)`
3195 // * `position + additional`
3196 // * `v.len() + additional`
3197 //
3198 // `v.len() - position` cannot overflow because we asserted that
3199 // `position <= v.len()`.
3200 unsafe {
3201 // This is a potentially overlapping copy.
3202 let ptr = v.as_mut_ptr();
3203 #[allow(clippy::arithmetic_side_effects)]
3204 ptr.add(position).copy_to(ptr.add(position + additional), v.len() - position);
3205 ptr.add(position).write_bytes(0, additional);
3206 #[allow(clippy::arithmetic_side_effects)]
3207 v.set_len(v.len() + additional);
3208 }
3209
3210 Ok(())
3211 }
3212}
3213
3214/// Analyzes whether a type is [`FromBytes`].
3215///
3216/// This derive analyzes, at compile time, whether the annotated type satisfies
3217/// the [safety conditions] of `FromBytes` and implements `FromBytes` and its
3218/// supertraits if it is sound to do so. This derive can be applied to structs,
3219/// enums, and unions;
3220/// e.g.:
3221///
3222/// ```
3223/// # use zerocopy_derive::{FromBytes, FromZeros, Immutable};
3224/// #[derive(FromBytes)]
3225/// struct MyStruct {
3226/// # /*
3227/// ...
3228/// # */
3229/// }
3230///
3231/// #[derive(FromBytes)]
3232/// #[repr(u8)]
3233/// enum MyEnum {
3234/// # V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, V0A, V0B, V0C, V0D, V0E,
3235/// # V0F, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V1A, V1B, V1C, V1D,
3236/// # V1E, V1F, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V2A, V2B, V2C,
3237/// # V2D, V2E, V2F, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V3A, V3B,
3238/// # V3C, V3D, V3E, V3F, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V4A,
3239/// # V4B, V4C, V4D, V4E, V4F, V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
3240/// # V5A, V5B, V5C, V5D, V5E, V5F, V60, V61, V62, V63, V64, V65, V66, V67, V68,
3241/// # V69, V6A, V6B, V6C, V6D, V6E, V6F, V70, V71, V72, V73, V74, V75, V76, V77,
3242/// # V78, V79, V7A, V7B, V7C, V7D, V7E, V7F, V80, V81, V82, V83, V84, V85, V86,
3243/// # V87, V88, V89, V8A, V8B, V8C, V8D, V8E, V8F, V90, V91, V92, V93, V94, V95,
3244/// # V96, V97, V98, V99, V9A, V9B, V9C, V9D, V9E, V9F, VA0, VA1, VA2, VA3, VA4,
3245/// # VA5, VA6, VA7, VA8, VA9, VAA, VAB, VAC, VAD, VAE, VAF, VB0, VB1, VB2, VB3,
3246/// # VB4, VB5, VB6, VB7, VB8, VB9, VBA, VBB, VBC, VBD, VBE, VBF, VC0, VC1, VC2,
3247/// # VC3, VC4, VC5, VC6, VC7, VC8, VC9, VCA, VCB, VCC, VCD, VCE, VCF, VD0, VD1,
3248/// # VD2, VD3, VD4, VD5, VD6, VD7, VD8, VD9, VDA, VDB, VDC, VDD, VDE, VDF, VE0,
3249/// # VE1, VE2, VE3, VE4, VE5, VE6, VE7, VE8, VE9, VEA, VEB, VEC, VED, VEE, VEF,
3250/// # VF0, VF1, VF2, VF3, VF4, VF5, VF6, VF7, VF8, VF9, VFA, VFB, VFC, VFD, VFE,
3251/// # VFF,
3252/// # /*
3253/// ...
3254/// # */
3255/// }
3256///
3257/// #[derive(FromBytes, Immutable)]
3258/// union MyUnion {
3259/// # variant: u8,
3260/// # /*
3261/// ...
3262/// # */
3263/// }
3264/// ```
3265///
3266/// [safety conditions]: trait@FromBytes#safety
3267///
3268/// # Analysis
3269///
3270/// *This section describes, roughly, the analysis performed by this derive to
3271/// determine whether it is sound to implement `FromBytes` for a given type.
3272/// Unless you are modifying the implementation of this derive, or attempting to
3273/// manually implement `FromBytes` for a type yourself, you don't need to read
3274/// this section.*
3275///
3276/// If a type has the following properties, then this derive can implement
3277/// `FromBytes` for that type:
3278///
3279/// - If the type is a struct, all of its fields must be `FromBytes`.
3280/// - If the type is an enum:
3281/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`,
3282/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`).
3283/// - The maximum number of discriminants must be used (so that every possible
3284/// bit pattern is a valid one). Be very careful when using the `C`,
3285/// `usize`, or `isize` representations, as their size is
3286/// platform-dependent.
3287/// - Its fields must be `FromBytes`.
3288///
3289/// This analysis is subject to change. Unsafe code may *only* rely on the
3290/// documented [safety conditions] of `FromBytes`, and must *not* rely on the
3291/// implementation details of this derive.
3292///
3293/// ## Why isn't an explicit representation required for structs?
3294///
3295/// Neither this derive, nor the [safety conditions] of `FromBytes`, requires
3296/// that structs are marked with `#[repr(C)]`.
3297///
3298/// Per the [Rust reference](reference),
3299///
3300/// > The representation of a type can change the padding between fields, but
3301/// > does not change the layout of the fields themselves.
3302///
3303/// [reference]: https://doc.rust-lang.org/reference/type-layout.html#representations
3304///
3305/// Since the layout of structs only consists of padding bytes and field bytes,
3306/// a struct is soundly `FromBytes` if:
3307/// 1. its padding is soundly `FromBytes`, and
3308/// 2. its fields are soundly `FromBytes`.
3309///
3310/// The answer to the first question is always yes: padding bytes do not have
3311/// any validity constraints. A [discussion] of this question in the Unsafe Code
3312/// Guidelines Working Group concluded that it would be virtually unimaginable
3313/// for future versions of rustc to add validity constraints to padding bytes.
3314///
3315/// [discussion]: https://github.com/rust-lang/unsafe-code-guidelines/issues/174
3316///
3317/// Whether a struct is soundly `FromBytes` therefore solely depends on whether
3318/// its fields are `FromBytes`.
3319// TODO(#146): Document why we don't require an enum to have an explicit `repr`
3320// attribute.
3321#[cfg(any(feature = "derive", test))]
3322#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
3323pub use zerocopy_derive::FromBytes;
3324
3325/// Types for which any bit pattern is valid.
3326///
3327/// Any memory region of the appropriate length which contains initialized bytes
3328/// can be viewed as any `FromBytes` type with no runtime overhead. This is
3329/// useful for efficiently parsing bytes as structured data.
3330///
3331/// # Warning: Padding bytes
3332///
3333/// Note that, when a value is moved or copied, only the non-padding bytes of
3334/// that value are guaranteed to be preserved. It is unsound to assume that
3335/// values written to padding bytes are preserved after a move or copy. For
3336/// example, the following is unsound:
3337///
3338/// ```rust,no_run
3339/// use core::mem::{size_of, transmute};
3340/// use zerocopy::FromZeros;
3341/// # use zerocopy_derive::*;
3342///
3343/// // Assume `Foo` is a type with padding bytes.
3344/// #[derive(FromZeros, Default)]
3345/// struct Foo {
3346/// # /*
3347/// ...
3348/// # */
3349/// }
3350///
3351/// let mut foo: Foo = Foo::default();
3352/// FromZeros::zero(&mut foo);
3353/// // UNSOUND: Although `FromZeros::zero` writes zeros to all bytes of `foo`,
3354/// // those writes are not guaranteed to be preserved in padding bytes when
3355/// // `foo` is moved, so this may expose padding bytes as `u8`s.
3356/// let foo_bytes: [u8; size_of::<Foo>()] = unsafe { transmute(foo) };
3357/// ```
3358///
3359/// # Implementation
3360///
3361/// **Do not implement this trait yourself!** Instead, use
3362/// [`#[derive(FromBytes)]`][derive]; e.g.:
3363///
3364/// ```
3365/// # use zerocopy_derive::{FromBytes, Immutable};
3366/// #[derive(FromBytes)]
3367/// struct MyStruct {
3368/// # /*
3369/// ...
3370/// # */
3371/// }
3372///
3373/// #[derive(FromBytes)]
3374/// #[repr(u8)]
3375/// enum MyEnum {
3376/// # V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, V0A, V0B, V0C, V0D, V0E,
3377/// # V0F, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V1A, V1B, V1C, V1D,
3378/// # V1E, V1F, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V2A, V2B, V2C,
3379/// # V2D, V2E, V2F, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V3A, V3B,
3380/// # V3C, V3D, V3E, V3F, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V4A,
3381/// # V4B, V4C, V4D, V4E, V4F, V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
3382/// # V5A, V5B, V5C, V5D, V5E, V5F, V60, V61, V62, V63, V64, V65, V66, V67, V68,
3383/// # V69, V6A, V6B, V6C, V6D, V6E, V6F, V70, V71, V72, V73, V74, V75, V76, V77,
3384/// # V78, V79, V7A, V7B, V7C, V7D, V7E, V7F, V80, V81, V82, V83, V84, V85, V86,
3385/// # V87, V88, V89, V8A, V8B, V8C, V8D, V8E, V8F, V90, V91, V92, V93, V94, V95,
3386/// # V96, V97, V98, V99, V9A, V9B, V9C, V9D, V9E, V9F, VA0, VA1, VA2, VA3, VA4,
3387/// # VA5, VA6, VA7, VA8, VA9, VAA, VAB, VAC, VAD, VAE, VAF, VB0, VB1, VB2, VB3,
3388/// # VB4, VB5, VB6, VB7, VB8, VB9, VBA, VBB, VBC, VBD, VBE, VBF, VC0, VC1, VC2,
3389/// # VC3, VC4, VC5, VC6, VC7, VC8, VC9, VCA, VCB, VCC, VCD, VCE, VCF, VD0, VD1,
3390/// # VD2, VD3, VD4, VD5, VD6, VD7, VD8, VD9, VDA, VDB, VDC, VDD, VDE, VDF, VE0,
3391/// # VE1, VE2, VE3, VE4, VE5, VE6, VE7, VE8, VE9, VEA, VEB, VEC, VED, VEE, VEF,
3392/// # VF0, VF1, VF2, VF3, VF4, VF5, VF6, VF7, VF8, VF9, VFA, VFB, VFC, VFD, VFE,
3393/// # VFF,
3394/// # /*
3395/// ...
3396/// # */
3397/// }
3398///
3399/// #[derive(FromBytes, Immutable)]
3400/// union MyUnion {
3401/// # variant: u8,
3402/// # /*
3403/// ...
3404/// # */
3405/// }
3406/// ```
3407///
3408/// This derive performs a sophisticated, compile-time safety analysis to
3409/// determine whether a type is `FromBytes`.
3410///
3411/// # Safety
3412///
3413/// *This section describes what is required in order for `T: FromBytes`, and
3414/// what unsafe code may assume of such types. If you don't plan on implementing
3415/// `FromBytes` manually, and you don't plan on writing unsafe code that
3416/// operates on `FromBytes` types, then you don't need to read this section.*
3417///
3418/// If `T: FromBytes`, then unsafe code may assume that it is sound to produce a
3419/// `T` whose bytes are initialized to any sequence of valid `u8`s (in other
3420/// words, any byte value which is not uninitialized). If a type is marked as
3421/// `FromBytes` which violates this contract, it may cause undefined behavior.
3422///
3423/// `#[derive(FromBytes)]` only permits [types which satisfy these
3424/// requirements][derive-analysis].
3425///
3426#[cfg_attr(
3427 feature = "derive",
3428 doc = "[derive]: zerocopy_derive::FromBytes",
3429 doc = "[derive-analysis]: zerocopy_derive::FromBytes#analysis"
3430)]
3431#[cfg_attr(
3432 not(feature = "derive"),
3433 doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromBytes.html"),
3434 doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromBytes.html#analysis"),
3435)]
3436#[cfg_attr(
3437 zerocopy_diagnostic_on_unimplemented_1_78_0,
3438 diagnostic::on_unimplemented(note = "Consider adding `#[derive(FromBytes)]` to `{Self}`")
3439)]
3440pub unsafe trait FromBytes: FromZeros {
3441 // The `Self: Sized` bound makes it so that `FromBytes` is still object
3442 // safe.
3443 #[doc(hidden)]
3444 fn only_derive_is_allowed_to_implement_this_trait()
3445 where
3446 Self: Sized;
3447
3448 /// Interprets the given `source` as a `&Self`.
3449 ///
3450 /// This method attempts to return a reference to `source` interpreted as a
3451 /// `Self`. If the length of `source` is not a [valid size of
3452 /// `Self`][valid-size], or if `source` is not appropriately aligned, this
3453 /// returns `Err`. If [`Self: Unaligned`][self-unaligned], you can
3454 /// [infallibly discard the alignment error][size-error-from].
3455 ///
3456 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
3457 ///
3458 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
3459 /// [self-unaligned]: Unaligned
3460 /// [size-error-from]: error/struct.SizeError.html#method.from-1
3461 /// [slice-dst]: KnownLayout#dynamically-sized-types
3462 ///
3463 /// # Compile-Time Assertions
3464 ///
3465 /// This method cannot yet be used on unsized types whose dynamically-sized
3466 /// component is zero-sized. Attempting to use this method on such types
3467 /// results in a compile-time assertion error; e.g.:
3468 ///
3469 /// ```compile_fail,E0080
3470 /// use zerocopy::*;
3471 /// # use zerocopy_derive::*;
3472 ///
3473 /// #[derive(FromBytes, Immutable, KnownLayout)]
3474 /// #[repr(C)]
3475 /// struct ZSTy {
3476 /// leading_sized: u16,
3477 /// trailing_dst: [()],
3478 /// }
3479 ///
3480 /// let _ = ZSTy::ref_from_bytes(0u16.as_bytes()); // âš Compile Error!
3481 /// ```
3482 ///
3483 /// # Examples
3484 ///
3485 /// ```
3486 /// use zerocopy::FromBytes;
3487 /// # use zerocopy_derive::*;
3488 ///
3489 /// #[derive(FromBytes, KnownLayout, Immutable)]
3490 /// #[repr(C)]
3491 /// struct PacketHeader {
3492 /// src_port: [u8; 2],
3493 /// dst_port: [u8; 2],
3494 /// length: [u8; 2],
3495 /// checksum: [u8; 2],
3496 /// }
3497 ///
3498 /// #[derive(FromBytes, KnownLayout, Immutable)]
3499 /// #[repr(C)]
3500 /// struct Packet {
3501 /// header: PacketHeader,
3502 /// body: [u8],
3503 /// }
3504 ///
3505 /// // These bytes encode a `Packet`.
3506 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11][..];
3507 ///
3508 /// let packet = Packet::ref_from_bytes(bytes).unwrap();
3509 ///
3510 /// assert_eq!(packet.header.src_port, [0, 1]);
3511 /// assert_eq!(packet.header.dst_port, [2, 3]);
3512 /// assert_eq!(packet.header.length, [4, 5]);
3513 /// assert_eq!(packet.header.checksum, [6, 7]);
3514 /// assert_eq!(packet.body, [8, 9, 10, 11]);
3515 /// ```
3516 #[must_use = "has no side effects"]
3517 #[inline]
3518 fn ref_from_bytes(source: &[u8]) -> Result<&Self, CastError<&[u8], Self>>
3519 where
3520 Self: KnownLayout + Immutable,
3521 {
3522 static_assert_dst_is_not_zst!(Self);
3523 match Ptr::from_ref(source).try_cast_into_no_leftover::<_, BecauseImmutable>(None) {
3524 Ok(ptr) => Ok(ptr.bikeshed_recall_valid().as_ref()),
3525 Err(err) => Err(err.map_src(|src| src.as_ref())),
3526 }
3527 }
3528
3529 /// Interprets the prefix of the given `source` as a `&Self` without
3530 /// copying.
3531 ///
3532 /// This method computes the [largest possible size of `Self`][valid-size]
3533 /// that can fit in the leading bytes of `source`, then attempts to return
3534 /// both a reference to those bytes interpreted as a `Self`, and a reference
3535 /// to the remaining bytes. If there are insufficient bytes, or if `source`
3536 /// is not appropriately aligned, this returns `Err`. If [`Self:
3537 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
3538 /// error][size-error-from].
3539 ///
3540 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
3541 ///
3542 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
3543 /// [self-unaligned]: Unaligned
3544 /// [size-error-from]: error/struct.SizeError.html#method.from-1
3545 /// [slice-dst]: KnownLayout#dynamically-sized-types
3546 ///
3547 /// # Compile-Time Assertions
3548 ///
3549 /// This method cannot yet be used on unsized types whose dynamically-sized
3550 /// component is zero-sized. See [`ref_from_prefix_with_elems`], which does
3551 /// support such types. Attempting to use this method on such types results
3552 /// in a compile-time assertion error; e.g.:
3553 ///
3554 /// ```compile_fail,E0080
3555 /// use zerocopy::*;
3556 /// # use zerocopy_derive::*;
3557 ///
3558 /// #[derive(FromBytes, Immutable, KnownLayout)]
3559 /// #[repr(C)]
3560 /// struct ZSTy {
3561 /// leading_sized: u16,
3562 /// trailing_dst: [()],
3563 /// }
3564 ///
3565 /// let _ = ZSTy::ref_from_prefix(0u16.as_bytes()); // âš Compile Error!
3566 /// ```
3567 ///
3568 /// [`ref_from_prefix_with_elems`]: FromBytes::ref_from_prefix_with_elems
3569 ///
3570 /// # Examples
3571 ///
3572 /// ```
3573 /// use zerocopy::FromBytes;
3574 /// # use zerocopy_derive::*;
3575 ///
3576 /// #[derive(FromBytes, KnownLayout, Immutable)]
3577 /// #[repr(C)]
3578 /// struct PacketHeader {
3579 /// src_port: [u8; 2],
3580 /// dst_port: [u8; 2],
3581 /// length: [u8; 2],
3582 /// checksum: [u8; 2],
3583 /// }
3584 ///
3585 /// #[derive(FromBytes, KnownLayout, Immutable)]
3586 /// #[repr(C)]
3587 /// struct Packet {
3588 /// header: PacketHeader,
3589 /// body: [[u8; 2]],
3590 /// }
3591 ///
3592 /// // These are more bytes than are needed to encode a `Packet`.
3593 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14][..];
3594 ///
3595 /// let (packet, suffix) = Packet::ref_from_prefix(bytes).unwrap();
3596 ///
3597 /// assert_eq!(packet.header.src_port, [0, 1]);
3598 /// assert_eq!(packet.header.dst_port, [2, 3]);
3599 /// assert_eq!(packet.header.length, [4, 5]);
3600 /// assert_eq!(packet.header.checksum, [6, 7]);
3601 /// assert_eq!(packet.body, [[8, 9], [10, 11], [12, 13]]);
3602 /// assert_eq!(suffix, &[14u8][..]);
3603 /// ```
3604 #[must_use = "has no side effects"]
3605 #[inline]
3606 fn ref_from_prefix(source: &[u8]) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>
3607 where
3608 Self: KnownLayout + Immutable,
3609 {
3610 static_assert_dst_is_not_zst!(Self);
3611 ref_from_prefix_suffix(source, None, CastType::Prefix)
3612 }
3613
3614 /// Interprets the suffix of the given bytes as a `&Self`.
3615 ///
3616 /// This method computes the [largest possible size of `Self`][valid-size]
3617 /// that can fit in the trailing bytes of `source`, then attempts to return
3618 /// both a reference to those bytes interpreted as a `Self`, and a reference
3619 /// to the preceding bytes. If there are insufficient bytes, or if that
3620 /// suffix of `source` is not appropriately aligned, this returns `Err`. If
3621 /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
3622 /// alignment error][size-error-from].
3623 ///
3624 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
3625 ///
3626 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
3627 /// [self-unaligned]: Unaligned
3628 /// [size-error-from]: error/struct.SizeError.html#method.from-1
3629 /// [slice-dst]: KnownLayout#dynamically-sized-types
3630 ///
3631 /// # Compile-Time Assertions
3632 ///
3633 /// This method cannot yet be used on unsized types whose dynamically-sized
3634 /// component is zero-sized. See [`ref_from_suffix_with_elems`], which does
3635 /// support such types. Attempting to use this method on such types results
3636 /// in a compile-time assertion error; e.g.:
3637 ///
3638 /// ```compile_fail,E0080
3639 /// use zerocopy::*;
3640 /// # use zerocopy_derive::*;
3641 ///
3642 /// #[derive(FromBytes, Immutable, KnownLayout)]
3643 /// #[repr(C)]
3644 /// struct ZSTy {
3645 /// leading_sized: u16,
3646 /// trailing_dst: [()],
3647 /// }
3648 ///
3649 /// let _ = ZSTy::ref_from_suffix(0u16.as_bytes()); // âš Compile Error!
3650 /// ```
3651 ///
3652 /// [`ref_from_suffix_with_elems`]: FromBytes::ref_from_suffix_with_elems
3653 ///
3654 /// # Examples
3655 ///
3656 /// ```
3657 /// use zerocopy::FromBytes;
3658 /// # use zerocopy_derive::*;
3659 ///
3660 /// #[derive(FromBytes, Immutable, KnownLayout)]
3661 /// #[repr(C)]
3662 /// struct PacketTrailer {
3663 /// frame_check_sequence: [u8; 4],
3664 /// }
3665 ///
3666 /// // These are more bytes than are needed to encode a `PacketTrailer`.
3667 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
3668 ///
3669 /// let (prefix, trailer) = PacketTrailer::ref_from_suffix(bytes).unwrap();
3670 ///
3671 /// assert_eq!(prefix, &[0, 1, 2, 3, 4, 5][..]);
3672 /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
3673 /// ```
3674 #[must_use = "has no side effects"]
3675 #[inline]
3676 fn ref_from_suffix(source: &[u8]) -> Result<(&[u8], &Self), CastError<&[u8], Self>>
3677 where
3678 Self: Immutable + KnownLayout,
3679 {
3680 static_assert_dst_is_not_zst!(Self);
3681 ref_from_prefix_suffix(source, None, CastType::Suffix).map(swap)
3682 }
3683
3684 /// Interprets the given `source` as a `&mut Self`.
3685 ///
3686 /// This method attempts to return a reference to `source` interpreted as a
3687 /// `Self`. If the length of `source` is not a [valid size of
3688 /// `Self`][valid-size], or if `source` is not appropriately aligned, this
3689 /// returns `Err`. If [`Self: Unaligned`][self-unaligned], you can
3690 /// [infallibly discard the alignment error][size-error-from].
3691 ///
3692 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
3693 ///
3694 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
3695 /// [self-unaligned]: Unaligned
3696 /// [size-error-from]: error/struct.SizeError.html#method.from-1
3697 /// [slice-dst]: KnownLayout#dynamically-sized-types
3698 ///
3699 /// # Compile-Time Assertions
3700 ///
3701 /// This method cannot yet be used on unsized types whose dynamically-sized
3702 /// component is zero-sized. See [`mut_from_prefix_with_elems`], which does
3703 /// support such types. Attempting to use this method on such types results
3704 /// in a compile-time assertion error; e.g.:
3705 ///
3706 /// ```compile_fail,E0080
3707 /// use zerocopy::*;
3708 /// # use zerocopy_derive::*;
3709 ///
3710 /// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
3711 /// #[repr(C, packed)]
3712 /// struct ZSTy {
3713 /// leading_sized: [u8; 2],
3714 /// trailing_dst: [()],
3715 /// }
3716 ///
3717 /// let mut source = [85, 85];
3718 /// let _ = ZSTy::mut_from_bytes(&mut source[..]); // âš Compile Error!
3719 /// ```
3720 ///
3721 /// [`mut_from_prefix_with_elems`]: FromBytes::mut_from_prefix_with_elems
3722 ///
3723 /// # Examples
3724 ///
3725 /// ```
3726 /// use zerocopy::FromBytes;
3727 /// # use zerocopy_derive::*;
3728 ///
3729 /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
3730 /// #[repr(C)]
3731 /// struct PacketHeader {
3732 /// src_port: [u8; 2],
3733 /// dst_port: [u8; 2],
3734 /// length: [u8; 2],
3735 /// checksum: [u8; 2],
3736 /// }
3737 ///
3738 /// // These bytes encode a `PacketHeader`.
3739 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..];
3740 ///
3741 /// let header = PacketHeader::mut_from_bytes(bytes).unwrap();
3742 ///
3743 /// assert_eq!(header.src_port, [0, 1]);
3744 /// assert_eq!(header.dst_port, [2, 3]);
3745 /// assert_eq!(header.length, [4, 5]);
3746 /// assert_eq!(header.checksum, [6, 7]);
3747 ///
3748 /// header.checksum = [0, 0];
3749 ///
3750 /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0]);
3751 /// ```
3752 #[must_use = "has no side effects"]
3753 #[inline]
3754 fn mut_from_bytes(source: &mut [u8]) -> Result<&mut Self, CastError<&mut [u8], Self>>
3755 where
3756 Self: IntoBytes + KnownLayout,
3757 {
3758 static_assert_dst_is_not_zst!(Self);
3759 match Ptr::from_mut(source).try_cast_into_no_leftover::<_, BecauseExclusive>(None) {
3760 Ok(ptr) => Ok(ptr.bikeshed_recall_valid().as_mut()),
3761 Err(err) => Err(err.map_src(|src| src.as_mut())),
3762 }
3763 }
3764
3765 /// Interprets the prefix of the given `source` as a `&mut Self` without
3766 /// copying.
3767 ///
3768 /// This method computes the [largest possible size of `Self`][valid-size]
3769 /// that can fit in the leading bytes of `source`, then attempts to return
3770 /// both a reference to those bytes interpreted as a `Self`, and a reference
3771 /// to the remaining bytes. If there are insufficient bytes, or if `source`
3772 /// is not appropriately aligned, this returns `Err`. If [`Self:
3773 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
3774 /// error][size-error-from].
3775 ///
3776 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
3777 ///
3778 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
3779 /// [self-unaligned]: Unaligned
3780 /// [size-error-from]: error/struct.SizeError.html#method.from-1
3781 /// [slice-dst]: KnownLayout#dynamically-sized-types
3782 ///
3783 /// # Compile-Time Assertions
3784 ///
3785 /// This method cannot yet be used on unsized types whose dynamically-sized
3786 /// component is zero-sized. See [`mut_from_suffix_with_elems`], which does
3787 /// support such types. Attempting to use this method on such types results
3788 /// in a compile-time assertion error; e.g.:
3789 ///
3790 /// ```compile_fail,E0080
3791 /// use zerocopy::*;
3792 /// # use zerocopy_derive::*;
3793 ///
3794 /// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
3795 /// #[repr(C, packed)]
3796 /// struct ZSTy {
3797 /// leading_sized: [u8; 2],
3798 /// trailing_dst: [()],
3799 /// }
3800 ///
3801 /// let mut source = [85, 85];
3802 /// let _ = ZSTy::mut_from_prefix(&mut source[..]); // âš Compile Error!
3803 /// ```
3804 ///
3805 /// [`mut_from_suffix_with_elems`]: FromBytes::mut_from_suffix_with_elems
3806 ///
3807 /// # Examples
3808 ///
3809 /// ```
3810 /// use zerocopy::FromBytes;
3811 /// # use zerocopy_derive::*;
3812 ///
3813 /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
3814 /// #[repr(C)]
3815 /// struct PacketHeader {
3816 /// src_port: [u8; 2],
3817 /// dst_port: [u8; 2],
3818 /// length: [u8; 2],
3819 /// checksum: [u8; 2],
3820 /// }
3821 ///
3822 /// // These are more bytes than are needed to encode a `PacketHeader`.
3823 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
3824 ///
3825 /// let (header, body) = PacketHeader::mut_from_prefix(bytes).unwrap();
3826 ///
3827 /// assert_eq!(header.src_port, [0, 1]);
3828 /// assert_eq!(header.dst_port, [2, 3]);
3829 /// assert_eq!(header.length, [4, 5]);
3830 /// assert_eq!(header.checksum, [6, 7]);
3831 /// assert_eq!(body, &[8, 9][..]);
3832 ///
3833 /// header.checksum = [0, 0];
3834 /// body.fill(1);
3835 ///
3836 /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 1, 1]);
3837 /// ```
3838 #[must_use = "has no side effects"]
3839 #[inline]
3840 fn mut_from_prefix(
3841 source: &mut [u8],
3842 ) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>
3843 where
3844 Self: IntoBytes + KnownLayout,
3845 {
3846 static_assert_dst_is_not_zst!(Self);
3847 mut_from_prefix_suffix(source, None, CastType::Prefix)
3848 }
3849
3850 /// Interprets the suffix of the given `source` as a `&mut Self` without
3851 /// copying.
3852 ///
3853 /// This method computes the [largest possible size of `Self`][valid-size]
3854 /// that can fit in the trailing bytes of `source`, then attempts to return
3855 /// both a reference to those bytes interpreted as a `Self`, and a reference
3856 /// to the preceding bytes. If there are insufficient bytes, or if that
3857 /// suffix of `source` is not appropriately aligned, this returns `Err`. If
3858 /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
3859 /// alignment error][size-error-from].
3860 ///
3861 /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
3862 ///
3863 /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
3864 /// [self-unaligned]: Unaligned
3865 /// [size-error-from]: error/struct.SizeError.html#method.from-1
3866 /// [slice-dst]: KnownLayout#dynamically-sized-types
3867 ///
3868 /// # Compile-Time Assertions
3869 ///
3870 /// This method cannot yet be used on unsized types whose dynamically-sized
3871 /// component is zero-sized. Attempting to use this method on such types
3872 /// results in a compile-time assertion error; e.g.:
3873 ///
3874 /// ```compile_fail,E0080
3875 /// use zerocopy::*;
3876 /// # use zerocopy_derive::*;
3877 ///
3878 /// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
3879 /// #[repr(C, packed)]
3880 /// struct ZSTy {
3881 /// leading_sized: [u8; 2],
3882 /// trailing_dst: [()],
3883 /// }
3884 ///
3885 /// let mut source = [85, 85];
3886 /// let _ = ZSTy::mut_from_suffix(&mut source[..]); // âš Compile Error!
3887 /// ```
3888 ///
3889 /// # Examples
3890 ///
3891 /// ```
3892 /// use zerocopy::FromBytes;
3893 /// # use zerocopy_derive::*;
3894 ///
3895 /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
3896 /// #[repr(C)]
3897 /// struct PacketTrailer {
3898 /// frame_check_sequence: [u8; 4],
3899 /// }
3900 ///
3901 /// // These are more bytes than are needed to encode a `PacketTrailer`.
3902 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
3903 ///
3904 /// let (prefix, trailer) = PacketTrailer::mut_from_suffix(bytes).unwrap();
3905 ///
3906 /// assert_eq!(prefix, &[0u8, 1, 2, 3, 4, 5][..]);
3907 /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
3908 ///
3909 /// prefix.fill(0);
3910 /// trailer.frame_check_sequence.fill(1);
3911 ///
3912 /// assert_eq!(bytes, [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]);
3913 /// ```
3914 #[must_use = "has no side effects"]
3915 #[inline]
3916 fn mut_from_suffix(
3917 source: &mut [u8],
3918 ) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>
3919 where
3920 Self: IntoBytes + KnownLayout,
3921 {
3922 static_assert_dst_is_not_zst!(Self);
3923 mut_from_prefix_suffix(source, None, CastType::Suffix).map(swap)
3924 }
3925
3926 /// Interprets the given `source` as a `&Self` with a DST length equal to
3927 /// `count`.
3928 ///
3929 /// This method attempts to return a reference to `source` interpreted as a
3930 /// `Self` with `count` trailing elements. If the length of `source` is not
3931 /// equal to the size of `Self` with `count` elements, or if `source` is not
3932 /// appropriately aligned, this returns `Err`. If [`Self:
3933 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
3934 /// error][size-error-from].
3935 ///
3936 /// [self-unaligned]: Unaligned
3937 /// [size-error-from]: error/struct.SizeError.html#method.from-1
3938 ///
3939 /// # Examples
3940 ///
3941 /// ```
3942 /// use zerocopy::FromBytes;
3943 /// # use zerocopy_derive::*;
3944 ///
3945 /// # #[derive(Debug, PartialEq, Eq)]
3946 /// #[derive(FromBytes, Immutable)]
3947 /// #[repr(C)]
3948 /// struct Pixel {
3949 /// r: u8,
3950 /// g: u8,
3951 /// b: u8,
3952 /// a: u8,
3953 /// }
3954 ///
3955 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..];
3956 ///
3957 /// let pixels = <[Pixel]>::ref_from_bytes_with_elems(bytes, 2).unwrap();
3958 ///
3959 /// assert_eq!(pixels, &[
3960 /// Pixel { r: 0, g: 1, b: 2, a: 3 },
3961 /// Pixel { r: 4, g: 5, b: 6, a: 7 },
3962 /// ]);
3963 ///
3964 /// ```
3965 ///
3966 /// Since an explicit `count` is provided, this method supports types with
3967 /// zero-sized trailing slice elements. Methods such as [`ref_from_bytes`]
3968 /// which do not take an explicit count do not support such types.
3969 ///
3970 /// ```
3971 /// use zerocopy::*;
3972 /// # use zerocopy_derive::*;
3973 ///
3974 /// #[derive(FromBytes, Immutable, KnownLayout)]
3975 /// #[repr(C)]
3976 /// struct ZSTy {
3977 /// leading_sized: [u8; 2],
3978 /// trailing_dst: [()],
3979 /// }
3980 ///
3981 /// let src = &[85, 85][..];
3982 /// let zsty = ZSTy::ref_from_bytes_with_elems(src, 42).unwrap();
3983 /// assert_eq!(zsty.trailing_dst.len(), 42);
3984 /// ```
3985 ///
3986 /// [`ref_from_bytes`]: FromBytes::ref_from_bytes
3987 #[must_use = "has no side effects"]
3988 #[inline]
3989 fn ref_from_bytes_with_elems(
3990 source: &[u8],
3991 count: usize,
3992 ) -> Result<&Self, CastError<&[u8], Self>>
3993 where
3994 Self: KnownLayout<PointerMetadata = usize> + Immutable,
3995 {
3996 let source = Ptr::from_ref(source);
3997 let maybe_slf = source.try_cast_into_no_leftover::<_, BecauseImmutable>(Some(count));
3998 match maybe_slf {
3999 Ok(slf) => Ok(slf.bikeshed_recall_valid().as_ref()),
4000 Err(err) => Err(err.map_src(|s| s.as_ref())),
4001 }
4002 }
4003
4004 /// Interprets the prefix of the given `source` as a DST `&Self` with length
4005 /// equal to `count`.
4006 ///
4007 /// This method attempts to return a reference to the prefix of `source`
4008 /// interpreted as a `Self` with `count` trailing elements, and a reference
4009 /// to the remaining bytes. If there are insufficient bytes, or if `source`
4010 /// is not appropriately aligned, this returns `Err`. If [`Self:
4011 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
4012 /// error][size-error-from].
4013 ///
4014 /// [self-unaligned]: Unaligned
4015 /// [size-error-from]: error/struct.SizeError.html#method.from-1
4016 ///
4017 /// # Examples
4018 ///
4019 /// ```
4020 /// use zerocopy::FromBytes;
4021 /// # use zerocopy_derive::*;
4022 ///
4023 /// # #[derive(Debug, PartialEq, Eq)]
4024 /// #[derive(FromBytes, Immutable)]
4025 /// #[repr(C)]
4026 /// struct Pixel {
4027 /// r: u8,
4028 /// g: u8,
4029 /// b: u8,
4030 /// a: u8,
4031 /// }
4032 ///
4033 /// // These are more bytes than are needed to encode two `Pixel`s.
4034 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4035 ///
4036 /// let (pixels, suffix) = <[Pixel]>::ref_from_prefix_with_elems(bytes, 2).unwrap();
4037 ///
4038 /// assert_eq!(pixels, &[
4039 /// Pixel { r: 0, g: 1, b: 2, a: 3 },
4040 /// Pixel { r: 4, g: 5, b: 6, a: 7 },
4041 /// ]);
4042 ///
4043 /// assert_eq!(suffix, &[8, 9]);
4044 /// ```
4045 ///
4046 /// Since an explicit `count` is provided, this method supports types with
4047 /// zero-sized trailing slice elements. Methods such as [`ref_from_prefix`]
4048 /// which do not take an explicit count do not support such types.
4049 ///
4050 /// ```
4051 /// use zerocopy::*;
4052 /// # use zerocopy_derive::*;
4053 ///
4054 /// #[derive(FromBytes, Immutable, KnownLayout)]
4055 /// #[repr(C)]
4056 /// struct ZSTy {
4057 /// leading_sized: [u8; 2],
4058 /// trailing_dst: [()],
4059 /// }
4060 ///
4061 /// let src = &[85, 85][..];
4062 /// let (zsty, _) = ZSTy::ref_from_prefix_with_elems(src, 42).unwrap();
4063 /// assert_eq!(zsty.trailing_dst.len(), 42);
4064 /// ```
4065 ///
4066 /// [`ref_from_prefix`]: FromBytes::ref_from_prefix
4067 #[must_use = "has no side effects"]
4068 #[inline]
4069 fn ref_from_prefix_with_elems(
4070 source: &[u8],
4071 count: usize,
4072 ) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>
4073 where
4074 Self: KnownLayout<PointerMetadata = usize> + Immutable,
4075 {
4076 ref_from_prefix_suffix(source, Some(count), CastType::Prefix)
4077 }
4078
4079 /// Interprets the suffix of the given `source` as a DST `&Self` with length
4080 /// equal to `count`.
4081 ///
4082 /// This method attempts to return a reference to the suffix of `source`
4083 /// interpreted as a `Self` with `count` trailing elements, and a reference
4084 /// to the preceding bytes. If there are insufficient bytes, or if that
4085 /// suffix of `source` is not appropriately aligned, this returns `Err`. If
4086 /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
4087 /// alignment error][size-error-from].
4088 ///
4089 /// [self-unaligned]: Unaligned
4090 /// [size-error-from]: error/struct.SizeError.html#method.from-1
4091 ///
4092 /// # Examples
4093 ///
4094 /// ```
4095 /// use zerocopy::FromBytes;
4096 /// # use zerocopy_derive::*;
4097 ///
4098 /// # #[derive(Debug, PartialEq, Eq)]
4099 /// #[derive(FromBytes, Immutable)]
4100 /// #[repr(C)]
4101 /// struct Pixel {
4102 /// r: u8,
4103 /// g: u8,
4104 /// b: u8,
4105 /// a: u8,
4106 /// }
4107 ///
4108 /// // These are more bytes than are needed to encode two `Pixel`s.
4109 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4110 ///
4111 /// let (prefix, pixels) = <[Pixel]>::ref_from_suffix_with_elems(bytes, 2).unwrap();
4112 ///
4113 /// assert_eq!(prefix, &[0, 1]);
4114 ///
4115 /// assert_eq!(pixels, &[
4116 /// Pixel { r: 2, g: 3, b: 4, a: 5 },
4117 /// Pixel { r: 6, g: 7, b: 8, a: 9 },
4118 /// ]);
4119 /// ```
4120 ///
4121 /// Since an explicit `count` is provided, this method supports types with
4122 /// zero-sized trailing slice elements. Methods such as [`ref_from_suffix`]
4123 /// which do not take an explicit count do not support such types.
4124 ///
4125 /// ```
4126 /// use zerocopy::*;
4127 /// # use zerocopy_derive::*;
4128 ///
4129 /// #[derive(FromBytes, Immutable, KnownLayout)]
4130 /// #[repr(C)]
4131 /// struct ZSTy {
4132 /// leading_sized: [u8; 2],
4133 /// trailing_dst: [()],
4134 /// }
4135 ///
4136 /// let src = &[85, 85][..];
4137 /// let (_, zsty) = ZSTy::ref_from_suffix_with_elems(src, 42).unwrap();
4138 /// assert_eq!(zsty.trailing_dst.len(), 42);
4139 /// ```
4140 ///
4141 /// [`ref_from_suffix`]: FromBytes::ref_from_suffix
4142 #[must_use = "has no side effects"]
4143 #[inline]
4144 fn ref_from_suffix_with_elems(
4145 source: &[u8],
4146 count: usize,
4147 ) -> Result<(&[u8], &Self), CastError<&[u8], Self>>
4148 where
4149 Self: KnownLayout<PointerMetadata = usize> + Immutable,
4150 {
4151 ref_from_prefix_suffix(source, Some(count), CastType::Suffix).map(swap)
4152 }
4153
4154 /// Interprets the given `source` as a `&mut Self` with a DST length equal
4155 /// to `count`.
4156 ///
4157 /// This method attempts to return a reference to `source` interpreted as a
4158 /// `Self` with `count` trailing elements. If the length of `source` is not
4159 /// equal to the size of `Self` with `count` elements, or if `source` is not
4160 /// appropriately aligned, this returns `Err`. If [`Self:
4161 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
4162 /// error][size-error-from].
4163 ///
4164 /// [self-unaligned]: Unaligned
4165 /// [size-error-from]: error/struct.SizeError.html#method.from-1
4166 ///
4167 /// # Examples
4168 ///
4169 /// ```
4170 /// use zerocopy::FromBytes;
4171 /// # use zerocopy_derive::*;
4172 ///
4173 /// # #[derive(Debug, PartialEq, Eq)]
4174 /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
4175 /// #[repr(C)]
4176 /// struct Pixel {
4177 /// r: u8,
4178 /// g: u8,
4179 /// b: u8,
4180 /// a: u8,
4181 /// }
4182 ///
4183 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..];
4184 ///
4185 /// let pixels = <[Pixel]>::mut_from_bytes_with_elems(bytes, 2).unwrap();
4186 ///
4187 /// assert_eq!(pixels, &[
4188 /// Pixel { r: 0, g: 1, b: 2, a: 3 },
4189 /// Pixel { r: 4, g: 5, b: 6, a: 7 },
4190 /// ]);
4191 ///
4192 /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
4193 ///
4194 /// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0]);
4195 /// ```
4196 ///
4197 /// Since an explicit `count` is provided, this method supports types with
4198 /// zero-sized trailing slice elements. Methods such as [`mut_from`] which
4199 /// do not take an explicit count do not support such types.
4200 ///
4201 /// ```
4202 /// use zerocopy::*;
4203 /// # use zerocopy_derive::*;
4204 ///
4205 /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
4206 /// #[repr(C, packed)]
4207 /// struct ZSTy {
4208 /// leading_sized: [u8; 2],
4209 /// trailing_dst: [()],
4210 /// }
4211 ///
4212 /// let src = &mut [85, 85][..];
4213 /// let zsty = ZSTy::mut_from_bytes_with_elems(src, 42).unwrap();
4214 /// assert_eq!(zsty.trailing_dst.len(), 42);
4215 /// ```
4216 ///
4217 /// [`mut_from`]: FromBytes::mut_from
4218 #[must_use = "has no side effects"]
4219 #[inline]
4220 fn mut_from_bytes_with_elems(
4221 source: &mut [u8],
4222 count: usize,
4223 ) -> Result<&mut Self, CastError<&mut [u8], Self>>
4224 where
4225 Self: IntoBytes + KnownLayout<PointerMetadata = usize> + Immutable,
4226 {
4227 let source = Ptr::from_mut(source);
4228 let maybe_slf = source.try_cast_into_no_leftover::<_, BecauseImmutable>(Some(count));
4229 match maybe_slf {
4230 Ok(slf) => Ok(slf.bikeshed_recall_valid().as_mut()),
4231 Err(err) => Err(err.map_src(|s| s.as_mut())),
4232 }
4233 }
4234
4235 /// Interprets the prefix of the given `source` as a `&mut Self` with DST
4236 /// length equal to `count`.
4237 ///
4238 /// This method attempts to return a reference to the prefix of `source`
4239 /// interpreted as a `Self` with `count` trailing elements, and a reference
4240 /// to the preceding bytes. If there are insufficient bytes, or if `source`
4241 /// is not appropriately aligned, this returns `Err`. If [`Self:
4242 /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
4243 /// error][size-error-from].
4244 ///
4245 /// [self-unaligned]: Unaligned
4246 /// [size-error-from]: error/struct.SizeError.html#method.from-1
4247 ///
4248 /// # Examples
4249 ///
4250 /// ```
4251 /// use zerocopy::FromBytes;
4252 /// # use zerocopy_derive::*;
4253 ///
4254 /// # #[derive(Debug, PartialEq, Eq)]
4255 /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
4256 /// #[repr(C)]
4257 /// struct Pixel {
4258 /// r: u8,
4259 /// g: u8,
4260 /// b: u8,
4261 /// a: u8,
4262 /// }
4263 ///
4264 /// // These are more bytes than are needed to encode two `Pixel`s.
4265 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4266 ///
4267 /// let (pixels, suffix) = <[Pixel]>::mut_from_prefix_with_elems(bytes, 2).unwrap();
4268 ///
4269 /// assert_eq!(pixels, &[
4270 /// Pixel { r: 0, g: 1, b: 2, a: 3 },
4271 /// Pixel { r: 4, g: 5, b: 6, a: 7 },
4272 /// ]);
4273 ///
4274 /// assert_eq!(suffix, &[8, 9]);
4275 ///
4276 /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
4277 /// suffix.fill(1);
4278 ///
4279 /// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0, 1, 1]);
4280 /// ```
4281 ///
4282 /// Since an explicit `count` is provided, this method supports types with
4283 /// zero-sized trailing slice elements. Methods such as [`mut_from_prefix`]
4284 /// which do not take an explicit count do not support such types.
4285 ///
4286 /// ```
4287 /// use zerocopy::*;
4288 /// # use zerocopy_derive::*;
4289 ///
4290 /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
4291 /// #[repr(C, packed)]
4292 /// struct ZSTy {
4293 /// leading_sized: [u8; 2],
4294 /// trailing_dst: [()],
4295 /// }
4296 ///
4297 /// let src = &mut [85, 85][..];
4298 /// let (zsty, _) = ZSTy::mut_from_prefix_with_elems(src, 42).unwrap();
4299 /// assert_eq!(zsty.trailing_dst.len(), 42);
4300 /// ```
4301 ///
4302 /// [`mut_from_prefix`]: FromBytes::mut_from_prefix
4303 #[must_use = "has no side effects"]
4304 #[inline]
4305 fn mut_from_prefix_with_elems(
4306 source: &mut [u8],
4307 count: usize,
4308 ) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>
4309 where
4310 Self: IntoBytes + KnownLayout<PointerMetadata = usize>,
4311 {
4312 mut_from_prefix_suffix(source, Some(count), CastType::Prefix)
4313 }
4314
4315 /// Interprets the suffix of the given `source` as a `&mut Self` with DST
4316 /// length equal to `count`.
4317 ///
4318 /// This method attempts to return a reference to the suffix of `source`
4319 /// interpreted as a `Self` with `count` trailing elements, and a reference
4320 /// to the remaining bytes. If there are insufficient bytes, or if that
4321 /// suffix of `source` is not appropriately aligned, this returns `Err`. If
4322 /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
4323 /// alignment error][size-error-from].
4324 ///
4325 /// [self-unaligned]: Unaligned
4326 /// [size-error-from]: error/struct.SizeError.html#method.from-1
4327 ///
4328 /// # Examples
4329 ///
4330 /// ```
4331 /// use zerocopy::FromBytes;
4332 /// # use zerocopy_derive::*;
4333 ///
4334 /// # #[derive(Debug, PartialEq, Eq)]
4335 /// #[derive(FromBytes, IntoBytes, Immutable)]
4336 /// #[repr(C)]
4337 /// struct Pixel {
4338 /// r: u8,
4339 /// g: u8,
4340 /// b: u8,
4341 /// a: u8,
4342 /// }
4343 ///
4344 /// // These are more bytes than are needed to encode two `Pixel`s.
4345 /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4346 ///
4347 /// let (prefix, pixels) = <[Pixel]>::mut_from_suffix_with_elems(bytes, 2).unwrap();
4348 ///
4349 /// assert_eq!(prefix, &[0, 1]);
4350 ///
4351 /// assert_eq!(pixels, &[
4352 /// Pixel { r: 2, g: 3, b: 4, a: 5 },
4353 /// Pixel { r: 6, g: 7, b: 8, a: 9 },
4354 /// ]);
4355 ///
4356 /// prefix.fill(9);
4357 /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
4358 ///
4359 /// assert_eq!(bytes, [9, 9, 2, 3, 4, 5, 0, 0, 0, 0]);
4360 /// ```
4361 ///
4362 /// Since an explicit `count` is provided, this method supports types with
4363 /// zero-sized trailing slice elements. Methods such as [`mut_from_suffix`]
4364 /// which do not take an explicit count do not support such types.
4365 ///
4366 /// ```
4367 /// use zerocopy::*;
4368 /// # use zerocopy_derive::*;
4369 ///
4370 /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
4371 /// #[repr(C, packed)]
4372 /// struct ZSTy {
4373 /// leading_sized: [u8; 2],
4374 /// trailing_dst: [()],
4375 /// }
4376 ///
4377 /// let src = &mut [85, 85][..];
4378 /// let (_, zsty) = ZSTy::mut_from_suffix_with_elems(src, 42).unwrap();
4379 /// assert_eq!(zsty.trailing_dst.len(), 42);
4380 /// ```
4381 ///
4382 /// [`mut_from_suffix`]: FromBytes::mut_from_suffix
4383 #[must_use = "has no side effects"]
4384 #[inline]
4385 fn mut_from_suffix_with_elems(
4386 source: &mut [u8],
4387 count: usize,
4388 ) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>
4389 where
4390 Self: IntoBytes + KnownLayout<PointerMetadata = usize>,
4391 {
4392 mut_from_prefix_suffix(source, Some(count), CastType::Suffix).map(swap)
4393 }
4394
4395 /// Reads a copy of `Self` from the given `source`.
4396 ///
4397 /// If `source.len() != size_of::<Self>()`, `read_from_bytes` returns `Err`.
4398 ///
4399 /// # Examples
4400 ///
4401 /// ```
4402 /// use zerocopy::FromBytes;
4403 /// # use zerocopy_derive::*;
4404 ///
4405 /// #[derive(FromBytes)]
4406 /// #[repr(C)]
4407 /// struct PacketHeader {
4408 /// src_port: [u8; 2],
4409 /// dst_port: [u8; 2],
4410 /// length: [u8; 2],
4411 /// checksum: [u8; 2],
4412 /// }
4413 ///
4414 /// // These bytes encode a `PacketHeader`.
4415 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..];
4416 ///
4417 /// let header = PacketHeader::read_from_bytes(bytes).unwrap();
4418 ///
4419 /// assert_eq!(header.src_port, [0, 1]);
4420 /// assert_eq!(header.dst_port, [2, 3]);
4421 /// assert_eq!(header.length, [4, 5]);
4422 /// assert_eq!(header.checksum, [6, 7]);
4423 /// ```
4424 #[must_use = "has no side effects"]
4425 #[inline]
4426 fn read_from_bytes(source: &[u8]) -> Result<Self, SizeError<&[u8], Self>>
4427 where
4428 Self: Sized,
4429 {
4430 match Ref::<_, Unalign<Self>>::sized_from(source) {
4431 Ok(r) => Ok(Ref::read(&r).into_inner()),
4432 Err(CastError::Size(e)) => Err(e.with_dst()),
4433 Err(CastError::Alignment(_)) => {
4434 // SAFETY: `Unalign<Self>` is trivially aligned, so
4435 // `Ref::sized_from` cannot fail due to unmet alignment
4436 // requirements.
4437 unsafe { core::hint::unreachable_unchecked() }
4438 }
4439 Err(CastError::Validity(i)) => match i {},
4440 }
4441 }
4442
4443 /// Reads a copy of `Self` from the prefix of the given `source`.
4444 ///
4445 /// This attempts to read a `Self` from the first `size_of::<Self>()` bytes
4446 /// of `source`, returning that `Self` and any remaining bytes. If
4447 /// `source.len() < size_of::<Self>()`, it returns `Err`.
4448 ///
4449 /// # Examples
4450 ///
4451 /// ```
4452 /// use zerocopy::FromBytes;
4453 /// # use zerocopy_derive::*;
4454 ///
4455 /// #[derive(FromBytes)]
4456 /// #[repr(C)]
4457 /// struct PacketHeader {
4458 /// src_port: [u8; 2],
4459 /// dst_port: [u8; 2],
4460 /// length: [u8; 2],
4461 /// checksum: [u8; 2],
4462 /// }
4463 ///
4464 /// // These are more bytes than are needed to encode a `PacketHeader`.
4465 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4466 ///
4467 /// let (header, body) = PacketHeader::read_from_prefix(bytes).unwrap();
4468 ///
4469 /// assert_eq!(header.src_port, [0, 1]);
4470 /// assert_eq!(header.dst_port, [2, 3]);
4471 /// assert_eq!(header.length, [4, 5]);
4472 /// assert_eq!(header.checksum, [6, 7]);
4473 /// assert_eq!(body, [8, 9]);
4474 /// ```
4475 #[must_use = "has no side effects"]
4476 #[inline]
4477 fn read_from_prefix(source: &[u8]) -> Result<(Self, &[u8]), SizeError<&[u8], Self>>
4478 where
4479 Self: Sized,
4480 {
4481 match Ref::<_, Unalign<Self>>::sized_from_prefix(source) {
4482 Ok((r, suffix)) => Ok((Ref::read(&r).into_inner(), suffix)),
4483 Err(CastError::Size(e)) => Err(e.with_dst()),
4484 Err(CastError::Alignment(_)) => {
4485 // SAFETY: `Unalign<Self>` is trivially aligned, so
4486 // `Ref::sized_from_prefix` cannot fail due to unmet alignment
4487 // requirements.
4488 unsafe { core::hint::unreachable_unchecked() }
4489 }
4490 Err(CastError::Validity(i)) => match i {},
4491 }
4492 }
4493
4494 /// Reads a copy of `Self` from the suffix of the given `source`.
4495 ///
4496 /// This attempts to read a `Self` from the last `size_of::<Self>()` bytes
4497 /// of `source`, returning that `Self` and any preceding bytes. If
4498 /// `source.len() < size_of::<Self>()`, it returns `Err`.
4499 ///
4500 /// # Examples
4501 ///
4502 /// ```
4503 /// use zerocopy::FromBytes;
4504 /// # use zerocopy_derive::*;
4505 ///
4506 /// #[derive(FromBytes)]
4507 /// #[repr(C)]
4508 /// struct PacketTrailer {
4509 /// frame_check_sequence: [u8; 4],
4510 /// }
4511 ///
4512 /// // These are more bytes than are needed to encode a `PacketTrailer`.
4513 /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4514 ///
4515 /// let (prefix, trailer) = PacketTrailer::read_from_suffix(bytes).unwrap();
4516 ///
4517 /// assert_eq!(prefix, [0, 1, 2, 3, 4, 5]);
4518 /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
4519 /// ```
4520 #[must_use = "has no side effects"]
4521 #[inline]
4522 fn read_from_suffix(source: &[u8]) -> Result<(&[u8], Self), SizeError<&[u8], Self>>
4523 where
4524 Self: Sized,
4525 {
4526 match Ref::<_, Unalign<Self>>::sized_from_suffix(source) {
4527 Ok((prefix, r)) => Ok((prefix, Ref::read(&r).into_inner())),
4528 Err(CastError::Size(e)) => Err(e.with_dst()),
4529 Err(CastError::Alignment(_)) => {
4530 // SAFETY: `Unalign<Self>` is trivially aligned, so
4531 // `Ref::sized_from_suffix` cannot fail due to unmet alignment
4532 // requirements.
4533 unsafe { core::hint::unreachable_unchecked() }
4534 }
4535 Err(CastError::Validity(i)) => match i {},
4536 }
4537 }
4538
4539 /// Reads a copy of `self` from an `io::Read`.
4540 ///
4541 /// This is useful for interfacing with operating system byte sinks (files,
4542 /// sockets, etc.).
4543 ///
4544 /// # Examples
4545 ///
4546 /// ```no_run
4547 /// use zerocopy::{byteorder::big_endian::*, FromBytes};
4548 /// use std::fs::File;
4549 /// # use zerocopy_derive::*;
4550 ///
4551 /// #[derive(FromBytes)]
4552 /// #[repr(C)]
4553 /// struct BitmapFileHeader {
4554 /// signature: [u8; 2],
4555 /// size: U32,
4556 /// reserved: U64,
4557 /// offset: U64,
4558 /// }
4559 ///
4560 /// let mut file = File::open("image.bin").unwrap();
4561 /// let header = BitmapFileHeader::read_from_io(&mut file).unwrap();
4562 /// ```
4563 #[cfg(feature = "std")]
4564 #[inline(always)]
4565 fn read_from_io<R>(mut src: R) -> io::Result<Self>
4566 where
4567 Self: Sized,
4568 R: io::Read,
4569 {
4570 let mut buf = CoreMaybeUninit::<Self>::zeroed();
4571 let ptr = Ptr::from_mut(&mut buf);
4572 // SAFETY: `buf` consists entirely of initialized, zeroed bytes.
4573 let ptr = unsafe { ptr.assume_validity::<invariant::Initialized>() };
4574 let ptr = ptr.as_bytes::<BecauseExclusive>();
4575 src.read_exact(ptr.as_mut())?;
4576 // SAFETY: `buf` entirely consists of initialized bytes, and `Self` is
4577 // `FromBytes`.
4578 Ok(unsafe { buf.assume_init() })
4579 }
4580
4581 #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::ref_from_bytes`")]
4582 #[doc(hidden)]
4583 #[must_use = "has no side effects"]
4584 #[inline(always)]
4585 fn ref_from(source: &[u8]) -> Option<&Self>
4586 where
4587 Self: KnownLayout + Immutable,
4588 {
4589 Self::ref_from_bytes(source).ok()
4590 }
4591
4592 #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::mut_from_bytes`")]
4593 #[doc(hidden)]
4594 #[must_use = "has no side effects"]
4595 #[inline(always)]
4596 fn mut_from(source: &mut [u8]) -> Option<&mut Self>
4597 where
4598 Self: KnownLayout + IntoBytes,
4599 {
4600 Self::mut_from_bytes(source).ok()
4601 }
4602
4603 #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::ref_from_prefix_with_elems`")]
4604 #[doc(hidden)]
4605 #[must_use = "has no side effects"]
4606 #[inline(always)]
4607 fn slice_from_prefix(source: &[u8], count: usize) -> Option<(&[Self], &[u8])>
4608 where
4609 Self: Sized + Immutable,
4610 {
4611 <[Self]>::ref_from_prefix_with_elems(source, count).ok()
4612 }
4613
4614 #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::ref_from_suffix_with_elems`")]
4615 #[doc(hidden)]
4616 #[must_use = "has no side effects"]
4617 #[inline(always)]
4618 fn slice_from_suffix(source: &[u8], count: usize) -> Option<(&[u8], &[Self])>
4619 where
4620 Self: Sized + Immutable,
4621 {
4622 <[Self]>::ref_from_suffix_with_elems(source, count).ok()
4623 }
4624
4625 #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::mut_from_prefix_with_elems`")]
4626 #[doc(hidden)]
4627 #[must_use = "has no side effects"]
4628 #[inline(always)]
4629 fn mut_slice_from_prefix(source: &mut [u8], count: usize) -> Option<(&mut [Self], &mut [u8])>
4630 where
4631 Self: Sized + IntoBytes,
4632 {
4633 <[Self]>::mut_from_prefix_with_elems(source, count).ok()
4634 }
4635
4636 #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::mut_from_suffix_with_elems`")]
4637 #[doc(hidden)]
4638 #[must_use = "has no side effects"]
4639 #[inline(always)]
4640 fn mut_slice_from_suffix(source: &mut [u8], count: usize) -> Option<(&mut [u8], &mut [Self])>
4641 where
4642 Self: Sized + IntoBytes,
4643 {
4644 <[Self]>::mut_from_suffix_with_elems(source, count).ok()
4645 }
4646
4647 #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::read_from_bytes`")]
4648 #[doc(hidden)]
4649 #[must_use = "has no side effects"]
4650 #[inline(always)]
4651 fn read_from(source: &[u8]) -> Option<Self>
4652 where
4653 Self: Sized,
4654 {
4655 Self::read_from_bytes(source).ok()
4656 }
4657}
4658
4659/// Interprets the given affix of the given bytes as a `&Self`.
4660///
4661/// This method computes the largest possible size of `Self` that can fit in the
4662/// prefix or suffix bytes of `source`, then attempts to return both a reference
4663/// to those bytes interpreted as a `Self`, and a reference to the excess bytes.
4664/// If there are insufficient bytes, or if that affix of `source` is not
4665/// appropriately aligned, this returns `Err`.
4666#[inline(always)]
4667fn ref_from_prefix_suffix<T: FromBytes + KnownLayout + Immutable + ?Sized>(
4668 source: &[u8],
4669 meta: Option<T::PointerMetadata>,
4670 cast_type: CastType,
4671) -> Result<(&T, &[u8]), CastError<&[u8], T>> {
4672 let (slf, prefix_suffix) = Ptr::from_ref(source)
4673 .try_cast_into::<_, BecauseImmutable>(cast_type, meta)
4674 .map_err(|err| err.map_src(|s| s.as_ref()))?;
4675 Ok((slf.bikeshed_recall_valid().as_ref(), prefix_suffix.as_ref()))
4676}
4677
4678/// Interprets the given affix of the given bytes as a `&mut Self` without
4679/// copying.
4680///
4681/// This method computes the largest possible size of `Self` that can fit in the
4682/// prefix or suffix bytes of `source`, then attempts to return both a reference
4683/// to those bytes interpreted as a `Self`, and a reference to the excess bytes.
4684/// If there are insufficient bytes, or if that affix of `source` is not
4685/// appropriately aligned, this returns `Err`.
4686#[inline(always)]
4687fn mut_from_prefix_suffix<T: FromBytes + KnownLayout + ?Sized>(
4688 source: &mut [u8],
4689 meta: Option<T::PointerMetadata>,
4690 cast_type: CastType,
4691) -> Result<(&mut T, &mut [u8]), CastError<&mut [u8], T>> {
4692 let (slf, prefix_suffix) = Ptr::from_mut(source)
4693 .try_cast_into::<_, BecauseExclusive>(cast_type, meta)
4694 .map_err(|err| err.map_src(|s| s.as_mut()))?;
4695 Ok((slf.bikeshed_recall_valid().as_mut(), prefix_suffix.as_mut()))
4696}
4697
4698/// Analyzes whether a type is [`IntoBytes`].
4699///
4700/// This derive analyzes, at compile time, whether the annotated type satisfies
4701/// the [safety conditions] of `IntoBytes` and implements `IntoBytes` if it is
4702/// sound to do so. This derive can be applied to structs and enums (see below
4703/// for union support); e.g.:
4704///
4705/// ```
4706/// # use zerocopy_derive::{IntoBytes};
4707/// #[derive(IntoBytes)]
4708/// #[repr(C)]
4709/// struct MyStruct {
4710/// # /*
4711/// ...
4712/// # */
4713/// }
4714///
4715/// #[derive(IntoBytes)]
4716/// #[repr(u8)]
4717/// enum MyEnum {
4718/// # Variant,
4719/// # /*
4720/// ...
4721/// # */
4722/// }
4723/// ```
4724///
4725/// [safety conditions]: trait@IntoBytes#safety
4726///
4727/// # Error Messages
4728///
4729/// On Rust toolchains prior to 1.78.0, due to the way that the custom derive
4730/// for `IntoBytes` is implemented, you may get an error like this:
4731///
4732/// ```text
4733/// error[E0277]: the trait bound `(): PaddingFree<Foo, true>` is not satisfied
4734/// --> lib.rs:23:10
4735/// |
4736/// 1 | #[derive(IntoBytes)]
4737/// | ^^^^^^^^^ the trait `PaddingFree<Foo, true>` is not implemented for `()`
4738/// |
4739/// = help: the following implementations were found:
4740/// <() as PaddingFree<T, false>>
4741/// ```
4742///
4743/// This error indicates that the type being annotated has padding bytes, which
4744/// is illegal for `IntoBytes` types. Consider reducing the alignment of some
4745/// fields by using types in the [`byteorder`] module, wrapping field types in
4746/// [`Unalign`], adding explicit struct fields where those padding bytes would
4747/// be, or using `#[repr(packed)]`. See the Rust Reference's page on [type
4748/// layout] for more information about type layout and padding.
4749///
4750/// [type layout]: https://doc.rust-lang.org/reference/type-layout.html
4751///
4752/// # Unions
4753///
4754/// Currently, union bit validity is [up in the air][union-validity], and so
4755/// zerocopy does not support `#[derive(IntoBytes)]` on unions by default.
4756/// However, implementing `IntoBytes` on a union type is likely sound on all
4757/// existing Rust toolchains - it's just that it may become unsound in the
4758/// future. You can opt-in to `#[derive(IntoBytes)]` support on unions by
4759/// passing the unstable `zerocopy_derive_union_into_bytes` cfg:
4760///
4761/// ```shell
4762/// $ RUSTFLAGS='--cfg zerocopy_derive_union_into_bytes' cargo build
4763/// ```
4764///
4765/// However, it is your responsibility to ensure that this derive is sound on
4766/// the specific versions of the Rust toolchain you are using! We make no
4767/// stability or soundness guarantees regarding this cfg, and may remove it at
4768/// any point.
4769///
4770/// We are actively working with Rust to stabilize the necessary language
4771/// guarantees to support this in a forwards-compatible way, which will enable
4772/// us to remove the cfg gate. As part of this effort, we need to know how much
4773/// demand there is for this feature. If you would like to use `IntoBytes` on
4774/// unions, [please let us know][discussion].
4775///
4776/// [union-validity]: https://github.com/rust-lang/unsafe-code-guidelines/issues/438
4777/// [discussion]: https://github.com/google/zerocopy/discussions/1802
4778///
4779/// # Analysis
4780///
4781/// *This section describes, roughly, the analysis performed by this derive to
4782/// determine whether it is sound to implement `IntoBytes` for a given type.
4783/// Unless you are modifying the implementation of this derive, or attempting to
4784/// manually implement `IntoBytes` for a type yourself, you don't need to read
4785/// this section.*
4786///
4787/// If a type has the following properties, then this derive can implement
4788/// `IntoBytes` for that type:
4789///
4790/// - If the type is a struct, its fields must be [`IntoBytes`]. Additionally:
4791/// - if the type is `repr(transparent)` or `repr(packed)`, it is
4792/// [`IntoBytes`] if its fields are [`IntoBytes`]; else,
4793/// - if the type is `repr(C)` with at most one field, it is [`IntoBytes`]
4794/// if its field is [`IntoBytes`]; else,
4795/// - if the type has no generic parameters, it is [`IntoBytes`] if the type
4796/// is sized and has no padding bytes; else,
4797/// - if the type is `repr(C)`, its fields must be [`Unaligned`].
4798/// - If the type is an enum:
4799/// - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`,
4800/// `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`).
4801/// - It must have no padding bytes.
4802/// - Its fields must be [`IntoBytes`].
4803///
4804/// This analysis is subject to change. Unsafe code may *only* rely on the
4805/// documented [safety conditions] of `FromBytes`, and must *not* rely on the
4806/// implementation details of this derive.
4807///
4808/// [Rust Reference]: https://doc.rust-lang.org/reference/type-layout.html
4809#[cfg(any(feature = "derive", test))]
4810#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
4811pub use zerocopy_derive::IntoBytes;
4812
4813/// Types that can be converted to an immutable slice of initialized bytes.
4814///
4815/// Any `IntoBytes` type can be converted to a slice of initialized bytes of the
4816/// same size. This is useful for efficiently serializing structured data as raw
4817/// bytes.
4818///
4819/// # Implementation
4820///
4821/// **Do not implement this trait yourself!** Instead, use
4822/// [`#[derive(IntoBytes)]`][derive]; e.g.:
4823///
4824/// ```
4825/// # use zerocopy_derive::IntoBytes;
4826/// #[derive(IntoBytes)]
4827/// #[repr(C)]
4828/// struct MyStruct {
4829/// # /*
4830/// ...
4831/// # */
4832/// }
4833///
4834/// #[derive(IntoBytes)]
4835/// #[repr(u8)]
4836/// enum MyEnum {
4837/// # Variant0,
4838/// # /*
4839/// ...
4840/// # */
4841/// }
4842/// ```
4843///
4844/// This derive performs a sophisticated, compile-time safety analysis to
4845/// determine whether a type is `IntoBytes`. See the [derive
4846/// documentation][derive] for guidance on how to interpret error messages
4847/// produced by the derive's analysis.
4848///
4849/// # Safety
4850///
4851/// *This section describes what is required in order for `T: IntoBytes`, and
4852/// what unsafe code may assume of such types. If you don't plan on implementing
4853/// `IntoBytes` manually, and you don't plan on writing unsafe code that
4854/// operates on `IntoBytes` types, then you don't need to read this section.*
4855///
4856/// If `T: IntoBytes`, then unsafe code may assume that it is sound to treat any
4857/// `t: T` as an immutable `[u8]` of length `size_of_val(t)`. If a type is
4858/// marked as `IntoBytes` which violates this contract, it may cause undefined
4859/// behavior.
4860///
4861/// `#[derive(IntoBytes)]` only permits [types which satisfy these
4862/// requirements][derive-analysis].
4863///
4864#[cfg_attr(
4865 feature = "derive",
4866 doc = "[derive]: zerocopy_derive::IntoBytes",
4867 doc = "[derive-analysis]: zerocopy_derive::IntoBytes#analysis"
4868)]
4869#[cfg_attr(
4870 not(feature = "derive"),
4871 doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.IntoBytes.html"),
4872 doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.IntoBytes.html#analysis"),
4873)]
4874#[cfg_attr(
4875 zerocopy_diagnostic_on_unimplemented_1_78_0,
4876 diagnostic::on_unimplemented(note = "Consider adding `#[derive(IntoBytes)]` to `{Self}`")
4877)]
4878pub unsafe trait IntoBytes {
4879 // The `Self: Sized` bound makes it so that this function doesn't prevent
4880 // `IntoBytes` from being object safe. Note that other `IntoBytes` methods
4881 // prevent object safety, but those provide a benefit in exchange for object
4882 // safety. If at some point we remove those methods, change their type
4883 // signatures, or move them out of this trait so that `IntoBytes` is object
4884 // safe again, it's important that this function not prevent object safety.
4885 #[doc(hidden)]
4886 fn only_derive_is_allowed_to_implement_this_trait()
4887 where
4888 Self: Sized;
4889
4890 /// Gets the bytes of this value.
4891 ///
4892 /// # Examples
4893 ///
4894 /// ```
4895 /// use zerocopy::IntoBytes;
4896 /// # use zerocopy_derive::*;
4897 ///
4898 /// #[derive(IntoBytes, Immutable)]
4899 /// #[repr(C)]
4900 /// struct PacketHeader {
4901 /// src_port: [u8; 2],
4902 /// dst_port: [u8; 2],
4903 /// length: [u8; 2],
4904 /// checksum: [u8; 2],
4905 /// }
4906 ///
4907 /// let header = PacketHeader {
4908 /// src_port: [0, 1],
4909 /// dst_port: [2, 3],
4910 /// length: [4, 5],
4911 /// checksum: [6, 7],
4912 /// };
4913 ///
4914 /// let bytes = header.as_bytes();
4915 ///
4916 /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]);
4917 /// ```
4918 #[must_use = "has no side effects"]
4919 #[inline(always)]
4920 fn as_bytes(&self) -> &[u8]
4921 where
4922 Self: Immutable,
4923 {
4924 // Note that this method does not have a `Self: Sized` bound;
4925 // `size_of_val` works for unsized values too.
4926 let len = mem::size_of_val(self);
4927 let slf: *const Self = self;
4928
4929 // SAFETY:
4930 // - `slf.cast::<u8>()` is valid for reads for `len * size_of::<u8>()`
4931 // many bytes because...
4932 // - `slf` is the same pointer as `self`, and `self` is a reference
4933 // which points to an object whose size is `len`. Thus...
4934 // - The entire region of `len` bytes starting at `slf` is contained
4935 // within a single allocation.
4936 // - `slf` is non-null.
4937 // - `slf` is trivially aligned to `align_of::<u8>() == 1`.
4938 // - `Self: IntoBytes` ensures that all of the bytes of `slf` are
4939 // initialized.
4940 // - Since `slf` is derived from `self`, and `self` is an immutable
4941 // reference, the only other references to this memory region that
4942 // could exist are other immutable references, and those don't allow
4943 // mutation. `Self: Immutable` prohibits types which contain
4944 // `UnsafeCell`s, which are the only types for which this rule
4945 // wouldn't be sufficient.
4946 // - The total size of the resulting slice is no larger than
4947 // `isize::MAX` because no allocation produced by safe code can be
4948 // larger than `isize::MAX`.
4949 //
4950 // TODO(#429): Add references to docs and quotes.
4951 unsafe { slice::from_raw_parts(slf.cast::<u8>(), len) }
4952 }
4953
4954 /// Gets the bytes of this value mutably.
4955 ///
4956 /// # Examples
4957 ///
4958 /// ```
4959 /// use zerocopy::IntoBytes;
4960 /// # use zerocopy_derive::*;
4961 ///
4962 /// # #[derive(Eq, PartialEq, Debug)]
4963 /// #[derive(FromBytes, IntoBytes, Immutable)]
4964 /// #[repr(C)]
4965 /// struct PacketHeader {
4966 /// src_port: [u8; 2],
4967 /// dst_port: [u8; 2],
4968 /// length: [u8; 2],
4969 /// checksum: [u8; 2],
4970 /// }
4971 ///
4972 /// let mut header = PacketHeader {
4973 /// src_port: [0, 1],
4974 /// dst_port: [2, 3],
4975 /// length: [4, 5],
4976 /// checksum: [6, 7],
4977 /// };
4978 ///
4979 /// let bytes = header.as_mut_bytes();
4980 ///
4981 /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]);
4982 ///
4983 /// bytes.reverse();
4984 ///
4985 /// assert_eq!(header, PacketHeader {
4986 /// src_port: [7, 6],
4987 /// dst_port: [5, 4],
4988 /// length: [3, 2],
4989 /// checksum: [1, 0],
4990 /// });
4991 /// ```
4992 #[must_use = "has no side effects"]
4993 #[inline(always)]
4994 fn as_mut_bytes(&mut self) -> &mut [u8]
4995 where
4996 Self: FromBytes,
4997 {
4998 // Note that this method does not have a `Self: Sized` bound;
4999 // `size_of_val` works for unsized values too.
5000 let len = mem::size_of_val(self);
5001 let slf: *mut Self = self;
5002
5003 // SAFETY:
5004 // - `slf.cast::<u8>()` is valid for reads and writes for `len *
5005 // size_of::<u8>()` many bytes because...
5006 // - `slf` is the same pointer as `self`, and `self` is a reference
5007 // which points to an object whose size is `len`. Thus...
5008 // - The entire region of `len` bytes starting at `slf` is contained
5009 // within a single allocation.
5010 // - `slf` is non-null.
5011 // - `slf` is trivially aligned to `align_of::<u8>() == 1`.
5012 // - `Self: IntoBytes` ensures that all of the bytes of `slf` are
5013 // initialized.
5014 // - `Self: FromBytes` ensures that no write to this memory region
5015 // could result in it containing an invalid `Self`.
5016 // - Since `slf` is derived from `self`, and `self` is a mutable
5017 // reference, no other references to this memory region can exist.
5018 // - The total size of the resulting slice is no larger than
5019 // `isize::MAX` because no allocation produced by safe code can be
5020 // larger than `isize::MAX`.
5021 //
5022 // TODO(#429): Add references to docs and quotes.
5023 unsafe { slice::from_raw_parts_mut(slf.cast::<u8>(), len) }
5024 }
5025
5026 /// Writes a copy of `self` to `dst`.
5027 ///
5028 /// If `dst.len() != size_of_val(self)`, `write_to` returns `Err`.
5029 ///
5030 /// # Examples
5031 ///
5032 /// ```
5033 /// use zerocopy::IntoBytes;
5034 /// # use zerocopy_derive::*;
5035 ///
5036 /// #[derive(IntoBytes, Immutable)]
5037 /// #[repr(C)]
5038 /// struct PacketHeader {
5039 /// src_port: [u8; 2],
5040 /// dst_port: [u8; 2],
5041 /// length: [u8; 2],
5042 /// checksum: [u8; 2],
5043 /// }
5044 ///
5045 /// let header = PacketHeader {
5046 /// src_port: [0, 1],
5047 /// dst_port: [2, 3],
5048 /// length: [4, 5],
5049 /// checksum: [6, 7],
5050 /// };
5051 ///
5052 /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0];
5053 ///
5054 /// header.write_to(&mut bytes[..]);
5055 ///
5056 /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]);
5057 /// ```
5058 ///
5059 /// If too many or too few target bytes are provided, `write_to` returns
5060 /// `Err` and leaves the target bytes unmodified:
5061 ///
5062 /// ```
5063 /// # use zerocopy::IntoBytes;
5064 /// # let header = u128::MAX;
5065 /// let mut excessive_bytes = &mut [0u8; 128][..];
5066 ///
5067 /// let write_result = header.write_to(excessive_bytes);
5068 ///
5069 /// assert!(write_result.is_err());
5070 /// assert_eq!(excessive_bytes, [0u8; 128]);
5071 /// ```
5072 #[must_use = "callers should check the return value to see if the operation succeeded"]
5073 #[inline]
5074 fn write_to(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>>
5075 where
5076 Self: Immutable,
5077 {
5078 let src = self.as_bytes();
5079 if dst.len() == src.len() {
5080 // SAFETY: Within this branch of the conditional, we have ensured
5081 // that `dst.len()` is equal to `src.len()`. Neither the size of the
5082 // source nor the size of the destination change between the above
5083 // size check and the invocation of `copy_unchecked`.
5084 unsafe { util::copy_unchecked(src, dst) }
5085 Ok(())
5086 } else {
5087 Err(SizeError::new(self))
5088 }
5089 }
5090
5091 /// Writes a copy of `self` to the prefix of `dst`.
5092 ///
5093 /// `write_to_prefix` writes `self` to the first `size_of_val(self)` bytes
5094 /// of `dst`. If `dst.len() < size_of_val(self)`, it returns `Err`.
5095 ///
5096 /// # Examples
5097 ///
5098 /// ```
5099 /// use zerocopy::IntoBytes;
5100 /// # use zerocopy_derive::*;
5101 ///
5102 /// #[derive(IntoBytes, Immutable)]
5103 /// #[repr(C)]
5104 /// struct PacketHeader {
5105 /// src_port: [u8; 2],
5106 /// dst_port: [u8; 2],
5107 /// length: [u8; 2],
5108 /// checksum: [u8; 2],
5109 /// }
5110 ///
5111 /// let header = PacketHeader {
5112 /// src_port: [0, 1],
5113 /// dst_port: [2, 3],
5114 /// length: [4, 5],
5115 /// checksum: [6, 7],
5116 /// };
5117 ///
5118 /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
5119 ///
5120 /// header.write_to_prefix(&mut bytes[..]);
5121 ///
5122 /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
5123 /// ```
5124 ///
5125 /// If insufficient target bytes are provided, `write_to_prefix` returns
5126 /// `Err` and leaves the target bytes unmodified:
5127 ///
5128 /// ```
5129 /// # use zerocopy::IntoBytes;
5130 /// # let header = u128::MAX;
5131 /// let mut insufficent_bytes = &mut [0, 0][..];
5132 ///
5133 /// let write_result = header.write_to_suffix(insufficent_bytes);
5134 ///
5135 /// assert!(write_result.is_err());
5136 /// assert_eq!(insufficent_bytes, [0, 0]);
5137 /// ```
5138 #[must_use = "callers should check the return value to see if the operation succeeded"]
5139 #[inline]
5140 fn write_to_prefix(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>>
5141 where
5142 Self: Immutable,
5143 {
5144 let src = self.as_bytes();
5145 match dst.get_mut(..src.len()) {
5146 Some(dst) => {
5147 // SAFETY: Within this branch of the `match`, we have ensured
5148 // through fallible subslicing that `dst.len()` is equal to
5149 // `src.len()`. Neither the size of the source nor the size of
5150 // the destination change between the above subslicing operation
5151 // and the invocation of `copy_unchecked`.
5152 unsafe { util::copy_unchecked(src, dst) }
5153 Ok(())
5154 }
5155 None => Err(SizeError::new(self)),
5156 }
5157 }
5158
5159 /// Writes a copy of `self` to the suffix of `dst`.
5160 ///
5161 /// `write_to_suffix` writes `self` to the last `size_of_val(self)` bytes of
5162 /// `dst`. If `dst.len() < size_of_val(self)`, it returns `Err`.
5163 ///
5164 /// # Examples
5165 ///
5166 /// ```
5167 /// use zerocopy::IntoBytes;
5168 /// # use zerocopy_derive::*;
5169 ///
5170 /// #[derive(IntoBytes, Immutable)]
5171 /// #[repr(C)]
5172 /// struct PacketHeader {
5173 /// src_port: [u8; 2],
5174 /// dst_port: [u8; 2],
5175 /// length: [u8; 2],
5176 /// checksum: [u8; 2],
5177 /// }
5178 ///
5179 /// let header = PacketHeader {
5180 /// src_port: [0, 1],
5181 /// dst_port: [2, 3],
5182 /// length: [4, 5],
5183 /// checksum: [6, 7],
5184 /// };
5185 ///
5186 /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
5187 ///
5188 /// header.write_to_suffix(&mut bytes[..]);
5189 ///
5190 /// assert_eq!(bytes, [0, 0, 0, 1, 2, 3, 4, 5, 6, 7]);
5191 ///
5192 /// let mut insufficent_bytes = &mut [0, 0][..];
5193 ///
5194 /// let write_result = header.write_to_suffix(insufficent_bytes);
5195 ///
5196 /// assert!(write_result.is_err());
5197 /// assert_eq!(insufficent_bytes, [0, 0]);
5198 /// ```
5199 ///
5200 /// If insufficient target bytes are provided, `write_to_suffix` returns
5201 /// `Err` and leaves the target bytes unmodified:
5202 ///
5203 /// ```
5204 /// # use zerocopy::IntoBytes;
5205 /// # let header = u128::MAX;
5206 /// let mut insufficent_bytes = &mut [0, 0][..];
5207 ///
5208 /// let write_result = header.write_to_suffix(insufficent_bytes);
5209 ///
5210 /// assert!(write_result.is_err());
5211 /// assert_eq!(insufficent_bytes, [0, 0]);
5212 /// ```
5213 #[must_use = "callers should check the return value to see if the operation succeeded"]
5214 #[inline]
5215 fn write_to_suffix(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>>
5216 where
5217 Self: Immutable,
5218 {
5219 let src = self.as_bytes();
5220 let start = if let Some(start) = dst.len().checked_sub(src.len()) {
5221 start
5222 } else {
5223 return Err(SizeError::new(self));
5224 };
5225 let dst = if let Some(dst) = dst.get_mut(start..) {
5226 dst
5227 } else {
5228 // get_mut() should never return None here. We return a `SizeError`
5229 // rather than .unwrap() because in the event the branch is not
5230 // optimized away, returning a value is generally lighter-weight
5231 // than panicking.
5232 return Err(SizeError::new(self));
5233 };
5234 // SAFETY: Through fallible subslicing of `dst`, we have ensured that
5235 // `dst.len()` is equal to `src.len()`. Neither the size of the source
5236 // nor the size of the destination change between the above subslicing
5237 // operation and the invocation of `copy_unchecked`.
5238 unsafe {
5239 util::copy_unchecked(src, dst);
5240 }
5241 Ok(())
5242 }
5243
5244 /// Writes a copy of `self` to an `io::Write`.
5245 ///
5246 /// This is a shorthand for `dst.write_all(self.as_bytes())`, and is useful
5247 /// for interfacing with operating system byte sinks (files, sockets, etc.).
5248 ///
5249 /// # Examples
5250 ///
5251 /// ```no_run
5252 /// use zerocopy::{byteorder::big_endian::U16, FromBytes, IntoBytes};
5253 /// use std::fs::File;
5254 /// # use zerocopy_derive::*;
5255 ///
5256 /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
5257 /// #[repr(C, packed)]
5258 /// struct GrayscaleImage {
5259 /// height: U16,
5260 /// width: U16,
5261 /// pixels: [U16],
5262 /// }
5263 ///
5264 /// let image = GrayscaleImage::ref_from_bytes(&[0, 0, 0, 0][..]).unwrap();
5265 /// let mut file = File::create("image.bin").unwrap();
5266 /// image.write_to_io(&mut file).unwrap();
5267 /// ```
5268 ///
5269 /// If the write fails, `write_to_io` returns `Err` and a partial write may
5270 /// have occured; e.g.:
5271 ///
5272 /// ```
5273 /// # use zerocopy::IntoBytes;
5274 ///
5275 /// let src = u128::MAX;
5276 /// let mut dst = [0u8; 2];
5277 ///
5278 /// let write_result = src.write_to_io(&mut dst[..]);
5279 ///
5280 /// assert!(write_result.is_err());
5281 /// assert_eq!(dst, [255, 255]);
5282 /// ```
5283 #[cfg(feature = "std")]
5284 #[inline(always)]
5285 fn write_to_io<W>(&self, mut dst: W) -> io::Result<()>
5286 where
5287 Self: Immutable,
5288 W: io::Write,
5289 {
5290 dst.write_all(self.as_bytes())
5291 }
5292
5293 #[deprecated(since = "0.8.0", note = "`IntoBytes::as_bytes_mut` was renamed to `as_mut_bytes`")]
5294 #[doc(hidden)]
5295 #[inline]
5296 fn as_bytes_mut(&mut self) -> &mut [u8]
5297 where
5298 Self: FromBytes,
5299 {
5300 self.as_mut_bytes()
5301 }
5302}
5303
5304/// Analyzes whether a type is [`Unaligned`].
5305///
5306/// This derive analyzes, at compile time, whether the annotated type satisfies
5307/// the [safety conditions] of `Unaligned` and implements `Unaligned` if it is
5308/// sound to do so. This derive can be applied to structs, enums, and unions;
5309/// e.g.:
5310///
5311/// ```
5312/// # use zerocopy_derive::Unaligned;
5313/// #[derive(Unaligned)]
5314/// #[repr(C)]
5315/// struct MyStruct {
5316/// # /*
5317/// ...
5318/// # */
5319/// }
5320///
5321/// #[derive(Unaligned)]
5322/// #[repr(u8)]
5323/// enum MyEnum {
5324/// # Variant0,
5325/// # /*
5326/// ...
5327/// # */
5328/// }
5329///
5330/// #[derive(Unaligned)]
5331/// #[repr(packed)]
5332/// union MyUnion {
5333/// # variant: u8,
5334/// # /*
5335/// ...
5336/// # */
5337/// }
5338/// ```
5339///
5340/// # Analysis
5341///
5342/// *This section describes, roughly, the analysis performed by this derive to
5343/// determine whether it is sound to implement `Unaligned` for a given type.
5344/// Unless you are modifying the implementation of this derive, or attempting to
5345/// manually implement `Unaligned` for a type yourself, you don't need to read
5346/// this section.*
5347///
5348/// If a type has the following properties, then this derive can implement
5349/// `Unaligned` for that type:
5350///
5351/// - If the type is a struct or union:
5352/// - If `repr(align(N))` is provided, `N` must equal 1.
5353/// - If the type is `repr(C)` or `repr(transparent)`, all fields must be
5354/// [`Unaligned`].
5355/// - If the type is not `repr(C)` or `repr(transparent)`, it must be
5356/// `repr(packed)` or `repr(packed(1))`.
5357/// - If the type is an enum:
5358/// - If `repr(align(N))` is provided, `N` must equal 1.
5359/// - It must be a field-less enum (meaning that all variants have no fields).
5360/// - It must be `repr(i8)` or `repr(u8)`.
5361///
5362/// [safety conditions]: trait@Unaligned#safety
5363#[cfg(any(feature = "derive", test))]
5364#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
5365pub use zerocopy_derive::Unaligned;
5366
5367/// Types with no alignment requirement.
5368///
5369/// If `T: Unaligned`, then `align_of::<T>() == 1`.
5370///
5371/// # Implementation
5372///
5373/// **Do not implement this trait yourself!** Instead, use
5374/// [`#[derive(Unaligned)]`][derive]; e.g.:
5375///
5376/// ```
5377/// # use zerocopy_derive::Unaligned;
5378/// #[derive(Unaligned)]
5379/// #[repr(C)]
5380/// struct MyStruct {
5381/// # /*
5382/// ...
5383/// # */
5384/// }
5385///
5386/// #[derive(Unaligned)]
5387/// #[repr(u8)]
5388/// enum MyEnum {
5389/// # Variant0,
5390/// # /*
5391/// ...
5392/// # */
5393/// }
5394///
5395/// #[derive(Unaligned)]
5396/// #[repr(packed)]
5397/// union MyUnion {
5398/// # variant: u8,
5399/// # /*
5400/// ...
5401/// # */
5402/// }
5403/// ```
5404///
5405/// This derive performs a sophisticated, compile-time safety analysis to
5406/// determine whether a type is `Unaligned`.
5407///
5408/// # Safety
5409///
5410/// *This section describes what is required in order for `T: Unaligned`, and
5411/// what unsafe code may assume of such types. If you don't plan on implementing
5412/// `Unaligned` manually, and you don't plan on writing unsafe code that
5413/// operates on `Unaligned` types, then you don't need to read this section.*
5414///
5415/// If `T: Unaligned`, then unsafe code may assume that it is sound to produce a
5416/// reference to `T` at any memory location regardless of alignment. If a type
5417/// is marked as `Unaligned` which violates this contract, it may cause
5418/// undefined behavior.
5419///
5420/// `#[derive(Unaligned)]` only permits [types which satisfy these
5421/// requirements][derive-analysis].
5422///
5423#[cfg_attr(
5424 feature = "derive",
5425 doc = "[derive]: zerocopy_derive::Unaligned",
5426 doc = "[derive-analysis]: zerocopy_derive::Unaligned#analysis"
5427)]
5428#[cfg_attr(
5429 not(feature = "derive"),
5430 doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Unaligned.html"),
5431 doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Unaligned.html#analysis"),
5432)]
5433#[cfg_attr(
5434 zerocopy_diagnostic_on_unimplemented_1_78_0,
5435 diagnostic::on_unimplemented(note = "Consider adding `#[derive(Unaligned)]` to `{Self}`")
5436)]
5437pub unsafe trait Unaligned {
5438 // The `Self: Sized` bound makes it so that `Unaligned` is still object
5439 // safe.
5440 #[doc(hidden)]
5441 fn only_derive_is_allowed_to_implement_this_trait()
5442 where
5443 Self: Sized;
5444}
5445
5446/// Derives an optimized implementation of [`Hash`] for types that implement
5447/// [`IntoBytes`] and [`Immutable`].
5448///
5449/// The standard library's derive for `Hash` generates a recursive descent
5450/// into the fields of the type it is applied to. Instead, the implementation
5451/// derived by this macro makes a single call to [`Hasher::write()`] for both
5452/// [`Hash::hash()`] and [`Hash::hash_slice()`], feeding the hasher the bytes
5453/// of the type or slice all at once.
5454///
5455/// [`Hash`]: core::hash::Hash
5456/// [`Hash::hash()`]: core::hash::Hash::hash()
5457/// [`Hash::hash_slice()`]: core::hash::Hash::hash_slice()
5458#[cfg(any(feature = "derive", test))]
5459#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
5460pub use zerocopy_derive::ByteHash;
5461
5462/// Derives an optimized implementation of [`PartialEq`] and [`Eq`] for types
5463/// that implement [`IntoBytes`] and [`Immutable`].
5464///
5465/// The standard library's derive for [`PartialEq`] generates a recursive
5466/// descent into the fields of the type it is applied to. Instead, the
5467/// implementation derived by this macro performs a single slice comparison of
5468/// the bytes of the two values being compared.
5469#[cfg(any(feature = "derive", test))]
5470#[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
5471pub use zerocopy_derive::ByteEq;
5472
5473#[cfg(feature = "alloc")]
5474#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
5475#[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
5476mod alloc_support {
5477 use super::*;
5478
5479 /// Extends a `Vec<T>` by pushing `additional` new items onto the end of the
5480 /// vector. The new items are initialized with zeros.
5481 #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
5482 #[doc(hidden)]
5483 #[deprecated(since = "0.8.0", note = "moved to `FromZeros`")]
5484 #[inline(always)]
5485 pub fn extend_vec_zeroed<T: FromZeros>(
5486 v: &mut Vec<T>,
5487 additional: usize,
5488 ) -> Result<(), AllocError> {
5489 <T as FromZeros>::extend_vec_zeroed(v, additional)
5490 }
5491
5492 /// Inserts `additional` new items into `Vec<T>` at `position`. The new
5493 /// items are initialized with zeros.
5494 ///
5495 /// # Panics
5496 ///
5497 /// Panics if `position > v.len()`.
5498 #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
5499 #[doc(hidden)]
5500 #[deprecated(since = "0.8.0", note = "moved to `FromZeros`")]
5501 #[inline(always)]
5502 pub fn insert_vec_zeroed<T: FromZeros>(
5503 v: &mut Vec<T>,
5504 position: usize,
5505 additional: usize,
5506 ) -> Result<(), AllocError> {
5507 <T as FromZeros>::insert_vec_zeroed(v, position, additional)
5508 }
5509}
5510
5511#[cfg(feature = "alloc")]
5512#[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
5513#[doc(hidden)]
5514pub use alloc_support::*;
5515
5516#[cfg(test)]
5517#[allow(clippy::assertions_on_result_states, clippy::unreadable_literal)]
5518mod tests {
5519 use static_assertions::assert_impl_all;
5520
5521 use super::*;
5522 use crate::util::testutil::*;
5523
5524 // An unsized type.
5525 //
5526 // This is used to test the custom derives of our traits. The `[u8]` type
5527 // gets a hand-rolled impl, so it doesn't exercise our custom derives.
5528 #[derive(Debug, Eq, PartialEq, FromBytes, IntoBytes, Unaligned, Immutable)]
5529 #[repr(transparent)]
5530 struct Unsized([u8]);
5531
5532 impl Unsized {
5533 fn from_mut_slice(slc: &mut [u8]) -> &mut Unsized {
5534 // SAFETY: This *probably* sound - since the layouts of `[u8]` and
5535 // `Unsized` are the same, so are the layouts of `&mut [u8]` and
5536 // `&mut Unsized`. [1] Even if it turns out that this isn't actually
5537 // guaranteed by the language spec, we can just change this since
5538 // it's in test code.
5539 //
5540 // [1] https://github.com/rust-lang/unsafe-code-guidelines/issues/375
5541 unsafe { mem::transmute(slc) }
5542 }
5543 }
5544
5545 #[test]
5546 fn test_known_layout() {
5547 // Test that `$ty` and `ManuallyDrop<$ty>` have the expected layout.
5548 // Test that `PhantomData<$ty>` has the same layout as `()` regardless
5549 // of `$ty`.
5550 macro_rules! test {
5551 ($ty:ty, $expect:expr) => {
5552 let expect = $expect;
5553 assert_eq!(<$ty as KnownLayout>::LAYOUT, expect);
5554 assert_eq!(<ManuallyDrop<$ty> as KnownLayout>::LAYOUT, expect);
5555 assert_eq!(<PhantomData<$ty> as KnownLayout>::LAYOUT, <() as KnownLayout>::LAYOUT);
5556 };
5557 }
5558
5559 let layout = |offset, align, _trailing_slice_elem_size| DstLayout {
5560 align: NonZeroUsize::new(align).unwrap(),
5561 size_info: match _trailing_slice_elem_size {
5562 None => SizeInfo::Sized { size: offset },
5563 Some(elem_size) => SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }),
5564 },
5565 };
5566
5567 test!((), layout(0, 1, None));
5568 test!(u8, layout(1, 1, None));
5569 // Use `align_of` because `u64` alignment may be smaller than 8 on some
5570 // platforms.
5571 test!(u64, layout(8, mem::align_of::<u64>(), None));
5572 test!(AU64, layout(8, 8, None));
5573
5574 test!(Option<&'static ()>, usize::LAYOUT);
5575
5576 test!([()], layout(0, 1, Some(0)));
5577 test!([u8], layout(0, 1, Some(1)));
5578 test!(str, layout(0, 1, Some(1)));
5579 }
5580
5581 #[cfg(feature = "derive")]
5582 #[test]
5583 fn test_known_layout_derive() {
5584 // In this and other files (`late_compile_pass.rs`,
5585 // `mid_compile_pass.rs`, and `struct.rs`), we test success and failure
5586 // modes of `derive(KnownLayout)` for the following combination of
5587 // properties:
5588 //
5589 // +------------+--------------------------------------+-----------+
5590 // | | trailing field properties | |
5591 // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
5592 // |------------+----------+----------------+----------+-----------|
5593 // | N | N | N | N | KL00 |
5594 // | N | N | N | Y | KL01 |
5595 // | N | N | Y | N | KL02 |
5596 // | N | N | Y | Y | KL03 |
5597 // | N | Y | N | N | KL04 |
5598 // | N | Y | N | Y | KL05 |
5599 // | N | Y | Y | N | KL06 |
5600 // | N | Y | Y | Y | KL07 |
5601 // | Y | N | N | N | KL08 |
5602 // | Y | N | N | Y | KL09 |
5603 // | Y | N | Y | N | KL10 |
5604 // | Y | N | Y | Y | KL11 |
5605 // | Y | Y | N | N | KL12 |
5606 // | Y | Y | N | Y | KL13 |
5607 // | Y | Y | Y | N | KL14 |
5608 // | Y | Y | Y | Y | KL15 |
5609 // +------------+----------+----------------+----------+-----------+
5610
5611 struct NotKnownLayout<T = ()> {
5612 _t: T,
5613 }
5614
5615 #[derive(KnownLayout)]
5616 #[repr(C)]
5617 struct AlignSize<const ALIGN: usize, const SIZE: usize>
5618 where
5619 elain::Align<ALIGN>: elain::Alignment,
5620 {
5621 _align: elain::Align<ALIGN>,
5622 size: [u8; SIZE],
5623 }
5624
5625 type AU16 = AlignSize<2, 2>;
5626 type AU32 = AlignSize<4, 4>;
5627
5628 fn _assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
5629
5630 let sized_layout = |align, size| DstLayout {
5631 align: NonZeroUsize::new(align).unwrap(),
5632 size_info: SizeInfo::Sized { size },
5633 };
5634
5635 let unsized_layout = |align, elem_size, offset| DstLayout {
5636 align: NonZeroUsize::new(align).unwrap(),
5637 size_info: SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }),
5638 };
5639
5640 // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
5641 // | N | N | N | Y | KL01 |
5642 #[allow(dead_code)]
5643 #[derive(KnownLayout)]
5644 struct KL01(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
5645
5646 let expected = DstLayout::for_type::<KL01>();
5647
5648 assert_eq!(<KL01 as KnownLayout>::LAYOUT, expected);
5649 assert_eq!(<KL01 as KnownLayout>::LAYOUT, sized_layout(4, 8));
5650
5651 // ...with `align(N)`:
5652 #[allow(dead_code)]
5653 #[derive(KnownLayout)]
5654 #[repr(align(64))]
5655 struct KL01Align(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
5656
5657 let expected = DstLayout::for_type::<KL01Align>();
5658
5659 assert_eq!(<KL01Align as KnownLayout>::LAYOUT, expected);
5660 assert_eq!(<KL01Align as KnownLayout>::LAYOUT, sized_layout(64, 64));
5661
5662 // ...with `packed`:
5663 #[allow(dead_code)]
5664 #[derive(KnownLayout)]
5665 #[repr(packed)]
5666 struct KL01Packed(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
5667
5668 let expected = DstLayout::for_type::<KL01Packed>();
5669
5670 assert_eq!(<KL01Packed as KnownLayout>::LAYOUT, expected);
5671 assert_eq!(<KL01Packed as KnownLayout>::LAYOUT, sized_layout(1, 6));
5672
5673 // ...with `packed(N)`:
5674 #[allow(dead_code)]
5675 #[derive(KnownLayout)]
5676 #[repr(packed(2))]
5677 struct KL01PackedN(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
5678
5679 assert_impl_all!(KL01PackedN: KnownLayout);
5680
5681 let expected = DstLayout::for_type::<KL01PackedN>();
5682
5683 assert_eq!(<KL01PackedN as KnownLayout>::LAYOUT, expected);
5684 assert_eq!(<KL01PackedN as KnownLayout>::LAYOUT, sized_layout(2, 6));
5685
5686 // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
5687 // | N | N | Y | Y | KL03 |
5688 #[allow(dead_code)]
5689 #[derive(KnownLayout)]
5690 struct KL03(NotKnownLayout, u8);
5691
5692 let expected = DstLayout::for_type::<KL03>();
5693
5694 assert_eq!(<KL03 as KnownLayout>::LAYOUT, expected);
5695 assert_eq!(<KL03 as KnownLayout>::LAYOUT, sized_layout(1, 1));
5696
5697 // ... with `align(N)`
5698 #[allow(dead_code)]
5699 #[derive(KnownLayout)]
5700 #[repr(align(64))]
5701 struct KL03Align(NotKnownLayout<AU32>, u8);
5702
5703 let expected = DstLayout::for_type::<KL03Align>();
5704
5705 assert_eq!(<KL03Align as KnownLayout>::LAYOUT, expected);
5706 assert_eq!(<KL03Align as KnownLayout>::LAYOUT, sized_layout(64, 64));
5707
5708 // ... with `packed`:
5709 #[allow(dead_code)]
5710 #[derive(KnownLayout)]
5711 #[repr(packed)]
5712 struct KL03Packed(NotKnownLayout<AU32>, u8);
5713
5714 let expected = DstLayout::for_type::<KL03Packed>();
5715
5716 assert_eq!(<KL03Packed as KnownLayout>::LAYOUT, expected);
5717 assert_eq!(<KL03Packed as KnownLayout>::LAYOUT, sized_layout(1, 5));
5718
5719 // ... with `packed(N)`
5720 #[allow(dead_code)]
5721 #[derive(KnownLayout)]
5722 #[repr(packed(2))]
5723 struct KL03PackedN(NotKnownLayout<AU32>, u8);
5724
5725 assert_impl_all!(KL03PackedN: KnownLayout);
5726
5727 let expected = DstLayout::for_type::<KL03PackedN>();
5728
5729 assert_eq!(<KL03PackedN as KnownLayout>::LAYOUT, expected);
5730 assert_eq!(<KL03PackedN as KnownLayout>::LAYOUT, sized_layout(2, 6));
5731
5732 // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
5733 // | N | Y | N | Y | KL05 |
5734 #[allow(dead_code)]
5735 #[derive(KnownLayout)]
5736 struct KL05<T>(u8, T);
5737
5738 fn _test_kl05<T>(t: T) -> impl KnownLayout {
5739 KL05(0u8, t)
5740 }
5741
5742 // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
5743 // | N | Y | Y | Y | KL07 |
5744 #[allow(dead_code)]
5745 #[derive(KnownLayout)]
5746 struct KL07<T: KnownLayout>(u8, T);
5747
5748 fn _test_kl07<T: KnownLayout>(t: T) -> impl KnownLayout {
5749 let _ = KL07(0u8, t);
5750 }
5751
5752 // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
5753 // | Y | N | Y | N | KL10 |
5754 #[allow(dead_code)]
5755 #[derive(KnownLayout)]
5756 #[repr(C)]
5757 struct KL10(NotKnownLayout<AU32>, [u8]);
5758
5759 let expected = DstLayout::new_zst(None)
5760 .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), None)
5761 .extend(<[u8] as KnownLayout>::LAYOUT, None)
5762 .pad_to_align();
5763
5764 assert_eq!(<KL10 as KnownLayout>::LAYOUT, expected);
5765 assert_eq!(<KL10 as KnownLayout>::LAYOUT, unsized_layout(4, 1, 4));
5766
5767 // ...with `align(N)`:
5768 #[allow(dead_code)]
5769 #[derive(KnownLayout)]
5770 #[repr(C, align(64))]
5771 struct KL10Align(NotKnownLayout<AU32>, [u8]);
5772
5773 let repr_align = NonZeroUsize::new(64);
5774
5775 let expected = DstLayout::new_zst(repr_align)
5776 .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), None)
5777 .extend(<[u8] as KnownLayout>::LAYOUT, None)
5778 .pad_to_align();
5779
5780 assert_eq!(<KL10Align as KnownLayout>::LAYOUT, expected);
5781 assert_eq!(<KL10Align as KnownLayout>::LAYOUT, unsized_layout(64, 1, 4));
5782
5783 // ...with `packed`:
5784 #[allow(dead_code)]
5785 #[derive(KnownLayout)]
5786 #[repr(C, packed)]
5787 struct KL10Packed(NotKnownLayout<AU32>, [u8]);
5788
5789 let repr_packed = NonZeroUsize::new(1);
5790
5791 let expected = DstLayout::new_zst(None)
5792 .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), repr_packed)
5793 .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed)
5794 .pad_to_align();
5795
5796 assert_eq!(<KL10Packed as KnownLayout>::LAYOUT, expected);
5797 assert_eq!(<KL10Packed as KnownLayout>::LAYOUT, unsized_layout(1, 1, 4));
5798
5799 // ...with `packed(N)`:
5800 #[allow(dead_code)]
5801 #[derive(KnownLayout)]
5802 #[repr(C, packed(2))]
5803 struct KL10PackedN(NotKnownLayout<AU32>, [u8]);
5804
5805 let repr_packed = NonZeroUsize::new(2);
5806
5807 let expected = DstLayout::new_zst(None)
5808 .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), repr_packed)
5809 .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed)
5810 .pad_to_align();
5811
5812 assert_eq!(<KL10PackedN as KnownLayout>::LAYOUT, expected);
5813 assert_eq!(<KL10PackedN as KnownLayout>::LAYOUT, unsized_layout(2, 1, 4));
5814
5815 // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
5816 // | Y | N | Y | Y | KL11 |
5817 #[allow(dead_code)]
5818 #[derive(KnownLayout)]
5819 #[repr(C)]
5820 struct KL11(NotKnownLayout<AU64>, u8);
5821
5822 let expected = DstLayout::new_zst(None)
5823 .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), None)
5824 .extend(<u8 as KnownLayout>::LAYOUT, None)
5825 .pad_to_align();
5826
5827 assert_eq!(<KL11 as KnownLayout>::LAYOUT, expected);
5828 assert_eq!(<KL11 as KnownLayout>::LAYOUT, sized_layout(8, 16));
5829
5830 // ...with `align(N)`:
5831 #[allow(dead_code)]
5832 #[derive(KnownLayout)]
5833 #[repr(C, align(64))]
5834 struct KL11Align(NotKnownLayout<AU64>, u8);
5835
5836 let repr_align = NonZeroUsize::new(64);
5837
5838 let expected = DstLayout::new_zst(repr_align)
5839 .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), None)
5840 .extend(<u8 as KnownLayout>::LAYOUT, None)
5841 .pad_to_align();
5842
5843 assert_eq!(<KL11Align as KnownLayout>::LAYOUT, expected);
5844 assert_eq!(<KL11Align as KnownLayout>::LAYOUT, sized_layout(64, 64));
5845
5846 // ...with `packed`:
5847 #[allow(dead_code)]
5848 #[derive(KnownLayout)]
5849 #[repr(C, packed)]
5850 struct KL11Packed(NotKnownLayout<AU64>, u8);
5851
5852 let repr_packed = NonZeroUsize::new(1);
5853
5854 let expected = DstLayout::new_zst(None)
5855 .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), repr_packed)
5856 .extend(<u8 as KnownLayout>::LAYOUT, repr_packed)
5857 .pad_to_align();
5858
5859 assert_eq!(<KL11Packed as KnownLayout>::LAYOUT, expected);
5860 assert_eq!(<KL11Packed as KnownLayout>::LAYOUT, sized_layout(1, 9));
5861
5862 // ...with `packed(N)`:
5863 #[allow(dead_code)]
5864 #[derive(KnownLayout)]
5865 #[repr(C, packed(2))]
5866 struct KL11PackedN(NotKnownLayout<AU64>, u8);
5867
5868 let repr_packed = NonZeroUsize::new(2);
5869
5870 let expected = DstLayout::new_zst(None)
5871 .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), repr_packed)
5872 .extend(<u8 as KnownLayout>::LAYOUT, repr_packed)
5873 .pad_to_align();
5874
5875 assert_eq!(<KL11PackedN as KnownLayout>::LAYOUT, expected);
5876 assert_eq!(<KL11PackedN as KnownLayout>::LAYOUT, sized_layout(2, 10));
5877
5878 // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
5879 // | Y | Y | Y | N | KL14 |
5880 #[allow(dead_code)]
5881 #[derive(KnownLayout)]
5882 #[repr(C)]
5883 struct KL14<T: ?Sized + KnownLayout>(u8, T);
5884
5885 fn _test_kl14<T: ?Sized + KnownLayout>(kl: &KL14<T>) {
5886 _assert_kl(kl)
5887 }
5888
5889 // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
5890 // | Y | Y | Y | Y | KL15 |
5891 #[allow(dead_code)]
5892 #[derive(KnownLayout)]
5893 #[repr(C)]
5894 struct KL15<T: KnownLayout>(u8, T);
5895
5896 fn _test_kl15<T: KnownLayout>(t: T) -> impl KnownLayout {
5897 let _ = KL15(0u8, t);
5898 }
5899
5900 // Test a variety of combinations of field types:
5901 // - ()
5902 // - u8
5903 // - AU16
5904 // - [()]
5905 // - [u8]
5906 // - [AU16]
5907
5908 #[allow(clippy::upper_case_acronyms, dead_code)]
5909 #[derive(KnownLayout)]
5910 #[repr(C)]
5911 struct KLTU<T, U: ?Sized>(T, U);
5912
5913 assert_eq!(<KLTU<(), ()> as KnownLayout>::LAYOUT, sized_layout(1, 0));
5914
5915 assert_eq!(<KLTU<(), u8> as KnownLayout>::LAYOUT, sized_layout(1, 1));
5916
5917 assert_eq!(<KLTU<(), AU16> as KnownLayout>::LAYOUT, sized_layout(2, 2));
5918
5919 assert_eq!(<KLTU<(), [()]> as KnownLayout>::LAYOUT, unsized_layout(1, 0, 0));
5920
5921 assert_eq!(<KLTU<(), [u8]> as KnownLayout>::LAYOUT, unsized_layout(1, 1, 0));
5922
5923 assert_eq!(<KLTU<(), [AU16]> as KnownLayout>::LAYOUT, unsized_layout(2, 2, 0));
5924
5925 assert_eq!(<KLTU<u8, ()> as KnownLayout>::LAYOUT, sized_layout(1, 1));
5926
5927 assert_eq!(<KLTU<u8, u8> as KnownLayout>::LAYOUT, sized_layout(1, 2));
5928
5929 assert_eq!(<KLTU<u8, AU16> as KnownLayout>::LAYOUT, sized_layout(2, 4));
5930
5931 assert_eq!(<KLTU<u8, [()]> as KnownLayout>::LAYOUT, unsized_layout(1, 0, 1));
5932
5933 assert_eq!(<KLTU<u8, [u8]> as KnownLayout>::LAYOUT, unsized_layout(1, 1, 1));
5934
5935 assert_eq!(<KLTU<u8, [AU16]> as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2));
5936
5937 assert_eq!(<KLTU<AU16, ()> as KnownLayout>::LAYOUT, sized_layout(2, 2));
5938
5939 assert_eq!(<KLTU<AU16, u8> as KnownLayout>::LAYOUT, sized_layout(2, 4));
5940
5941 assert_eq!(<KLTU<AU16, AU16> as KnownLayout>::LAYOUT, sized_layout(2, 4));
5942
5943 assert_eq!(<KLTU<AU16, [()]> as KnownLayout>::LAYOUT, unsized_layout(2, 0, 2));
5944
5945 assert_eq!(<KLTU<AU16, [u8]> as KnownLayout>::LAYOUT, unsized_layout(2, 1, 2));
5946
5947 assert_eq!(<KLTU<AU16, [AU16]> as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2));
5948
5949 // Test a variety of field counts.
5950
5951 #[derive(KnownLayout)]
5952 #[repr(C)]
5953 struct KLF0;
5954
5955 assert_eq!(<KLF0 as KnownLayout>::LAYOUT, sized_layout(1, 0));
5956
5957 #[derive(KnownLayout)]
5958 #[repr(C)]
5959 struct KLF1([u8]);
5960
5961 assert_eq!(<KLF1 as KnownLayout>::LAYOUT, unsized_layout(1, 1, 0));
5962
5963 #[derive(KnownLayout)]
5964 #[repr(C)]
5965 struct KLF2(NotKnownLayout<u8>, [u8]);
5966
5967 assert_eq!(<KLF2 as KnownLayout>::LAYOUT, unsized_layout(1, 1, 1));
5968
5969 #[derive(KnownLayout)]
5970 #[repr(C)]
5971 struct KLF3(NotKnownLayout<u8>, NotKnownLayout<AU16>, [u8]);
5972
5973 assert_eq!(<KLF3 as KnownLayout>::LAYOUT, unsized_layout(2, 1, 4));
5974
5975 #[derive(KnownLayout)]
5976 #[repr(C)]
5977 struct KLF4(NotKnownLayout<u8>, NotKnownLayout<AU16>, NotKnownLayout<AU32>, [u8]);
5978
5979 assert_eq!(<KLF4 as KnownLayout>::LAYOUT, unsized_layout(4, 1, 8));
5980 }
5981
5982 #[test]
5983 fn test_object_safety() {
5984 fn _takes_no_cell(_: &dyn Immutable) {}
5985 fn _takes_unaligned(_: &dyn Unaligned) {}
5986 }
5987
5988 #[test]
5989 fn test_from_zeros_only() {
5990 // Test types that implement `FromZeros` but not `FromBytes`.
5991
5992 assert!(!bool::new_zeroed());
5993 assert_eq!(char::new_zeroed(), '\0');
5994
5995 #[cfg(feature = "alloc")]
5996 {
5997 assert_eq!(bool::new_box_zeroed(), Ok(Box::new(false)));
5998 assert_eq!(char::new_box_zeroed(), Ok(Box::new('\0')));
5999
6000 assert_eq!(
6001 <[bool]>::new_box_zeroed_with_elems(3).unwrap().as_ref(),
6002 [false, false, false]
6003 );
6004 assert_eq!(
6005 <[char]>::new_box_zeroed_with_elems(3).unwrap().as_ref(),
6006 ['\0', '\0', '\0']
6007 );
6008
6009 assert_eq!(bool::new_vec_zeroed(3).unwrap().as_ref(), [false, false, false]);
6010 assert_eq!(char::new_vec_zeroed(3).unwrap().as_ref(), ['\0', '\0', '\0']);
6011 }
6012
6013 let mut string = "hello".to_string();
6014 let s: &mut str = string.as_mut();
6015 assert_eq!(s, "hello");
6016 s.zero();
6017 assert_eq!(s, "\0\0\0\0\0");
6018 }
6019
6020 #[test]
6021 fn test_zst_count_preserved() {
6022 // Test that, when an explicit count is provided to for a type with a
6023 // ZST trailing slice element, that count is preserved. This is
6024 // important since, for such types, all element counts result in objects
6025 // of the same size, and so the correct behavior is ambiguous. However,
6026 // preserving the count as requested by the user is the behavior that we
6027 // document publicly.
6028
6029 // FromZeros methods
6030 #[cfg(feature = "alloc")]
6031 assert_eq!(<[()]>::new_box_zeroed_with_elems(3).unwrap().len(), 3);
6032 #[cfg(feature = "alloc")]
6033 assert_eq!(<()>::new_vec_zeroed(3).unwrap().len(), 3);
6034
6035 // FromBytes methods
6036 assert_eq!(<[()]>::ref_from_bytes_with_elems(&[][..], 3).unwrap().len(), 3);
6037 assert_eq!(<[()]>::ref_from_prefix_with_elems(&[][..], 3).unwrap().0.len(), 3);
6038 assert_eq!(<[()]>::ref_from_suffix_with_elems(&[][..], 3).unwrap().1.len(), 3);
6039 assert_eq!(<[()]>::mut_from_bytes_with_elems(&mut [][..], 3).unwrap().len(), 3);
6040 assert_eq!(<[()]>::mut_from_prefix_with_elems(&mut [][..], 3).unwrap().0.len(), 3);
6041 assert_eq!(<[()]>::mut_from_suffix_with_elems(&mut [][..], 3).unwrap().1.len(), 3);
6042 }
6043
6044 #[test]
6045 fn test_read_write() {
6046 const VAL: u64 = 0x12345678;
6047 #[cfg(target_endian = "big")]
6048 const VAL_BYTES: [u8; 8] = VAL.to_be_bytes();
6049 #[cfg(target_endian = "little")]
6050 const VAL_BYTES: [u8; 8] = VAL.to_le_bytes();
6051 const ZEROS: [u8; 8] = [0u8; 8];
6052
6053 // Test `FromBytes::{read_from, read_from_prefix, read_from_suffix}`.
6054
6055 assert_eq!(u64::read_from_bytes(&VAL_BYTES[..]), Ok(VAL));
6056 // The first 8 bytes are from `VAL_BYTES` and the second 8 bytes are all
6057 // zeros.
6058 let bytes_with_prefix: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]);
6059 assert_eq!(u64::read_from_prefix(&bytes_with_prefix[..]), Ok((VAL, &ZEROS[..])));
6060 assert_eq!(u64::read_from_suffix(&bytes_with_prefix[..]), Ok((&VAL_BYTES[..], 0)));
6061 // The first 8 bytes are all zeros and the second 8 bytes are from
6062 // `VAL_BYTES`
6063 let bytes_with_suffix: [u8; 16] = transmute!([[0; 8], VAL_BYTES]);
6064 assert_eq!(u64::read_from_prefix(&bytes_with_suffix[..]), Ok((0, &VAL_BYTES[..])));
6065 assert_eq!(u64::read_from_suffix(&bytes_with_suffix[..]), Ok((&ZEROS[..], VAL)));
6066
6067 // Test `IntoBytes::{write_to, write_to_prefix, write_to_suffix}`.
6068
6069 let mut bytes = [0u8; 8];
6070 assert_eq!(VAL.write_to(&mut bytes[..]), Ok(()));
6071 assert_eq!(bytes, VAL_BYTES);
6072 let mut bytes = [0u8; 16];
6073 assert_eq!(VAL.write_to_prefix(&mut bytes[..]), Ok(()));
6074 let want: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]);
6075 assert_eq!(bytes, want);
6076 let mut bytes = [0u8; 16];
6077 assert_eq!(VAL.write_to_suffix(&mut bytes[..]), Ok(()));
6078 let want: [u8; 16] = transmute!([[0; 8], VAL_BYTES]);
6079 assert_eq!(bytes, want);
6080 }
6081
6082 #[test]
6083 #[cfg(feature = "std")]
6084 fn test_read_write_io() {
6085 let mut long_buffer = [0, 0, 0, 0];
6086 assert!(matches!(u16::MAX.write_to_io(&mut long_buffer[..]), Ok(())));
6087 assert_eq!(long_buffer, [255, 255, 0, 0]);
6088 assert!(matches!(u16::read_from_io(&long_buffer[..]), Ok(u16::MAX)));
6089
6090 let mut short_buffer = [0, 0];
6091 assert!(u32::MAX.write_to_io(&mut short_buffer[..]).is_err());
6092 assert_eq!(short_buffer, [255, 255]);
6093 assert!(u32::read_from_io(&short_buffer[..]).is_err());
6094 }
6095
6096 #[test]
6097 fn test_try_from_bytes_try_read_from() {
6098 assert_eq!(<bool as TryFromBytes>::try_read_from_bytes(&[0]), Ok(false));
6099 assert_eq!(<bool as TryFromBytes>::try_read_from_bytes(&[1]), Ok(true));
6100
6101 assert_eq!(<bool as TryFromBytes>::try_read_from_prefix(&[0, 2]), Ok((false, &[2][..])));
6102 assert_eq!(<bool as TryFromBytes>::try_read_from_prefix(&[1, 2]), Ok((true, &[2][..])));
6103
6104 assert_eq!(<bool as TryFromBytes>::try_read_from_suffix(&[2, 0]), Ok((&[2][..], false)));
6105 assert_eq!(<bool as TryFromBytes>::try_read_from_suffix(&[2, 1]), Ok((&[2][..], true)));
6106
6107 // If we don't pass enough bytes, it fails.
6108 assert!(matches!(
6109 <u8 as TryFromBytes>::try_read_from_bytes(&[]),
6110 Err(TryReadError::Size(_))
6111 ));
6112 assert!(matches!(
6113 <u8 as TryFromBytes>::try_read_from_prefix(&[]),
6114 Err(TryReadError::Size(_))
6115 ));
6116 assert!(matches!(
6117 <u8 as TryFromBytes>::try_read_from_suffix(&[]),
6118 Err(TryReadError::Size(_))
6119 ));
6120
6121 // If we pass too many bytes, it fails.
6122 assert!(matches!(
6123 <u8 as TryFromBytes>::try_read_from_bytes(&[0, 0]),
6124 Err(TryReadError::Size(_))
6125 ));
6126
6127 // If we pass an invalid value, it fails.
6128 assert!(matches!(
6129 <bool as TryFromBytes>::try_read_from_bytes(&[2]),
6130 Err(TryReadError::Validity(_))
6131 ));
6132 assert!(matches!(
6133 <bool as TryFromBytes>::try_read_from_prefix(&[2, 0]),
6134 Err(TryReadError::Validity(_))
6135 ));
6136 assert!(matches!(
6137 <bool as TryFromBytes>::try_read_from_suffix(&[0, 2]),
6138 Err(TryReadError::Validity(_))
6139 ));
6140
6141 // Reading from a misaligned buffer should still succeed. Since `AU64`'s
6142 // alignment is 8, and since we read from two adjacent addresses one
6143 // byte apart, it is guaranteed that at least one of them (though
6144 // possibly both) will be misaligned.
6145 let bytes: [u8; 9] = [0, 0, 0, 0, 0, 0, 0, 0, 0];
6146 assert_eq!(<AU64 as TryFromBytes>::try_read_from_bytes(&bytes[..8]), Ok(AU64(0)));
6147 assert_eq!(<AU64 as TryFromBytes>::try_read_from_bytes(&bytes[1..9]), Ok(AU64(0)));
6148
6149 assert_eq!(
6150 <AU64 as TryFromBytes>::try_read_from_prefix(&bytes[..8]),
6151 Ok((AU64(0), &[][..]))
6152 );
6153 assert_eq!(
6154 <AU64 as TryFromBytes>::try_read_from_prefix(&bytes[1..9]),
6155 Ok((AU64(0), &[][..]))
6156 );
6157
6158 assert_eq!(
6159 <AU64 as TryFromBytes>::try_read_from_suffix(&bytes[..8]),
6160 Ok((&[][..], AU64(0)))
6161 );
6162 assert_eq!(
6163 <AU64 as TryFromBytes>::try_read_from_suffix(&bytes[1..9]),
6164 Ok((&[][..], AU64(0)))
6165 );
6166 }
6167
6168 #[test]
6169 fn test_ref_from_mut_from() {
6170 // Test `FromBytes::{ref_from, mut_from}{,_prefix,Suffix}` success cases
6171 // Exhaustive coverage for these methods is covered by the `Ref` tests above,
6172 // which these helper methods defer to.
6173
6174 let mut buf =
6175 Align::<[u8; 16], AU64>::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
6176
6177 assert_eq!(
6178 AU64::ref_from_bytes(&buf.t[8..]).unwrap().0.to_ne_bytes(),
6179 [8, 9, 10, 11, 12, 13, 14, 15]
6180 );
6181 let suffix = AU64::mut_from_bytes(&mut buf.t[8..]).unwrap();
6182 suffix.0 = 0x0101010101010101;
6183 // The `[u8:9]` is a non-half size of the full buffer, which would catch
6184 // `from_prefix` having the same implementation as `from_suffix` (issues #506, #511).
6185 assert_eq!(
6186 <[u8; 9]>::ref_from_suffix(&buf.t[..]).unwrap(),
6187 (&[0, 1, 2, 3, 4, 5, 6][..], &[7u8, 1, 1, 1, 1, 1, 1, 1, 1])
6188 );
6189 let (prefix, suffix) = AU64::mut_from_suffix(&mut buf.t[1..]).unwrap();
6190 assert_eq!(prefix, &mut [1u8, 2, 3, 4, 5, 6, 7][..]);
6191 suffix.0 = 0x0202020202020202;
6192 let (prefix, suffix) = <[u8; 10]>::mut_from_suffix(&mut buf.t[..]).unwrap();
6193 assert_eq!(prefix, &mut [0u8, 1, 2, 3, 4, 5][..]);
6194 suffix[0] = 42;
6195 assert_eq!(
6196 <[u8; 9]>::ref_from_prefix(&buf.t[..]).unwrap(),
6197 (&[0u8, 1, 2, 3, 4, 5, 42, 7, 2], &[2u8, 2, 2, 2, 2, 2, 2][..])
6198 );
6199 <[u8; 2]>::mut_from_prefix(&mut buf.t[..]).unwrap().0[1] = 30;
6200 assert_eq!(buf.t, [0, 30, 2, 3, 4, 5, 42, 7, 2, 2, 2, 2, 2, 2, 2, 2]);
6201 }
6202
6203 #[test]
6204 fn test_ref_from_mut_from_error() {
6205 // Test `FromBytes::{ref_from, mut_from}{,_prefix,Suffix}` error cases.
6206
6207 // Fail because the buffer is too large.
6208 let mut buf = Align::<[u8; 16], AU64>::default();
6209 // `buf.t` should be aligned to 8, so only the length check should fail.
6210 assert!(AU64::ref_from_bytes(&buf.t[..]).is_err());
6211 assert!(AU64::mut_from_bytes(&mut buf.t[..]).is_err());
6212 assert!(<[u8; 8]>::ref_from_bytes(&buf.t[..]).is_err());
6213 assert!(<[u8; 8]>::mut_from_bytes(&mut buf.t[..]).is_err());
6214
6215 // Fail because the buffer is too small.
6216 let mut buf = Align::<[u8; 4], AU64>::default();
6217 assert!(AU64::ref_from_bytes(&buf.t[..]).is_err());
6218 assert!(AU64::mut_from_bytes(&mut buf.t[..]).is_err());
6219 assert!(<[u8; 8]>::ref_from_bytes(&buf.t[..]).is_err());
6220 assert!(<[u8; 8]>::mut_from_bytes(&mut buf.t[..]).is_err());
6221 assert!(AU64::ref_from_prefix(&buf.t[..]).is_err());
6222 assert!(AU64::mut_from_prefix(&mut buf.t[..]).is_err());
6223 assert!(AU64::ref_from_suffix(&buf.t[..]).is_err());
6224 assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_err());
6225 assert!(<[u8; 8]>::ref_from_prefix(&buf.t[..]).is_err());
6226 assert!(<[u8; 8]>::mut_from_prefix(&mut buf.t[..]).is_err());
6227 assert!(<[u8; 8]>::ref_from_suffix(&buf.t[..]).is_err());
6228 assert!(<[u8; 8]>::mut_from_suffix(&mut buf.t[..]).is_err());
6229
6230 // Fail because the alignment is insufficient.
6231 let mut buf = Align::<[u8; 13], AU64>::default();
6232 assert!(AU64::ref_from_bytes(&buf.t[1..]).is_err());
6233 assert!(AU64::mut_from_bytes(&mut buf.t[1..]).is_err());
6234 assert!(AU64::ref_from_bytes(&buf.t[1..]).is_err());
6235 assert!(AU64::mut_from_bytes(&mut buf.t[1..]).is_err());
6236 assert!(AU64::ref_from_prefix(&buf.t[1..]).is_err());
6237 assert!(AU64::mut_from_prefix(&mut buf.t[1..]).is_err());
6238 assert!(AU64::ref_from_suffix(&buf.t[..]).is_err());
6239 assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_err());
6240 }
6241
6242 #[test]
6243 fn test_to_methods() {
6244 /// Run a series of tests by calling `IntoBytes` methods on `t`.
6245 ///
6246 /// `bytes` is the expected byte sequence returned from `t.as_bytes()`
6247 /// before `t` has been modified. `post_mutation` is the expected
6248 /// sequence returned from `t.as_bytes()` after `t.as_mut_bytes()[0]`
6249 /// has had its bits flipped (by applying `^= 0xFF`).
6250 ///
6251 /// `N` is the size of `t` in bytes.
6252 fn test<T: FromBytes + IntoBytes + Immutable + Debug + Eq + ?Sized, const N: usize>(
6253 t: &mut T,
6254 bytes: &[u8],
6255 post_mutation: &T,
6256 ) {
6257 // Test that we can access the underlying bytes, and that we get the
6258 // right bytes and the right number of bytes.
6259 assert_eq!(t.as_bytes(), bytes);
6260
6261 // Test that changes to the underlying byte slices are reflected in
6262 // the original object.
6263 t.as_mut_bytes()[0] ^= 0xFF;
6264 assert_eq!(t, post_mutation);
6265 t.as_mut_bytes()[0] ^= 0xFF;
6266
6267 // `write_to` rejects slices that are too small or too large.
6268 assert!(t.write_to(&mut vec![0; N - 1][..]).is_err());
6269 assert!(t.write_to(&mut vec![0; N + 1][..]).is_err());
6270
6271 // `write_to` works as expected.
6272 let mut bytes = [0; N];
6273 assert_eq!(t.write_to(&mut bytes[..]), Ok(()));
6274 assert_eq!(bytes, t.as_bytes());
6275
6276 // `write_to_prefix` rejects slices that are too small.
6277 assert!(t.write_to_prefix(&mut vec![0; N - 1][..]).is_err());
6278
6279 // `write_to_prefix` works with exact-sized slices.
6280 let mut bytes = [0; N];
6281 assert_eq!(t.write_to_prefix(&mut bytes[..]), Ok(()));
6282 assert_eq!(bytes, t.as_bytes());
6283
6284 // `write_to_prefix` works with too-large slices, and any bytes past
6285 // the prefix aren't modified.
6286 let mut too_many_bytes = vec![0; N + 1];
6287 too_many_bytes[N] = 123;
6288 assert_eq!(t.write_to_prefix(&mut too_many_bytes[..]), Ok(()));
6289 assert_eq!(&too_many_bytes[..N], t.as_bytes());
6290 assert_eq!(too_many_bytes[N], 123);
6291
6292 // `write_to_suffix` rejects slices that are too small.
6293 assert!(t.write_to_suffix(&mut vec![0; N - 1][..]).is_err());
6294
6295 // `write_to_suffix` works with exact-sized slices.
6296 let mut bytes = [0; N];
6297 assert_eq!(t.write_to_suffix(&mut bytes[..]), Ok(()));
6298 assert_eq!(bytes, t.as_bytes());
6299
6300 // `write_to_suffix` works with too-large slices, and any bytes
6301 // before the suffix aren't modified.
6302 let mut too_many_bytes = vec![0; N + 1];
6303 too_many_bytes[0] = 123;
6304 assert_eq!(t.write_to_suffix(&mut too_many_bytes[..]), Ok(()));
6305 assert_eq!(&too_many_bytes[1..], t.as_bytes());
6306 assert_eq!(too_many_bytes[0], 123);
6307 }
6308
6309 #[derive(Debug, Eq, PartialEq, FromBytes, IntoBytes, Immutable)]
6310 #[repr(C)]
6311 struct Foo {
6312 a: u32,
6313 b: Wrapping<u32>,
6314 c: Option<NonZeroU32>,
6315 }
6316
6317 let expected_bytes: Vec<u8> = if cfg!(target_endian = "little") {
6318 vec![1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]
6319 } else {
6320 vec![0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0]
6321 };
6322 let post_mutation_expected_a =
6323 if cfg!(target_endian = "little") { 0x00_00_00_FE } else { 0xFF_00_00_01 };
6324 test::<_, 12>(
6325 &mut Foo { a: 1, b: Wrapping(2), c: None },
6326 expected_bytes.as_bytes(),
6327 &Foo { a: post_mutation_expected_a, b: Wrapping(2), c: None },
6328 );
6329 test::<_, 3>(
6330 Unsized::from_mut_slice(&mut [1, 2, 3]),
6331 &[1, 2, 3],
6332 Unsized::from_mut_slice(&mut [0xFE, 2, 3]),
6333 );
6334 }
6335
6336 #[test]
6337 fn test_array() {
6338 #[derive(FromBytes, IntoBytes, Immutable)]
6339 #[repr(C)]
6340 struct Foo {
6341 a: [u16; 33],
6342 }
6343
6344 let foo = Foo { a: [0xFFFF; 33] };
6345 let expected = [0xFFu8; 66];
6346 assert_eq!(foo.as_bytes(), &expected[..]);
6347 }
6348
6349 #[test]
6350 fn test_new_zeroed() {
6351 assert!(!bool::new_zeroed());
6352 assert_eq!(u64::new_zeroed(), 0);
6353 // This test exists in order to exercise unsafe code, especially when
6354 // running under Miri.
6355 #[allow(clippy::unit_cmp)]
6356 {
6357 assert_eq!(<()>::new_zeroed(), ());
6358 }
6359 }
6360
6361 #[test]
6362 fn test_transparent_packed_generic_struct() {
6363 #[derive(IntoBytes, FromBytes, Unaligned)]
6364 #[repr(transparent)]
6365 #[allow(dead_code)] // We never construct this type
6366 struct Foo<T> {
6367 _t: T,
6368 _phantom: PhantomData<()>,
6369 }
6370
6371 assert_impl_all!(Foo<u32>: FromZeros, FromBytes, IntoBytes);
6372 assert_impl_all!(Foo<u8>: Unaligned);
6373
6374 #[derive(IntoBytes, FromBytes, Unaligned)]
6375 #[repr(C, packed)]
6376 #[allow(dead_code)] // We never construct this type
6377 struct Bar<T, U> {
6378 _t: T,
6379 _u: U,
6380 }
6381
6382 assert_impl_all!(Bar<u8, AU64>: FromZeros, FromBytes, IntoBytes, Unaligned);
6383 }
6384
6385 #[cfg(feature = "alloc")]
6386 mod alloc {
6387 use super::*;
6388
6389 #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
6390 #[test]
6391 fn test_extend_vec_zeroed() {
6392 // Test extending when there is an existing allocation.
6393 let mut v = vec![100u16, 200, 300];
6394 FromZeros::extend_vec_zeroed(&mut v, 3).unwrap();
6395 assert_eq!(v.len(), 6);
6396 assert_eq!(&*v, &[100, 200, 300, 0, 0, 0]);
6397 drop(v);
6398
6399 // Test extending when there is no existing allocation.
6400 let mut v: Vec<u64> = Vec::new();
6401 FromZeros::extend_vec_zeroed(&mut v, 3).unwrap();
6402 assert_eq!(v.len(), 3);
6403 assert_eq!(&*v, &[0, 0, 0]);
6404 drop(v);
6405 }
6406
6407 #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
6408 #[test]
6409 fn test_extend_vec_zeroed_zst() {
6410 // Test extending when there is an existing (fake) allocation.
6411 let mut v = vec![(), (), ()];
6412 <()>::extend_vec_zeroed(&mut v, 3).unwrap();
6413 assert_eq!(v.len(), 6);
6414 assert_eq!(&*v, &[(), (), (), (), (), ()]);
6415 drop(v);
6416
6417 // Test extending when there is no existing (fake) allocation.
6418 let mut v: Vec<()> = Vec::new();
6419 <()>::extend_vec_zeroed(&mut v, 3).unwrap();
6420 assert_eq!(&*v, &[(), (), ()]);
6421 drop(v);
6422 }
6423
6424 #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
6425 #[test]
6426 fn test_insert_vec_zeroed() {
6427 // Insert at start (no existing allocation).
6428 let mut v: Vec<u64> = Vec::new();
6429 u64::insert_vec_zeroed(&mut v, 0, 2).unwrap();
6430 assert_eq!(v.len(), 2);
6431 assert_eq!(&*v, &[0, 0]);
6432 drop(v);
6433
6434 // Insert at start.
6435 let mut v = vec![100u64, 200, 300];
6436 u64::insert_vec_zeroed(&mut v, 0, 2).unwrap();
6437 assert_eq!(v.len(), 5);
6438 assert_eq!(&*v, &[0, 0, 100, 200, 300]);
6439 drop(v);
6440
6441 // Insert at middle.
6442 let mut v = vec![100u64, 200, 300];
6443 u64::insert_vec_zeroed(&mut v, 1, 1).unwrap();
6444 assert_eq!(v.len(), 4);
6445 assert_eq!(&*v, &[100, 0, 200, 300]);
6446 drop(v);
6447
6448 // Insert at end.
6449 let mut v = vec![100u64, 200, 300];
6450 u64::insert_vec_zeroed(&mut v, 3, 1).unwrap();
6451 assert_eq!(v.len(), 4);
6452 assert_eq!(&*v, &[100, 200, 300, 0]);
6453 drop(v);
6454 }
6455
6456 #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
6457 #[test]
6458 fn test_insert_vec_zeroed_zst() {
6459 // Insert at start (no existing fake allocation).
6460 let mut v: Vec<()> = Vec::new();
6461 <()>::insert_vec_zeroed(&mut v, 0, 2).unwrap();
6462 assert_eq!(v.len(), 2);
6463 assert_eq!(&*v, &[(), ()]);
6464 drop(v);
6465
6466 // Insert at start.
6467 let mut v = vec![(), (), ()];
6468 <()>::insert_vec_zeroed(&mut v, 0, 2).unwrap();
6469 assert_eq!(v.len(), 5);
6470 assert_eq!(&*v, &[(), (), (), (), ()]);
6471 drop(v);
6472
6473 // Insert at middle.
6474 let mut v = vec![(), (), ()];
6475 <()>::insert_vec_zeroed(&mut v, 1, 1).unwrap();
6476 assert_eq!(v.len(), 4);
6477 assert_eq!(&*v, &[(), (), (), ()]);
6478 drop(v);
6479
6480 // Insert at end.
6481 let mut v = vec![(), (), ()];
6482 <()>::insert_vec_zeroed(&mut v, 3, 1).unwrap();
6483 assert_eq!(v.len(), 4);
6484 assert_eq!(&*v, &[(), (), (), ()]);
6485 drop(v);
6486 }
6487
6488 #[test]
6489 fn test_new_box_zeroed() {
6490 assert_eq!(u64::new_box_zeroed(), Ok(Box::new(0)));
6491 }
6492
6493 #[test]
6494 fn test_new_box_zeroed_array() {
6495 drop(<[u32; 0x1000]>::new_box_zeroed());
6496 }
6497
6498 #[test]
6499 fn test_new_box_zeroed_zst() {
6500 // This test exists in order to exercise unsafe code, especially
6501 // when running under Miri.
6502 #[allow(clippy::unit_cmp)]
6503 {
6504 assert_eq!(<()>::new_box_zeroed(), Ok(Box::new(())));
6505 }
6506 }
6507
6508 #[test]
6509 fn test_new_box_zeroed_with_elems() {
6510 let mut s: Box<[u64]> = <[u64]>::new_box_zeroed_with_elems(3).unwrap();
6511 assert_eq!(s.len(), 3);
6512 assert_eq!(&*s, &[0, 0, 0]);
6513 s[1] = 3;
6514 assert_eq!(&*s, &[0, 3, 0]);
6515 }
6516
6517 #[test]
6518 fn test_new_box_zeroed_with_elems_empty() {
6519 let s: Box<[u64]> = <[u64]>::new_box_zeroed_with_elems(0).unwrap();
6520 assert_eq!(s.len(), 0);
6521 }
6522
6523 #[test]
6524 fn test_new_box_zeroed_with_elems_zst() {
6525 let mut s: Box<[()]> = <[()]>::new_box_zeroed_with_elems(3).unwrap();
6526 assert_eq!(s.len(), 3);
6527 assert!(s.get(10).is_none());
6528 // This test exists in order to exercise unsafe code, especially
6529 // when running under Miri.
6530 #[allow(clippy::unit_cmp)]
6531 {
6532 assert_eq!(s[1], ());
6533 }
6534 s[2] = ();
6535 }
6536
6537 #[test]
6538 fn test_new_box_zeroed_with_elems_zst_empty() {
6539 let s: Box<[()]> = <[()]>::new_box_zeroed_with_elems(0).unwrap();
6540 assert_eq!(s.len(), 0);
6541 }
6542
6543 #[test]
6544 fn new_box_zeroed_with_elems_errors() {
6545 assert_eq!(<[u16]>::new_box_zeroed_with_elems(usize::MAX), Err(AllocError));
6546
6547 let max = <usize as core::convert::TryFrom<_>>::try_from(isize::MAX).unwrap();
6548 assert_eq!(
6549 <[u16]>::new_box_zeroed_with_elems((max / mem::size_of::<u16>()) + 1),
6550 Err(AllocError)
6551 );
6552 }
6553 }
6554}
6555
6556#[cfg(kani)]
6557mod proofs {
6558 use super::*;
6559
6560 impl kani::Arbitrary for DstLayout {
6561 fn any() -> Self {
6562 let align: NonZeroUsize = kani::any();
6563 let size_info: SizeInfo = kani::any();
6564
6565 kani::assume(align.is_power_of_two());
6566 kani::assume(align < DstLayout::THEORETICAL_MAX_ALIGN);
6567
6568 // For testing purposes, we most care about instantiations of
6569 // `DstLayout` that can correspond to actual Rust types. We use
6570 // `Layout` to verify that our `DstLayout` satisfies the validity
6571 // conditions of Rust layouts.
6572 kani::assume(
6573 match size_info {
6574 SizeInfo::Sized { size } => Layout::from_size_align(size, align.get()),
6575 SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size: _ }) => {
6576 // `SliceDst`` cannot encode an exact size, but we know
6577 // it is at least `offset` bytes.
6578 Layout::from_size_align(offset, align.get())
6579 }
6580 }
6581 .is_ok(),
6582 );
6583
6584 Self { align: align, size_info: size_info }
6585 }
6586 }
6587
6588 impl kani::Arbitrary for SizeInfo {
6589 fn any() -> Self {
6590 let is_sized: bool = kani::any();
6591
6592 match is_sized {
6593 true => {
6594 let size: usize = kani::any();
6595
6596 kani::assume(size <= isize::MAX as _);
6597
6598 SizeInfo::Sized { size }
6599 }
6600 false => SizeInfo::SliceDst(kani::any()),
6601 }
6602 }
6603 }
6604
6605 impl kani::Arbitrary for TrailingSliceLayout {
6606 fn any() -> Self {
6607 let elem_size: usize = kani::any();
6608 let offset: usize = kani::any();
6609
6610 kani::assume(elem_size < isize::MAX as _);
6611 kani::assume(offset < isize::MAX as _);
6612
6613 TrailingSliceLayout { elem_size, offset }
6614 }
6615 }
6616
6617 #[kani::proof]
6618 fn prove_dst_layout_extend() {
6619 use crate::util::{max, min, padding_needed_for};
6620
6621 let base: DstLayout = kani::any();
6622 let field: DstLayout = kani::any();
6623 let packed: Option<NonZeroUsize> = kani::any();
6624
6625 if let Some(max_align) = packed {
6626 kani::assume(max_align.is_power_of_two());
6627 kani::assume(base.align <= max_align);
6628 }
6629
6630 // The base can only be extended if it's sized.
6631 kani::assume(matches!(base.size_info, SizeInfo::Sized { .. }));
6632 let base_size = if let SizeInfo::Sized { size } = base.size_info {
6633 size
6634 } else {
6635 unreachable!();
6636 };
6637
6638 // Under the above conditions, `DstLayout::extend` will not panic.
6639 let composite = base.extend(field, packed);
6640
6641 // The field's alignment is clamped by `max_align` (i.e., the
6642 // `packed` attribute, if any) [1].
6643 //
6644 // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers:
6645 //
6646 // The alignments of each field, for the purpose of positioning
6647 // fields, is the smaller of the specified alignment and the
6648 // alignment of the field's type.
6649 let field_align = min(field.align, packed.unwrap_or(DstLayout::THEORETICAL_MAX_ALIGN));
6650
6651 // The struct's alignment is the maximum of its previous alignment and
6652 // `field_align`.
6653 assert_eq!(composite.align, max(base.align, field_align));
6654
6655 // Compute the minimum amount of inter-field padding needed to
6656 // satisfy the field's alignment, and offset of the trailing field.
6657 // [1]
6658 //
6659 // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers:
6660 //
6661 // Inter-field padding is guaranteed to be the minimum required in
6662 // order to satisfy each field's (possibly altered) alignment.
6663 let padding = padding_needed_for(base_size, field_align);
6664 let offset = base_size + padding;
6665
6666 // For testing purposes, we'll also construct `alloc::Layout`
6667 // stand-ins for `DstLayout`, and show that `extend` behaves
6668 // comparably on both types.
6669 let base_analog = Layout::from_size_align(base_size, base.align.get()).unwrap();
6670
6671 match field.size_info {
6672 SizeInfo::Sized { size: field_size } => {
6673 if let SizeInfo::Sized { size: composite_size } = composite.size_info {
6674 // If the trailing field is sized, the resulting layout will
6675 // be sized. Its size will be the sum of the preceding
6676 // layout, the size of the new field, and the size of
6677 // inter-field padding between the two.
6678 assert_eq!(composite_size, offset + field_size);
6679
6680 let field_analog =
6681 Layout::from_size_align(field_size, field_align.get()).unwrap();
6682
6683 if let Ok((actual_composite, actual_offset)) = base_analog.extend(field_analog)
6684 {
6685 assert_eq!(actual_offset, offset);
6686 assert_eq!(actual_composite.size(), composite_size);
6687 assert_eq!(actual_composite.align(), composite.align.get());
6688 } else {
6689 // An error here reflects that composite of `base`
6690 // and `field` cannot correspond to a real Rust type
6691 // fragment, because such a fragment would violate
6692 // the basic invariants of a valid Rust layout. At
6693 // the time of writing, `DstLayout` is a little more
6694 // permissive than `Layout`, so we don't assert
6695 // anything in this branch (e.g., unreachability).
6696 }
6697 } else {
6698 panic!("The composite of two sized layouts must be sized.")
6699 }
6700 }
6701 SizeInfo::SliceDst(TrailingSliceLayout {
6702 offset: field_offset,
6703 elem_size: field_elem_size,
6704 }) => {
6705 if let SizeInfo::SliceDst(TrailingSliceLayout {
6706 offset: composite_offset,
6707 elem_size: composite_elem_size,
6708 }) = composite.size_info
6709 {
6710 // The offset of the trailing slice component is the sum
6711 // of the offset of the trailing field and the trailing
6712 // slice offset within that field.
6713 assert_eq!(composite_offset, offset + field_offset);
6714 // The elem size is unchanged.
6715 assert_eq!(composite_elem_size, field_elem_size);
6716
6717 let field_analog =
6718 Layout::from_size_align(field_offset, field_align.get()).unwrap();
6719
6720 if let Ok((actual_composite, actual_offset)) = base_analog.extend(field_analog)
6721 {
6722 assert_eq!(actual_offset, offset);
6723 assert_eq!(actual_composite.size(), composite_offset);
6724 assert_eq!(actual_composite.align(), composite.align.get());
6725 } else {
6726 // An error here reflects that composite of `base`
6727 // and `field` cannot correspond to a real Rust type
6728 // fragment, because such a fragment would violate
6729 // the basic invariants of a valid Rust layout. At
6730 // the time of writing, `DstLayout` is a little more
6731 // permissive than `Layout`, so we don't assert
6732 // anything in this branch (e.g., unreachability).
6733 }
6734 } else {
6735 panic!("The extension of a layout with a DST must result in a DST.")
6736 }
6737 }
6738 }
6739 }
6740
6741 #[kani::proof]
6742 #[kani::should_panic]
6743 fn prove_dst_layout_extend_dst_panics() {
6744 let base: DstLayout = kani::any();
6745 let field: DstLayout = kani::any();
6746 let packed: Option<NonZeroUsize> = kani::any();
6747
6748 if let Some(max_align) = packed {
6749 kani::assume(max_align.is_power_of_two());
6750 kani::assume(base.align <= max_align);
6751 }
6752
6753 kani::assume(matches!(base.size_info, SizeInfo::SliceDst(..)));
6754
6755 let _ = base.extend(field, packed);
6756 }
6757
6758 #[kani::proof]
6759 fn prove_dst_layout_pad_to_align() {
6760 use crate::util::padding_needed_for;
6761
6762 let layout: DstLayout = kani::any();
6763
6764 let padded: DstLayout = layout.pad_to_align();
6765
6766 // Calling `pad_to_align` does not alter the `DstLayout`'s alignment.
6767 assert_eq!(padded.align, layout.align);
6768
6769 if let SizeInfo::Sized { size: unpadded_size } = layout.size_info {
6770 if let SizeInfo::Sized { size: padded_size } = padded.size_info {
6771 // If the layout is sized, it will remain sized after padding is
6772 // added. Its sum will be its unpadded size and the size of the
6773 // trailing padding needed to satisfy its alignment
6774 // requirements.
6775 let padding = padding_needed_for(unpadded_size, layout.align);
6776 assert_eq!(padded_size, unpadded_size + padding);
6777
6778 // Prove that calling `DstLayout::pad_to_align` behaves
6779 // identically to `Layout::pad_to_align`.
6780 let layout_analog =
6781 Layout::from_size_align(unpadded_size, layout.align.get()).unwrap();
6782 let padded_analog = layout_analog.pad_to_align();
6783 assert_eq!(padded_analog.align(), layout.align.get());
6784 assert_eq!(padded_analog.size(), padded_size);
6785 } else {
6786 panic!("The padding of a sized layout must result in a sized layout.")
6787 }
6788 } else {
6789 // If the layout is a DST, padding cannot be statically added.
6790 assert_eq!(padded.size_info, layout.size_info);
6791 }
6792 }
6793}