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