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