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