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