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