xref: /linux/rust/zerocopy/src/lib.rs (revision c37398010a05055e78cf0c75defb90df06c4e999)
1*c3739801SMiguel Ojeda // Copyright 2018 The Fuchsia Authors
2*c3739801SMiguel Ojeda //
3*c3739801SMiguel Ojeda // Licensed under the 2-Clause BSD License <LICENSE-BSD or
4*c3739801SMiguel Ojeda // https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0
5*c3739801SMiguel Ojeda // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
6*c3739801SMiguel Ojeda // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
7*c3739801SMiguel Ojeda // This file may not be copied, modified, or distributed except according to
8*c3739801SMiguel Ojeda // those terms.
9*c3739801SMiguel Ojeda 
10*c3739801SMiguel Ojeda // After updating the following doc comment, make sure to run the following
11*c3739801SMiguel Ojeda // command to update `README.md` based on its contents:
12*c3739801SMiguel Ojeda //
13*c3739801SMiguel Ojeda //   cargo -q run --manifest-path tools/Cargo.toml -p generate-readme > README.md
14*c3739801SMiguel Ojeda 
15*c3739801SMiguel Ojeda //! ***<span style="font-size: 140%">Fast, safe, <span
16*c3739801SMiguel Ojeda //! style="color:red;">compile error</span>. Pick two.</span>***
17*c3739801SMiguel Ojeda //!
18*c3739801SMiguel Ojeda //! Zerocopy makes zero-cost memory manipulation effortless. We write `unsafe`
19*c3739801SMiguel Ojeda //! so you don't have to.
20*c3739801SMiguel Ojeda //!
21*c3739801SMiguel Ojeda //! *For an overview of what's changed from zerocopy 0.7, check out our [release
22*c3739801SMiguel Ojeda //! notes][release-notes], which include a step-by-step upgrading guide.*
23*c3739801SMiguel Ojeda //!
24*c3739801SMiguel Ojeda //! *Have questions? Need more out of zerocopy? Submit a [customer request
25*c3739801SMiguel Ojeda //! issue][customer-request-issue] or ask the maintainers on
26*c3739801SMiguel Ojeda //! [GitHub][github-q-a] or [Discord][discord]!*
27*c3739801SMiguel Ojeda //!
28*c3739801SMiguel Ojeda //! [customer-request-issue]: https://github.com/google/zerocopy/issues/new/choose
29*c3739801SMiguel Ojeda //! [release-notes]: https://github.com/google/zerocopy/discussions/1680
30*c3739801SMiguel Ojeda //! [github-q-a]: https://github.com/google/zerocopy/discussions/categories/q-a
31*c3739801SMiguel Ojeda //! [discord]: https://discord.gg/MAvWH2R6zk
32*c3739801SMiguel Ojeda //!
33*c3739801SMiguel Ojeda //! # Overview
34*c3739801SMiguel Ojeda //!
35*c3739801SMiguel Ojeda //! ##### Conversion Traits
36*c3739801SMiguel Ojeda //!
37*c3739801SMiguel Ojeda //! Zerocopy provides four derivable traits for zero-cost conversions:
38*c3739801SMiguel Ojeda //! - [`TryFromBytes`] indicates that a type may safely be converted from
39*c3739801SMiguel Ojeda //!   certain byte sequences (conditional on runtime checks)
40*c3739801SMiguel Ojeda //! - [`FromZeros`] indicates that a sequence of zero bytes represents a valid
41*c3739801SMiguel Ojeda //!   instance of a type
42*c3739801SMiguel Ojeda //! - [`FromBytes`] indicates that a type may safely be converted from an
43*c3739801SMiguel Ojeda //!   arbitrary byte sequence
44*c3739801SMiguel Ojeda //! - [`IntoBytes`] indicates that a type may safely be converted *to* a byte
45*c3739801SMiguel Ojeda //!   sequence
46*c3739801SMiguel Ojeda //!
47*c3739801SMiguel Ojeda //! These traits support sized types, slices, and [slice DSTs][slice-dsts].
48*c3739801SMiguel Ojeda //!
49*c3739801SMiguel Ojeda //! [slice-dsts]: KnownLayout#dynamically-sized-types
50*c3739801SMiguel Ojeda //!
51*c3739801SMiguel Ojeda //! ##### Marker Traits
52*c3739801SMiguel Ojeda //!
53*c3739801SMiguel Ojeda //! Zerocopy provides three derivable marker traits that do not provide any
54*c3739801SMiguel Ojeda //! functionality themselves, but are required to call certain methods provided
55*c3739801SMiguel Ojeda //! by the conversion traits:
56*c3739801SMiguel Ojeda //! - [`KnownLayout`] indicates that zerocopy can reason about certain layout
57*c3739801SMiguel Ojeda //!   qualities of a type
58*c3739801SMiguel Ojeda //! - [`Immutable`] indicates that a type is free from interior mutability,
59*c3739801SMiguel Ojeda //!   except by ownership or an exclusive (`&mut`) borrow
60*c3739801SMiguel Ojeda //! - [`Unaligned`] indicates that a type's alignment requirement is 1
61*c3739801SMiguel Ojeda //!
62*c3739801SMiguel Ojeda //! You should generally derive these marker traits whenever possible.
63*c3739801SMiguel Ojeda //!
64*c3739801SMiguel Ojeda //! ##### Conversion Macros
65*c3739801SMiguel Ojeda //!
66*c3739801SMiguel Ojeda //! Zerocopy provides six macros for safe casting between types:
67*c3739801SMiguel Ojeda //!
68*c3739801SMiguel Ojeda //! - ([`try_`][try_transmute])[`transmute`] (conditionally) converts a value of
69*c3739801SMiguel Ojeda //!   one type to a value of another type of the same size
70*c3739801SMiguel Ojeda //! - ([`try_`][try_transmute_mut])[`transmute_mut`] (conditionally) converts a
71*c3739801SMiguel Ojeda //!   mutable reference of one type to a mutable reference of another type of
72*c3739801SMiguel Ojeda //!   the same size
73*c3739801SMiguel Ojeda //! - ([`try_`][try_transmute_ref])[`transmute_ref`] (conditionally) converts a
74*c3739801SMiguel Ojeda //!   mutable or immutable reference of one type to an immutable reference of
75*c3739801SMiguel Ojeda //!   another type of the same size
76*c3739801SMiguel Ojeda //!
77*c3739801SMiguel Ojeda //! These macros perform *compile-time* size and alignment checks, meaning that
78*c3739801SMiguel Ojeda //! unconditional casts have zero cost at runtime. Conditional casts do not need
79*c3739801SMiguel Ojeda //! to validate size or alignment runtime, but do need to validate contents.
80*c3739801SMiguel Ojeda //!
81*c3739801SMiguel Ojeda //! These macros cannot be used in generic contexts. For generic conversions,
82*c3739801SMiguel Ojeda //! use the methods defined by the [conversion traits](#conversion-traits).
83*c3739801SMiguel Ojeda //!
84*c3739801SMiguel Ojeda //! ##### Byteorder-Aware Numerics
85*c3739801SMiguel Ojeda //!
86*c3739801SMiguel Ojeda //! Zerocopy provides byte-order aware integer types that support these
87*c3739801SMiguel Ojeda //! conversions; see the [`byteorder`] module. These types are especially useful
88*c3739801SMiguel Ojeda //! for network parsing.
89*c3739801SMiguel Ojeda //!
90*c3739801SMiguel Ojeda //! # Cargo Features
91*c3739801SMiguel Ojeda //!
92*c3739801SMiguel Ojeda //! - **`alloc`**
93*c3739801SMiguel Ojeda //!   By default, `zerocopy` is `no_std`. When the `alloc` feature is enabled,
94*c3739801SMiguel Ojeda //!   the `alloc` crate is added as a dependency, and some allocation-related
95*c3739801SMiguel Ojeda //!   functionality is added.
96*c3739801SMiguel Ojeda //!
97*c3739801SMiguel Ojeda //! - **`std`**
98*c3739801SMiguel Ojeda //!   By default, `zerocopy` is `no_std`. When the `std` feature is enabled, the
99*c3739801SMiguel Ojeda //!   `std` crate is added as a dependency (ie, `no_std` is disabled), and
100*c3739801SMiguel Ojeda //!   support for some `std` types is added. `std` implies `alloc`.
101*c3739801SMiguel Ojeda //!
102*c3739801SMiguel Ojeda //! - **`derive`**
103*c3739801SMiguel Ojeda //!   Provides derives for the core marker traits via the `zerocopy-derive`
104*c3739801SMiguel Ojeda //!   crate. These derives are re-exported from `zerocopy`, so it is not
105*c3739801SMiguel Ojeda //!   necessary to depend on `zerocopy-derive` directly.
106*c3739801SMiguel Ojeda //!
107*c3739801SMiguel Ojeda //!   However, you may experience better compile times if you instead directly
108*c3739801SMiguel Ojeda //!   depend on both `zerocopy` and `zerocopy-derive` in your `Cargo.toml`,
109*c3739801SMiguel Ojeda //!   since doing so will allow Rust to compile these crates in parallel. To do
110*c3739801SMiguel Ojeda //!   so, do *not* enable the `derive` feature, and list both dependencies in
111*c3739801SMiguel Ojeda //!   your `Cargo.toml` with the same leading non-zero version number; e.g:
112*c3739801SMiguel Ojeda //!
113*c3739801SMiguel Ojeda //!   ```toml
114*c3739801SMiguel Ojeda //!   [dependencies]
115*c3739801SMiguel Ojeda //!   zerocopy = "0.X"
116*c3739801SMiguel Ojeda //!   zerocopy-derive = "0.X"
117*c3739801SMiguel Ojeda //!   ```
118*c3739801SMiguel Ojeda //!
119*c3739801SMiguel Ojeda //!   To avoid the risk of [duplicate import errors][duplicate-import-errors] if
120*c3739801SMiguel Ojeda //!   one of your dependencies enables zerocopy's `derive` feature, import
121*c3739801SMiguel Ojeda //!   derives as `use zerocopy_derive::*` rather than by name (e.g., `use
122*c3739801SMiguel Ojeda //!   zerocopy_derive::FromBytes`).
123*c3739801SMiguel Ojeda //!
124*c3739801SMiguel Ojeda //! - **`simd`**
125*c3739801SMiguel Ojeda //!   When the `simd` feature is enabled, `FromZeros`, `FromBytes`, and
126*c3739801SMiguel Ojeda //!   `IntoBytes` impls are emitted for all stable SIMD types which exist on the
127*c3739801SMiguel Ojeda //!   target platform. Note that the layout of SIMD types is not yet stabilized,
128*c3739801SMiguel Ojeda //!   so these impls may be removed in the future if layout changes make them
129*c3739801SMiguel Ojeda //!   invalid. For more information, see the Unsafe Code Guidelines Reference
130*c3739801SMiguel Ojeda //!   page on the [layout of packed SIMD vectors][simd-layout].
131*c3739801SMiguel Ojeda //!
132*c3739801SMiguel Ojeda //! - **`simd-nightly`**
133*c3739801SMiguel Ojeda //!   Enables the `simd` feature and adds support for SIMD types which are only
134*c3739801SMiguel Ojeda //!   available on nightly. Since these types are unstable, support for any type
135*c3739801SMiguel Ojeda //!   may be removed at any point in the future.
136*c3739801SMiguel Ojeda //!
137*c3739801SMiguel Ojeda //! - **`float-nightly`**
138*c3739801SMiguel Ojeda //!   Adds support for the unstable `f16` and `f128` types. These types are
139*c3739801SMiguel Ojeda //!   not yet fully implemented and may not be supported on all platforms.
140*c3739801SMiguel Ojeda //!
141*c3739801SMiguel Ojeda //! [duplicate-import-errors]: https://github.com/google/zerocopy/issues/1587
142*c3739801SMiguel Ojeda //! [simd-layout]: https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html
143*c3739801SMiguel Ojeda //!
144*c3739801SMiguel Ojeda //! # Build Tuning
145*c3739801SMiguel Ojeda //!
146*c3739801SMiguel Ojeda //! ## `--cfg zerocopy_inline_always`
147*c3739801SMiguel Ojeda //!
148*c3739801SMiguel Ojeda //! Upgrades `#[inline]` to `#[inline(always)]` on many of zerocopy's public
149*c3739801SMiguel Ojeda //! functions and methods. This provides a narrowly-scoped alternative that
150*c3739801SMiguel Ojeda //! *may* improve the optimization of hot paths using zerocopy without the broad
151*c3739801SMiguel Ojeda //! compile-time penalties of configuring `codegen-units=1`.
152*c3739801SMiguel Ojeda //!
153*c3739801SMiguel Ojeda //! # Security Ethos
154*c3739801SMiguel Ojeda //!
155*c3739801SMiguel Ojeda //! Zerocopy is expressly designed for use in security-critical contexts. We
156*c3739801SMiguel Ojeda //! strive to ensure that that zerocopy code is sound under Rust's current
157*c3739801SMiguel Ojeda //! memory model, and *any future memory model*. We ensure this by:
158*c3739801SMiguel Ojeda //! - **...not 'guessing' about Rust's semantics.**
159*c3739801SMiguel Ojeda //!   We annotate `unsafe` code with a precise rationale for its soundness that
160*c3739801SMiguel Ojeda //!   cites a relevant section of Rust's official documentation. When Rust's
161*c3739801SMiguel Ojeda //!   documented semantics are unclear, we work with the Rust Operational
162*c3739801SMiguel Ojeda //!   Semantics Team to clarify Rust's documentation.
163*c3739801SMiguel Ojeda //! - **...rigorously testing our implementation.**
164*c3739801SMiguel Ojeda //!   We run tests using [Miri], ensuring that zerocopy is sound across a wide
165*c3739801SMiguel Ojeda //!   array of supported target platforms of varying endianness and pointer
166*c3739801SMiguel Ojeda //!   width, and across both current and experimental memory models of Rust.
167*c3739801SMiguel Ojeda //! - **...formally proving the correctness of our implementation.**
168*c3739801SMiguel Ojeda //!   We apply formal verification tools like [Kani][kani] to prove zerocopy's
169*c3739801SMiguel Ojeda //!   correctness.
170*c3739801SMiguel Ojeda //!
171*c3739801SMiguel Ojeda //! For more information, see our full [soundness policy].
172*c3739801SMiguel Ojeda //!
173*c3739801SMiguel Ojeda //! [Miri]: https://github.com/rust-lang/miri
174*c3739801SMiguel Ojeda //! [Kani]: https://github.com/model-checking/kani
175*c3739801SMiguel Ojeda //! [soundness policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#soundness
176*c3739801SMiguel Ojeda //!
177*c3739801SMiguel Ojeda //! # Relationship to Project Safe Transmute
178*c3739801SMiguel Ojeda //!
179*c3739801SMiguel Ojeda //! [Project Safe Transmute] is an official initiative of the Rust Project to
180*c3739801SMiguel Ojeda //! develop language-level support for safer transmutation. The Project consults
181*c3739801SMiguel Ojeda //! with crates like zerocopy to identify aspects of safer transmutation that
182*c3739801SMiguel Ojeda //! would benefit from compiler support, and has developed an [experimental,
183*c3739801SMiguel Ojeda //! compiler-supported analysis][mcp-transmutability] which determines whether,
184*c3739801SMiguel Ojeda //! for a given type, any value of that type may be soundly transmuted into
185*c3739801SMiguel Ojeda //! another type. Once this functionality is sufficiently mature, zerocopy
186*c3739801SMiguel Ojeda //! intends to replace its internal transmutability analysis (implemented by our
187*c3739801SMiguel Ojeda //! custom derives) with the compiler-supported one. This change will likely be
188*c3739801SMiguel Ojeda //! an implementation detail that is invisible to zerocopy's users.
189*c3739801SMiguel Ojeda //!
190*c3739801SMiguel Ojeda //! Project Safe Transmute will not replace the need for most of zerocopy's
191*c3739801SMiguel Ojeda //! higher-level abstractions. The experimental compiler analysis is a tool for
192*c3739801SMiguel Ojeda //! checking the soundness of `unsafe` code, not a tool to avoid writing
193*c3739801SMiguel Ojeda //! `unsafe` code altogether. For the foreseeable future, crates like zerocopy
194*c3739801SMiguel Ojeda //! will still be required in order to provide higher-level abstractions on top
195*c3739801SMiguel Ojeda //! of the building block provided by Project Safe Transmute.
196*c3739801SMiguel Ojeda //!
197*c3739801SMiguel Ojeda //! [Project Safe Transmute]: https://rust-lang.github.io/rfcs/2835-project-safe-transmute.html
198*c3739801SMiguel Ojeda //! [mcp-transmutability]: https://github.com/rust-lang/compiler-team/issues/411
199*c3739801SMiguel Ojeda //!
200*c3739801SMiguel Ojeda //! # MSRV
201*c3739801SMiguel Ojeda //!
202*c3739801SMiguel Ojeda //! See our [MSRV policy].
203*c3739801SMiguel Ojeda //!
204*c3739801SMiguel Ojeda //! [MSRV policy]: https://github.com/google/zerocopy/blob/main/POLICIES.md#msrv
205*c3739801SMiguel Ojeda //!
206*c3739801SMiguel Ojeda //! # Changelog
207*c3739801SMiguel Ojeda //!
208*c3739801SMiguel Ojeda //! Zerocopy uses [GitHub Releases].
209*c3739801SMiguel Ojeda //!
210*c3739801SMiguel Ojeda //! [GitHub Releases]: https://github.com/google/zerocopy/releases
211*c3739801SMiguel Ojeda //!
212*c3739801SMiguel Ojeda //! # Thanks
213*c3739801SMiguel Ojeda //!
214*c3739801SMiguel Ojeda //! Zerocopy is maintained by engineers at Google with help from [many wonderful
215*c3739801SMiguel Ojeda //! contributors][contributors]. Thank you to everyone who has lent a hand in
216*c3739801SMiguel Ojeda //! making Rust a little more secure!
217*c3739801SMiguel Ojeda //!
218*c3739801SMiguel Ojeda //! [contributors]: https://github.com/google/zerocopy/graphs/contributors
219*c3739801SMiguel Ojeda 
220*c3739801SMiguel Ojeda // Sometimes we want to use lints which were added after our MSRV.
221*c3739801SMiguel Ojeda // `unknown_lints` is `warn` by default and we deny warnings in CI, so without
222*c3739801SMiguel Ojeda // this attribute, any unknown lint would cause a CI failure when testing with
223*c3739801SMiguel Ojeda // our MSRV.
224*c3739801SMiguel Ojeda #![allow(unknown_lints, non_local_definitions, unreachable_patterns)]
225*c3739801SMiguel Ojeda #![deny(renamed_and_removed_lints)]
226*c3739801SMiguel Ojeda #![deny(
227*c3739801SMiguel Ojeda     anonymous_parameters,
228*c3739801SMiguel Ojeda     deprecated_in_future,
229*c3739801SMiguel Ojeda     late_bound_lifetime_arguments,
230*c3739801SMiguel Ojeda     missing_copy_implementations,
231*c3739801SMiguel Ojeda     missing_debug_implementations,
232*c3739801SMiguel Ojeda     missing_docs,
233*c3739801SMiguel Ojeda     path_statements,
234*c3739801SMiguel Ojeda     patterns_in_fns_without_body,
235*c3739801SMiguel Ojeda     rust_2018_idioms,
236*c3739801SMiguel Ojeda     trivial_numeric_casts,
237*c3739801SMiguel Ojeda     unreachable_pub,
238*c3739801SMiguel Ojeda     unsafe_op_in_unsafe_fn,
239*c3739801SMiguel Ojeda     unused_extern_crates,
240*c3739801SMiguel Ojeda     // We intentionally choose not to deny `unused_qualifications`. When items
241*c3739801SMiguel Ojeda     // are added to the prelude (e.g., `core::mem::size_of`), this has the
242*c3739801SMiguel Ojeda     // consequence of making some uses trigger this lint on the latest toolchain
243*c3739801SMiguel Ojeda     // (e.g., `mem::size_of`), but fixing it (e.g. by replacing with `size_of`)
244*c3739801SMiguel Ojeda     // does not work on older toolchains.
245*c3739801SMiguel Ojeda     //
246*c3739801SMiguel Ojeda     // We tested a more complicated fix in #1413, but ultimately decided that,
247*c3739801SMiguel Ojeda     // since this lint is just a minor style lint, the complexity isn't worth it
248*c3739801SMiguel Ojeda     // - it's fine to occasionally have unused qualifications slip through,
249*c3739801SMiguel Ojeda     // especially since these do not affect our user-facing API in any way.
250*c3739801SMiguel Ojeda     variant_size_differences
251*c3739801SMiguel Ojeda )]
252*c3739801SMiguel Ojeda #![cfg_attr(
253*c3739801SMiguel Ojeda     __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS,
254*c3739801SMiguel Ojeda     deny(fuzzy_provenance_casts, lossy_provenance_casts)
255*c3739801SMiguel Ojeda )]
256*c3739801SMiguel Ojeda #![deny(
257*c3739801SMiguel Ojeda     clippy::all,
258*c3739801SMiguel Ojeda     clippy::alloc_instead_of_core,
259*c3739801SMiguel Ojeda     clippy::arithmetic_side_effects,
260*c3739801SMiguel Ojeda     clippy::as_underscore,
261*c3739801SMiguel Ojeda     clippy::assertions_on_result_states,
262*c3739801SMiguel Ojeda     clippy::as_conversions,
263*c3739801SMiguel Ojeda     clippy::correctness,
264*c3739801SMiguel Ojeda     clippy::dbg_macro,
265*c3739801SMiguel Ojeda     clippy::decimal_literal_representation,
266*c3739801SMiguel Ojeda     clippy::double_must_use,
267*c3739801SMiguel Ojeda     clippy::get_unwrap,
268*c3739801SMiguel Ojeda     clippy::indexing_slicing,
269*c3739801SMiguel Ojeda     clippy::missing_inline_in_public_items,
270*c3739801SMiguel Ojeda     clippy::missing_safety_doc,
271*c3739801SMiguel Ojeda     clippy::multiple_unsafe_ops_per_block,
272*c3739801SMiguel Ojeda     clippy::must_use_candidate,
273*c3739801SMiguel Ojeda     clippy::must_use_unit,
274*c3739801SMiguel Ojeda     clippy::obfuscated_if_else,
275*c3739801SMiguel Ojeda     clippy::perf,
276*c3739801SMiguel Ojeda     clippy::print_stdout,
277*c3739801SMiguel Ojeda     clippy::return_self_not_must_use,
278*c3739801SMiguel Ojeda     clippy::std_instead_of_core,
279*c3739801SMiguel Ojeda     clippy::style,
280*c3739801SMiguel Ojeda     clippy::suspicious,
281*c3739801SMiguel Ojeda     clippy::todo,
282*c3739801SMiguel Ojeda     clippy::undocumented_unsafe_blocks,
283*c3739801SMiguel Ojeda     clippy::unimplemented,
284*c3739801SMiguel Ojeda     clippy::unnested_or_patterns,
285*c3739801SMiguel Ojeda     clippy::unwrap_used,
286*c3739801SMiguel Ojeda     clippy::use_debug
287*c3739801SMiguel Ojeda )]
288*c3739801SMiguel Ojeda // `clippy::incompatible_msrv` (implied by `clippy::suspicious`): This sometimes
289*c3739801SMiguel Ojeda // has false positives, and we test on our MSRV in CI, so it doesn't help us
290*c3739801SMiguel Ojeda // anyway.
291*c3739801SMiguel Ojeda #![allow(clippy::needless_lifetimes, clippy::type_complexity, clippy::incompatible_msrv)]
292*c3739801SMiguel Ojeda #![deny(
293*c3739801SMiguel Ojeda     rustdoc::bare_urls,
294*c3739801SMiguel Ojeda     rustdoc::broken_intra_doc_links,
295*c3739801SMiguel Ojeda     rustdoc::invalid_codeblock_attributes,
296*c3739801SMiguel Ojeda     rustdoc::invalid_html_tags,
297*c3739801SMiguel Ojeda     rustdoc::invalid_rust_codeblocks,
298*c3739801SMiguel Ojeda     rustdoc::missing_crate_level_docs,
299*c3739801SMiguel Ojeda     rustdoc::private_intra_doc_links
300*c3739801SMiguel Ojeda )]
301*c3739801SMiguel Ojeda // In test code, it makes sense to weight more heavily towards concise, readable
302*c3739801SMiguel Ojeda // code over correct or debuggable code.
303*c3739801SMiguel Ojeda #![cfg_attr(any(test, kani), allow(
304*c3739801SMiguel Ojeda     // In tests, you get line numbers and have access to source code, so panic
305*c3739801SMiguel Ojeda     // messages are less important. You also often unwrap a lot, which would
306*c3739801SMiguel Ojeda     // make expect'ing instead very verbose.
307*c3739801SMiguel Ojeda     clippy::unwrap_used,
308*c3739801SMiguel Ojeda     // In tests, there's no harm to "panic risks" - the worst that can happen is
309*c3739801SMiguel Ojeda     // that your test will fail, and you'll fix it. By contrast, panic risks in
310*c3739801SMiguel Ojeda     // production code introduce the possibly of code panicking unexpectedly "in
311*c3739801SMiguel Ojeda     // the field".
312*c3739801SMiguel Ojeda     clippy::arithmetic_side_effects,
313*c3739801SMiguel Ojeda     clippy::indexing_slicing,
314*c3739801SMiguel Ojeda ))]
315*c3739801SMiguel Ojeda #![cfg_attr(not(any(test, kani, feature = "std")), no_std)]
316*c3739801SMiguel Ojeda #![cfg_attr(
317*c3739801SMiguel Ojeda     all(feature = "simd-nightly", target_arch = "arm"),
318*c3739801SMiguel Ojeda     feature(stdarch_arm_neon_intrinsics)
319*c3739801SMiguel Ojeda )]
320*c3739801SMiguel Ojeda #![cfg_attr(
321*c3739801SMiguel Ojeda     all(feature = "simd-nightly", any(target_arch = "powerpc", target_arch = "powerpc64")),
322*c3739801SMiguel Ojeda     feature(stdarch_powerpc)
323*c3739801SMiguel Ojeda )]
324*c3739801SMiguel Ojeda #![cfg_attr(feature = "float-nightly", feature(f16, f128))]
325*c3739801SMiguel Ojeda #![cfg_attr(doc_cfg, feature(doc_cfg))]
326*c3739801SMiguel Ojeda #![cfg_attr(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS, feature(coverage_attribute))]
327*c3739801SMiguel Ojeda #![cfg_attr(
328*c3739801SMiguel Ojeda     any(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS, miri),
329*c3739801SMiguel Ojeda     feature(layout_for_ptr)
330*c3739801SMiguel Ojeda )]
331*c3739801SMiguel Ojeda #![cfg_attr(all(test, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), feature(test))]
332*c3739801SMiguel Ojeda 
333*c3739801SMiguel Ojeda // This is a hack to allow zerocopy-derive derives to work in this crate. They
334*c3739801SMiguel Ojeda // assume that zerocopy is linked as an extern crate, so they access items from
335*c3739801SMiguel Ojeda // it as `zerocopy::Xxx`. This makes that still work.
336*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
337*c3739801SMiguel Ojeda extern crate self as zerocopy;
338*c3739801SMiguel Ojeda 
339*c3739801SMiguel Ojeda #[cfg(all(test, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS))]
340*c3739801SMiguel Ojeda extern crate test;
341*c3739801SMiguel Ojeda 
342*c3739801SMiguel Ojeda #[doc(hidden)]
343*c3739801SMiguel Ojeda #[macro_use]
344*c3739801SMiguel Ojeda pub mod util;
345*c3739801SMiguel Ojeda 
346*c3739801SMiguel Ojeda pub mod byte_slice;
347*c3739801SMiguel Ojeda pub mod byteorder;
348*c3739801SMiguel Ojeda mod deprecated;
349*c3739801SMiguel Ojeda 
350*c3739801SMiguel Ojeda #[cfg(__ZEROCOPY_INTERNAL_USE_ONLY_DEV_MODE)]
351*c3739801SMiguel Ojeda pub mod doctests;
352*c3739801SMiguel Ojeda 
353*c3739801SMiguel Ojeda // This module is `pub` so that zerocopy's error types and error handling
354*c3739801SMiguel Ojeda // documentation is grouped together in a cohesive module. In practice, we
355*c3739801SMiguel Ojeda // expect most users to use the re-export of `error`'s items to avoid identifier
356*c3739801SMiguel Ojeda // stuttering.
357*c3739801SMiguel Ojeda pub mod error;
358*c3739801SMiguel Ojeda mod impls;
359*c3739801SMiguel Ojeda #[doc(hidden)]
360*c3739801SMiguel Ojeda pub mod layout;
361*c3739801SMiguel Ojeda mod macros;
362*c3739801SMiguel Ojeda #[cfg_attr(not(zerocopy_unstable_ptr), doc(hidden))]
363*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(zerocopy_unstable_ptr)))]
364*c3739801SMiguel Ojeda pub mod pointer;
365*c3739801SMiguel Ojeda mod r#ref;
366*c3739801SMiguel Ojeda mod split_at;
367*c3739801SMiguel Ojeda // FIXME(#252): If we make this pub, come up with a better name.
368*c3739801SMiguel Ojeda mod wrappers;
369*c3739801SMiguel Ojeda 
370*c3739801SMiguel Ojeda use core::{
371*c3739801SMiguel Ojeda     cell::{Cell, UnsafeCell},
372*c3739801SMiguel Ojeda     cmp::Ordering,
373*c3739801SMiguel Ojeda     fmt::{self, Debug, Display, Formatter},
374*c3739801SMiguel Ojeda     hash::Hasher,
375*c3739801SMiguel Ojeda     marker::PhantomData,
376*c3739801SMiguel Ojeda     mem::{self, ManuallyDrop, MaybeUninit as CoreMaybeUninit},
377*c3739801SMiguel Ojeda     num::{
378*c3739801SMiguel Ojeda         NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
379*c3739801SMiguel Ojeda         NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping,
380*c3739801SMiguel Ojeda     },
381*c3739801SMiguel Ojeda     ops::{Deref, DerefMut},
382*c3739801SMiguel Ojeda     ptr::{self, NonNull},
383*c3739801SMiguel Ojeda     slice,
384*c3739801SMiguel Ojeda };
385*c3739801SMiguel Ojeda #[cfg(feature = "std")]
386*c3739801SMiguel Ojeda use std::io;
387*c3739801SMiguel Ojeda 
388*c3739801SMiguel Ojeda #[doc(hidden)]
389*c3739801SMiguel Ojeda pub use crate::pointer::{
390*c3739801SMiguel Ojeda     invariant::{self, BecauseExclusive},
391*c3739801SMiguel Ojeda     PtrInner,
392*c3739801SMiguel Ojeda };
393*c3739801SMiguel Ojeda pub use crate::{
394*c3739801SMiguel Ojeda     byte_slice::*,
395*c3739801SMiguel Ojeda     byteorder::*,
396*c3739801SMiguel Ojeda     error::*,
397*c3739801SMiguel Ojeda     r#ref::*,
398*c3739801SMiguel Ojeda     split_at::{Split, SplitAt},
399*c3739801SMiguel Ojeda     wrappers::*,
400*c3739801SMiguel Ojeda };
401*c3739801SMiguel Ojeda 
402*c3739801SMiguel Ojeda #[cfg(any(feature = "alloc", test, kani))]
403*c3739801SMiguel Ojeda extern crate alloc;
404*c3739801SMiguel Ojeda #[cfg(any(feature = "alloc", test))]
405*c3739801SMiguel Ojeda use alloc::{boxed::Box, vec::Vec};
406*c3739801SMiguel Ojeda #[cfg(any(feature = "alloc", test))]
407*c3739801SMiguel Ojeda use core::alloc::Layout;
408*c3739801SMiguel Ojeda 
409*c3739801SMiguel Ojeda // Used by `KnownLayout`.
410*c3739801SMiguel Ojeda #[doc(hidden)]
411*c3739801SMiguel Ojeda pub use crate::layout::*;
412*c3739801SMiguel Ojeda // Used by `TryFromBytes::is_bit_valid`.
413*c3739801SMiguel Ojeda #[doc(hidden)]
414*c3739801SMiguel Ojeda pub use crate::pointer::{invariant::BecauseImmutable, Maybe, Ptr};
415*c3739801SMiguel Ojeda // For each trait polyfill, as soon as the corresponding feature is stable, the
416*c3739801SMiguel Ojeda // polyfill import will be unused because method/function resolution will prefer
417*c3739801SMiguel Ojeda // the inherent method/function over a trait method/function. Thus, we suppress
418*c3739801SMiguel Ojeda // the `unused_imports` warning.
419*c3739801SMiguel Ojeda //
420*c3739801SMiguel Ojeda // See the documentation on `util::polyfills` for more information.
421*c3739801SMiguel Ojeda #[allow(unused_imports)]
422*c3739801SMiguel Ojeda use crate::util::polyfills::{self, NonNullExt as _, NumExt as _};
423*c3739801SMiguel Ojeda #[cfg_attr(not(zerocopy_unstable_ptr), doc(hidden))]
424*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(zerocopy_unstable_ptr)))]
425*c3739801SMiguel Ojeda pub use crate::util::MetadataOf;
426*c3739801SMiguel Ojeda 
427*c3739801SMiguel Ojeda #[cfg(all(test, not(__ZEROCOPY_INTERNAL_USE_ONLY_DEV_MODE)))]
428*c3739801SMiguel Ojeda const _: () = {
429*c3739801SMiguel Ojeda     #[deprecated = "Development of zerocopy using cargo is not supported. Please use `cargo.sh` or `win-cargo.bat` instead."]
430*c3739801SMiguel Ojeda     #[allow(unused)]
431*c3739801SMiguel Ojeda     const WARNING: () = ();
432*c3739801SMiguel Ojeda     #[warn(deprecated)]
433*c3739801SMiguel Ojeda     WARNING
434*c3739801SMiguel Ojeda };
435*c3739801SMiguel Ojeda 
436*c3739801SMiguel Ojeda /// Implements [`KnownLayout`].
437*c3739801SMiguel Ojeda ///
438*c3739801SMiguel Ojeda /// This derive analyzes various aspects of a type's layout that are needed for
439*c3739801SMiguel Ojeda /// some of zerocopy's APIs. It can be applied to structs, enums, and unions;
440*c3739801SMiguel Ojeda /// e.g.:
441*c3739801SMiguel Ojeda ///
442*c3739801SMiguel Ojeda /// ```
443*c3739801SMiguel Ojeda /// # use zerocopy_derive::KnownLayout;
444*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
445*c3739801SMiguel Ojeda /// struct MyStruct {
446*c3739801SMiguel Ojeda /// # /*
447*c3739801SMiguel Ojeda ///     ...
448*c3739801SMiguel Ojeda /// # */
449*c3739801SMiguel Ojeda /// }
450*c3739801SMiguel Ojeda ///
451*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
452*c3739801SMiguel Ojeda /// enum MyEnum {
453*c3739801SMiguel Ojeda /// #   V00,
454*c3739801SMiguel Ojeda /// # /*
455*c3739801SMiguel Ojeda ///     ...
456*c3739801SMiguel Ojeda /// # */
457*c3739801SMiguel Ojeda /// }
458*c3739801SMiguel Ojeda ///
459*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
460*c3739801SMiguel Ojeda /// union MyUnion {
461*c3739801SMiguel Ojeda /// #   variant: u8,
462*c3739801SMiguel Ojeda /// # /*
463*c3739801SMiguel Ojeda ///     ...
464*c3739801SMiguel Ojeda /// # */
465*c3739801SMiguel Ojeda /// }
466*c3739801SMiguel Ojeda /// ```
467*c3739801SMiguel Ojeda ///
468*c3739801SMiguel Ojeda /// # Limitations
469*c3739801SMiguel Ojeda ///
470*c3739801SMiguel Ojeda /// This derive cannot currently be applied to unsized structs without an
471*c3739801SMiguel Ojeda /// explicit `repr` attribute.
472*c3739801SMiguel Ojeda ///
473*c3739801SMiguel Ojeda /// Some invocations of this derive run afoul of a [known bug] in Rust's type
474*c3739801SMiguel Ojeda /// privacy checker. For example, this code:
475*c3739801SMiguel Ojeda ///
476*c3739801SMiguel Ojeda /// ```compile_fail,E0446
477*c3739801SMiguel Ojeda /// use zerocopy::*;
478*c3739801SMiguel Ojeda /// # use zerocopy_derive::*;
479*c3739801SMiguel Ojeda ///
480*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
481*c3739801SMiguel Ojeda /// #[repr(C)]
482*c3739801SMiguel Ojeda /// pub struct PublicType {
483*c3739801SMiguel Ojeda ///     leading: Foo,
484*c3739801SMiguel Ojeda ///     trailing: Bar,
485*c3739801SMiguel Ojeda /// }
486*c3739801SMiguel Ojeda ///
487*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
488*c3739801SMiguel Ojeda /// struct Foo;
489*c3739801SMiguel Ojeda ///
490*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
491*c3739801SMiguel Ojeda /// struct Bar;
492*c3739801SMiguel Ojeda /// ```
493*c3739801SMiguel Ojeda ///
494*c3739801SMiguel Ojeda /// ...results in a compilation error:
495*c3739801SMiguel Ojeda ///
496*c3739801SMiguel Ojeda /// ```text
497*c3739801SMiguel Ojeda /// error[E0446]: private type `Bar` in public interface
498*c3739801SMiguel Ojeda ///  --> examples/bug.rs:3:10
499*c3739801SMiguel Ojeda ///    |
500*c3739801SMiguel Ojeda /// 3  | #[derive(KnownLayout)]
501*c3739801SMiguel Ojeda ///    |          ^^^^^^^^^^^ can't leak private type
502*c3739801SMiguel Ojeda /// ...
503*c3739801SMiguel Ojeda /// 14 | struct Bar;
504*c3739801SMiguel Ojeda ///    | ---------- `Bar` declared as private
505*c3739801SMiguel Ojeda ///    |
506*c3739801SMiguel Ojeda ///    = note: this error originates in the derive macro `KnownLayout` (in Nightly builds, run with -Z macro-backtrace for more info)
507*c3739801SMiguel Ojeda /// ```
508*c3739801SMiguel Ojeda ///
509*c3739801SMiguel Ojeda /// This issue arises when `#[derive(KnownLayout)]` is applied to `repr(C)`
510*c3739801SMiguel Ojeda /// structs whose trailing field type is less public than the enclosing struct.
511*c3739801SMiguel Ojeda ///
512*c3739801SMiguel Ojeda /// To work around this, mark the trailing field type `pub` and annotate it with
513*c3739801SMiguel Ojeda /// `#[doc(hidden)]`; e.g.:
514*c3739801SMiguel Ojeda ///
515*c3739801SMiguel Ojeda /// ```no_run
516*c3739801SMiguel Ojeda /// use zerocopy::*;
517*c3739801SMiguel Ojeda /// # use zerocopy_derive::*;
518*c3739801SMiguel Ojeda ///
519*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
520*c3739801SMiguel Ojeda /// #[repr(C)]
521*c3739801SMiguel Ojeda /// pub struct PublicType {
522*c3739801SMiguel Ojeda ///     leading: Foo,
523*c3739801SMiguel Ojeda ///     trailing: Bar,
524*c3739801SMiguel Ojeda /// }
525*c3739801SMiguel Ojeda ///
526*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
527*c3739801SMiguel Ojeda /// struct Foo;
528*c3739801SMiguel Ojeda ///
529*c3739801SMiguel Ojeda /// #[doc(hidden)]
530*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
531*c3739801SMiguel Ojeda /// pub struct Bar; // <- `Bar` is now also `pub`
532*c3739801SMiguel Ojeda /// ```
533*c3739801SMiguel Ojeda ///
534*c3739801SMiguel Ojeda /// [known bug]: https://github.com/rust-lang/rust/issues/45713
535*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
536*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
537*c3739801SMiguel Ojeda pub use zerocopy_derive::KnownLayout;
538*c3739801SMiguel Ojeda // These exist so that code which was written against the old names will get
539*c3739801SMiguel Ojeda // less confusing error messages when they upgrade to a more recent version of
540*c3739801SMiguel Ojeda // zerocopy. On our MSRV toolchain, the error messages read, for example:
541*c3739801SMiguel Ojeda //
542*c3739801SMiguel Ojeda //   error[E0603]: trait `FromZeroes` is private
543*c3739801SMiguel Ojeda //       --> examples/deprecated.rs:1:15
544*c3739801SMiguel Ojeda //        |
545*c3739801SMiguel Ojeda //   1    | use zerocopy::FromZeroes;
546*c3739801SMiguel Ojeda //        |               ^^^^^^^^^^ private trait
547*c3739801SMiguel Ojeda //        |
548*c3739801SMiguel Ojeda //   note: the trait `FromZeroes` is defined here
549*c3739801SMiguel Ojeda //       --> /Users/josh/workspace/zerocopy/src/lib.rs:1845:5
550*c3739801SMiguel Ojeda //        |
551*c3739801SMiguel Ojeda //   1845 | use FromZeros as FromZeroes;
552*c3739801SMiguel Ojeda //        |     ^^^^^^^^^^^^^^^^^^^^^^^
553*c3739801SMiguel Ojeda //
554*c3739801SMiguel Ojeda // The "note" provides enough context to make it easy to figure out how to fix
555*c3739801SMiguel Ojeda // the error.
556*c3739801SMiguel Ojeda #[allow(unused)]
557*c3739801SMiguel Ojeda use {FromZeros as FromZeroes, IntoBytes as AsBytes, Ref as LayoutVerified};
558*c3739801SMiguel Ojeda 
559*c3739801SMiguel Ojeda /// Indicates that zerocopy can reason about certain aspects of a type's layout.
560*c3739801SMiguel Ojeda ///
561*c3739801SMiguel Ojeda /// This trait is required by many of zerocopy's APIs. It supports sized types,
562*c3739801SMiguel Ojeda /// slices, and [slice DSTs](#dynamically-sized-types).
563*c3739801SMiguel Ojeda ///
564*c3739801SMiguel Ojeda /// # Implementation
565*c3739801SMiguel Ojeda ///
566*c3739801SMiguel Ojeda /// **Do not implement this trait yourself!** Instead, use
567*c3739801SMiguel Ojeda /// [`#[derive(KnownLayout)]`][derive]; e.g.:
568*c3739801SMiguel Ojeda ///
569*c3739801SMiguel Ojeda /// ```
570*c3739801SMiguel Ojeda /// # use zerocopy_derive::KnownLayout;
571*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
572*c3739801SMiguel Ojeda /// struct MyStruct {
573*c3739801SMiguel Ojeda /// # /*
574*c3739801SMiguel Ojeda ///     ...
575*c3739801SMiguel Ojeda /// # */
576*c3739801SMiguel Ojeda /// }
577*c3739801SMiguel Ojeda ///
578*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
579*c3739801SMiguel Ojeda /// enum MyEnum {
580*c3739801SMiguel Ojeda /// # /*
581*c3739801SMiguel Ojeda ///     ...
582*c3739801SMiguel Ojeda /// # */
583*c3739801SMiguel Ojeda /// }
584*c3739801SMiguel Ojeda ///
585*c3739801SMiguel Ojeda /// #[derive(KnownLayout)]
586*c3739801SMiguel Ojeda /// union MyUnion {
587*c3739801SMiguel Ojeda /// #   variant: u8,
588*c3739801SMiguel Ojeda /// # /*
589*c3739801SMiguel Ojeda ///     ...
590*c3739801SMiguel Ojeda /// # */
591*c3739801SMiguel Ojeda /// }
592*c3739801SMiguel Ojeda /// ```
593*c3739801SMiguel Ojeda ///
594*c3739801SMiguel Ojeda /// This derive performs a sophisticated analysis to deduce the layout
595*c3739801SMiguel Ojeda /// characteristics of types. You **must** implement this trait via the derive.
596*c3739801SMiguel Ojeda ///
597*c3739801SMiguel Ojeda /// # Dynamically-sized types
598*c3739801SMiguel Ojeda ///
599*c3739801SMiguel Ojeda /// `KnownLayout` supports slice-based dynamically sized types ("slice DSTs").
600*c3739801SMiguel Ojeda ///
601*c3739801SMiguel Ojeda /// A slice DST is a type whose trailing field is either a slice or another
602*c3739801SMiguel Ojeda /// slice DST, rather than a type with fixed size. For example:
603*c3739801SMiguel Ojeda ///
604*c3739801SMiguel Ojeda /// ```
605*c3739801SMiguel Ojeda /// #[repr(C)]
606*c3739801SMiguel Ojeda /// struct PacketHeader {
607*c3739801SMiguel Ojeda /// # /*
608*c3739801SMiguel Ojeda ///     ...
609*c3739801SMiguel Ojeda /// # */
610*c3739801SMiguel Ojeda /// }
611*c3739801SMiguel Ojeda ///
612*c3739801SMiguel Ojeda /// #[repr(C)]
613*c3739801SMiguel Ojeda /// struct Packet {
614*c3739801SMiguel Ojeda ///     header: PacketHeader,
615*c3739801SMiguel Ojeda ///     body: [u8],
616*c3739801SMiguel Ojeda /// }
617*c3739801SMiguel Ojeda /// ```
618*c3739801SMiguel Ojeda ///
619*c3739801SMiguel Ojeda /// It can be useful to think of slice DSTs as a generalization of slices - in
620*c3739801SMiguel Ojeda /// other words, a normal slice is just the special case of a slice DST with
621*c3739801SMiguel Ojeda /// zero leading fields. In particular:
622*c3739801SMiguel Ojeda /// - Like slices, slice DSTs can have different lengths at runtime
623*c3739801SMiguel Ojeda /// - Like slices, slice DSTs cannot be passed by-value, but only by reference
624*c3739801SMiguel Ojeda ///   or via other indirection such as `Box`
625*c3739801SMiguel Ojeda /// - Like slices, a reference (or `Box`, or other pointer type) to a slice DST
626*c3739801SMiguel Ojeda ///   encodes the number of elements in the trailing slice field
627*c3739801SMiguel Ojeda ///
628*c3739801SMiguel Ojeda /// ## Slice DST layout
629*c3739801SMiguel Ojeda ///
630*c3739801SMiguel Ojeda /// Just like other composite Rust types, the layout of a slice DST is not
631*c3739801SMiguel Ojeda /// well-defined unless it is specified using an explicit `#[repr(...)]`
632*c3739801SMiguel Ojeda /// attribute such as `#[repr(C)]`. [Other representations are
633*c3739801SMiguel Ojeda /// supported][reprs], but in this section, we'll use `#[repr(C)]` as our
634*c3739801SMiguel Ojeda /// example.
635*c3739801SMiguel Ojeda ///
636*c3739801SMiguel Ojeda /// A `#[repr(C)]` slice DST is laid out [just like sized `#[repr(C)]`
637*c3739801SMiguel Ojeda /// types][repr-c-structs], but the presence of a variable-length field
638*c3739801SMiguel Ojeda /// introduces the possibility of *dynamic padding*. In particular, it may be
639*c3739801SMiguel Ojeda /// necessary to add trailing padding *after* the trailing slice field in order
640*c3739801SMiguel Ojeda /// to satisfy the outer type's alignment, and the amount of padding required
641*c3739801SMiguel Ojeda /// may be a function of the length of the trailing slice field. This is just a
642*c3739801SMiguel Ojeda /// natural consequence of the normal `#[repr(C)]` rules applied to slice DSTs,
643*c3739801SMiguel Ojeda /// but it can result in surprising behavior. For example, consider the
644*c3739801SMiguel Ojeda /// following type:
645*c3739801SMiguel Ojeda ///
646*c3739801SMiguel Ojeda /// ```
647*c3739801SMiguel Ojeda /// #[repr(C)]
648*c3739801SMiguel Ojeda /// struct Foo {
649*c3739801SMiguel Ojeda ///     a: u32,
650*c3739801SMiguel Ojeda ///     b: u8,
651*c3739801SMiguel Ojeda ///     z: [u16],
652*c3739801SMiguel Ojeda /// }
653*c3739801SMiguel Ojeda /// ```
654*c3739801SMiguel Ojeda ///
655*c3739801SMiguel Ojeda /// Assuming that `u32` has alignment 4 (this is not true on all platforms),
656*c3739801SMiguel Ojeda /// then `Foo` has alignment 4 as well. Here is the smallest possible value for
657*c3739801SMiguel Ojeda /// `Foo`:
658*c3739801SMiguel Ojeda ///
659*c3739801SMiguel Ojeda /// ```text
660*c3739801SMiguel Ojeda /// byte offset | 01234567
661*c3739801SMiguel Ojeda ///       field | aaaab---
662*c3739801SMiguel Ojeda ///                    ><
663*c3739801SMiguel Ojeda /// ```
664*c3739801SMiguel Ojeda ///
665*c3739801SMiguel Ojeda /// In this value, `z` has length 0. Abiding by `#[repr(C)]`, the lowest offset
666*c3739801SMiguel Ojeda /// that we can place `z` at is 5, but since `z` has alignment 2, we need to
667*c3739801SMiguel Ojeda /// round up to offset 6. This means that there is one byte of padding between
668*c3739801SMiguel Ojeda /// `b` and `z`, then 0 bytes of `z` itself (denoted `><` in this diagram), and
669*c3739801SMiguel Ojeda /// then two bytes of padding after `z` in order to satisfy the overall
670*c3739801SMiguel Ojeda /// alignment of `Foo`. The size of this instance is 8 bytes.
671*c3739801SMiguel Ojeda ///
672*c3739801SMiguel Ojeda /// What about if `z` has length 1?
673*c3739801SMiguel Ojeda ///
674*c3739801SMiguel Ojeda /// ```text
675*c3739801SMiguel Ojeda /// byte offset | 01234567
676*c3739801SMiguel Ojeda ///       field | aaaab-zz
677*c3739801SMiguel Ojeda /// ```
678*c3739801SMiguel Ojeda ///
679*c3739801SMiguel Ojeda /// In this instance, `z` has length 1, and thus takes up 2 bytes. That means
680*c3739801SMiguel Ojeda /// that we no longer need padding after `z` in order to satisfy `Foo`'s
681*c3739801SMiguel Ojeda /// alignment. We've now seen two different values of `Foo` with two different
682*c3739801SMiguel Ojeda /// lengths of `z`, but they both have the same size - 8 bytes.
683*c3739801SMiguel Ojeda ///
684*c3739801SMiguel Ojeda /// What about if `z` has length 2?
685*c3739801SMiguel Ojeda ///
686*c3739801SMiguel Ojeda /// ```text
687*c3739801SMiguel Ojeda /// byte offset | 012345678901
688*c3739801SMiguel Ojeda ///       field | aaaab-zzzz--
689*c3739801SMiguel Ojeda /// ```
690*c3739801SMiguel Ojeda ///
691*c3739801SMiguel Ojeda /// Now `z` has length 2, and thus takes up 4 bytes. This brings our un-padded
692*c3739801SMiguel Ojeda /// size to 10, and so we now need another 2 bytes of padding after `z` to
693*c3739801SMiguel Ojeda /// satisfy `Foo`'s alignment.
694*c3739801SMiguel Ojeda ///
695*c3739801SMiguel Ojeda /// Again, all of this is just a logical consequence of the `#[repr(C)]` rules
696*c3739801SMiguel Ojeda /// applied to slice DSTs, but it can be surprising that the amount of trailing
697*c3739801SMiguel Ojeda /// padding becomes a function of the trailing slice field's length, and thus
698*c3739801SMiguel Ojeda /// can only be computed at runtime.
699*c3739801SMiguel Ojeda ///
700*c3739801SMiguel Ojeda /// [reprs]: https://doc.rust-lang.org/reference/type-layout.html#representations
701*c3739801SMiguel Ojeda /// [repr-c-structs]: https://doc.rust-lang.org/reference/type-layout.html#reprc-structs
702*c3739801SMiguel Ojeda ///
703*c3739801SMiguel Ojeda /// ## What is a valid size?
704*c3739801SMiguel Ojeda ///
705*c3739801SMiguel Ojeda /// There are two places in zerocopy's API that we refer to "a valid size" of a
706*c3739801SMiguel Ojeda /// type. In normal casts or conversions, where the source is a byte slice, we
707*c3739801SMiguel Ojeda /// need to know whether the source byte slice is a valid size of the
708*c3739801SMiguel Ojeda /// destination type. In prefix or suffix casts, we need to know whether *there
709*c3739801SMiguel Ojeda /// exists* a valid size of the destination type which fits in the source byte
710*c3739801SMiguel Ojeda /// slice and, if so, what the largest such size is.
711*c3739801SMiguel Ojeda ///
712*c3739801SMiguel Ojeda /// As outlined above, a slice DST's size is defined by the number of elements
713*c3739801SMiguel Ojeda /// in its trailing slice field. However, there is not necessarily a 1-to-1
714*c3739801SMiguel Ojeda /// mapping between trailing slice field length and overall size. As we saw in
715*c3739801SMiguel Ojeda /// the previous section with the type `Foo`, instances with both 0 and 1
716*c3739801SMiguel Ojeda /// elements in the trailing `z` field result in a `Foo` whose size is 8 bytes.
717*c3739801SMiguel Ojeda ///
718*c3739801SMiguel Ojeda /// When we say "x is a valid size of `T`", we mean one of two things:
719*c3739801SMiguel Ojeda /// - If `T: Sized`, then we mean that `x == size_of::<T>()`
720*c3739801SMiguel Ojeda /// - If `T` is a slice DST, then we mean that there exists a `len` such that the instance of
721*c3739801SMiguel Ojeda ///   `T` with `len` trailing slice elements has size `x`
722*c3739801SMiguel Ojeda ///
723*c3739801SMiguel Ojeda /// When we say "largest possible size of `T` that fits in a byte slice", we
724*c3739801SMiguel Ojeda /// mean one of two things:
725*c3739801SMiguel Ojeda /// - If `T: Sized`, then we mean `size_of::<T>()` if the byte slice is at least
726*c3739801SMiguel Ojeda ///   `size_of::<T>()` bytes long
727*c3739801SMiguel Ojeda /// - If `T` is a slice DST, then we mean to consider all values, `len`, such
728*c3739801SMiguel Ojeda ///   that the instance of `T` with `len` trailing slice elements fits in the
729*c3739801SMiguel Ojeda ///   byte slice, and to choose the largest such `len`, if any
730*c3739801SMiguel Ojeda ///
731*c3739801SMiguel Ojeda ///
732*c3739801SMiguel Ojeda /// # Safety
733*c3739801SMiguel Ojeda ///
734*c3739801SMiguel Ojeda /// This trait does not convey any safety guarantees to code outside this crate.
735*c3739801SMiguel Ojeda ///
736*c3739801SMiguel Ojeda /// You must not rely on the `#[doc(hidden)]` internals of `KnownLayout`. Future
737*c3739801SMiguel Ojeda /// releases of zerocopy may make backwards-breaking changes to these items,
738*c3739801SMiguel Ojeda /// including changes that only affect soundness, which may cause code which
739*c3739801SMiguel Ojeda /// uses those items to silently become unsound.
740*c3739801SMiguel Ojeda ///
741*c3739801SMiguel Ojeda #[cfg_attr(feature = "derive", doc = "[derive]: zerocopy_derive::KnownLayout")]
742*c3739801SMiguel Ojeda #[cfg_attr(
743*c3739801SMiguel Ojeda     not(feature = "derive"),
744*c3739801SMiguel Ojeda     doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.KnownLayout.html"),
745*c3739801SMiguel Ojeda )]
746*c3739801SMiguel Ojeda #[cfg_attr(
747*c3739801SMiguel Ojeda     not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
748*c3739801SMiguel Ojeda     diagnostic::on_unimplemented(note = "Consider adding `#[derive(KnownLayout)]` to `{Self}`")
749*c3739801SMiguel Ojeda )]
750*c3739801SMiguel Ojeda pub unsafe trait KnownLayout {
751*c3739801SMiguel Ojeda     // The `Self: Sized` bound makes it so that `KnownLayout` can still be
752*c3739801SMiguel Ojeda     // object safe. It's not currently object safe thanks to `const LAYOUT`, and
753*c3739801SMiguel Ojeda     // it likely won't be in the future, but there's no reason not to be
754*c3739801SMiguel Ojeda     // forwards-compatible with object safety.
755*c3739801SMiguel Ojeda     #[doc(hidden)]
756*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
757*c3739801SMiguel Ojeda     where
758*c3739801SMiguel Ojeda         Self: Sized;
759*c3739801SMiguel Ojeda 
760*c3739801SMiguel Ojeda     /// The type of metadata stored in a pointer to `Self`.
761*c3739801SMiguel Ojeda     ///
762*c3739801SMiguel Ojeda     /// This is `()` for sized types and [`usize`] for slice DSTs.
763*c3739801SMiguel Ojeda     type PointerMetadata: PointerMetadata;
764*c3739801SMiguel Ojeda 
765*c3739801SMiguel Ojeda     /// A maybe-uninitialized analog of `Self`
766*c3739801SMiguel Ojeda     ///
767*c3739801SMiguel Ojeda     /// # Safety
768*c3739801SMiguel Ojeda     ///
769*c3739801SMiguel Ojeda     /// `Self::LAYOUT` and `Self::MaybeUninit::LAYOUT` are identical.
770*c3739801SMiguel Ojeda     /// `Self::MaybeUninit` admits uninitialized bytes in all positions.
771*c3739801SMiguel Ojeda     #[doc(hidden)]
772*c3739801SMiguel Ojeda     type MaybeUninit: ?Sized + KnownLayout<PointerMetadata = Self::PointerMetadata>;
773*c3739801SMiguel Ojeda 
774*c3739801SMiguel Ojeda     /// The layout of `Self`.
775*c3739801SMiguel Ojeda     ///
776*c3739801SMiguel Ojeda     /// # Safety
777*c3739801SMiguel Ojeda     ///
778*c3739801SMiguel Ojeda     /// Callers may assume that `LAYOUT` accurately reflects the layout of
779*c3739801SMiguel Ojeda     /// `Self`. In particular:
780*c3739801SMiguel Ojeda     /// - `LAYOUT.align` is equal to `Self`'s alignment
781*c3739801SMiguel Ojeda     /// - If `Self: Sized`, then `LAYOUT.size_info == SizeInfo::Sized { size }`
782*c3739801SMiguel Ojeda     ///   where `size == size_of::<Self>()`
783*c3739801SMiguel Ojeda     /// - If `Self` is a slice DST, then `LAYOUT.size_info ==
784*c3739801SMiguel Ojeda     ///   SizeInfo::SliceDst(slice_layout)` where:
785*c3739801SMiguel Ojeda     ///   - The size, `size`, of an instance of `Self` with `elems` trailing
786*c3739801SMiguel Ojeda     ///     slice elements is equal to `slice_layout.offset +
787*c3739801SMiguel Ojeda     ///     slice_layout.elem_size * elems` rounded up to the nearest multiple
788*c3739801SMiguel Ojeda     ///     of `LAYOUT.align`
789*c3739801SMiguel Ojeda     ///   - For such an instance, any bytes in the range `[slice_layout.offset +
790*c3739801SMiguel Ojeda     ///     slice_layout.elem_size * elems, size)` are padding and must not be
791*c3739801SMiguel Ojeda     ///     assumed to be initialized
792*c3739801SMiguel Ojeda     #[doc(hidden)]
793*c3739801SMiguel Ojeda     const LAYOUT: DstLayout;
794*c3739801SMiguel Ojeda 
795*c3739801SMiguel Ojeda     /// SAFETY: The returned pointer has the same address and provenance as
796*c3739801SMiguel Ojeda     /// `bytes`. If `Self` is a DST, the returned pointer's referent has `elems`
797*c3739801SMiguel Ojeda     /// elements in its trailing slice.
798*c3739801SMiguel Ojeda     #[doc(hidden)]
799*c3739801SMiguel Ojeda     fn raw_from_ptr_len(bytes: NonNull<u8>, meta: Self::PointerMetadata) -> NonNull<Self>;
800*c3739801SMiguel Ojeda 
801*c3739801SMiguel Ojeda     /// Extracts the metadata from a pointer to `Self`.
802*c3739801SMiguel Ojeda     ///
803*c3739801SMiguel Ojeda     /// # Safety
804*c3739801SMiguel Ojeda     ///
805*c3739801SMiguel Ojeda     /// `pointer_to_metadata` always returns the correct metadata stored in
806*c3739801SMiguel Ojeda     /// `ptr`.
807*c3739801SMiguel Ojeda     #[doc(hidden)]
808*c3739801SMiguel Ojeda     fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata;
809*c3739801SMiguel Ojeda 
810*c3739801SMiguel Ojeda     /// Computes the length of the byte range addressed by `ptr`.
811*c3739801SMiguel Ojeda     ///
812*c3739801SMiguel Ojeda     /// Returns `None` if the resulting length would not fit in an `usize`.
813*c3739801SMiguel Ojeda     ///
814*c3739801SMiguel Ojeda     /// # Safety
815*c3739801SMiguel Ojeda     ///
816*c3739801SMiguel Ojeda     /// Callers may assume that `size_of_val_raw` always returns the correct
817*c3739801SMiguel Ojeda     /// size.
818*c3739801SMiguel Ojeda     ///
819*c3739801SMiguel Ojeda     /// Callers may assume that, if `ptr` addresses a byte range whose length
820*c3739801SMiguel Ojeda     /// fits in an `usize`, this will return `Some`.
821*c3739801SMiguel Ojeda     #[doc(hidden)]
822*c3739801SMiguel Ojeda     #[must_use]
823*c3739801SMiguel Ojeda     #[inline(always)]
824*c3739801SMiguel Ojeda     fn size_of_val_raw(ptr: NonNull<Self>) -> Option<usize> {
825*c3739801SMiguel Ojeda         let meta = Self::pointer_to_metadata(ptr.as_ptr());
826*c3739801SMiguel Ojeda         // SAFETY: `size_for_metadata` promises to only return `None` if the
827*c3739801SMiguel Ojeda         // resulting size would not fit in a `usize`.
828*c3739801SMiguel Ojeda         Self::size_for_metadata(meta)
829*c3739801SMiguel Ojeda     }
830*c3739801SMiguel Ojeda 
831*c3739801SMiguel Ojeda     #[doc(hidden)]
832*c3739801SMiguel Ojeda     #[must_use]
833*c3739801SMiguel Ojeda     #[inline(always)]
834*c3739801SMiguel Ojeda     fn raw_dangling() -> NonNull<Self> {
835*c3739801SMiguel Ojeda         let meta = Self::PointerMetadata::from_elem_count(0);
836*c3739801SMiguel Ojeda         Self::raw_from_ptr_len(NonNull::dangling(), meta)
837*c3739801SMiguel Ojeda     }
838*c3739801SMiguel Ojeda 
839*c3739801SMiguel Ojeda     /// Computes the size of an object of type `Self` with the given pointer
840*c3739801SMiguel Ojeda     /// metadata.
841*c3739801SMiguel Ojeda     ///
842*c3739801SMiguel Ojeda     /// # Safety
843*c3739801SMiguel Ojeda     ///
844*c3739801SMiguel Ojeda     /// `size_for_metadata` promises to return `None` if and only if the
845*c3739801SMiguel Ojeda     /// resulting size would not fit in a [`usize`]. Note that the returned size
846*c3739801SMiguel Ojeda     /// could exceed the actual maximum valid size of an allocated object,
847*c3739801SMiguel Ojeda     /// [`isize::MAX`].
848*c3739801SMiguel Ojeda     ///
849*c3739801SMiguel Ojeda     /// # Examples
850*c3739801SMiguel Ojeda     ///
851*c3739801SMiguel Ojeda     /// ```
852*c3739801SMiguel Ojeda     /// use zerocopy::KnownLayout;
853*c3739801SMiguel Ojeda     ///
854*c3739801SMiguel Ojeda     /// assert_eq!(u8::size_for_metadata(()), Some(1));
855*c3739801SMiguel Ojeda     /// assert_eq!(u16::size_for_metadata(()), Some(2));
856*c3739801SMiguel Ojeda     /// assert_eq!(<[u8]>::size_for_metadata(42), Some(42));
857*c3739801SMiguel Ojeda     /// assert_eq!(<[u16]>::size_for_metadata(42), Some(84));
858*c3739801SMiguel Ojeda     ///
859*c3739801SMiguel Ojeda     /// // This size exceeds the maximum valid object size (`isize::MAX`):
860*c3739801SMiguel Ojeda     /// assert_eq!(<[u8]>::size_for_metadata(usize::MAX), Some(usize::MAX));
861*c3739801SMiguel Ojeda     ///
862*c3739801SMiguel Ojeda     /// // This size, if computed, would exceed `usize::MAX`:
863*c3739801SMiguel Ojeda     /// assert_eq!(<[u16]>::size_for_metadata(usize::MAX), None);
864*c3739801SMiguel Ojeda     /// ```
865*c3739801SMiguel Ojeda     #[inline(always)]
866*c3739801SMiguel Ojeda     fn size_for_metadata(meta: Self::PointerMetadata) -> Option<usize> {
867*c3739801SMiguel Ojeda         meta.size_for_metadata(Self::LAYOUT)
868*c3739801SMiguel Ojeda     }
869*c3739801SMiguel Ojeda 
870*c3739801SMiguel Ojeda     /// Computes whether `meta` can describe a valid allocation of `Self`.
871*c3739801SMiguel Ojeda     ///
872*c3739801SMiguel Ojeda     /// # Safety
873*c3739801SMiguel Ojeda     ///
874*c3739801SMiguel Ojeda     /// `is_valid_metadata` promises to return `true` if and only if the size of
875*c3739801SMiguel Ojeda     /// an allocation of `Self` with `meta` would not overflow an
876*c3739801SMiguel Ojeda     /// [`isize::MAX`].
877*c3739801SMiguel Ojeda     #[doc(hidden)]
878*c3739801SMiguel Ojeda     #[inline(always)]
879*c3739801SMiguel Ojeda     fn is_valid_metadata(meta: Self::PointerMetadata) -> bool {
880*c3739801SMiguel Ojeda         meta.to_elem_count() <= maximum_trailing_slice_len::<Self>().to_elem_count()
881*c3739801SMiguel Ojeda     }
882*c3739801SMiguel Ojeda }
883*c3739801SMiguel Ojeda 
884*c3739801SMiguel Ojeda /// Efficiently produces the [`TrailingSliceLayout`] of `T`.
885*c3739801SMiguel Ojeda #[inline(always)]
886*c3739801SMiguel Ojeda pub(crate) fn trailing_slice_layout<T>() -> TrailingSliceLayout
887*c3739801SMiguel Ojeda where
888*c3739801SMiguel Ojeda     T: ?Sized + KnownLayout<PointerMetadata = usize>,
889*c3739801SMiguel Ojeda {
890*c3739801SMiguel Ojeda     trait LayoutFacts {
891*c3739801SMiguel Ojeda         const SIZE_INFO: TrailingSliceLayout;
892*c3739801SMiguel Ojeda     }
893*c3739801SMiguel Ojeda 
894*c3739801SMiguel Ojeda     impl<T: ?Sized> LayoutFacts for T
895*c3739801SMiguel Ojeda     where
896*c3739801SMiguel Ojeda         T: KnownLayout<PointerMetadata = usize>,
897*c3739801SMiguel Ojeda     {
898*c3739801SMiguel Ojeda         const SIZE_INFO: TrailingSliceLayout = match T::LAYOUT.size_info {
899*c3739801SMiguel Ojeda             crate::SizeInfo::Sized { .. } => const_panic!("unreachable"),
900*c3739801SMiguel Ojeda             crate::SizeInfo::SliceDst(info) => info,
901*c3739801SMiguel Ojeda         };
902*c3739801SMiguel Ojeda     }
903*c3739801SMiguel Ojeda 
904*c3739801SMiguel Ojeda     T::SIZE_INFO
905*c3739801SMiguel Ojeda }
906*c3739801SMiguel Ojeda 
907*c3739801SMiguel Ojeda /// Efficiently produces the maximum trailing slice length `T`.
908*c3739801SMiguel Ojeda #[inline(always)]
909*c3739801SMiguel Ojeda pub(crate) fn maximum_trailing_slice_len<T>() -> usize
910*c3739801SMiguel Ojeda where
911*c3739801SMiguel Ojeda     T: ?Sized + KnownLayout,
912*c3739801SMiguel Ojeda {
913*c3739801SMiguel Ojeda     trait LayoutFacts {
914*c3739801SMiguel Ojeda         const MAX_LEN: usize;
915*c3739801SMiguel Ojeda     }
916*c3739801SMiguel Ojeda 
917*c3739801SMiguel Ojeda     impl<T: ?Sized> LayoutFacts for T
918*c3739801SMiguel Ojeda     where
919*c3739801SMiguel Ojeda         T: KnownLayout,
920*c3739801SMiguel Ojeda     {
921*c3739801SMiguel Ojeda         const MAX_LEN: usize = match T::LAYOUT.size_info {
922*c3739801SMiguel Ojeda             SizeInfo::SliceDst(TrailingSliceLayout { elem_size: 0, .. }) => usize::MAX,
923*c3739801SMiguel Ojeda             _ => match T::LAYOUT.validate_cast_and_convert_metadata(
924*c3739801SMiguel Ojeda                 T::LAYOUT.align.get(),
925*c3739801SMiguel Ojeda                 DstLayout::MAX_SIZE,
926*c3739801SMiguel Ojeda                 CastType::Prefix,
927*c3739801SMiguel Ojeda             ) {
928*c3739801SMiguel Ojeda                 Ok((elems, _)) => elems,
929*c3739801SMiguel Ojeda                 Err(_) => const_panic!("unreachable"),
930*c3739801SMiguel Ojeda             },
931*c3739801SMiguel Ojeda         };
932*c3739801SMiguel Ojeda     }
933*c3739801SMiguel Ojeda 
934*c3739801SMiguel Ojeda     T::MAX_LEN
935*c3739801SMiguel Ojeda }
936*c3739801SMiguel Ojeda 
937*c3739801SMiguel Ojeda /// The metadata associated with a [`KnownLayout`] type.
938*c3739801SMiguel Ojeda #[doc(hidden)]
939*c3739801SMiguel Ojeda pub trait PointerMetadata: Copy + Eq + Debug + Ord {
940*c3739801SMiguel Ojeda     /// Constructs a `Self` from an element count.
941*c3739801SMiguel Ojeda     ///
942*c3739801SMiguel Ojeda     /// If `Self = ()`, this returns `()`. If `Self = usize`, this returns
943*c3739801SMiguel Ojeda     /// `elems`. No other types are currently supported.
944*c3739801SMiguel Ojeda     fn from_elem_count(elems: usize) -> Self;
945*c3739801SMiguel Ojeda 
946*c3739801SMiguel Ojeda     /// Converts `self` to an element count.
947*c3739801SMiguel Ojeda     ///
948*c3739801SMiguel Ojeda     /// If `Self = ()`, this returns `0`. If `Self = usize`, this returns
949*c3739801SMiguel Ojeda     /// `self`. No other types are currently supported.
950*c3739801SMiguel Ojeda     fn to_elem_count(self) -> usize;
951*c3739801SMiguel Ojeda 
952*c3739801SMiguel Ojeda     /// Computes the size of the object with the given layout and pointer
953*c3739801SMiguel Ojeda     /// metadata.
954*c3739801SMiguel Ojeda     ///
955*c3739801SMiguel Ojeda     /// # Panics
956*c3739801SMiguel Ojeda     ///
957*c3739801SMiguel Ojeda     /// If `Self = ()`, `layout` must describe a sized type. If `Self = usize`,
958*c3739801SMiguel Ojeda     /// `layout` must describe a slice DST. Otherwise, `size_for_metadata` may
959*c3739801SMiguel Ojeda     /// panic.
960*c3739801SMiguel Ojeda     ///
961*c3739801SMiguel Ojeda     /// # Safety
962*c3739801SMiguel Ojeda     ///
963*c3739801SMiguel Ojeda     /// `size_for_metadata` promises to only return `None` if the resulting size
964*c3739801SMiguel Ojeda     /// would not fit in a `usize`.
965*c3739801SMiguel Ojeda     fn size_for_metadata(self, layout: DstLayout) -> Option<usize>;
966*c3739801SMiguel Ojeda }
967*c3739801SMiguel Ojeda 
968*c3739801SMiguel Ojeda impl PointerMetadata for () {
969*c3739801SMiguel Ojeda     #[inline]
970*c3739801SMiguel Ojeda     #[allow(clippy::unused_unit)]
971*c3739801SMiguel Ojeda     fn from_elem_count(_elems: usize) -> () {}
972*c3739801SMiguel Ojeda 
973*c3739801SMiguel Ojeda     #[inline]
974*c3739801SMiguel Ojeda     fn to_elem_count(self) -> usize {
975*c3739801SMiguel Ojeda         0
976*c3739801SMiguel Ojeda     }
977*c3739801SMiguel Ojeda 
978*c3739801SMiguel Ojeda     #[inline]
979*c3739801SMiguel Ojeda     fn size_for_metadata(self, layout: DstLayout) -> Option<usize> {
980*c3739801SMiguel Ojeda         match layout.size_info {
981*c3739801SMiguel Ojeda             SizeInfo::Sized { size } => Some(size),
982*c3739801SMiguel Ojeda             // NOTE: This branch is unreachable, but we return `None` rather
983*c3739801SMiguel Ojeda             // than `unreachable!()` to avoid generating panic paths.
984*c3739801SMiguel Ojeda             SizeInfo::SliceDst(_) => None,
985*c3739801SMiguel Ojeda         }
986*c3739801SMiguel Ojeda     }
987*c3739801SMiguel Ojeda }
988*c3739801SMiguel Ojeda 
989*c3739801SMiguel Ojeda impl PointerMetadata for usize {
990*c3739801SMiguel Ojeda     #[inline]
991*c3739801SMiguel Ojeda     fn from_elem_count(elems: usize) -> usize {
992*c3739801SMiguel Ojeda         elems
993*c3739801SMiguel Ojeda     }
994*c3739801SMiguel Ojeda 
995*c3739801SMiguel Ojeda     #[inline]
996*c3739801SMiguel Ojeda     fn to_elem_count(self) -> usize {
997*c3739801SMiguel Ojeda         self
998*c3739801SMiguel Ojeda     }
999*c3739801SMiguel Ojeda 
1000*c3739801SMiguel Ojeda     #[inline]
1001*c3739801SMiguel Ojeda     fn size_for_metadata(self, layout: DstLayout) -> Option<usize> {
1002*c3739801SMiguel Ojeda         match layout.size_info {
1003*c3739801SMiguel Ojeda             SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }) => {
1004*c3739801SMiguel Ojeda                 let slice_len = elem_size.checked_mul(self)?;
1005*c3739801SMiguel Ojeda                 let without_padding = offset.checked_add(slice_len)?;
1006*c3739801SMiguel Ojeda                 without_padding.checked_add(util::padding_needed_for(without_padding, layout.align))
1007*c3739801SMiguel Ojeda             }
1008*c3739801SMiguel Ojeda             // NOTE: This branch is unreachable, but we return `None` rather
1009*c3739801SMiguel Ojeda             // than `unreachable!()` to avoid generating panic paths.
1010*c3739801SMiguel Ojeda             SizeInfo::Sized { .. } => None,
1011*c3739801SMiguel Ojeda         }
1012*c3739801SMiguel Ojeda     }
1013*c3739801SMiguel Ojeda }
1014*c3739801SMiguel Ojeda 
1015*c3739801SMiguel Ojeda // SAFETY: Delegates safety to `DstLayout::for_slice`.
1016*c3739801SMiguel Ojeda unsafe impl<T> KnownLayout for [T] {
1017*c3739801SMiguel Ojeda     #[allow(clippy::missing_inline_in_public_items, dead_code)]
1018*c3739801SMiguel Ojeda     #[cfg_attr(
1019*c3739801SMiguel Ojeda         all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
1020*c3739801SMiguel Ojeda         coverage(off)
1021*c3739801SMiguel Ojeda     )]
1022*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
1023*c3739801SMiguel Ojeda     where
1024*c3739801SMiguel Ojeda         Self: Sized,
1025*c3739801SMiguel Ojeda     {
1026*c3739801SMiguel Ojeda     }
1027*c3739801SMiguel Ojeda 
1028*c3739801SMiguel Ojeda     type PointerMetadata = usize;
1029*c3739801SMiguel Ojeda 
1030*c3739801SMiguel Ojeda     // SAFETY: `CoreMaybeUninit<T>::LAYOUT` and `T::LAYOUT` are identical
1031*c3739801SMiguel Ojeda     // because `CoreMaybeUninit<T>` has the same size and alignment as `T` [1].
1032*c3739801SMiguel Ojeda     // Consequently, `[CoreMaybeUninit<T>]::LAYOUT` and `[T]::LAYOUT` are
1033*c3739801SMiguel Ojeda     // identical, because they both lack a fixed-sized prefix and because they
1034*c3739801SMiguel Ojeda     // inherit the alignments of their inner element type (which are identical)
1035*c3739801SMiguel Ojeda     // [2][3].
1036*c3739801SMiguel Ojeda     //
1037*c3739801SMiguel Ojeda     // `[CoreMaybeUninit<T>]` admits uninitialized bytes at all positions
1038*c3739801SMiguel Ojeda     // because `CoreMaybeUninit<T>` admits uninitialized bytes at all positions
1039*c3739801SMiguel Ojeda     // and because the inner elements of `[CoreMaybeUninit<T>]` are laid out
1040*c3739801SMiguel Ojeda     // back-to-back [2][3].
1041*c3739801SMiguel Ojeda     //
1042*c3739801SMiguel Ojeda     // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1:
1043*c3739801SMiguel Ojeda     //
1044*c3739801SMiguel Ojeda     //   `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as
1045*c3739801SMiguel Ojeda     //   `T`
1046*c3739801SMiguel Ojeda     //
1047*c3739801SMiguel Ojeda     // [2] Per https://doc.rust-lang.org/1.82.0/reference/type-layout.html#slice-layout:
1048*c3739801SMiguel Ojeda     //
1049*c3739801SMiguel Ojeda     //   Slices have the same layout as the section of the array they slice.
1050*c3739801SMiguel Ojeda     //
1051*c3739801SMiguel Ojeda     // [3] Per https://doc.rust-lang.org/1.82.0/reference/type-layout.html#array-layout:
1052*c3739801SMiguel Ojeda     //
1053*c3739801SMiguel Ojeda     //   An array of `[T; N]` has a size of `size_of::<T>() * N` and the same
1054*c3739801SMiguel Ojeda     //   alignment of `T`. Arrays are laid out so that the zero-based `nth`
1055*c3739801SMiguel Ojeda     //   element of the array is offset from the start of the array by `n *
1056*c3739801SMiguel Ojeda     //   size_of::<T>()` bytes.
1057*c3739801SMiguel Ojeda     type MaybeUninit = [CoreMaybeUninit<T>];
1058*c3739801SMiguel Ojeda 
1059*c3739801SMiguel Ojeda     const LAYOUT: DstLayout = DstLayout::for_slice::<T>();
1060*c3739801SMiguel Ojeda 
1061*c3739801SMiguel Ojeda     // SAFETY: `.cast` preserves address and provenance. The returned pointer
1062*c3739801SMiguel Ojeda     // refers to an object with `elems` elements by construction.
1063*c3739801SMiguel Ojeda     #[inline(always)]
1064*c3739801SMiguel Ojeda     fn raw_from_ptr_len(data: NonNull<u8>, elems: usize) -> NonNull<Self> {
1065*c3739801SMiguel Ojeda         // FIXME(#67): Remove this allow. See NonNullExt for more details.
1066*c3739801SMiguel Ojeda         #[allow(unstable_name_collisions)]
1067*c3739801SMiguel Ojeda         NonNull::slice_from_raw_parts(data.cast::<T>(), elems)
1068*c3739801SMiguel Ojeda     }
1069*c3739801SMiguel Ojeda 
1070*c3739801SMiguel Ojeda     #[inline(always)]
1071*c3739801SMiguel Ojeda     fn pointer_to_metadata(ptr: *mut [T]) -> usize {
1072*c3739801SMiguel Ojeda         #[allow(clippy::as_conversions)]
1073*c3739801SMiguel Ojeda         let slc = ptr as *const [()];
1074*c3739801SMiguel Ojeda 
1075*c3739801SMiguel Ojeda         // SAFETY:
1076*c3739801SMiguel Ojeda         // - `()` has alignment 1, so `slc` is trivially aligned.
1077*c3739801SMiguel Ojeda         // - `slc` was derived from a non-null pointer.
1078*c3739801SMiguel Ojeda         // - The size is 0 regardless of the length, so it is sound to
1079*c3739801SMiguel Ojeda         //   materialize a reference regardless of location.
1080*c3739801SMiguel Ojeda         // - By invariant, `self.ptr` has valid provenance.
1081*c3739801SMiguel Ojeda         let slc = unsafe { &*slc };
1082*c3739801SMiguel Ojeda 
1083*c3739801SMiguel Ojeda         // This is correct because the preceding `as` cast preserves the number
1084*c3739801SMiguel Ojeda         // of slice elements. [1]
1085*c3739801SMiguel Ojeda         //
1086*c3739801SMiguel Ojeda         // [1] Per https://doc.rust-lang.org/reference/expressions/operator-expr.html#pointer-to-pointer-cast:
1087*c3739801SMiguel Ojeda         //
1088*c3739801SMiguel Ojeda         //   For slice types like `[T]` and `[U]`, the raw pointer types `*const
1089*c3739801SMiguel Ojeda         //   [T]`, `*mut [T]`, `*const [U]`, and `*mut [U]` encode the number of
1090*c3739801SMiguel Ojeda         //   elements in this slice. Casts between these raw pointer types
1091*c3739801SMiguel Ojeda         //   preserve the number of elements. ... The same holds for `str` and
1092*c3739801SMiguel Ojeda         //   any compound type whose unsized tail is a slice type, such as
1093*c3739801SMiguel Ojeda         //   struct `Foo(i32, [u8])` or `(u64, Foo)`.
1094*c3739801SMiguel Ojeda         slc.len()
1095*c3739801SMiguel Ojeda     }
1096*c3739801SMiguel Ojeda }
1097*c3739801SMiguel Ojeda 
1098*c3739801SMiguel Ojeda #[rustfmt::skip]
1099*c3739801SMiguel Ojeda impl_known_layout!(
1100*c3739801SMiguel Ojeda     (),
1101*c3739801SMiguel Ojeda     u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64,
1102*c3739801SMiguel Ojeda     bool, char,
1103*c3739801SMiguel Ojeda     NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32,
1104*c3739801SMiguel Ojeda     NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize
1105*c3739801SMiguel Ojeda );
1106*c3739801SMiguel Ojeda #[rustfmt::skip]
1107*c3739801SMiguel Ojeda #[cfg(feature = "float-nightly")]
1108*c3739801SMiguel Ojeda impl_known_layout!(
1109*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))]
1110*c3739801SMiguel Ojeda     f16,
1111*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(feature = "float-nightly")))]
1112*c3739801SMiguel Ojeda     f128
1113*c3739801SMiguel Ojeda );
1114*c3739801SMiguel Ojeda #[rustfmt::skip]
1115*c3739801SMiguel Ojeda impl_known_layout!(
1116*c3739801SMiguel Ojeda     T         => Option<T>,
1117*c3739801SMiguel Ojeda     T: ?Sized => PhantomData<T>,
1118*c3739801SMiguel Ojeda     T         => Wrapping<T>,
1119*c3739801SMiguel Ojeda     T         => CoreMaybeUninit<T>,
1120*c3739801SMiguel Ojeda     T: ?Sized => *const T,
1121*c3739801SMiguel Ojeda     T: ?Sized => *mut T,
1122*c3739801SMiguel Ojeda     T: ?Sized => &'_ T,
1123*c3739801SMiguel Ojeda     T: ?Sized => &'_ mut T,
1124*c3739801SMiguel Ojeda );
1125*c3739801SMiguel Ojeda impl_known_layout!(const N: usize, T => [T; N]);
1126*c3739801SMiguel Ojeda 
1127*c3739801SMiguel Ojeda // SAFETY: `str` has the same representation as `[u8]`. `ManuallyDrop<T>` [1],
1128*c3739801SMiguel Ojeda // `UnsafeCell<T>` [2], and `Cell<T>` [3] have the same representation as `T`.
1129*c3739801SMiguel Ojeda //
1130*c3739801SMiguel Ojeda // [1] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html:
1131*c3739801SMiguel Ojeda //
1132*c3739801SMiguel Ojeda //   `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
1133*c3739801SMiguel Ojeda //   `T`
1134*c3739801SMiguel Ojeda //
1135*c3739801SMiguel Ojeda // [2] Per https://doc.rust-lang.org/1.85.0/core/cell/struct.UnsafeCell.html#memory-layout:
1136*c3739801SMiguel Ojeda //
1137*c3739801SMiguel Ojeda //   `UnsafeCell<T>` has the same in-memory representation as its inner type
1138*c3739801SMiguel Ojeda //   `T`.
1139*c3739801SMiguel Ojeda //
1140*c3739801SMiguel Ojeda // [3] Per https://doc.rust-lang.org/1.85.0/core/cell/struct.Cell.html#memory-layout:
1141*c3739801SMiguel Ojeda //
1142*c3739801SMiguel Ojeda //   `Cell<T>` has the same in-memory representation as `T`.
1143*c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)]
1144*c3739801SMiguel Ojeda const _: () = unsafe {
1145*c3739801SMiguel Ojeda     unsafe_impl_known_layout!(
1146*c3739801SMiguel Ojeda         #[repr([u8])]
1147*c3739801SMiguel Ojeda         str
1148*c3739801SMiguel Ojeda     );
1149*c3739801SMiguel Ojeda     unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] ManuallyDrop<T>);
1150*c3739801SMiguel Ojeda     unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] UnsafeCell<T>);
1151*c3739801SMiguel Ojeda     unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] Cell<T>);
1152*c3739801SMiguel Ojeda };
1153*c3739801SMiguel Ojeda 
1154*c3739801SMiguel Ojeda // SAFETY:
1155*c3739801SMiguel Ojeda // - By consequence of the invariant on `T::MaybeUninit` that `T::LAYOUT` and
1156*c3739801SMiguel Ojeda //   `T::MaybeUninit::LAYOUT` are equal, `T` and `T::MaybeUninit` have the same:
1157*c3739801SMiguel Ojeda //   - Fixed prefix size
1158*c3739801SMiguel Ojeda //   - Alignment
1159*c3739801SMiguel Ojeda //   - (For DSTs) trailing slice element size
1160*c3739801SMiguel Ojeda // - By consequence of the above, referents `T::MaybeUninit` and `T` have the
1161*c3739801SMiguel Ojeda //   require the same kind of pointer metadata, and thus it is valid to perform
1162*c3739801SMiguel Ojeda //   an `as` cast from `*mut T` and `*mut T::MaybeUninit`, and this operation
1163*c3739801SMiguel Ojeda //   preserves referent size (ie, `size_of_val_raw`).
1164*c3739801SMiguel Ojeda const _: () = unsafe {
1165*c3739801SMiguel Ojeda     unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T::MaybeUninit)] MaybeUninit<T>)
1166*c3739801SMiguel Ojeda };
1167*c3739801SMiguel Ojeda 
1168*c3739801SMiguel Ojeda // FIXME(#196, #2856): Eventually, we'll want to support enums variants and
1169*c3739801SMiguel Ojeda // union fields being treated uniformly since they behave similarly to each
1170*c3739801SMiguel Ojeda // other in terms of projecting validity – specifically, for a type `T` with
1171*c3739801SMiguel Ojeda // validity `V`, if `T` is a struct type, then its fields straightforwardly also
1172*c3739801SMiguel Ojeda // have validity `V`. By contrast, if `T` is an enum or union type, then
1173*c3739801SMiguel Ojeda // validity is not straightforwardly recursive in this way.
1174*c3739801SMiguel Ojeda #[doc(hidden)]
1175*c3739801SMiguel Ojeda pub const STRUCT_VARIANT_ID: i128 = -1;
1176*c3739801SMiguel Ojeda #[doc(hidden)]
1177*c3739801SMiguel Ojeda pub const UNION_VARIANT_ID: i128 = -2;
1178*c3739801SMiguel Ojeda #[doc(hidden)]
1179*c3739801SMiguel Ojeda pub const REPR_C_UNION_VARIANT_ID: i128 = -3;
1180*c3739801SMiguel Ojeda 
1181*c3739801SMiguel Ojeda /// # Safety
1182*c3739801SMiguel Ojeda ///
1183*c3739801SMiguel Ojeda /// `Self::ProjectToTag` must satisfy its safety invariant.
1184*c3739801SMiguel Ojeda #[doc(hidden)]
1185*c3739801SMiguel Ojeda pub unsafe trait HasTag {
1186*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
1187*c3739801SMiguel Ojeda     where
1188*c3739801SMiguel Ojeda         Self: Sized;
1189*c3739801SMiguel Ojeda 
1190*c3739801SMiguel Ojeda     /// The type's enum tag, or `()` for non-enum types.
1191*c3739801SMiguel Ojeda     type Tag: Immutable;
1192*c3739801SMiguel Ojeda 
1193*c3739801SMiguel Ojeda     /// A pointer projection from `Self` to its tag.
1194*c3739801SMiguel Ojeda     ///
1195*c3739801SMiguel Ojeda     /// # Safety
1196*c3739801SMiguel Ojeda     ///
1197*c3739801SMiguel Ojeda     /// It must be the case that, for all `slf: Ptr<'_, Self, I>`, it is sound
1198*c3739801SMiguel Ojeda     /// to project from `slf` to `Ptr<'_, Self::Tag, I>` using this projection.
1199*c3739801SMiguel Ojeda     type ProjectToTag: pointer::cast::Project<Self, Self::Tag>;
1200*c3739801SMiguel Ojeda }
1201*c3739801SMiguel Ojeda 
1202*c3739801SMiguel Ojeda /// Projects a given field from `Self`.
1203*c3739801SMiguel Ojeda ///
1204*c3739801SMiguel Ojeda /// All implementations of `HasField` for a particular field `f` in `Self`
1205*c3739801SMiguel Ojeda /// should use the same `Field` type; this ensures that `Field` is inferable
1206*c3739801SMiguel Ojeda /// given an explicit `VARIANT_ID` and `FIELD_ID`.
1207*c3739801SMiguel Ojeda ///
1208*c3739801SMiguel Ojeda /// # Safety
1209*c3739801SMiguel Ojeda ///
1210*c3739801SMiguel Ojeda /// A field `f` is `HasField` for `Self` if and only if:
1211*c3739801SMiguel Ojeda ///
1212*c3739801SMiguel Ojeda /// - If `Self` has the layout of a struct or union type, then `VARIANT_ID` is
1213*c3739801SMiguel Ojeda ///   `STRUCT_VARIANT_ID` or `UNION_VARIANT_ID` respectively; otherwise, if
1214*c3739801SMiguel Ojeda ///   `Self` has the layout of an enum type, `VARIANT_ID` is the numerical index
1215*c3739801SMiguel Ojeda ///   of the enum variant in which `f` appears. Note that `Self` does not need
1216*c3739801SMiguel Ojeda ///   to actually *be* such a type – it just needs to have the same layout as
1217*c3739801SMiguel Ojeda ///   such a type. For example, a `#[repr(transparent)]` wrapper around an enum
1218*c3739801SMiguel Ojeda ///   has the same layout as that enum.
1219*c3739801SMiguel Ojeda /// - If `f` has name `n`, `FIELD_ID` is `zerocopy::ident_id!(n)`; otherwise,
1220*c3739801SMiguel Ojeda ///   if `f` is at index `i`, `FIELD_ID` is `zerocopy::ident_id!(i)`.
1221*c3739801SMiguel Ojeda /// - `Field` is a type with the same visibility as `f`.
1222*c3739801SMiguel Ojeda /// - `Type` has the same type as `f`.
1223*c3739801SMiguel Ojeda ///
1224*c3739801SMiguel Ojeda /// The caller must **not** assume that a pointer's referent being aligned
1225*c3739801SMiguel Ojeda /// implies that calling `project` on that pointer will result in a pointer to
1226*c3739801SMiguel Ojeda /// an aligned referent. For example, `HasField` may be implemented for
1227*c3739801SMiguel Ojeda /// `#[repr(packed)]` structs.
1228*c3739801SMiguel Ojeda ///
1229*c3739801SMiguel Ojeda /// The implementation of `project` must satisfy its safety post-condition.
1230*c3739801SMiguel Ojeda #[doc(hidden)]
1231*c3739801SMiguel Ojeda pub unsafe trait HasField<Field, const VARIANT_ID: i128, const FIELD_ID: i128>:
1232*c3739801SMiguel Ojeda     HasTag
1233*c3739801SMiguel Ojeda {
1234*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
1235*c3739801SMiguel Ojeda     where
1236*c3739801SMiguel Ojeda         Self: Sized;
1237*c3739801SMiguel Ojeda 
1238*c3739801SMiguel Ojeda     /// The type of the field.
1239*c3739801SMiguel Ojeda     type Type: ?Sized;
1240*c3739801SMiguel Ojeda 
1241*c3739801SMiguel Ojeda     /// Projects from `slf` to the field.
1242*c3739801SMiguel Ojeda     ///
1243*c3739801SMiguel Ojeda     /// Users should generally not call `project` directly, and instead should
1244*c3739801SMiguel Ojeda     /// use high-level APIs like [`PtrInner::project`] or [`Ptr::project`].
1245*c3739801SMiguel Ojeda     ///
1246*c3739801SMiguel Ojeda     /// # Safety
1247*c3739801SMiguel Ojeda     ///
1248*c3739801SMiguel Ojeda     /// The returned pointer refers to a non-strict subset of the bytes of
1249*c3739801SMiguel Ojeda     /// `slf`'s referent, and has the same provenance as `slf`.
1250*c3739801SMiguel Ojeda     #[must_use]
1251*c3739801SMiguel Ojeda     fn project(slf: PtrInner<'_, Self>) -> *mut Self::Type;
1252*c3739801SMiguel Ojeda }
1253*c3739801SMiguel Ojeda 
1254*c3739801SMiguel Ojeda /// Projects a given field from `Self`.
1255*c3739801SMiguel Ojeda ///
1256*c3739801SMiguel Ojeda /// Implementations of this trait encode the conditions under which a field can
1257*c3739801SMiguel Ojeda /// be projected from a `Ptr<'_, Self, I>`, and how the invariants of that
1258*c3739801SMiguel Ojeda /// [`Ptr`] (`I`) determine the invariants of pointers projected from it. In
1259*c3739801SMiguel Ojeda /// other words, it is a type-level function over invariants; `I` goes in,
1260*c3739801SMiguel Ojeda /// `Self::Invariants` comes out.
1261*c3739801SMiguel Ojeda ///
1262*c3739801SMiguel Ojeda /// # Safety
1263*c3739801SMiguel Ojeda ///
1264*c3739801SMiguel Ojeda /// `T: ProjectField<Field, I, VARIANT_ID, FIELD_ID>` if, for a
1265*c3739801SMiguel Ojeda /// `ptr: Ptr<'_, T, I>` such that `T::is_projectable(ptr).is_ok()`,
1266*c3739801SMiguel Ojeda /// `<T as HasField<Field, VARIANT_ID, FIELD_ID>>::project(ptr.as_inner())`
1267*c3739801SMiguel Ojeda /// conforms to `T::Invariants`.
1268*c3739801SMiguel Ojeda #[doc(hidden)]
1269*c3739801SMiguel Ojeda pub unsafe trait ProjectField<Field, I, const VARIANT_ID: i128, const FIELD_ID: i128>:
1270*c3739801SMiguel Ojeda     HasField<Field, VARIANT_ID, FIELD_ID>
1271*c3739801SMiguel Ojeda where
1272*c3739801SMiguel Ojeda     I: invariant::Invariants,
1273*c3739801SMiguel Ojeda {
1274*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
1275*c3739801SMiguel Ojeda     where
1276*c3739801SMiguel Ojeda         Self: Sized;
1277*c3739801SMiguel Ojeda 
1278*c3739801SMiguel Ojeda     /// The invariants of the projected field pointer, with respect to the
1279*c3739801SMiguel Ojeda     /// invariants, `I`, of the containing pointer. The aliasing dimension of
1280*c3739801SMiguel Ojeda     /// the invariants is guaranteed to remain unchanged.
1281*c3739801SMiguel Ojeda     type Invariants: invariant::Invariants<Aliasing = I::Aliasing>;
1282*c3739801SMiguel Ojeda 
1283*c3739801SMiguel Ojeda     /// The failure mode of projection. `()` if the projection is fallible,
1284*c3739801SMiguel Ojeda     /// otherwise [`core::convert::Infallible`].
1285*c3739801SMiguel Ojeda     type Error;
1286*c3739801SMiguel Ojeda 
1287*c3739801SMiguel Ojeda     /// Is the given field projectable from `ptr`?
1288*c3739801SMiguel Ojeda     ///
1289*c3739801SMiguel Ojeda     /// If a field with [`Self::Invariants`] is projectable from the referent,
1290*c3739801SMiguel Ojeda     /// this function produces an `Ok(ptr)` from which the projection can be
1291*c3739801SMiguel Ojeda     /// made; otherwise `Err`.
1292*c3739801SMiguel Ojeda     ///
1293*c3739801SMiguel Ojeda     /// This method must be overriden if the field's projectability depends on
1294*c3739801SMiguel Ojeda     /// the value of the bytes in `ptr`.
1295*c3739801SMiguel Ojeda     #[inline(always)]
1296*c3739801SMiguel Ojeda     fn is_projectable<'a>(_ptr: Ptr<'a, Self::Tag, I>) -> Result<(), Self::Error> {
1297*c3739801SMiguel Ojeda         trait IsInfallible {
1298*c3739801SMiguel Ojeda             const IS_INFALLIBLE: bool;
1299*c3739801SMiguel Ojeda         }
1300*c3739801SMiguel Ojeda 
1301*c3739801SMiguel Ojeda         struct Projection<T, Field, I, const VARIANT_ID: i128, const FIELD_ID: i128>(
1302*c3739801SMiguel Ojeda             PhantomData<(Field, I, T)>,
1303*c3739801SMiguel Ojeda         )
1304*c3739801SMiguel Ojeda         where
1305*c3739801SMiguel Ojeda             T: ?Sized + HasField<Field, VARIANT_ID, FIELD_ID>,
1306*c3739801SMiguel Ojeda             I: invariant::Invariants;
1307*c3739801SMiguel Ojeda 
1308*c3739801SMiguel Ojeda         impl<T, Field, I, const VARIANT_ID: i128, const FIELD_ID: i128> IsInfallible
1309*c3739801SMiguel Ojeda             for Projection<T, Field, I, VARIANT_ID, FIELD_ID>
1310*c3739801SMiguel Ojeda         where
1311*c3739801SMiguel Ojeda             T: ?Sized + HasField<Field, VARIANT_ID, FIELD_ID>,
1312*c3739801SMiguel Ojeda             I: invariant::Invariants,
1313*c3739801SMiguel Ojeda         {
1314*c3739801SMiguel Ojeda             const IS_INFALLIBLE: bool = {
1315*c3739801SMiguel Ojeda                 let is_infallible = match VARIANT_ID {
1316*c3739801SMiguel Ojeda                     // For nondestructive projections of struct and union
1317*c3739801SMiguel Ojeda                     // fields, the projected field's satisfaction of
1318*c3739801SMiguel Ojeda                     // `Invariants` does not depend on the value of the
1319*c3739801SMiguel Ojeda                     // referent. This default implementation of `is_projectable`
1320*c3739801SMiguel Ojeda                     // is non-destructive, as it does not overwrite any part of
1321*c3739801SMiguel Ojeda                     // the referent.
1322*c3739801SMiguel Ojeda                     crate::STRUCT_VARIANT_ID | crate::UNION_VARIANT_ID => true,
1323*c3739801SMiguel Ojeda                     _enum_variant => {
1324*c3739801SMiguel Ojeda                         use crate::invariant::{Validity, ValidityKind};
1325*c3739801SMiguel Ojeda                         match I::Validity::KIND {
1326*c3739801SMiguel Ojeda                             // The `Uninit` and `Initialized` validity
1327*c3739801SMiguel Ojeda                             // invariants do not depend on the enum's tag. In
1328*c3739801SMiguel Ojeda                             // particular, we don't actually care about what
1329*c3739801SMiguel Ojeda                             // variant is present – we can treat *any* range of
1330*c3739801SMiguel Ojeda                             // uninitialized or initialized memory as containing
1331*c3739801SMiguel Ojeda                             // an uninitialized or initialized instance of *any*
1332*c3739801SMiguel Ojeda                             // type – the type itself is irrelevant.
1333*c3739801SMiguel Ojeda                             ValidityKind::Uninit | ValidityKind::Initialized => true,
1334*c3739801SMiguel Ojeda                             // The projectability of an enum field from an
1335*c3739801SMiguel Ojeda                             // `AsInitialized` or `Valid` state is a dynamic
1336*c3739801SMiguel Ojeda                             // property of its tag.
1337*c3739801SMiguel Ojeda                             ValidityKind::AsInitialized | ValidityKind::Valid => false,
1338*c3739801SMiguel Ojeda                         }
1339*c3739801SMiguel Ojeda                     }
1340*c3739801SMiguel Ojeda                 };
1341*c3739801SMiguel Ojeda                 const_assert!(is_infallible);
1342*c3739801SMiguel Ojeda                 is_infallible
1343*c3739801SMiguel Ojeda             };
1344*c3739801SMiguel Ojeda         }
1345*c3739801SMiguel Ojeda 
1346*c3739801SMiguel Ojeda         const_assert!(
1347*c3739801SMiguel Ojeda             <Projection<Self, Field, I, VARIANT_ID, FIELD_ID> as IsInfallible>::IS_INFALLIBLE
1348*c3739801SMiguel Ojeda         );
1349*c3739801SMiguel Ojeda 
1350*c3739801SMiguel Ojeda         Ok(())
1351*c3739801SMiguel Ojeda     }
1352*c3739801SMiguel Ojeda }
1353*c3739801SMiguel Ojeda 
1354*c3739801SMiguel Ojeda /// Analyzes whether a type is [`FromZeros`].
1355*c3739801SMiguel Ojeda ///
1356*c3739801SMiguel Ojeda /// This derive analyzes, at compile time, whether the annotated type satisfies
1357*c3739801SMiguel Ojeda /// the [safety conditions] of `FromZeros` and implements `FromZeros` and its
1358*c3739801SMiguel Ojeda /// supertraits if it is sound to do so. This derive can be applied to structs,
1359*c3739801SMiguel Ojeda /// enums, and unions; e.g.:
1360*c3739801SMiguel Ojeda ///
1361*c3739801SMiguel Ojeda /// ```
1362*c3739801SMiguel Ojeda /// # use zerocopy_derive::{FromZeros, Immutable};
1363*c3739801SMiguel Ojeda /// #[derive(FromZeros)]
1364*c3739801SMiguel Ojeda /// struct MyStruct {
1365*c3739801SMiguel Ojeda /// # /*
1366*c3739801SMiguel Ojeda ///     ...
1367*c3739801SMiguel Ojeda /// # */
1368*c3739801SMiguel Ojeda /// }
1369*c3739801SMiguel Ojeda ///
1370*c3739801SMiguel Ojeda /// #[derive(FromZeros)]
1371*c3739801SMiguel Ojeda /// #[repr(u8)]
1372*c3739801SMiguel Ojeda /// enum MyEnum {
1373*c3739801SMiguel Ojeda /// #   Variant0,
1374*c3739801SMiguel Ojeda /// # /*
1375*c3739801SMiguel Ojeda ///     ...
1376*c3739801SMiguel Ojeda /// # */
1377*c3739801SMiguel Ojeda /// }
1378*c3739801SMiguel Ojeda ///
1379*c3739801SMiguel Ojeda /// #[derive(FromZeros, Immutable)]
1380*c3739801SMiguel Ojeda /// union MyUnion {
1381*c3739801SMiguel Ojeda /// #   variant: u8,
1382*c3739801SMiguel Ojeda /// # /*
1383*c3739801SMiguel Ojeda ///     ...
1384*c3739801SMiguel Ojeda /// # */
1385*c3739801SMiguel Ojeda /// }
1386*c3739801SMiguel Ojeda /// ```
1387*c3739801SMiguel Ojeda ///
1388*c3739801SMiguel Ojeda /// [safety conditions]: trait@FromZeros#safety
1389*c3739801SMiguel Ojeda ///
1390*c3739801SMiguel Ojeda /// # Analysis
1391*c3739801SMiguel Ojeda ///
1392*c3739801SMiguel Ojeda /// *This section describes, roughly, the analysis performed by this derive to
1393*c3739801SMiguel Ojeda /// determine whether it is sound to implement `FromZeros` for a given type.
1394*c3739801SMiguel Ojeda /// Unless you are modifying the implementation of this derive, or attempting to
1395*c3739801SMiguel Ojeda /// manually implement `FromZeros` for a type yourself, you don't need to read
1396*c3739801SMiguel Ojeda /// this section.*
1397*c3739801SMiguel Ojeda ///
1398*c3739801SMiguel Ojeda /// If a type has the following properties, then this derive can implement
1399*c3739801SMiguel Ojeda /// `FromZeros` for that type:
1400*c3739801SMiguel Ojeda ///
1401*c3739801SMiguel Ojeda /// - If the type is a struct, all of its fields must be `FromZeros`.
1402*c3739801SMiguel Ojeda /// - If the type is an enum:
1403*c3739801SMiguel Ojeda ///   - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`,
1404*c3739801SMiguel Ojeda ///     `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`).
1405*c3739801SMiguel Ojeda ///   - It must have a variant with a discriminant/tag of `0`, and its fields
1406*c3739801SMiguel Ojeda ///     must be `FromZeros`. See [the reference] for a description of
1407*c3739801SMiguel Ojeda ///     discriminant values are specified.
1408*c3739801SMiguel Ojeda ///   - The fields of that variant must be `FromZeros`.
1409*c3739801SMiguel Ojeda ///
1410*c3739801SMiguel Ojeda /// This analysis is subject to change. Unsafe code may *only* rely on the
1411*c3739801SMiguel Ojeda /// documented [safety conditions] of `FromZeros`, and must *not* rely on the
1412*c3739801SMiguel Ojeda /// implementation details of this derive.
1413*c3739801SMiguel Ojeda ///
1414*c3739801SMiguel Ojeda /// [the reference]: https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations
1415*c3739801SMiguel Ojeda ///
1416*c3739801SMiguel Ojeda /// ## Why isn't an explicit representation required for structs?
1417*c3739801SMiguel Ojeda ///
1418*c3739801SMiguel Ojeda /// Neither this derive, nor the [safety conditions] of `FromZeros`, requires
1419*c3739801SMiguel Ojeda /// that structs are marked with `#[repr(C)]`.
1420*c3739801SMiguel Ojeda ///
1421*c3739801SMiguel Ojeda /// Per the [Rust reference](reference),
1422*c3739801SMiguel Ojeda ///
1423*c3739801SMiguel Ojeda /// > The representation of a type can change the padding between fields, but
1424*c3739801SMiguel Ojeda /// > does not change the layout of the fields themselves.
1425*c3739801SMiguel Ojeda ///
1426*c3739801SMiguel Ojeda /// [reference]: https://doc.rust-lang.org/reference/type-layout.html#representations
1427*c3739801SMiguel Ojeda ///
1428*c3739801SMiguel Ojeda /// Since the layout of structs only consists of padding bytes and field bytes,
1429*c3739801SMiguel Ojeda /// a struct is soundly `FromZeros` if:
1430*c3739801SMiguel Ojeda /// 1. its padding is soundly `FromZeros`, and
1431*c3739801SMiguel Ojeda /// 2. its fields are soundly `FromZeros`.
1432*c3739801SMiguel Ojeda ///
1433*c3739801SMiguel Ojeda /// The answer to the first question is always yes: padding bytes do not have
1434*c3739801SMiguel Ojeda /// any validity constraints. A [discussion] of this question in the Unsafe Code
1435*c3739801SMiguel Ojeda /// Guidelines Working Group concluded that it would be virtually unimaginable
1436*c3739801SMiguel Ojeda /// for future versions of rustc to add validity constraints to padding bytes.
1437*c3739801SMiguel Ojeda ///
1438*c3739801SMiguel Ojeda /// [discussion]: https://github.com/rust-lang/unsafe-code-guidelines/issues/174
1439*c3739801SMiguel Ojeda ///
1440*c3739801SMiguel Ojeda /// Whether a struct is soundly `FromZeros` therefore solely depends on whether
1441*c3739801SMiguel Ojeda /// its fields are `FromZeros`.
1442*c3739801SMiguel Ojeda // FIXME(#146): Document why we don't require an enum to have an explicit `repr`
1443*c3739801SMiguel Ojeda // attribute.
1444*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
1445*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
1446*c3739801SMiguel Ojeda pub use zerocopy_derive::FromZeros;
1447*c3739801SMiguel Ojeda /// Analyzes whether a type is [`Immutable`].
1448*c3739801SMiguel Ojeda ///
1449*c3739801SMiguel Ojeda /// This derive analyzes, at compile time, whether the annotated type satisfies
1450*c3739801SMiguel Ojeda /// the [safety conditions] of `Immutable` and implements `Immutable` if it is
1451*c3739801SMiguel Ojeda /// sound to do so. This derive can be applied to structs, enums, and unions;
1452*c3739801SMiguel Ojeda /// e.g.:
1453*c3739801SMiguel Ojeda ///
1454*c3739801SMiguel Ojeda /// ```
1455*c3739801SMiguel Ojeda /// # use zerocopy_derive::Immutable;
1456*c3739801SMiguel Ojeda /// #[derive(Immutable)]
1457*c3739801SMiguel Ojeda /// struct MyStruct {
1458*c3739801SMiguel Ojeda /// # /*
1459*c3739801SMiguel Ojeda ///     ...
1460*c3739801SMiguel Ojeda /// # */
1461*c3739801SMiguel Ojeda /// }
1462*c3739801SMiguel Ojeda ///
1463*c3739801SMiguel Ojeda /// #[derive(Immutable)]
1464*c3739801SMiguel Ojeda /// enum MyEnum {
1465*c3739801SMiguel Ojeda /// #   Variant0,
1466*c3739801SMiguel Ojeda /// # /*
1467*c3739801SMiguel Ojeda ///     ...
1468*c3739801SMiguel Ojeda /// # */
1469*c3739801SMiguel Ojeda /// }
1470*c3739801SMiguel Ojeda ///
1471*c3739801SMiguel Ojeda /// #[derive(Immutable)]
1472*c3739801SMiguel Ojeda /// union MyUnion {
1473*c3739801SMiguel Ojeda /// #   variant: u8,
1474*c3739801SMiguel Ojeda /// # /*
1475*c3739801SMiguel Ojeda ///     ...
1476*c3739801SMiguel Ojeda /// # */
1477*c3739801SMiguel Ojeda /// }
1478*c3739801SMiguel Ojeda /// ```
1479*c3739801SMiguel Ojeda ///
1480*c3739801SMiguel Ojeda /// # Analysis
1481*c3739801SMiguel Ojeda ///
1482*c3739801SMiguel Ojeda /// *This section describes, roughly, the analysis performed by this derive to
1483*c3739801SMiguel Ojeda /// determine whether it is sound to implement `Immutable` for a given type.
1484*c3739801SMiguel Ojeda /// Unless you are modifying the implementation of this derive, you don't need
1485*c3739801SMiguel Ojeda /// to read this section.*
1486*c3739801SMiguel Ojeda ///
1487*c3739801SMiguel Ojeda /// If a type has the following properties, then this derive can implement
1488*c3739801SMiguel Ojeda /// `Immutable` for that type:
1489*c3739801SMiguel Ojeda ///
1490*c3739801SMiguel Ojeda /// - All fields must be `Immutable`.
1491*c3739801SMiguel Ojeda ///
1492*c3739801SMiguel Ojeda /// This analysis is subject to change. Unsafe code may *only* rely on the
1493*c3739801SMiguel Ojeda /// documented [safety conditions] of `Immutable`, and must *not* rely on the
1494*c3739801SMiguel Ojeda /// implementation details of this derive.
1495*c3739801SMiguel Ojeda ///
1496*c3739801SMiguel Ojeda /// [safety conditions]: trait@Immutable#safety
1497*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
1498*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
1499*c3739801SMiguel Ojeda pub use zerocopy_derive::Immutable;
1500*c3739801SMiguel Ojeda 
1501*c3739801SMiguel Ojeda /// Types which are free from interior mutability.
1502*c3739801SMiguel Ojeda ///
1503*c3739801SMiguel Ojeda /// `T: Immutable` indicates that `T` does not permit interior mutation, except
1504*c3739801SMiguel Ojeda /// by ownership or an exclusive (`&mut`) borrow.
1505*c3739801SMiguel Ojeda ///
1506*c3739801SMiguel Ojeda /// # Implementation
1507*c3739801SMiguel Ojeda ///
1508*c3739801SMiguel Ojeda /// **Do not implement this trait yourself!** Instead, use
1509*c3739801SMiguel Ojeda /// [`#[derive(Immutable)]`][derive] (requires the `derive` Cargo feature);
1510*c3739801SMiguel Ojeda /// e.g.:
1511*c3739801SMiguel Ojeda ///
1512*c3739801SMiguel Ojeda /// ```
1513*c3739801SMiguel Ojeda /// # use zerocopy_derive::Immutable;
1514*c3739801SMiguel Ojeda /// #[derive(Immutable)]
1515*c3739801SMiguel Ojeda /// struct MyStruct {
1516*c3739801SMiguel Ojeda /// # /*
1517*c3739801SMiguel Ojeda ///     ...
1518*c3739801SMiguel Ojeda /// # */
1519*c3739801SMiguel Ojeda /// }
1520*c3739801SMiguel Ojeda ///
1521*c3739801SMiguel Ojeda /// #[derive(Immutable)]
1522*c3739801SMiguel Ojeda /// enum MyEnum {
1523*c3739801SMiguel Ojeda /// # /*
1524*c3739801SMiguel Ojeda ///     ...
1525*c3739801SMiguel Ojeda /// # */
1526*c3739801SMiguel Ojeda /// }
1527*c3739801SMiguel Ojeda ///
1528*c3739801SMiguel Ojeda /// #[derive(Immutable)]
1529*c3739801SMiguel Ojeda /// union MyUnion {
1530*c3739801SMiguel Ojeda /// #   variant: u8,
1531*c3739801SMiguel Ojeda /// # /*
1532*c3739801SMiguel Ojeda ///     ...
1533*c3739801SMiguel Ojeda /// # */
1534*c3739801SMiguel Ojeda /// }
1535*c3739801SMiguel Ojeda /// ```
1536*c3739801SMiguel Ojeda ///
1537*c3739801SMiguel Ojeda /// This derive performs a sophisticated, compile-time safety analysis to
1538*c3739801SMiguel Ojeda /// determine whether a type is `Immutable`.
1539*c3739801SMiguel Ojeda ///
1540*c3739801SMiguel Ojeda /// # Safety
1541*c3739801SMiguel Ojeda ///
1542*c3739801SMiguel Ojeda /// Unsafe code outside of this crate must not make any assumptions about `T`
1543*c3739801SMiguel Ojeda /// based on `T: Immutable`. We reserve the right to relax the requirements for
1544*c3739801SMiguel Ojeda /// `Immutable` in the future, and if unsafe code outside of this crate makes
1545*c3739801SMiguel Ojeda /// assumptions based on `T: Immutable`, future relaxations may cause that code
1546*c3739801SMiguel Ojeda /// to become unsound.
1547*c3739801SMiguel Ojeda ///
1548*c3739801SMiguel Ojeda // # Safety (Internal)
1549*c3739801SMiguel Ojeda //
1550*c3739801SMiguel Ojeda // If `T: Immutable`, unsafe code *inside of this crate* may assume that, given
1551*c3739801SMiguel Ojeda // `t: &T`, `t` does not permit interior mutation of its referent. Because
1552*c3739801SMiguel Ojeda // [`UnsafeCell`] is the only type which permits interior mutation, it is
1553*c3739801SMiguel Ojeda // sufficient (though not necessary) to guarantee that `T` contains no
1554*c3739801SMiguel Ojeda // `UnsafeCell`s.
1555*c3739801SMiguel Ojeda //
1556*c3739801SMiguel Ojeda // [`UnsafeCell`]: core::cell::UnsafeCell
1557*c3739801SMiguel Ojeda #[cfg_attr(
1558*c3739801SMiguel Ojeda     feature = "derive",
1559*c3739801SMiguel Ojeda     doc = "[derive]: zerocopy_derive::Immutable",
1560*c3739801SMiguel Ojeda     doc = "[derive-analysis]: zerocopy_derive::Immutable#analysis"
1561*c3739801SMiguel Ojeda )]
1562*c3739801SMiguel Ojeda #[cfg_attr(
1563*c3739801SMiguel Ojeda     not(feature = "derive"),
1564*c3739801SMiguel Ojeda     doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Immutable.html"),
1565*c3739801SMiguel Ojeda     doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Immutable.html#analysis"),
1566*c3739801SMiguel Ojeda )]
1567*c3739801SMiguel Ojeda #[cfg_attr(
1568*c3739801SMiguel Ojeda     not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
1569*c3739801SMiguel Ojeda     diagnostic::on_unimplemented(note = "Consider adding `#[derive(Immutable)]` to `{Self}`")
1570*c3739801SMiguel Ojeda )]
1571*c3739801SMiguel Ojeda pub unsafe trait Immutable {
1572*c3739801SMiguel Ojeda     // The `Self: Sized` bound makes it so that `Immutable` is still object
1573*c3739801SMiguel Ojeda     // safe.
1574*c3739801SMiguel Ojeda     #[doc(hidden)]
1575*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
1576*c3739801SMiguel Ojeda     where
1577*c3739801SMiguel Ojeda         Self: Sized;
1578*c3739801SMiguel Ojeda }
1579*c3739801SMiguel Ojeda 
1580*c3739801SMiguel Ojeda /// Implements [`TryFromBytes`].
1581*c3739801SMiguel Ojeda ///
1582*c3739801SMiguel Ojeda /// This derive synthesizes the runtime checks required to check whether a
1583*c3739801SMiguel Ojeda /// sequence of initialized bytes corresponds to a valid instance of a type.
1584*c3739801SMiguel Ojeda /// This derive can be applied to structs, enums, and unions; e.g.:
1585*c3739801SMiguel Ojeda ///
1586*c3739801SMiguel Ojeda /// ```
1587*c3739801SMiguel Ojeda /// # use zerocopy_derive::{TryFromBytes, Immutable};
1588*c3739801SMiguel Ojeda /// #[derive(TryFromBytes)]
1589*c3739801SMiguel Ojeda /// struct MyStruct {
1590*c3739801SMiguel Ojeda /// # /*
1591*c3739801SMiguel Ojeda ///     ...
1592*c3739801SMiguel Ojeda /// # */
1593*c3739801SMiguel Ojeda /// }
1594*c3739801SMiguel Ojeda ///
1595*c3739801SMiguel Ojeda /// #[derive(TryFromBytes)]
1596*c3739801SMiguel Ojeda /// #[repr(u8)]
1597*c3739801SMiguel Ojeda /// enum MyEnum {
1598*c3739801SMiguel Ojeda /// #   V00,
1599*c3739801SMiguel Ojeda /// # /*
1600*c3739801SMiguel Ojeda ///     ...
1601*c3739801SMiguel Ojeda /// # */
1602*c3739801SMiguel Ojeda /// }
1603*c3739801SMiguel Ojeda ///
1604*c3739801SMiguel Ojeda /// #[derive(TryFromBytes, Immutable)]
1605*c3739801SMiguel Ojeda /// union MyUnion {
1606*c3739801SMiguel Ojeda /// #   variant: u8,
1607*c3739801SMiguel Ojeda /// # /*
1608*c3739801SMiguel Ojeda ///     ...
1609*c3739801SMiguel Ojeda /// # */
1610*c3739801SMiguel Ojeda /// }
1611*c3739801SMiguel Ojeda /// ```
1612*c3739801SMiguel Ojeda ///
1613*c3739801SMiguel Ojeda /// # Portability
1614*c3739801SMiguel Ojeda ///
1615*c3739801SMiguel Ojeda /// To ensure consistent endianness for enums with multi-byte representations,
1616*c3739801SMiguel Ojeda /// explicitly specify and convert each discriminant using `.to_le()` or
1617*c3739801SMiguel Ojeda /// `.to_be()`; e.g.:
1618*c3739801SMiguel Ojeda ///
1619*c3739801SMiguel Ojeda /// ```
1620*c3739801SMiguel Ojeda /// # use zerocopy_derive::TryFromBytes;
1621*c3739801SMiguel Ojeda /// // `DataStoreVersion` is encoded in little-endian.
1622*c3739801SMiguel Ojeda /// #[derive(TryFromBytes)]
1623*c3739801SMiguel Ojeda /// #[repr(u32)]
1624*c3739801SMiguel Ojeda /// pub enum DataStoreVersion {
1625*c3739801SMiguel Ojeda ///     /// Version 1 of the data store.
1626*c3739801SMiguel Ojeda ///     V1 = 9u32.to_le(),
1627*c3739801SMiguel Ojeda ///
1628*c3739801SMiguel Ojeda ///     /// Version 2 of the data store.
1629*c3739801SMiguel Ojeda ///     V2 = 10u32.to_le(),
1630*c3739801SMiguel Ojeda /// }
1631*c3739801SMiguel Ojeda /// ```
1632*c3739801SMiguel Ojeda ///
1633*c3739801SMiguel Ojeda /// [safety conditions]: trait@TryFromBytes#safety
1634*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
1635*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
1636*c3739801SMiguel Ojeda pub use zerocopy_derive::TryFromBytes;
1637*c3739801SMiguel Ojeda 
1638*c3739801SMiguel Ojeda /// Types for which some bit patterns are valid.
1639*c3739801SMiguel Ojeda ///
1640*c3739801SMiguel Ojeda /// A memory region of the appropriate length which contains initialized bytes
1641*c3739801SMiguel Ojeda /// can be viewed as a `TryFromBytes` type so long as the runtime value of those
1642*c3739801SMiguel Ojeda /// bytes corresponds to a [*valid instance*] of that type. For example,
1643*c3739801SMiguel Ojeda /// [`bool`] is `TryFromBytes`, so zerocopy can transmute a [`u8`] into a
1644*c3739801SMiguel Ojeda /// [`bool`] so long as it first checks that the value of the [`u8`] is `0` or
1645*c3739801SMiguel Ojeda /// `1`.
1646*c3739801SMiguel Ojeda ///
1647*c3739801SMiguel Ojeda /// # Implementation
1648*c3739801SMiguel Ojeda ///
1649*c3739801SMiguel Ojeda /// **Do not implement this trait yourself!** Instead, use
1650*c3739801SMiguel Ojeda /// [`#[derive(TryFromBytes)]`][derive]; e.g.:
1651*c3739801SMiguel Ojeda ///
1652*c3739801SMiguel Ojeda /// ```
1653*c3739801SMiguel Ojeda /// # use zerocopy_derive::{TryFromBytes, Immutable};
1654*c3739801SMiguel Ojeda /// #[derive(TryFromBytes)]
1655*c3739801SMiguel Ojeda /// struct MyStruct {
1656*c3739801SMiguel Ojeda /// # /*
1657*c3739801SMiguel Ojeda ///     ...
1658*c3739801SMiguel Ojeda /// # */
1659*c3739801SMiguel Ojeda /// }
1660*c3739801SMiguel Ojeda ///
1661*c3739801SMiguel Ojeda /// #[derive(TryFromBytes)]
1662*c3739801SMiguel Ojeda /// #[repr(u8)]
1663*c3739801SMiguel Ojeda /// enum MyEnum {
1664*c3739801SMiguel Ojeda /// #   V00,
1665*c3739801SMiguel Ojeda /// # /*
1666*c3739801SMiguel Ojeda ///     ...
1667*c3739801SMiguel Ojeda /// # */
1668*c3739801SMiguel Ojeda /// }
1669*c3739801SMiguel Ojeda ///
1670*c3739801SMiguel Ojeda /// #[derive(TryFromBytes, Immutable)]
1671*c3739801SMiguel Ojeda /// union MyUnion {
1672*c3739801SMiguel Ojeda /// #   variant: u8,
1673*c3739801SMiguel Ojeda /// # /*
1674*c3739801SMiguel Ojeda ///     ...
1675*c3739801SMiguel Ojeda /// # */
1676*c3739801SMiguel Ojeda /// }
1677*c3739801SMiguel Ojeda /// ```
1678*c3739801SMiguel Ojeda ///
1679*c3739801SMiguel Ojeda /// This derive ensures that the runtime check of whether bytes correspond to a
1680*c3739801SMiguel Ojeda /// valid instance is sound. You **must** implement this trait via the derive.
1681*c3739801SMiguel Ojeda ///
1682*c3739801SMiguel Ojeda /// # What is a "valid instance"?
1683*c3739801SMiguel Ojeda ///
1684*c3739801SMiguel Ojeda /// In Rust, each type has *bit validity*, which refers to the set of bit
1685*c3739801SMiguel Ojeda /// patterns which may appear in an instance of that type. It is impossible for
1686*c3739801SMiguel Ojeda /// safe Rust code to produce values which violate bit validity (ie, values
1687*c3739801SMiguel Ojeda /// outside of the "valid" set of bit patterns). If `unsafe` code produces an
1688*c3739801SMiguel Ojeda /// invalid value, this is considered [undefined behavior].
1689*c3739801SMiguel Ojeda ///
1690*c3739801SMiguel Ojeda /// Rust's bit validity rules are currently being decided, which means that some
1691*c3739801SMiguel Ojeda /// types have three classes of bit patterns: those which are definitely valid,
1692*c3739801SMiguel Ojeda /// and whose validity is documented in the language; those which may or may not
1693*c3739801SMiguel Ojeda /// be considered valid at some point in the future; and those which are
1694*c3739801SMiguel Ojeda /// definitely invalid.
1695*c3739801SMiguel Ojeda ///
1696*c3739801SMiguel Ojeda /// Zerocopy takes a conservative approach, and only considers a bit pattern to
1697*c3739801SMiguel Ojeda /// be valid if its validity is a documented guarantee provided by the
1698*c3739801SMiguel Ojeda /// language.
1699*c3739801SMiguel Ojeda ///
1700*c3739801SMiguel Ojeda /// For most use cases, Rust's current guarantees align with programmers'
1701*c3739801SMiguel Ojeda /// intuitions about what ought to be valid. As a result, zerocopy's
1702*c3739801SMiguel Ojeda /// conservatism should not affect most users.
1703*c3739801SMiguel Ojeda ///
1704*c3739801SMiguel Ojeda /// If you are negatively affected by lack of support for a particular type,
1705*c3739801SMiguel Ojeda /// we encourage you to let us know by [filing an issue][github-repo].
1706*c3739801SMiguel Ojeda ///
1707*c3739801SMiguel Ojeda /// # `TryFromBytes` is not symmetrical with [`IntoBytes`]
1708*c3739801SMiguel Ojeda ///
1709*c3739801SMiguel Ojeda /// There are some types which implement both `TryFromBytes` and [`IntoBytes`],
1710*c3739801SMiguel Ojeda /// but for which `TryFromBytes` is not guaranteed to accept all byte sequences
1711*c3739801SMiguel Ojeda /// produced by `IntoBytes`. In other words, for some `T: TryFromBytes +
1712*c3739801SMiguel Ojeda /// IntoBytes`, there exist values of `t: T` such that
1713*c3739801SMiguel Ojeda /// `TryFromBytes::try_ref_from_bytes(t.as_bytes()) == None`. Code should not
1714*c3739801SMiguel Ojeda /// generally assume that values produced by `IntoBytes` will necessarily be
1715*c3739801SMiguel Ojeda /// accepted as valid by `TryFromBytes`.
1716*c3739801SMiguel Ojeda ///
1717*c3739801SMiguel Ojeda /// # Safety
1718*c3739801SMiguel Ojeda ///
1719*c3739801SMiguel Ojeda /// On its own, `T: TryFromBytes` does not make any guarantees about the layout
1720*c3739801SMiguel Ojeda /// or representation of `T`. It merely provides the ability to perform a
1721*c3739801SMiguel Ojeda /// validity check at runtime via methods like [`try_ref_from_bytes`].
1722*c3739801SMiguel Ojeda ///
1723*c3739801SMiguel Ojeda /// You must not rely on the `#[doc(hidden)]` internals of `TryFromBytes`.
1724*c3739801SMiguel Ojeda /// Future releases of zerocopy may make backwards-breaking changes to these
1725*c3739801SMiguel Ojeda /// items, including changes that only affect soundness, which may cause code
1726*c3739801SMiguel Ojeda /// which uses those items to silently become unsound.
1727*c3739801SMiguel Ojeda ///
1728*c3739801SMiguel Ojeda /// [undefined behavior]: https://raphlinus.github.io/programming/rust/2018/08/17/undefined-behavior.html
1729*c3739801SMiguel Ojeda /// [github-repo]: https://github.com/google/zerocopy
1730*c3739801SMiguel Ojeda /// [`try_ref_from_bytes`]: TryFromBytes::try_ref_from_bytes
1731*c3739801SMiguel Ojeda /// [*valid instance*]: #what-is-a-valid-instance
1732*c3739801SMiguel Ojeda #[cfg_attr(feature = "derive", doc = "[derive]: zerocopy_derive::TryFromBytes")]
1733*c3739801SMiguel Ojeda #[cfg_attr(
1734*c3739801SMiguel Ojeda     not(feature = "derive"),
1735*c3739801SMiguel Ojeda     doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.TryFromBytes.html"),
1736*c3739801SMiguel Ojeda )]
1737*c3739801SMiguel Ojeda #[cfg_attr(
1738*c3739801SMiguel Ojeda     not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
1739*c3739801SMiguel Ojeda     diagnostic::on_unimplemented(note = "Consider adding `#[derive(TryFromBytes)]` to `{Self}`")
1740*c3739801SMiguel Ojeda )]
1741*c3739801SMiguel Ojeda pub unsafe trait TryFromBytes {
1742*c3739801SMiguel Ojeda     // The `Self: Sized` bound makes it so that `TryFromBytes` is still object
1743*c3739801SMiguel Ojeda     // safe.
1744*c3739801SMiguel Ojeda     #[doc(hidden)]
1745*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
1746*c3739801SMiguel Ojeda     where
1747*c3739801SMiguel Ojeda         Self: Sized;
1748*c3739801SMiguel Ojeda 
1749*c3739801SMiguel Ojeda     /// Does a given memory range contain a valid instance of `Self`?
1750*c3739801SMiguel Ojeda     ///
1751*c3739801SMiguel Ojeda     /// # Safety
1752*c3739801SMiguel Ojeda     ///
1753*c3739801SMiguel Ojeda     /// Unsafe code may assume that, if `is_bit_valid(candidate)` returns true,
1754*c3739801SMiguel Ojeda     /// `*candidate` contains a valid `Self`.
1755*c3739801SMiguel Ojeda     ///
1756*c3739801SMiguel Ojeda     /// # Panics
1757*c3739801SMiguel Ojeda     ///
1758*c3739801SMiguel Ojeda     /// `is_bit_valid` may panic. Callers are responsible for ensuring that any
1759*c3739801SMiguel Ojeda     /// `unsafe` code remains sound even in the face of `is_bit_valid`
1760*c3739801SMiguel Ojeda     /// panicking. (We support user-defined validation routines; so long as
1761*c3739801SMiguel Ojeda     /// these routines are not required to be `unsafe`, there is no way to
1762*c3739801SMiguel Ojeda     /// ensure that these do not generate panics.)
1763*c3739801SMiguel Ojeda     ///
1764*c3739801SMiguel Ojeda     /// Besides user-defined validation routines panicking, `is_bit_valid` will
1765*c3739801SMiguel Ojeda     /// either panic or fail to compile if called on a pointer with [`Shared`]
1766*c3739801SMiguel Ojeda     /// aliasing when `Self: !Immutable`.
1767*c3739801SMiguel Ojeda     ///
1768*c3739801SMiguel Ojeda     /// [`UnsafeCell`]: core::cell::UnsafeCell
1769*c3739801SMiguel Ojeda     /// [`Shared`]: invariant::Shared
1770*c3739801SMiguel Ojeda     #[doc(hidden)]
1771*c3739801SMiguel Ojeda     fn is_bit_valid<A>(candidate: Maybe<'_, Self, A>) -> bool
1772*c3739801SMiguel Ojeda     where
1773*c3739801SMiguel Ojeda         A: invariant::Alignment;
1774*c3739801SMiguel Ojeda 
1775*c3739801SMiguel Ojeda     /// Attempts to interpret the given `source` as a `&Self`.
1776*c3739801SMiguel Ojeda     ///
1777*c3739801SMiguel Ojeda     /// If the bytes of `source` are a valid instance of `Self`, this method
1778*c3739801SMiguel Ojeda     /// returns a reference to those bytes interpreted as a `Self`. If the
1779*c3739801SMiguel Ojeda     /// length of `source` is not a [valid size of `Self`][valid-size], or if
1780*c3739801SMiguel Ojeda     /// `source` is not appropriately aligned, or if `source` is not a valid
1781*c3739801SMiguel Ojeda     /// instance of `Self`, this returns `Err`. If [`Self:
1782*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
1783*c3739801SMiguel Ojeda     /// error][ConvertError::from].
1784*c3739801SMiguel Ojeda     ///
1785*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
1786*c3739801SMiguel Ojeda     ///
1787*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
1788*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
1789*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
1790*c3739801SMiguel Ojeda     ///
1791*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
1792*c3739801SMiguel Ojeda     ///
1793*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
1794*c3739801SMiguel Ojeda     /// component is zero-sized. Attempting to use this method on such types
1795*c3739801SMiguel Ojeda     /// results in a compile-time assertion error; e.g.:
1796*c3739801SMiguel Ojeda     ///
1797*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
1798*c3739801SMiguel Ojeda     /// use zerocopy::*;
1799*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
1800*c3739801SMiguel Ojeda     ///
1801*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, Immutable, KnownLayout)]
1802*c3739801SMiguel Ojeda     /// #[repr(C)]
1803*c3739801SMiguel Ojeda     /// struct ZSTy {
1804*c3739801SMiguel Ojeda     ///     leading_sized: u16,
1805*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
1806*c3739801SMiguel Ojeda     /// }
1807*c3739801SMiguel Ojeda     ///
1808*c3739801SMiguel Ojeda     /// let _ = ZSTy::try_ref_from_bytes(0u16.as_bytes()); // ⚠ Compile Error!
1809*c3739801SMiguel Ojeda     /// ```
1810*c3739801SMiguel Ojeda     ///
1811*c3739801SMiguel Ojeda     /// # Examples
1812*c3739801SMiguel Ojeda     ///
1813*c3739801SMiguel Ojeda     /// ```
1814*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
1815*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
1816*c3739801SMiguel Ojeda     ///
1817*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
1818*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1819*c3739801SMiguel Ojeda     /// #[repr(u8)]
1820*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
1821*c3739801SMiguel Ojeda     ///
1822*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte sequence `0xC0C0`.
1823*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1824*c3739801SMiguel Ojeda     /// #[repr(C)]
1825*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
1826*c3739801SMiguel Ojeda     ///
1827*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1828*c3739801SMiguel Ojeda     /// #[repr(C)]
1829*c3739801SMiguel Ojeda     /// struct Packet {
1830*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
1831*c3739801SMiguel Ojeda     ///     mug_size: u8,
1832*c3739801SMiguel Ojeda     ///     temperature: u8,
1833*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
1834*c3739801SMiguel Ojeda     /// }
1835*c3739801SMiguel Ojeda     ///
1836*c3739801SMiguel Ojeda     /// let bytes = &[0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5][..];
1837*c3739801SMiguel Ojeda     ///
1838*c3739801SMiguel Ojeda     /// let packet = Packet::try_ref_from_bytes(bytes).unwrap();
1839*c3739801SMiguel Ojeda     ///
1840*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
1841*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
1842*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]);
1843*c3739801SMiguel Ojeda     ///
1844*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
1845*c3739801SMiguel Ojeda     /// let bytes = &[0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5][..];
1846*c3739801SMiguel Ojeda     /// assert!(Packet::try_ref_from_bytes(bytes).is_err());
1847*c3739801SMiguel Ojeda     /// ```
1848*c3739801SMiguel Ojeda     ///
1849*c3739801SMiguel Ojeda     #[doc = codegen_section!(
1850*c3739801SMiguel Ojeda         header = "h5",
1851*c3739801SMiguel Ojeda         bench = "try_ref_from_bytes",
1852*c3739801SMiguel Ojeda         format = "coco",
1853*c3739801SMiguel Ojeda         arity = 3,
1854*c3739801SMiguel Ojeda         [
1855*c3739801SMiguel Ojeda             open
1856*c3739801SMiguel Ojeda             @index 1
1857*c3739801SMiguel Ojeda             @title "Sized"
1858*c3739801SMiguel Ojeda             @variant "static_size"
1859*c3739801SMiguel Ojeda         ],
1860*c3739801SMiguel Ojeda         [
1861*c3739801SMiguel Ojeda             @index 2
1862*c3739801SMiguel Ojeda             @title "Unsized"
1863*c3739801SMiguel Ojeda             @variant "dynamic_size"
1864*c3739801SMiguel Ojeda         ],
1865*c3739801SMiguel Ojeda         [
1866*c3739801SMiguel Ojeda             @index 3
1867*c3739801SMiguel Ojeda             @title "Dynamically Padded"
1868*c3739801SMiguel Ojeda             @variant "dynamic_padding"
1869*c3739801SMiguel Ojeda         ]
1870*c3739801SMiguel Ojeda     )]
1871*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
1872*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
1873*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
1874*c3739801SMiguel Ojeda     fn try_ref_from_bytes(source: &[u8]) -> Result<&Self, TryCastError<&[u8], Self>>
1875*c3739801SMiguel Ojeda     where
1876*c3739801SMiguel Ojeda         Self: KnownLayout + Immutable,
1877*c3739801SMiguel Ojeda     {
1878*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
1879*c3739801SMiguel Ojeda         match Ptr::from_ref(source).try_cast_into_no_leftover::<Self, BecauseImmutable>(None) {
1880*c3739801SMiguel Ojeda             Ok(source) => {
1881*c3739801SMiguel Ojeda                 // This call may panic. If that happens, it doesn't cause any soundness
1882*c3739801SMiguel Ojeda                 // issues, as we have not generated any invalid state which we need to
1883*c3739801SMiguel Ojeda                 // fix before returning.
1884*c3739801SMiguel Ojeda                 match source.try_into_valid() {
1885*c3739801SMiguel Ojeda                     Ok(valid) => Ok(valid.as_ref()),
1886*c3739801SMiguel Ojeda                     Err(e) => {
1887*c3739801SMiguel Ojeda                         Err(e.map_src(|src| src.as_bytes::<BecauseImmutable>().as_ref()).into())
1888*c3739801SMiguel Ojeda                     }
1889*c3739801SMiguel Ojeda                 }
1890*c3739801SMiguel Ojeda             }
1891*c3739801SMiguel Ojeda             Err(e) => Err(e.map_src(Ptr::as_ref).into()),
1892*c3739801SMiguel Ojeda         }
1893*c3739801SMiguel Ojeda     }
1894*c3739801SMiguel Ojeda 
1895*c3739801SMiguel Ojeda     /// Attempts to interpret the prefix of the given `source` as a `&Self`.
1896*c3739801SMiguel Ojeda     ///
1897*c3739801SMiguel Ojeda     /// This method computes the [largest possible size of `Self`][valid-size]
1898*c3739801SMiguel Ojeda     /// that can fit in the leading bytes of `source`. If that prefix is a valid
1899*c3739801SMiguel Ojeda     /// instance of `Self`, this method returns a reference to those bytes
1900*c3739801SMiguel Ojeda     /// interpreted as `Self`, and a reference to the remaining bytes. If there
1901*c3739801SMiguel Ojeda     /// are insufficient bytes, or if `source` is not appropriately aligned, or
1902*c3739801SMiguel Ojeda     /// if those bytes are not a valid instance of `Self`, this returns `Err`.
1903*c3739801SMiguel Ojeda     /// If [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
1904*c3739801SMiguel Ojeda     /// alignment error][ConvertError::from].
1905*c3739801SMiguel Ojeda     ///
1906*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
1907*c3739801SMiguel Ojeda     ///
1908*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
1909*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
1910*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
1911*c3739801SMiguel Ojeda     ///
1912*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
1913*c3739801SMiguel Ojeda     ///
1914*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
1915*c3739801SMiguel Ojeda     /// component is zero-sized. Attempting to use this method on such types
1916*c3739801SMiguel Ojeda     /// results in a compile-time assertion error; e.g.:
1917*c3739801SMiguel Ojeda     ///
1918*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
1919*c3739801SMiguel Ojeda     /// use zerocopy::*;
1920*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
1921*c3739801SMiguel Ojeda     ///
1922*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, Immutable, KnownLayout)]
1923*c3739801SMiguel Ojeda     /// #[repr(C)]
1924*c3739801SMiguel Ojeda     /// struct ZSTy {
1925*c3739801SMiguel Ojeda     ///     leading_sized: u16,
1926*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
1927*c3739801SMiguel Ojeda     /// }
1928*c3739801SMiguel Ojeda     ///
1929*c3739801SMiguel Ojeda     /// let _ = ZSTy::try_ref_from_prefix(0u16.as_bytes()); // ⚠ Compile Error!
1930*c3739801SMiguel Ojeda     /// ```
1931*c3739801SMiguel Ojeda     ///
1932*c3739801SMiguel Ojeda     /// # Examples
1933*c3739801SMiguel Ojeda     ///
1934*c3739801SMiguel Ojeda     /// ```
1935*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
1936*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
1937*c3739801SMiguel Ojeda     ///
1938*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
1939*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1940*c3739801SMiguel Ojeda     /// #[repr(u8)]
1941*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
1942*c3739801SMiguel Ojeda     ///
1943*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
1944*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1945*c3739801SMiguel Ojeda     /// #[repr(C)]
1946*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
1947*c3739801SMiguel Ojeda     ///
1948*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
1949*c3739801SMiguel Ojeda     /// #[repr(C)]
1950*c3739801SMiguel Ojeda     /// struct Packet {
1951*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
1952*c3739801SMiguel Ojeda     ///     mug_size: u8,
1953*c3739801SMiguel Ojeda     ///     temperature: u8,
1954*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
1955*c3739801SMiguel Ojeda     /// }
1956*c3739801SMiguel Ojeda     ///
1957*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `Packet`.
1958*c3739801SMiguel Ojeda     /// let bytes = &[0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
1959*c3739801SMiguel Ojeda     ///
1960*c3739801SMiguel Ojeda     /// let (packet, suffix) = Packet::try_ref_from_prefix(bytes).unwrap();
1961*c3739801SMiguel Ojeda     ///
1962*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
1963*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
1964*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]);
1965*c3739801SMiguel Ojeda     /// assert_eq!(suffix, &[6u8][..]);
1966*c3739801SMiguel Ojeda     ///
1967*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
1968*c3739801SMiguel Ojeda     /// let bytes = &[0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
1969*c3739801SMiguel Ojeda     /// assert!(Packet::try_ref_from_prefix(bytes).is_err());
1970*c3739801SMiguel Ojeda     /// ```
1971*c3739801SMiguel Ojeda     ///
1972*c3739801SMiguel Ojeda     #[doc = codegen_section!(
1973*c3739801SMiguel Ojeda         header = "h5",
1974*c3739801SMiguel Ojeda         bench = "try_ref_from_prefix",
1975*c3739801SMiguel Ojeda         format = "coco",
1976*c3739801SMiguel Ojeda         arity = 3,
1977*c3739801SMiguel Ojeda         [
1978*c3739801SMiguel Ojeda             open
1979*c3739801SMiguel Ojeda             @index 1
1980*c3739801SMiguel Ojeda             @title "Sized"
1981*c3739801SMiguel Ojeda             @variant "static_size"
1982*c3739801SMiguel Ojeda         ],
1983*c3739801SMiguel Ojeda         [
1984*c3739801SMiguel Ojeda             @index 2
1985*c3739801SMiguel Ojeda             @title "Unsized"
1986*c3739801SMiguel Ojeda             @variant "dynamic_size"
1987*c3739801SMiguel Ojeda         ],
1988*c3739801SMiguel Ojeda         [
1989*c3739801SMiguel Ojeda             @index 3
1990*c3739801SMiguel Ojeda             @title "Dynamically Padded"
1991*c3739801SMiguel Ojeda             @variant "dynamic_padding"
1992*c3739801SMiguel Ojeda         ]
1993*c3739801SMiguel Ojeda     )]
1994*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
1995*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
1996*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
1997*c3739801SMiguel Ojeda     fn try_ref_from_prefix(source: &[u8]) -> Result<(&Self, &[u8]), TryCastError<&[u8], Self>>
1998*c3739801SMiguel Ojeda     where
1999*c3739801SMiguel Ojeda         Self: KnownLayout + Immutable,
2000*c3739801SMiguel Ojeda     {
2001*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
2002*c3739801SMiguel Ojeda         try_ref_from_prefix_suffix(source, CastType::Prefix, None)
2003*c3739801SMiguel Ojeda     }
2004*c3739801SMiguel Ojeda 
2005*c3739801SMiguel Ojeda     /// Attempts to interpret the suffix of the given `source` as a `&Self`.
2006*c3739801SMiguel Ojeda     ///
2007*c3739801SMiguel Ojeda     /// This method computes the [largest possible size of `Self`][valid-size]
2008*c3739801SMiguel Ojeda     /// that can fit in the trailing bytes of `source`. If that suffix is a
2009*c3739801SMiguel Ojeda     /// valid instance of `Self`, this method returns a reference to those bytes
2010*c3739801SMiguel Ojeda     /// interpreted as `Self`, and a reference to the preceding bytes. If there
2011*c3739801SMiguel Ojeda     /// are insufficient bytes, or if the suffix of `source` would not be
2012*c3739801SMiguel Ojeda     /// appropriately aligned, or if the suffix is not a valid instance of
2013*c3739801SMiguel Ojeda     /// `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], you
2014*c3739801SMiguel Ojeda     /// can [infallibly discard the alignment error][ConvertError::from].
2015*c3739801SMiguel Ojeda     ///
2016*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
2017*c3739801SMiguel Ojeda     ///
2018*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
2019*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2020*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2021*c3739801SMiguel Ojeda     ///
2022*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
2023*c3739801SMiguel Ojeda     ///
2024*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
2025*c3739801SMiguel Ojeda     /// component is zero-sized. Attempting to use this method on such types
2026*c3739801SMiguel Ojeda     /// results in a compile-time assertion error; e.g.:
2027*c3739801SMiguel Ojeda     ///
2028*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
2029*c3739801SMiguel Ojeda     /// use zerocopy::*;
2030*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2031*c3739801SMiguel Ojeda     ///
2032*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, Immutable, KnownLayout)]
2033*c3739801SMiguel Ojeda     /// #[repr(C)]
2034*c3739801SMiguel Ojeda     /// struct ZSTy {
2035*c3739801SMiguel Ojeda     ///     leading_sized: u16,
2036*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
2037*c3739801SMiguel Ojeda     /// }
2038*c3739801SMiguel Ojeda     ///
2039*c3739801SMiguel Ojeda     /// let _ = ZSTy::try_ref_from_suffix(0u16.as_bytes()); // ⚠ Compile Error!
2040*c3739801SMiguel Ojeda     /// ```
2041*c3739801SMiguel Ojeda     ///
2042*c3739801SMiguel Ojeda     /// # Examples
2043*c3739801SMiguel Ojeda     ///
2044*c3739801SMiguel Ojeda     /// ```
2045*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2046*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2047*c3739801SMiguel Ojeda     ///
2048*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2049*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2050*c3739801SMiguel Ojeda     /// #[repr(u8)]
2051*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2052*c3739801SMiguel Ojeda     ///
2053*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2054*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2055*c3739801SMiguel Ojeda     /// #[repr(C)]
2056*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2057*c3739801SMiguel Ojeda     ///
2058*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2059*c3739801SMiguel Ojeda     /// #[repr(C)]
2060*c3739801SMiguel Ojeda     /// struct Packet {
2061*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2062*c3739801SMiguel Ojeda     ///     mug_size: u8,
2063*c3739801SMiguel Ojeda     ///     temperature: u8,
2064*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
2065*c3739801SMiguel Ojeda     /// }
2066*c3739801SMiguel Ojeda     ///
2067*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `Packet`.
2068*c3739801SMiguel Ojeda     /// let bytes = &[0, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
2069*c3739801SMiguel Ojeda     ///
2070*c3739801SMiguel Ojeda     /// let (prefix, packet) = Packet::try_ref_from_suffix(bytes).unwrap();
2071*c3739801SMiguel Ojeda     ///
2072*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
2073*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
2074*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2075*c3739801SMiguel Ojeda     /// assert_eq!(prefix, &[0u8][..]);
2076*c3739801SMiguel Ojeda     ///
2077*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
2078*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0x10][..];
2079*c3739801SMiguel Ojeda     /// assert!(Packet::try_ref_from_suffix(bytes).is_err());
2080*c3739801SMiguel Ojeda     /// ```
2081*c3739801SMiguel Ojeda     ///
2082*c3739801SMiguel Ojeda     #[doc = codegen_section!(
2083*c3739801SMiguel Ojeda         header = "h5",
2084*c3739801SMiguel Ojeda         bench = "try_ref_from_suffix",
2085*c3739801SMiguel Ojeda         format = "coco",
2086*c3739801SMiguel Ojeda         arity = 3,
2087*c3739801SMiguel Ojeda         [
2088*c3739801SMiguel Ojeda             open
2089*c3739801SMiguel Ojeda             @index 1
2090*c3739801SMiguel Ojeda             @title "Sized"
2091*c3739801SMiguel Ojeda             @variant "static_size"
2092*c3739801SMiguel Ojeda         ],
2093*c3739801SMiguel Ojeda         [
2094*c3739801SMiguel Ojeda             @index 2
2095*c3739801SMiguel Ojeda             @title "Unsized"
2096*c3739801SMiguel Ojeda             @variant "dynamic_size"
2097*c3739801SMiguel Ojeda         ],
2098*c3739801SMiguel Ojeda         [
2099*c3739801SMiguel Ojeda             @index 3
2100*c3739801SMiguel Ojeda             @title "Dynamically Padded"
2101*c3739801SMiguel Ojeda             @variant "dynamic_padding"
2102*c3739801SMiguel Ojeda         ]
2103*c3739801SMiguel Ojeda     )]
2104*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
2105*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
2106*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
2107*c3739801SMiguel Ojeda     fn try_ref_from_suffix(source: &[u8]) -> Result<(&[u8], &Self), TryCastError<&[u8], Self>>
2108*c3739801SMiguel Ojeda     where
2109*c3739801SMiguel Ojeda         Self: KnownLayout + Immutable,
2110*c3739801SMiguel Ojeda     {
2111*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
2112*c3739801SMiguel Ojeda         try_ref_from_prefix_suffix(source, CastType::Suffix, None).map(swap)
2113*c3739801SMiguel Ojeda     }
2114*c3739801SMiguel Ojeda 
2115*c3739801SMiguel Ojeda     /// Attempts to interpret the given `source` as a `&mut Self` without
2116*c3739801SMiguel Ojeda     /// copying.
2117*c3739801SMiguel Ojeda     ///
2118*c3739801SMiguel Ojeda     /// If the bytes of `source` are a valid instance of `Self`, this method
2119*c3739801SMiguel Ojeda     /// returns a reference to those bytes interpreted as a `Self`. If the
2120*c3739801SMiguel Ojeda     /// length of `source` is not a [valid size of `Self`][valid-size], or if
2121*c3739801SMiguel Ojeda     /// `source` is not appropriately aligned, or if `source` is not a valid
2122*c3739801SMiguel Ojeda     /// instance of `Self`, this returns `Err`. If [`Self:
2123*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
2124*c3739801SMiguel Ojeda     /// error][ConvertError::from].
2125*c3739801SMiguel Ojeda     ///
2126*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
2127*c3739801SMiguel Ojeda     ///
2128*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
2129*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2130*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2131*c3739801SMiguel Ojeda     ///
2132*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
2133*c3739801SMiguel Ojeda     ///
2134*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
2135*c3739801SMiguel Ojeda     /// component is zero-sized. Attempting to use this method on such types
2136*c3739801SMiguel Ojeda     /// results in a compile-time assertion error; e.g.:
2137*c3739801SMiguel Ojeda     ///
2138*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
2139*c3739801SMiguel Ojeda     /// use zerocopy::*;
2140*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2141*c3739801SMiguel Ojeda     ///
2142*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2143*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2144*c3739801SMiguel Ojeda     /// struct ZSTy {
2145*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
2146*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
2147*c3739801SMiguel Ojeda     /// }
2148*c3739801SMiguel Ojeda     ///
2149*c3739801SMiguel Ojeda     /// let mut source = [85, 85];
2150*c3739801SMiguel Ojeda     /// let _ = ZSTy::try_mut_from_bytes(&mut source[..]); // ⚠ Compile Error!
2151*c3739801SMiguel Ojeda     /// ```
2152*c3739801SMiguel Ojeda     ///
2153*c3739801SMiguel Ojeda     /// # Examples
2154*c3739801SMiguel Ojeda     ///
2155*c3739801SMiguel Ojeda     /// ```
2156*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2157*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2158*c3739801SMiguel Ojeda     ///
2159*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2160*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2161*c3739801SMiguel Ojeda     /// #[repr(u8)]
2162*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2163*c3739801SMiguel Ojeda     ///
2164*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2165*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2166*c3739801SMiguel Ojeda     /// #[repr(C)]
2167*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2168*c3739801SMiguel Ojeda     ///
2169*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2170*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2171*c3739801SMiguel Ojeda     /// struct Packet {
2172*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2173*c3739801SMiguel Ojeda     ///     mug_size: u8,
2174*c3739801SMiguel Ojeda     ///     temperature: u8,
2175*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
2176*c3739801SMiguel Ojeda     /// }
2177*c3739801SMiguel Ojeda     ///
2178*c3739801SMiguel Ojeda     /// let bytes = &mut [0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5][..];
2179*c3739801SMiguel Ojeda     ///
2180*c3739801SMiguel Ojeda     /// let packet = Packet::try_mut_from_bytes(bytes).unwrap();
2181*c3739801SMiguel Ojeda     ///
2182*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
2183*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
2184*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]);
2185*c3739801SMiguel Ojeda     ///
2186*c3739801SMiguel Ojeda     /// packet.temperature = 111;
2187*c3739801SMiguel Ojeda     ///
2188*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 0, 1, 2, 3, 4, 5]);
2189*c3739801SMiguel Ojeda     ///
2190*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
2191*c3739801SMiguel Ojeda     /// let bytes = &mut [0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
2192*c3739801SMiguel Ojeda     /// assert!(Packet::try_mut_from_bytes(bytes).is_err());
2193*c3739801SMiguel Ojeda     /// ```
2194*c3739801SMiguel Ojeda     ///
2195*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "try_mut_from_bytes")]
2196*c3739801SMiguel Ojeda     ///
2197*c3739801SMiguel Ojeda     /// See [`TryFromBytes::try_ref_from_bytes`](#method.try_ref_from_bytes.codegen).
2198*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
2199*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
2200*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
2201*c3739801SMiguel Ojeda     fn try_mut_from_bytes(bytes: &mut [u8]) -> Result<&mut Self, TryCastError<&mut [u8], Self>>
2202*c3739801SMiguel Ojeda     where
2203*c3739801SMiguel Ojeda         Self: KnownLayout + IntoBytes,
2204*c3739801SMiguel Ojeda     {
2205*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
2206*c3739801SMiguel Ojeda         match Ptr::from_mut(bytes).try_cast_into_no_leftover::<Self, BecauseExclusive>(None) {
2207*c3739801SMiguel Ojeda             Ok(source) => {
2208*c3739801SMiguel Ojeda                 // This call may panic. If that happens, it doesn't cause any soundness
2209*c3739801SMiguel Ojeda                 // issues, as we have not generated any invalid state which we need to
2210*c3739801SMiguel Ojeda                 // fix before returning.
2211*c3739801SMiguel Ojeda                 match source.try_into_valid() {
2212*c3739801SMiguel Ojeda                     Ok(source) => Ok(source.as_mut()),
2213*c3739801SMiguel Ojeda                     Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()),
2214*c3739801SMiguel Ojeda                 }
2215*c3739801SMiguel Ojeda             }
2216*c3739801SMiguel Ojeda             Err(e) => Err(e.map_src(Ptr::as_mut).into()),
2217*c3739801SMiguel Ojeda         }
2218*c3739801SMiguel Ojeda     }
2219*c3739801SMiguel Ojeda 
2220*c3739801SMiguel Ojeda     /// Attempts to interpret the prefix of the given `source` as a `&mut
2221*c3739801SMiguel Ojeda     /// Self`.
2222*c3739801SMiguel Ojeda     ///
2223*c3739801SMiguel Ojeda     /// This method computes the [largest possible size of `Self`][valid-size]
2224*c3739801SMiguel Ojeda     /// that can fit in the leading bytes of `source`. If that prefix is a valid
2225*c3739801SMiguel Ojeda     /// instance of `Self`, this method returns a reference to those bytes
2226*c3739801SMiguel Ojeda     /// interpreted as `Self`, and a reference to the remaining bytes. If there
2227*c3739801SMiguel Ojeda     /// are insufficient bytes, or if `source` is not appropriately aligned, or
2228*c3739801SMiguel Ojeda     /// if the bytes are not a valid instance of `Self`, this returns `Err`. If
2229*c3739801SMiguel Ojeda     /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
2230*c3739801SMiguel Ojeda     /// alignment error][ConvertError::from].
2231*c3739801SMiguel Ojeda     ///
2232*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
2233*c3739801SMiguel Ojeda     ///
2234*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
2235*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2236*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2237*c3739801SMiguel Ojeda     ///
2238*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
2239*c3739801SMiguel Ojeda     ///
2240*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
2241*c3739801SMiguel Ojeda     /// component is zero-sized. Attempting to use this method on such types
2242*c3739801SMiguel Ojeda     /// results in a compile-time assertion error; e.g.:
2243*c3739801SMiguel Ojeda     ///
2244*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
2245*c3739801SMiguel Ojeda     /// use zerocopy::*;
2246*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2247*c3739801SMiguel Ojeda     ///
2248*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2249*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2250*c3739801SMiguel Ojeda     /// struct ZSTy {
2251*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
2252*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
2253*c3739801SMiguel Ojeda     /// }
2254*c3739801SMiguel Ojeda     ///
2255*c3739801SMiguel Ojeda     /// let mut source = [85, 85];
2256*c3739801SMiguel Ojeda     /// let _ = ZSTy::try_mut_from_prefix(&mut source[..]); // ⚠ Compile Error!
2257*c3739801SMiguel Ojeda     /// ```
2258*c3739801SMiguel Ojeda     ///
2259*c3739801SMiguel Ojeda     /// # Examples
2260*c3739801SMiguel Ojeda     ///
2261*c3739801SMiguel Ojeda     /// ```
2262*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2263*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2264*c3739801SMiguel Ojeda     ///
2265*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2266*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2267*c3739801SMiguel Ojeda     /// #[repr(u8)]
2268*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2269*c3739801SMiguel Ojeda     ///
2270*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2271*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2272*c3739801SMiguel Ojeda     /// #[repr(C)]
2273*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2274*c3739801SMiguel Ojeda     ///
2275*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2276*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2277*c3739801SMiguel Ojeda     /// struct Packet {
2278*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2279*c3739801SMiguel Ojeda     ///     mug_size: u8,
2280*c3739801SMiguel Ojeda     ///     temperature: u8,
2281*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
2282*c3739801SMiguel Ojeda     /// }
2283*c3739801SMiguel Ojeda     ///
2284*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `Packet`.
2285*c3739801SMiguel Ojeda     /// let bytes = &mut [0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
2286*c3739801SMiguel Ojeda     ///
2287*c3739801SMiguel Ojeda     /// let (packet, suffix) = Packet::try_mut_from_prefix(bytes).unwrap();
2288*c3739801SMiguel Ojeda     ///
2289*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
2290*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
2291*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[0, 1], [2, 3], [4, 5]]);
2292*c3739801SMiguel Ojeda     /// assert_eq!(suffix, &[6u8][..]);
2293*c3739801SMiguel Ojeda     ///
2294*c3739801SMiguel Ojeda     /// packet.temperature = 111;
2295*c3739801SMiguel Ojeda     /// suffix[0] = 222;
2296*c3739801SMiguel Ojeda     ///
2297*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 0, 1, 2, 3, 4, 5, 222]);
2298*c3739801SMiguel Ojeda     ///
2299*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
2300*c3739801SMiguel Ojeda     /// let bytes = &mut [0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
2301*c3739801SMiguel Ojeda     /// assert!(Packet::try_mut_from_prefix(bytes).is_err());
2302*c3739801SMiguel Ojeda     /// ```
2303*c3739801SMiguel Ojeda     ///
2304*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "try_mut_from_prefix")]
2305*c3739801SMiguel Ojeda     ///
2306*c3739801SMiguel Ojeda     /// See [`TryFromBytes::try_ref_from_prefix`](#method.try_ref_from_prefix.codegen).
2307*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
2308*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
2309*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
2310*c3739801SMiguel Ojeda     fn try_mut_from_prefix(
2311*c3739801SMiguel Ojeda         source: &mut [u8],
2312*c3739801SMiguel Ojeda     ) -> Result<(&mut Self, &mut [u8]), TryCastError<&mut [u8], Self>>
2313*c3739801SMiguel Ojeda     where
2314*c3739801SMiguel Ojeda         Self: KnownLayout + IntoBytes,
2315*c3739801SMiguel Ojeda     {
2316*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
2317*c3739801SMiguel Ojeda         try_mut_from_prefix_suffix(source, CastType::Prefix, None)
2318*c3739801SMiguel Ojeda     }
2319*c3739801SMiguel Ojeda 
2320*c3739801SMiguel Ojeda     /// Attempts to interpret the suffix of the given `source` as a `&mut
2321*c3739801SMiguel Ojeda     /// Self`.
2322*c3739801SMiguel Ojeda     ///
2323*c3739801SMiguel Ojeda     /// This method computes the [largest possible size of `Self`][valid-size]
2324*c3739801SMiguel Ojeda     /// that can fit in the trailing bytes of `source`. If that suffix is a
2325*c3739801SMiguel Ojeda     /// valid instance of `Self`, this method returns a reference to those bytes
2326*c3739801SMiguel Ojeda     /// interpreted as `Self`, and a reference to the preceding bytes. If there
2327*c3739801SMiguel Ojeda     /// are insufficient bytes, or if the suffix of `source` would not be
2328*c3739801SMiguel Ojeda     /// appropriately aligned, or if the suffix is not a valid instance of
2329*c3739801SMiguel Ojeda     /// `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned], you
2330*c3739801SMiguel Ojeda     /// can [infallibly discard the alignment error][ConvertError::from].
2331*c3739801SMiguel Ojeda     ///
2332*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
2333*c3739801SMiguel Ojeda     ///
2334*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
2335*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2336*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2337*c3739801SMiguel Ojeda     ///
2338*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
2339*c3739801SMiguel Ojeda     ///
2340*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
2341*c3739801SMiguel Ojeda     /// component is zero-sized. Attempting to use this method on such types
2342*c3739801SMiguel Ojeda     /// results in a compile-time assertion error; e.g.:
2343*c3739801SMiguel Ojeda     ///
2344*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
2345*c3739801SMiguel Ojeda     /// use zerocopy::*;
2346*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2347*c3739801SMiguel Ojeda     ///
2348*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2349*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2350*c3739801SMiguel Ojeda     /// struct ZSTy {
2351*c3739801SMiguel Ojeda     ///     leading_sized: u16,
2352*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
2353*c3739801SMiguel Ojeda     /// }
2354*c3739801SMiguel Ojeda     ///
2355*c3739801SMiguel Ojeda     /// let mut source = [85, 85];
2356*c3739801SMiguel Ojeda     /// let _ = ZSTy::try_mut_from_suffix(&mut source[..]); // ⚠ Compile Error!
2357*c3739801SMiguel Ojeda     /// ```
2358*c3739801SMiguel Ojeda     ///
2359*c3739801SMiguel Ojeda     /// # Examples
2360*c3739801SMiguel Ojeda     ///
2361*c3739801SMiguel Ojeda     /// ```
2362*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2363*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2364*c3739801SMiguel Ojeda     ///
2365*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2366*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2367*c3739801SMiguel Ojeda     /// #[repr(u8)]
2368*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2369*c3739801SMiguel Ojeda     ///
2370*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2371*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2372*c3739801SMiguel Ojeda     /// #[repr(C)]
2373*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2374*c3739801SMiguel Ojeda     ///
2375*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2376*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2377*c3739801SMiguel Ojeda     /// struct Packet {
2378*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2379*c3739801SMiguel Ojeda     ///     mug_size: u8,
2380*c3739801SMiguel Ojeda     ///     temperature: u8,
2381*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
2382*c3739801SMiguel Ojeda     /// }
2383*c3739801SMiguel Ojeda     ///
2384*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `Packet`.
2385*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
2386*c3739801SMiguel Ojeda     ///
2387*c3739801SMiguel Ojeda     /// let (prefix, packet) = Packet::try_mut_from_suffix(bytes).unwrap();
2388*c3739801SMiguel Ojeda     ///
2389*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
2390*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
2391*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2392*c3739801SMiguel Ojeda     /// assert_eq!(prefix, &[0u8][..]);
2393*c3739801SMiguel Ojeda     ///
2394*c3739801SMiguel Ojeda     /// prefix[0] = 111;
2395*c3739801SMiguel Ojeda     /// packet.temperature = 222;
2396*c3739801SMiguel Ojeda     ///
2397*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [111, 0xC0, 0xC0, 240, 222, 2, 3, 4, 5, 6, 7]);
2398*c3739801SMiguel Ojeda     ///
2399*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
2400*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0x10][..];
2401*c3739801SMiguel Ojeda     /// assert!(Packet::try_mut_from_suffix(bytes).is_err());
2402*c3739801SMiguel Ojeda     /// ```
2403*c3739801SMiguel Ojeda     ///
2404*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "try_mut_from_suffix")]
2405*c3739801SMiguel Ojeda     ///
2406*c3739801SMiguel Ojeda     /// See [`TryFromBytes::try_ref_from_suffix`](#method.try_ref_from_suffix.codegen).
2407*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
2408*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
2409*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
2410*c3739801SMiguel Ojeda     fn try_mut_from_suffix(
2411*c3739801SMiguel Ojeda         source: &mut [u8],
2412*c3739801SMiguel Ojeda     ) -> Result<(&mut [u8], &mut Self), TryCastError<&mut [u8], Self>>
2413*c3739801SMiguel Ojeda     where
2414*c3739801SMiguel Ojeda         Self: KnownLayout + IntoBytes,
2415*c3739801SMiguel Ojeda     {
2416*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
2417*c3739801SMiguel Ojeda         try_mut_from_prefix_suffix(source, CastType::Suffix, None).map(swap)
2418*c3739801SMiguel Ojeda     }
2419*c3739801SMiguel Ojeda 
2420*c3739801SMiguel Ojeda     /// Attempts to interpret the given `source` as a `&Self` with a DST length
2421*c3739801SMiguel Ojeda     /// equal to `count`.
2422*c3739801SMiguel Ojeda     ///
2423*c3739801SMiguel Ojeda     /// This method attempts to return a reference to `source` interpreted as a
2424*c3739801SMiguel Ojeda     /// `Self` with `count` trailing elements. If the length of `source` is not
2425*c3739801SMiguel Ojeda     /// equal to the size of `Self` with `count` elements, if `source` is not
2426*c3739801SMiguel Ojeda     /// appropriately aligned, or if `source` does not contain a valid instance
2427*c3739801SMiguel Ojeda     /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned],
2428*c3739801SMiguel Ojeda     /// you can [infallibly discard the alignment error][ConvertError::from].
2429*c3739801SMiguel Ojeda     ///
2430*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2431*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2432*c3739801SMiguel Ojeda     ///
2433*c3739801SMiguel Ojeda     /// # Examples
2434*c3739801SMiguel Ojeda     ///
2435*c3739801SMiguel Ojeda     /// ```
2436*c3739801SMiguel Ojeda     /// # #![allow(non_camel_case_types)] // For C0::xC0
2437*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2438*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2439*c3739801SMiguel Ojeda     ///
2440*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2441*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2442*c3739801SMiguel Ojeda     /// #[repr(u8)]
2443*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2444*c3739801SMiguel Ojeda     ///
2445*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2446*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2447*c3739801SMiguel Ojeda     /// #[repr(C)]
2448*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2449*c3739801SMiguel Ojeda     ///
2450*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2451*c3739801SMiguel Ojeda     /// #[repr(C)]
2452*c3739801SMiguel Ojeda     /// struct Packet {
2453*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2454*c3739801SMiguel Ojeda     ///     mug_size: u8,
2455*c3739801SMiguel Ojeda     ///     temperature: u8,
2456*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
2457*c3739801SMiguel Ojeda     /// }
2458*c3739801SMiguel Ojeda     ///
2459*c3739801SMiguel Ojeda     /// let bytes = &[0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
2460*c3739801SMiguel Ojeda     ///
2461*c3739801SMiguel Ojeda     /// let packet = Packet::try_ref_from_bytes_with_elems(bytes, 3).unwrap();
2462*c3739801SMiguel Ojeda     ///
2463*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
2464*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
2465*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2466*c3739801SMiguel Ojeda     ///
2467*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
2468*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0xC0][..];
2469*c3739801SMiguel Ojeda     /// assert!(Packet::try_ref_from_bytes_with_elems(bytes, 3).is_err());
2470*c3739801SMiguel Ojeda     /// ```
2471*c3739801SMiguel Ojeda     ///
2472*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
2473*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`try_ref_from_bytes`]
2474*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
2475*c3739801SMiguel Ojeda     ///
2476*c3739801SMiguel Ojeda     /// ```
2477*c3739801SMiguel Ojeda     /// use core::num::NonZeroU16;
2478*c3739801SMiguel Ojeda     /// use zerocopy::*;
2479*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2480*c3739801SMiguel Ojeda     ///
2481*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, Immutable, KnownLayout)]
2482*c3739801SMiguel Ojeda     /// #[repr(C)]
2483*c3739801SMiguel Ojeda     /// struct ZSTy {
2484*c3739801SMiguel Ojeda     ///     leading_sized: NonZeroU16,
2485*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
2486*c3739801SMiguel Ojeda     /// }
2487*c3739801SMiguel Ojeda     ///
2488*c3739801SMiguel Ojeda     /// let src = 0xCAFEu16.as_bytes();
2489*c3739801SMiguel Ojeda     /// let zsty = ZSTy::try_ref_from_bytes_with_elems(src, 42).unwrap();
2490*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
2491*c3739801SMiguel Ojeda     /// ```
2492*c3739801SMiguel Ojeda     ///
2493*c3739801SMiguel Ojeda     /// [`try_ref_from_bytes`]: TryFromBytes::try_ref_from_bytes
2494*c3739801SMiguel Ojeda     ///
2495*c3739801SMiguel Ojeda     #[doc = codegen_section!(
2496*c3739801SMiguel Ojeda         header = "h5",
2497*c3739801SMiguel Ojeda         bench = "try_ref_from_bytes_with_elems",
2498*c3739801SMiguel Ojeda         format = "coco",
2499*c3739801SMiguel Ojeda         arity = 2,
2500*c3739801SMiguel Ojeda         [
2501*c3739801SMiguel Ojeda             open
2502*c3739801SMiguel Ojeda             @index 1
2503*c3739801SMiguel Ojeda             @title "Unsized"
2504*c3739801SMiguel Ojeda             @variant "dynamic_size"
2505*c3739801SMiguel Ojeda         ],
2506*c3739801SMiguel Ojeda         [
2507*c3739801SMiguel Ojeda             @index 2
2508*c3739801SMiguel Ojeda             @title "Dynamically Padded"
2509*c3739801SMiguel Ojeda             @variant "dynamic_padding"
2510*c3739801SMiguel Ojeda         ]
2511*c3739801SMiguel Ojeda     )]
2512*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
2513*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
2514*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
2515*c3739801SMiguel Ojeda     fn try_ref_from_bytes_with_elems(
2516*c3739801SMiguel Ojeda         source: &[u8],
2517*c3739801SMiguel Ojeda         count: usize,
2518*c3739801SMiguel Ojeda     ) -> Result<&Self, TryCastError<&[u8], Self>>
2519*c3739801SMiguel Ojeda     where
2520*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize> + Immutable,
2521*c3739801SMiguel Ojeda     {
2522*c3739801SMiguel Ojeda         match Ptr::from_ref(source).try_cast_into_no_leftover::<Self, BecauseImmutable>(Some(count))
2523*c3739801SMiguel Ojeda         {
2524*c3739801SMiguel Ojeda             Ok(source) => {
2525*c3739801SMiguel Ojeda                 // This call may panic. If that happens, it doesn't cause any soundness
2526*c3739801SMiguel Ojeda                 // issues, as we have not generated any invalid state which we need to
2527*c3739801SMiguel Ojeda                 // fix before returning.
2528*c3739801SMiguel Ojeda                 match source.try_into_valid() {
2529*c3739801SMiguel Ojeda                     Ok(source) => Ok(source.as_ref()),
2530*c3739801SMiguel Ojeda                     Err(e) => {
2531*c3739801SMiguel Ojeda                         Err(e.map_src(|src| src.as_bytes::<BecauseImmutable>().as_ref()).into())
2532*c3739801SMiguel Ojeda                     }
2533*c3739801SMiguel Ojeda                 }
2534*c3739801SMiguel Ojeda             }
2535*c3739801SMiguel Ojeda             Err(e) => Err(e.map_src(Ptr::as_ref).into()),
2536*c3739801SMiguel Ojeda         }
2537*c3739801SMiguel Ojeda     }
2538*c3739801SMiguel Ojeda 
2539*c3739801SMiguel Ojeda     /// Attempts to interpret the prefix of the given `source` as a `&Self` with
2540*c3739801SMiguel Ojeda     /// a DST length equal to `count`.
2541*c3739801SMiguel Ojeda     ///
2542*c3739801SMiguel Ojeda     /// This method attempts to return a reference to the prefix of `source`
2543*c3739801SMiguel Ojeda     /// interpreted as a `Self` with `count` trailing elements, and a reference
2544*c3739801SMiguel Ojeda     /// to the remaining bytes. If the length of `source` is less than the size
2545*c3739801SMiguel Ojeda     /// of `Self` with `count` elements, if `source` is not appropriately
2546*c3739801SMiguel Ojeda     /// aligned, or if the prefix of `source` does not contain a valid instance
2547*c3739801SMiguel Ojeda     /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned],
2548*c3739801SMiguel Ojeda     /// you can [infallibly discard the alignment error][ConvertError::from].
2549*c3739801SMiguel Ojeda     ///
2550*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2551*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2552*c3739801SMiguel Ojeda     ///
2553*c3739801SMiguel Ojeda     /// # Examples
2554*c3739801SMiguel Ojeda     ///
2555*c3739801SMiguel Ojeda     /// ```
2556*c3739801SMiguel Ojeda     /// # #![allow(non_camel_case_types)] // For C0::xC0
2557*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2558*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2559*c3739801SMiguel Ojeda     ///
2560*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2561*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2562*c3739801SMiguel Ojeda     /// #[repr(u8)]
2563*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2564*c3739801SMiguel Ojeda     ///
2565*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2566*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2567*c3739801SMiguel Ojeda     /// #[repr(C)]
2568*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2569*c3739801SMiguel Ojeda     ///
2570*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2571*c3739801SMiguel Ojeda     /// #[repr(C)]
2572*c3739801SMiguel Ojeda     /// struct Packet {
2573*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2574*c3739801SMiguel Ojeda     ///     mug_size: u8,
2575*c3739801SMiguel Ojeda     ///     temperature: u8,
2576*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
2577*c3739801SMiguel Ojeda     /// }
2578*c3739801SMiguel Ojeda     ///
2579*c3739801SMiguel Ojeda     /// let bytes = &[0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7, 8][..];
2580*c3739801SMiguel Ojeda     ///
2581*c3739801SMiguel Ojeda     /// let (packet, suffix) = Packet::try_ref_from_prefix_with_elems(bytes, 3).unwrap();
2582*c3739801SMiguel Ojeda     ///
2583*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
2584*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
2585*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2586*c3739801SMiguel Ojeda     /// assert_eq!(suffix, &[8u8][..]);
2587*c3739801SMiguel Ojeda     ///
2588*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
2589*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..];
2590*c3739801SMiguel Ojeda     /// assert!(Packet::try_ref_from_prefix_with_elems(bytes, 3).is_err());
2591*c3739801SMiguel Ojeda     /// ```
2592*c3739801SMiguel Ojeda     ///
2593*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
2594*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`try_ref_from_prefix`]
2595*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
2596*c3739801SMiguel Ojeda     ///
2597*c3739801SMiguel Ojeda     /// ```
2598*c3739801SMiguel Ojeda     /// use core::num::NonZeroU16;
2599*c3739801SMiguel Ojeda     /// use zerocopy::*;
2600*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2601*c3739801SMiguel Ojeda     ///
2602*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, Immutable, KnownLayout)]
2603*c3739801SMiguel Ojeda     /// #[repr(C)]
2604*c3739801SMiguel Ojeda     /// struct ZSTy {
2605*c3739801SMiguel Ojeda     ///     leading_sized: NonZeroU16,
2606*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
2607*c3739801SMiguel Ojeda     /// }
2608*c3739801SMiguel Ojeda     ///
2609*c3739801SMiguel Ojeda     /// let src = 0xCAFEu16.as_bytes();
2610*c3739801SMiguel Ojeda     /// let (zsty, _) = ZSTy::try_ref_from_prefix_with_elems(src, 42).unwrap();
2611*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
2612*c3739801SMiguel Ojeda     /// ```
2613*c3739801SMiguel Ojeda     ///
2614*c3739801SMiguel Ojeda     /// [`try_ref_from_prefix`]: TryFromBytes::try_ref_from_prefix
2615*c3739801SMiguel Ojeda     ///
2616*c3739801SMiguel Ojeda     #[doc = codegen_section!(
2617*c3739801SMiguel Ojeda         header = "h5",
2618*c3739801SMiguel Ojeda         bench = "try_ref_from_prefix_with_elems",
2619*c3739801SMiguel Ojeda         format = "coco",
2620*c3739801SMiguel Ojeda         arity = 2,
2621*c3739801SMiguel Ojeda         [
2622*c3739801SMiguel Ojeda             open
2623*c3739801SMiguel Ojeda             @index 1
2624*c3739801SMiguel Ojeda             @title "Unsized"
2625*c3739801SMiguel Ojeda             @variant "dynamic_size"
2626*c3739801SMiguel Ojeda         ],
2627*c3739801SMiguel Ojeda         [
2628*c3739801SMiguel Ojeda             @index 2
2629*c3739801SMiguel Ojeda             @title "Dynamically Padded"
2630*c3739801SMiguel Ojeda             @variant "dynamic_padding"
2631*c3739801SMiguel Ojeda         ]
2632*c3739801SMiguel Ojeda     )]
2633*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
2634*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
2635*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
2636*c3739801SMiguel Ojeda     fn try_ref_from_prefix_with_elems(
2637*c3739801SMiguel Ojeda         source: &[u8],
2638*c3739801SMiguel Ojeda         count: usize,
2639*c3739801SMiguel Ojeda     ) -> Result<(&Self, &[u8]), TryCastError<&[u8], Self>>
2640*c3739801SMiguel Ojeda     where
2641*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize> + Immutable,
2642*c3739801SMiguel Ojeda     {
2643*c3739801SMiguel Ojeda         try_ref_from_prefix_suffix(source, CastType::Prefix, Some(count))
2644*c3739801SMiguel Ojeda     }
2645*c3739801SMiguel Ojeda 
2646*c3739801SMiguel Ojeda     /// Attempts to interpret the suffix of the given `source` as a `&Self` with
2647*c3739801SMiguel Ojeda     /// a DST length equal to `count`.
2648*c3739801SMiguel Ojeda     ///
2649*c3739801SMiguel Ojeda     /// This method attempts to return a reference to the suffix of `source`
2650*c3739801SMiguel Ojeda     /// interpreted as a `Self` with `count` trailing elements, and a reference
2651*c3739801SMiguel Ojeda     /// to the preceding bytes. If the length of `source` is less than the size
2652*c3739801SMiguel Ojeda     /// of `Self` with `count` elements, if the suffix of `source` is not
2653*c3739801SMiguel Ojeda     /// appropriately aligned, or if the suffix of `source` does not contain a
2654*c3739801SMiguel Ojeda     /// valid instance of `Self`, this returns `Err`. If [`Self:
2655*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
2656*c3739801SMiguel Ojeda     /// error][ConvertError::from].
2657*c3739801SMiguel Ojeda     ///
2658*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2659*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2660*c3739801SMiguel Ojeda     ///
2661*c3739801SMiguel Ojeda     /// # Examples
2662*c3739801SMiguel Ojeda     ///
2663*c3739801SMiguel Ojeda     /// ```
2664*c3739801SMiguel Ojeda     /// # #![allow(non_camel_case_types)] // For C0::xC0
2665*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2666*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2667*c3739801SMiguel Ojeda     ///
2668*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2669*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2670*c3739801SMiguel Ojeda     /// #[repr(u8)]
2671*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2672*c3739801SMiguel Ojeda     ///
2673*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2674*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2675*c3739801SMiguel Ojeda     /// #[repr(C)]
2676*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2677*c3739801SMiguel Ojeda     ///
2678*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, KnownLayout, Immutable)]
2679*c3739801SMiguel Ojeda     /// #[repr(C)]
2680*c3739801SMiguel Ojeda     /// struct Packet {
2681*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2682*c3739801SMiguel Ojeda     ///     mug_size: u8,
2683*c3739801SMiguel Ojeda     ///     temperature: u8,
2684*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
2685*c3739801SMiguel Ojeda     /// }
2686*c3739801SMiguel Ojeda     ///
2687*c3739801SMiguel Ojeda     /// let bytes = &[123, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
2688*c3739801SMiguel Ojeda     ///
2689*c3739801SMiguel Ojeda     /// let (prefix, packet) = Packet::try_ref_from_suffix_with_elems(bytes, 3).unwrap();
2690*c3739801SMiguel Ojeda     ///
2691*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
2692*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
2693*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2694*c3739801SMiguel Ojeda     /// assert_eq!(prefix, &[123u8][..]);
2695*c3739801SMiguel Ojeda     ///
2696*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
2697*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..];
2698*c3739801SMiguel Ojeda     /// assert!(Packet::try_ref_from_suffix_with_elems(bytes, 3).is_err());
2699*c3739801SMiguel Ojeda     /// ```
2700*c3739801SMiguel Ojeda     ///
2701*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
2702*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`try_ref_from_prefix`]
2703*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
2704*c3739801SMiguel Ojeda     ///
2705*c3739801SMiguel Ojeda     /// ```
2706*c3739801SMiguel Ojeda     /// use core::num::NonZeroU16;
2707*c3739801SMiguel Ojeda     /// use zerocopy::*;
2708*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2709*c3739801SMiguel Ojeda     ///
2710*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, Immutable, KnownLayout)]
2711*c3739801SMiguel Ojeda     /// #[repr(C)]
2712*c3739801SMiguel Ojeda     /// struct ZSTy {
2713*c3739801SMiguel Ojeda     ///     leading_sized: NonZeroU16,
2714*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
2715*c3739801SMiguel Ojeda     /// }
2716*c3739801SMiguel Ojeda     ///
2717*c3739801SMiguel Ojeda     /// let src = 0xCAFEu16.as_bytes();
2718*c3739801SMiguel Ojeda     /// let (_, zsty) = ZSTy::try_ref_from_suffix_with_elems(src, 42).unwrap();
2719*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
2720*c3739801SMiguel Ojeda     /// ```
2721*c3739801SMiguel Ojeda     ///
2722*c3739801SMiguel Ojeda     /// [`try_ref_from_prefix`]: TryFromBytes::try_ref_from_prefix
2723*c3739801SMiguel Ojeda     ///
2724*c3739801SMiguel Ojeda     #[doc = codegen_section!(
2725*c3739801SMiguel Ojeda         header = "h5",
2726*c3739801SMiguel Ojeda         bench = "try_ref_from_suffix_with_elems",
2727*c3739801SMiguel Ojeda         format = "coco",
2728*c3739801SMiguel Ojeda         arity = 2,
2729*c3739801SMiguel Ojeda         [
2730*c3739801SMiguel Ojeda             open
2731*c3739801SMiguel Ojeda             @index 1
2732*c3739801SMiguel Ojeda             @title "Unsized"
2733*c3739801SMiguel Ojeda             @variant "dynamic_size"
2734*c3739801SMiguel Ojeda         ],
2735*c3739801SMiguel Ojeda         [
2736*c3739801SMiguel Ojeda             @index 2
2737*c3739801SMiguel Ojeda             @title "Dynamically Padded"
2738*c3739801SMiguel Ojeda             @variant "dynamic_padding"
2739*c3739801SMiguel Ojeda         ]
2740*c3739801SMiguel Ojeda     )]
2741*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
2742*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
2743*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
2744*c3739801SMiguel Ojeda     fn try_ref_from_suffix_with_elems(
2745*c3739801SMiguel Ojeda         source: &[u8],
2746*c3739801SMiguel Ojeda         count: usize,
2747*c3739801SMiguel Ojeda     ) -> Result<(&[u8], &Self), TryCastError<&[u8], Self>>
2748*c3739801SMiguel Ojeda     where
2749*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize> + Immutable,
2750*c3739801SMiguel Ojeda     {
2751*c3739801SMiguel Ojeda         try_ref_from_prefix_suffix(source, CastType::Suffix, Some(count)).map(swap)
2752*c3739801SMiguel Ojeda     }
2753*c3739801SMiguel Ojeda 
2754*c3739801SMiguel Ojeda     /// Attempts to interpret the given `source` as a `&mut Self` with a DST
2755*c3739801SMiguel Ojeda     /// length equal to `count`.
2756*c3739801SMiguel Ojeda     ///
2757*c3739801SMiguel Ojeda     /// This method attempts to return a reference to `source` interpreted as a
2758*c3739801SMiguel Ojeda     /// `Self` with `count` trailing elements. If the length of `source` is not
2759*c3739801SMiguel Ojeda     /// equal to the size of `Self` with `count` elements, if `source` is not
2760*c3739801SMiguel Ojeda     /// appropriately aligned, or if `source` does not contain a valid instance
2761*c3739801SMiguel Ojeda     /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned],
2762*c3739801SMiguel Ojeda     /// you can [infallibly discard the alignment error][ConvertError::from].
2763*c3739801SMiguel Ojeda     ///
2764*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2765*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2766*c3739801SMiguel Ojeda     ///
2767*c3739801SMiguel Ojeda     /// # Examples
2768*c3739801SMiguel Ojeda     ///
2769*c3739801SMiguel Ojeda     /// ```
2770*c3739801SMiguel Ojeda     /// # #![allow(non_camel_case_types)] // For C0::xC0
2771*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2772*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2773*c3739801SMiguel Ojeda     ///
2774*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2775*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2776*c3739801SMiguel Ojeda     /// #[repr(u8)]
2777*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2778*c3739801SMiguel Ojeda     ///
2779*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2780*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2781*c3739801SMiguel Ojeda     /// #[repr(C)]
2782*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2783*c3739801SMiguel Ojeda     ///
2784*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2785*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2786*c3739801SMiguel Ojeda     /// struct Packet {
2787*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2788*c3739801SMiguel Ojeda     ///     mug_size: u8,
2789*c3739801SMiguel Ojeda     ///     temperature: u8,
2790*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
2791*c3739801SMiguel Ojeda     /// }
2792*c3739801SMiguel Ojeda     ///
2793*c3739801SMiguel Ojeda     /// let bytes = &mut [0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
2794*c3739801SMiguel Ojeda     ///
2795*c3739801SMiguel Ojeda     /// let packet = Packet::try_mut_from_bytes_with_elems(bytes, 3).unwrap();
2796*c3739801SMiguel Ojeda     ///
2797*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
2798*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
2799*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2800*c3739801SMiguel Ojeda     ///
2801*c3739801SMiguel Ojeda     /// packet.temperature = 111;
2802*c3739801SMiguel Ojeda     ///
2803*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 2, 3, 4, 5, 6, 7]);
2804*c3739801SMiguel Ojeda     ///
2805*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
2806*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 77, 240, 0xC0, 0xC0][..];
2807*c3739801SMiguel Ojeda     /// assert!(Packet::try_mut_from_bytes_with_elems(bytes, 3).is_err());
2808*c3739801SMiguel Ojeda     /// ```
2809*c3739801SMiguel Ojeda     ///
2810*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
2811*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`try_mut_from_bytes`]
2812*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
2813*c3739801SMiguel Ojeda     ///
2814*c3739801SMiguel Ojeda     /// ```
2815*c3739801SMiguel Ojeda     /// use core::num::NonZeroU16;
2816*c3739801SMiguel Ojeda     /// use zerocopy::*;
2817*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2818*c3739801SMiguel Ojeda     ///
2819*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2820*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2821*c3739801SMiguel Ojeda     /// struct ZSTy {
2822*c3739801SMiguel Ojeda     ///     leading_sized: NonZeroU16,
2823*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
2824*c3739801SMiguel Ojeda     /// }
2825*c3739801SMiguel Ojeda     ///
2826*c3739801SMiguel Ojeda     /// let mut src = 0xCAFEu16;
2827*c3739801SMiguel Ojeda     /// let src = src.as_mut_bytes();
2828*c3739801SMiguel Ojeda     /// let zsty = ZSTy::try_mut_from_bytes_with_elems(src, 42).unwrap();
2829*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
2830*c3739801SMiguel Ojeda     /// ```
2831*c3739801SMiguel Ojeda     ///
2832*c3739801SMiguel Ojeda     /// [`try_mut_from_bytes`]: TryFromBytes::try_mut_from_bytes
2833*c3739801SMiguel Ojeda     ///
2834*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "try_mut_from_bytes_with_elems")]
2835*c3739801SMiguel Ojeda     ///
2836*c3739801SMiguel Ojeda     /// See [`TryFromBytes::try_ref_from_bytes_with_elems`](#method.try_ref_from_bytes_with_elems.codegen).
2837*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
2838*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
2839*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
2840*c3739801SMiguel Ojeda     fn try_mut_from_bytes_with_elems(
2841*c3739801SMiguel Ojeda         source: &mut [u8],
2842*c3739801SMiguel Ojeda         count: usize,
2843*c3739801SMiguel Ojeda     ) -> Result<&mut Self, TryCastError<&mut [u8], Self>>
2844*c3739801SMiguel Ojeda     where
2845*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
2846*c3739801SMiguel Ojeda     {
2847*c3739801SMiguel Ojeda         match Ptr::from_mut(source).try_cast_into_no_leftover::<Self, BecauseExclusive>(Some(count))
2848*c3739801SMiguel Ojeda         {
2849*c3739801SMiguel Ojeda             Ok(source) => {
2850*c3739801SMiguel Ojeda                 // This call may panic. If that happens, it doesn't cause any soundness
2851*c3739801SMiguel Ojeda                 // issues, as we have not generated any invalid state which we need to
2852*c3739801SMiguel Ojeda                 // fix before returning.
2853*c3739801SMiguel Ojeda                 match source.try_into_valid() {
2854*c3739801SMiguel Ojeda                     Ok(source) => Ok(source.as_mut()),
2855*c3739801SMiguel Ojeda                     Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()),
2856*c3739801SMiguel Ojeda                 }
2857*c3739801SMiguel Ojeda             }
2858*c3739801SMiguel Ojeda             Err(e) => Err(e.map_src(Ptr::as_mut).into()),
2859*c3739801SMiguel Ojeda         }
2860*c3739801SMiguel Ojeda     }
2861*c3739801SMiguel Ojeda 
2862*c3739801SMiguel Ojeda     /// Attempts to interpret the prefix of the given `source` as a `&mut Self`
2863*c3739801SMiguel Ojeda     /// with a DST length equal to `count`.
2864*c3739801SMiguel Ojeda     ///
2865*c3739801SMiguel Ojeda     /// This method attempts to return a reference to the prefix of `source`
2866*c3739801SMiguel Ojeda     /// interpreted as a `Self` with `count` trailing elements, and a reference
2867*c3739801SMiguel Ojeda     /// to the remaining bytes. If the length of `source` is less than the size
2868*c3739801SMiguel Ojeda     /// of `Self` with `count` elements, if `source` is not appropriately
2869*c3739801SMiguel Ojeda     /// aligned, or if the prefix of `source` does not contain a valid instance
2870*c3739801SMiguel Ojeda     /// of `Self`, this returns `Err`. If [`Self: Unaligned`][self-unaligned],
2871*c3739801SMiguel Ojeda     /// you can [infallibly discard the alignment error][ConvertError::from].
2872*c3739801SMiguel Ojeda     ///
2873*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2874*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2875*c3739801SMiguel Ojeda     ///
2876*c3739801SMiguel Ojeda     /// # Examples
2877*c3739801SMiguel Ojeda     ///
2878*c3739801SMiguel Ojeda     /// ```
2879*c3739801SMiguel Ojeda     /// # #![allow(non_camel_case_types)] // For C0::xC0
2880*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2881*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2882*c3739801SMiguel Ojeda     ///
2883*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2884*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2885*c3739801SMiguel Ojeda     /// #[repr(u8)]
2886*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2887*c3739801SMiguel Ojeda     ///
2888*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2889*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2890*c3739801SMiguel Ojeda     /// #[repr(C)]
2891*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2892*c3739801SMiguel Ojeda     ///
2893*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2894*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2895*c3739801SMiguel Ojeda     /// struct Packet {
2896*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2897*c3739801SMiguel Ojeda     ///     mug_size: u8,
2898*c3739801SMiguel Ojeda     ///     temperature: u8,
2899*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
2900*c3739801SMiguel Ojeda     /// }
2901*c3739801SMiguel Ojeda     ///
2902*c3739801SMiguel Ojeda     /// let bytes = &mut [0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7, 8][..];
2903*c3739801SMiguel Ojeda     ///
2904*c3739801SMiguel Ojeda     /// let (packet, suffix) = Packet::try_mut_from_prefix_with_elems(bytes, 3).unwrap();
2905*c3739801SMiguel Ojeda     ///
2906*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
2907*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
2908*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
2909*c3739801SMiguel Ojeda     /// assert_eq!(suffix, &[8u8][..]);
2910*c3739801SMiguel Ojeda     ///
2911*c3739801SMiguel Ojeda     /// packet.temperature = 111;
2912*c3739801SMiguel Ojeda     /// suffix[0] = 222;
2913*c3739801SMiguel Ojeda     ///
2914*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0xC0, 0xC0, 240, 111, 2, 3, 4, 5, 6, 7, 222]);
2915*c3739801SMiguel Ojeda     ///
2916*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
2917*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..];
2918*c3739801SMiguel Ojeda     /// assert!(Packet::try_mut_from_prefix_with_elems(bytes, 3).is_err());
2919*c3739801SMiguel Ojeda     /// ```
2920*c3739801SMiguel Ojeda     ///
2921*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
2922*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`try_mut_from_prefix`]
2923*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
2924*c3739801SMiguel Ojeda     ///
2925*c3739801SMiguel Ojeda     /// ```
2926*c3739801SMiguel Ojeda     /// use core::num::NonZeroU16;
2927*c3739801SMiguel Ojeda     /// use zerocopy::*;
2928*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2929*c3739801SMiguel Ojeda     ///
2930*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2931*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2932*c3739801SMiguel Ojeda     /// struct ZSTy {
2933*c3739801SMiguel Ojeda     ///     leading_sized: NonZeroU16,
2934*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
2935*c3739801SMiguel Ojeda     /// }
2936*c3739801SMiguel Ojeda     ///
2937*c3739801SMiguel Ojeda     /// let mut src = 0xCAFEu16;
2938*c3739801SMiguel Ojeda     /// let src = src.as_mut_bytes();
2939*c3739801SMiguel Ojeda     /// let (zsty, _) = ZSTy::try_mut_from_prefix_with_elems(src, 42).unwrap();
2940*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
2941*c3739801SMiguel Ojeda     /// ```
2942*c3739801SMiguel Ojeda     ///
2943*c3739801SMiguel Ojeda     /// [`try_mut_from_prefix`]: TryFromBytes::try_mut_from_prefix
2944*c3739801SMiguel Ojeda     ///
2945*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "try_mut_from_prefix_with_elems")]
2946*c3739801SMiguel Ojeda     ///
2947*c3739801SMiguel Ojeda     /// See [`TryFromBytes::try_ref_from_prefix_with_elems`](#method.try_ref_from_prefix_with_elems.codegen).
2948*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
2949*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
2950*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
2951*c3739801SMiguel Ojeda     fn try_mut_from_prefix_with_elems(
2952*c3739801SMiguel Ojeda         source: &mut [u8],
2953*c3739801SMiguel Ojeda         count: usize,
2954*c3739801SMiguel Ojeda     ) -> Result<(&mut Self, &mut [u8]), TryCastError<&mut [u8], Self>>
2955*c3739801SMiguel Ojeda     where
2956*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
2957*c3739801SMiguel Ojeda     {
2958*c3739801SMiguel Ojeda         try_mut_from_prefix_suffix(source, CastType::Prefix, Some(count))
2959*c3739801SMiguel Ojeda     }
2960*c3739801SMiguel Ojeda 
2961*c3739801SMiguel Ojeda     /// Attempts to interpret the suffix of the given `source` as a `&mut Self`
2962*c3739801SMiguel Ojeda     /// with a DST length equal to `count`.
2963*c3739801SMiguel Ojeda     ///
2964*c3739801SMiguel Ojeda     /// This method attempts to return a reference to the suffix of `source`
2965*c3739801SMiguel Ojeda     /// interpreted as a `Self` with `count` trailing elements, and a reference
2966*c3739801SMiguel Ojeda     /// to the preceding bytes. If the length of `source` is less than the size
2967*c3739801SMiguel Ojeda     /// of `Self` with `count` elements, if the suffix of `source` is not
2968*c3739801SMiguel Ojeda     /// appropriately aligned, or if the suffix of `source` does not contain a
2969*c3739801SMiguel Ojeda     /// valid instance of `Self`, this returns `Err`. If [`Self:
2970*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
2971*c3739801SMiguel Ojeda     /// error][ConvertError::from].
2972*c3739801SMiguel Ojeda     ///
2973*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
2974*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
2975*c3739801SMiguel Ojeda     ///
2976*c3739801SMiguel Ojeda     /// # Examples
2977*c3739801SMiguel Ojeda     ///
2978*c3739801SMiguel Ojeda     /// ```
2979*c3739801SMiguel Ojeda     /// # #![allow(non_camel_case_types)] // For C0::xC0
2980*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
2981*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
2982*c3739801SMiguel Ojeda     ///
2983*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
2984*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2985*c3739801SMiguel Ojeda     /// #[repr(u8)]
2986*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
2987*c3739801SMiguel Ojeda     ///
2988*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
2989*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2990*c3739801SMiguel Ojeda     /// #[repr(C)]
2991*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
2992*c3739801SMiguel Ojeda     ///
2993*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
2994*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
2995*c3739801SMiguel Ojeda     /// struct Packet {
2996*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
2997*c3739801SMiguel Ojeda     ///     mug_size: u8,
2998*c3739801SMiguel Ojeda     ///     temperature: u8,
2999*c3739801SMiguel Ojeda     ///     marshmallows: [[u8; 2]],
3000*c3739801SMiguel Ojeda     /// }
3001*c3739801SMiguel Ojeda     ///
3002*c3739801SMiguel Ojeda     /// let bytes = &mut [123, 0xC0, 0xC0, 240, 77, 2, 3, 4, 5, 6, 7][..];
3003*c3739801SMiguel Ojeda     ///
3004*c3739801SMiguel Ojeda     /// let (prefix, packet) = Packet::try_mut_from_suffix_with_elems(bytes, 3).unwrap();
3005*c3739801SMiguel Ojeda     ///
3006*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
3007*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
3008*c3739801SMiguel Ojeda     /// assert_eq!(packet.marshmallows, [[2, 3], [4, 5], [6, 7]]);
3009*c3739801SMiguel Ojeda     /// assert_eq!(prefix, &[123u8][..]);
3010*c3739801SMiguel Ojeda     ///
3011*c3739801SMiguel Ojeda     /// prefix[0] = 111;
3012*c3739801SMiguel Ojeda     /// packet.temperature = 222;
3013*c3739801SMiguel Ojeda     ///
3014*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [111, 0xC0, 0xC0, 240, 222, 2, 3, 4, 5, 6, 7]);
3015*c3739801SMiguel Ojeda     ///
3016*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
3017*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 77, 240, 0xC0, 0xC0][..];
3018*c3739801SMiguel Ojeda     /// assert!(Packet::try_mut_from_suffix_with_elems(bytes, 3).is_err());
3019*c3739801SMiguel Ojeda     /// ```
3020*c3739801SMiguel Ojeda     ///
3021*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
3022*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`try_mut_from_prefix`]
3023*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
3024*c3739801SMiguel Ojeda     ///
3025*c3739801SMiguel Ojeda     /// ```
3026*c3739801SMiguel Ojeda     /// use core::num::NonZeroU16;
3027*c3739801SMiguel Ojeda     /// use zerocopy::*;
3028*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
3029*c3739801SMiguel Ojeda     ///
3030*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes, IntoBytes, KnownLayout)]
3031*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
3032*c3739801SMiguel Ojeda     /// struct ZSTy {
3033*c3739801SMiguel Ojeda     ///     leading_sized: NonZeroU16,
3034*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
3035*c3739801SMiguel Ojeda     /// }
3036*c3739801SMiguel Ojeda     ///
3037*c3739801SMiguel Ojeda     /// let mut src = 0xCAFEu16;
3038*c3739801SMiguel Ojeda     /// let src = src.as_mut_bytes();
3039*c3739801SMiguel Ojeda     /// let (_, zsty) = ZSTy::try_mut_from_suffix_with_elems(src, 42).unwrap();
3040*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
3041*c3739801SMiguel Ojeda     /// ```
3042*c3739801SMiguel Ojeda     ///
3043*c3739801SMiguel Ojeda     /// [`try_mut_from_prefix`]: TryFromBytes::try_mut_from_prefix
3044*c3739801SMiguel Ojeda     ///
3045*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "try_mut_from_suffix_with_elems")]
3046*c3739801SMiguel Ojeda     ///
3047*c3739801SMiguel Ojeda     /// See [`TryFromBytes::try_ref_from_suffix_with_elems`](#method.try_ref_from_suffix_with_elems.codegen).
3048*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
3049*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
3050*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
3051*c3739801SMiguel Ojeda     fn try_mut_from_suffix_with_elems(
3052*c3739801SMiguel Ojeda         source: &mut [u8],
3053*c3739801SMiguel Ojeda         count: usize,
3054*c3739801SMiguel Ojeda     ) -> Result<(&mut [u8], &mut Self), TryCastError<&mut [u8], Self>>
3055*c3739801SMiguel Ojeda     where
3056*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize> + IntoBytes,
3057*c3739801SMiguel Ojeda     {
3058*c3739801SMiguel Ojeda         try_mut_from_prefix_suffix(source, CastType::Suffix, Some(count)).map(swap)
3059*c3739801SMiguel Ojeda     }
3060*c3739801SMiguel Ojeda 
3061*c3739801SMiguel Ojeda     /// Attempts to read the given `source` as a `Self`.
3062*c3739801SMiguel Ojeda     ///
3063*c3739801SMiguel Ojeda     /// If `source.len() != size_of::<Self>()` or the bytes are not a valid
3064*c3739801SMiguel Ojeda     /// instance of `Self`, this returns `Err`.
3065*c3739801SMiguel Ojeda     ///
3066*c3739801SMiguel Ojeda     /// # Examples
3067*c3739801SMiguel Ojeda     ///
3068*c3739801SMiguel Ojeda     /// ```
3069*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
3070*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
3071*c3739801SMiguel Ojeda     ///
3072*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
3073*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes)]
3074*c3739801SMiguel Ojeda     /// #[repr(u8)]
3075*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
3076*c3739801SMiguel Ojeda     ///
3077*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
3078*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes)]
3079*c3739801SMiguel Ojeda     /// #[repr(C)]
3080*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
3081*c3739801SMiguel Ojeda     ///
3082*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes)]
3083*c3739801SMiguel Ojeda     /// #[repr(C)]
3084*c3739801SMiguel Ojeda     /// struct Packet {
3085*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
3086*c3739801SMiguel Ojeda     ///     mug_size: u8,
3087*c3739801SMiguel Ojeda     ///     temperature: u8,
3088*c3739801SMiguel Ojeda     /// }
3089*c3739801SMiguel Ojeda     ///
3090*c3739801SMiguel Ojeda     /// let bytes = &[0xC0, 0xC0, 240, 77][..];
3091*c3739801SMiguel Ojeda     ///
3092*c3739801SMiguel Ojeda     /// let packet = Packet::try_read_from_bytes(bytes).unwrap();
3093*c3739801SMiguel Ojeda     ///
3094*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
3095*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
3096*c3739801SMiguel Ojeda     ///
3097*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
3098*c3739801SMiguel Ojeda     /// let bytes = &mut [0x10, 0xC0, 240, 77][..];
3099*c3739801SMiguel Ojeda     /// assert!(Packet::try_read_from_bytes(bytes).is_err());
3100*c3739801SMiguel Ojeda     /// ```
3101*c3739801SMiguel Ojeda     ///
3102*c3739801SMiguel Ojeda     /// # Performance Considerations
3103*c3739801SMiguel Ojeda     ///
3104*c3739801SMiguel Ojeda     /// In this version of zerocopy, this method reads the `source` into a
3105*c3739801SMiguel Ojeda     /// well-aligned stack allocation and *then* validates that the allocation
3106*c3739801SMiguel Ojeda     /// is a valid `Self`. This ensures that validation can be performed using
3107*c3739801SMiguel Ojeda     /// aligned reads (which carry a performance advantage over unaligned reads
3108*c3739801SMiguel Ojeda     /// on many platforms) at the cost of an unconditional copy.
3109*c3739801SMiguel Ojeda     ///
3110*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3111*c3739801SMiguel Ojeda         header = "h5",
3112*c3739801SMiguel Ojeda         bench = "try_read_from_bytes",
3113*c3739801SMiguel Ojeda         format = "coco_static_size",
3114*c3739801SMiguel Ojeda     )]
3115*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
3116*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
3117*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
3118*c3739801SMiguel Ojeda     fn try_read_from_bytes(source: &[u8]) -> Result<Self, TryReadError<&[u8], Self>>
3119*c3739801SMiguel Ojeda     where
3120*c3739801SMiguel Ojeda         Self: Sized,
3121*c3739801SMiguel Ojeda     {
3122*c3739801SMiguel Ojeda         // FIXME(#2981): If `align_of::<Self>() == 1`, validate `source` in-place.
3123*c3739801SMiguel Ojeda 
3124*c3739801SMiguel Ojeda         let candidate = match CoreMaybeUninit::<Self>::read_from_bytes(source) {
3125*c3739801SMiguel Ojeda             Ok(candidate) => candidate,
3126*c3739801SMiguel Ojeda             Err(e) => {
3127*c3739801SMiguel Ojeda                 return Err(TryReadError::Size(e.with_dst()));
3128*c3739801SMiguel Ojeda             }
3129*c3739801SMiguel Ojeda         };
3130*c3739801SMiguel Ojeda         // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
3131*c3739801SMiguel Ojeda         // its bytes are initialized.
3132*c3739801SMiguel Ojeda         unsafe { try_read_from(source, candidate) }
3133*c3739801SMiguel Ojeda     }
3134*c3739801SMiguel Ojeda 
3135*c3739801SMiguel Ojeda     /// Attempts to read a `Self` from the prefix of the given `source`.
3136*c3739801SMiguel Ojeda     ///
3137*c3739801SMiguel Ojeda     /// This attempts to read a `Self` from the first `size_of::<Self>()` bytes
3138*c3739801SMiguel Ojeda     /// of `source`, returning that `Self` and any remaining bytes. If
3139*c3739801SMiguel Ojeda     /// `source.len() < size_of::<Self>()` or the bytes are not a valid instance
3140*c3739801SMiguel Ojeda     /// of `Self`, it returns `Err`.
3141*c3739801SMiguel Ojeda     ///
3142*c3739801SMiguel Ojeda     /// # Examples
3143*c3739801SMiguel Ojeda     ///
3144*c3739801SMiguel Ojeda     /// ```
3145*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
3146*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
3147*c3739801SMiguel Ojeda     ///
3148*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
3149*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes)]
3150*c3739801SMiguel Ojeda     /// #[repr(u8)]
3151*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
3152*c3739801SMiguel Ojeda     ///
3153*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
3154*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes)]
3155*c3739801SMiguel Ojeda     /// #[repr(C)]
3156*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
3157*c3739801SMiguel Ojeda     ///
3158*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes)]
3159*c3739801SMiguel Ojeda     /// #[repr(C)]
3160*c3739801SMiguel Ojeda     /// struct Packet {
3161*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
3162*c3739801SMiguel Ojeda     ///     mug_size: u8,
3163*c3739801SMiguel Ojeda     ///     temperature: u8,
3164*c3739801SMiguel Ojeda     /// }
3165*c3739801SMiguel Ojeda     ///
3166*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `Packet`.
3167*c3739801SMiguel Ojeda     /// let bytes = &[0xC0, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
3168*c3739801SMiguel Ojeda     ///
3169*c3739801SMiguel Ojeda     /// let (packet, suffix) = Packet::try_read_from_prefix(bytes).unwrap();
3170*c3739801SMiguel Ojeda     ///
3171*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
3172*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
3173*c3739801SMiguel Ojeda     /// assert_eq!(suffix, &[0u8, 1, 2, 3, 4, 5, 6][..]);
3174*c3739801SMiguel Ojeda     ///
3175*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
3176*c3739801SMiguel Ojeda     /// let bytes = &[0x10, 0xC0, 240, 77, 0, 1, 2, 3, 4, 5, 6][..];
3177*c3739801SMiguel Ojeda     /// assert!(Packet::try_read_from_prefix(bytes).is_err());
3178*c3739801SMiguel Ojeda     /// ```
3179*c3739801SMiguel Ojeda     ///
3180*c3739801SMiguel Ojeda     /// # Performance Considerations
3181*c3739801SMiguel Ojeda     ///
3182*c3739801SMiguel Ojeda     /// In this version of zerocopy, this method reads the `source` into a
3183*c3739801SMiguel Ojeda     /// well-aligned stack allocation and *then* validates that the allocation
3184*c3739801SMiguel Ojeda     /// is a valid `Self`. This ensures that validation can be performed using
3185*c3739801SMiguel Ojeda     /// aligned reads (which carry a performance advantage over unaligned reads
3186*c3739801SMiguel Ojeda     /// on many platforms) at the cost of an unconditional copy.
3187*c3739801SMiguel Ojeda     ///
3188*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3189*c3739801SMiguel Ojeda         header = "h5",
3190*c3739801SMiguel Ojeda         bench = "try_read_from_prefix",
3191*c3739801SMiguel Ojeda         format = "coco_static_size",
3192*c3739801SMiguel Ojeda     )]
3193*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
3194*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
3195*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
3196*c3739801SMiguel Ojeda     fn try_read_from_prefix(source: &[u8]) -> Result<(Self, &[u8]), TryReadError<&[u8], Self>>
3197*c3739801SMiguel Ojeda     where
3198*c3739801SMiguel Ojeda         Self: Sized,
3199*c3739801SMiguel Ojeda     {
3200*c3739801SMiguel Ojeda         // FIXME(#2981): If `align_of::<Self>() == 1`, validate `source` in-place.
3201*c3739801SMiguel Ojeda 
3202*c3739801SMiguel Ojeda         let (candidate, suffix) = match CoreMaybeUninit::<Self>::read_from_prefix(source) {
3203*c3739801SMiguel Ojeda             Ok(candidate) => candidate,
3204*c3739801SMiguel Ojeda             Err(e) => {
3205*c3739801SMiguel Ojeda                 return Err(TryReadError::Size(e.with_dst()));
3206*c3739801SMiguel Ojeda             }
3207*c3739801SMiguel Ojeda         };
3208*c3739801SMiguel Ojeda         // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
3209*c3739801SMiguel Ojeda         // its bytes are initialized.
3210*c3739801SMiguel Ojeda         unsafe { try_read_from(source, candidate).map(|slf| (slf, suffix)) }
3211*c3739801SMiguel Ojeda     }
3212*c3739801SMiguel Ojeda 
3213*c3739801SMiguel Ojeda     /// Attempts to read a `Self` from the suffix of the given `source`.
3214*c3739801SMiguel Ojeda     ///
3215*c3739801SMiguel Ojeda     /// This attempts to read a `Self` from the last `size_of::<Self>()` bytes
3216*c3739801SMiguel Ojeda     /// of `source`, returning that `Self` and any preceding bytes. If
3217*c3739801SMiguel Ojeda     /// `source.len() < size_of::<Self>()` or the bytes are not a valid instance
3218*c3739801SMiguel Ojeda     /// of `Self`, it returns `Err`.
3219*c3739801SMiguel Ojeda     ///
3220*c3739801SMiguel Ojeda     /// # Examples
3221*c3739801SMiguel Ojeda     ///
3222*c3739801SMiguel Ojeda     /// ```
3223*c3739801SMiguel Ojeda     /// # #![allow(non_camel_case_types)] // For C0::xC0
3224*c3739801SMiguel Ojeda     /// use zerocopy::TryFromBytes;
3225*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
3226*c3739801SMiguel Ojeda     ///
3227*c3739801SMiguel Ojeda     /// // The only valid value of this type is the byte `0xC0`
3228*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes)]
3229*c3739801SMiguel Ojeda     /// #[repr(u8)]
3230*c3739801SMiguel Ojeda     /// enum C0 { xC0 = 0xC0 }
3231*c3739801SMiguel Ojeda     ///
3232*c3739801SMiguel Ojeda     /// // The only valid value of this type is the bytes `0xC0C0`.
3233*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes)]
3234*c3739801SMiguel Ojeda     /// #[repr(C)]
3235*c3739801SMiguel Ojeda     /// struct C0C0(C0, C0);
3236*c3739801SMiguel Ojeda     ///
3237*c3739801SMiguel Ojeda     /// #[derive(TryFromBytes)]
3238*c3739801SMiguel Ojeda     /// #[repr(C)]
3239*c3739801SMiguel Ojeda     /// struct Packet {
3240*c3739801SMiguel Ojeda     ///     magic_number: C0C0,
3241*c3739801SMiguel Ojeda     ///     mug_size: u8,
3242*c3739801SMiguel Ojeda     ///     temperature: u8,
3243*c3739801SMiguel Ojeda     /// }
3244*c3739801SMiguel Ojeda     ///
3245*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `Packet`.
3246*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 0xC0, 0xC0, 240, 77][..];
3247*c3739801SMiguel Ojeda     ///
3248*c3739801SMiguel Ojeda     /// let (prefix, packet) = Packet::try_read_from_suffix(bytes).unwrap();
3249*c3739801SMiguel Ojeda     ///
3250*c3739801SMiguel Ojeda     /// assert_eq!(packet.mug_size, 240);
3251*c3739801SMiguel Ojeda     /// assert_eq!(packet.temperature, 77);
3252*c3739801SMiguel Ojeda     /// assert_eq!(prefix, &[0u8, 1, 2, 3, 4, 5][..]);
3253*c3739801SMiguel Ojeda     ///
3254*c3739801SMiguel Ojeda     /// // These bytes are not valid instance of `Packet`.
3255*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 0x10, 0xC0, 240, 77][..];
3256*c3739801SMiguel Ojeda     /// assert!(Packet::try_read_from_suffix(bytes).is_err());
3257*c3739801SMiguel Ojeda     /// ```
3258*c3739801SMiguel Ojeda     ///
3259*c3739801SMiguel Ojeda     /// # Performance Considerations
3260*c3739801SMiguel Ojeda     ///
3261*c3739801SMiguel Ojeda     /// In this version of zerocopy, this method reads the `source` into a
3262*c3739801SMiguel Ojeda     /// well-aligned stack allocation and *then* validates that the allocation
3263*c3739801SMiguel Ojeda     /// is a valid `Self`. This ensures that validation can be performed using
3264*c3739801SMiguel Ojeda     /// aligned reads (which carry a performance advantage over unaligned reads
3265*c3739801SMiguel Ojeda     /// on many platforms) at the cost of an unconditional copy.
3266*c3739801SMiguel Ojeda     ///
3267*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3268*c3739801SMiguel Ojeda         header = "h5",
3269*c3739801SMiguel Ojeda         bench = "try_read_from_suffix",
3270*c3739801SMiguel Ojeda         format = "coco_static_size",
3271*c3739801SMiguel Ojeda     )]
3272*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
3273*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
3274*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
3275*c3739801SMiguel Ojeda     fn try_read_from_suffix(source: &[u8]) -> Result<(&[u8], Self), TryReadError<&[u8], Self>>
3276*c3739801SMiguel Ojeda     where
3277*c3739801SMiguel Ojeda         Self: Sized,
3278*c3739801SMiguel Ojeda     {
3279*c3739801SMiguel Ojeda         // FIXME(#2981): If `align_of::<Self>() == 1`, validate `source` in-place.
3280*c3739801SMiguel Ojeda 
3281*c3739801SMiguel Ojeda         let (prefix, candidate) = match CoreMaybeUninit::<Self>::read_from_suffix(source) {
3282*c3739801SMiguel Ojeda             Ok(candidate) => candidate,
3283*c3739801SMiguel Ojeda             Err(e) => {
3284*c3739801SMiguel Ojeda                 return Err(TryReadError::Size(e.with_dst()));
3285*c3739801SMiguel Ojeda             }
3286*c3739801SMiguel Ojeda         };
3287*c3739801SMiguel Ojeda         // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
3288*c3739801SMiguel Ojeda         // its bytes are initialized.
3289*c3739801SMiguel Ojeda         unsafe { try_read_from(source, candidate).map(|slf| (prefix, slf)) }
3290*c3739801SMiguel Ojeda     }
3291*c3739801SMiguel Ojeda }
3292*c3739801SMiguel Ojeda 
3293*c3739801SMiguel Ojeda #[inline(always)]
3294*c3739801SMiguel Ojeda fn try_ref_from_prefix_suffix<T: TryFromBytes + KnownLayout + Immutable + ?Sized>(
3295*c3739801SMiguel Ojeda     source: &[u8],
3296*c3739801SMiguel Ojeda     cast_type: CastType,
3297*c3739801SMiguel Ojeda     meta: Option<T::PointerMetadata>,
3298*c3739801SMiguel Ojeda ) -> Result<(&T, &[u8]), TryCastError<&[u8], T>> {
3299*c3739801SMiguel Ojeda     match Ptr::from_ref(source).try_cast_into::<T, BecauseImmutable>(cast_type, meta) {
3300*c3739801SMiguel Ojeda         Ok((source, prefix_suffix)) => {
3301*c3739801SMiguel Ojeda             // This call may panic. If that happens, it doesn't cause any soundness
3302*c3739801SMiguel Ojeda             // issues, as we have not generated any invalid state which we need to
3303*c3739801SMiguel Ojeda             // fix before returning.
3304*c3739801SMiguel Ojeda             match source.try_into_valid() {
3305*c3739801SMiguel Ojeda                 Ok(valid) => Ok((valid.as_ref(), prefix_suffix.as_ref())),
3306*c3739801SMiguel Ojeda                 Err(e) => Err(e.map_src(|src| src.as_bytes::<BecauseImmutable>().as_ref()).into()),
3307*c3739801SMiguel Ojeda             }
3308*c3739801SMiguel Ojeda         }
3309*c3739801SMiguel Ojeda         Err(e) => Err(e.map_src(Ptr::as_ref).into()),
3310*c3739801SMiguel Ojeda     }
3311*c3739801SMiguel Ojeda }
3312*c3739801SMiguel Ojeda 
3313*c3739801SMiguel Ojeda #[inline(always)]
3314*c3739801SMiguel Ojeda fn try_mut_from_prefix_suffix<T: IntoBytes + TryFromBytes + KnownLayout + ?Sized>(
3315*c3739801SMiguel Ojeda     candidate: &mut [u8],
3316*c3739801SMiguel Ojeda     cast_type: CastType,
3317*c3739801SMiguel Ojeda     meta: Option<T::PointerMetadata>,
3318*c3739801SMiguel Ojeda ) -> Result<(&mut T, &mut [u8]), TryCastError<&mut [u8], T>> {
3319*c3739801SMiguel Ojeda     match Ptr::from_mut(candidate).try_cast_into::<T, BecauseExclusive>(cast_type, meta) {
3320*c3739801SMiguel Ojeda         Ok((candidate, prefix_suffix)) => {
3321*c3739801SMiguel Ojeda             // This call may panic. If that happens, it doesn't cause any soundness
3322*c3739801SMiguel Ojeda             // issues, as we have not generated any invalid state which we need to
3323*c3739801SMiguel Ojeda             // fix before returning.
3324*c3739801SMiguel Ojeda             match candidate.try_into_valid() {
3325*c3739801SMiguel Ojeda                 Ok(valid) => Ok((valid.as_mut(), prefix_suffix.as_mut())),
3326*c3739801SMiguel Ojeda                 Err(e) => Err(e.map_src(|src| src.as_bytes().as_mut()).into()),
3327*c3739801SMiguel Ojeda             }
3328*c3739801SMiguel Ojeda         }
3329*c3739801SMiguel Ojeda         Err(e) => Err(e.map_src(Ptr::as_mut).into()),
3330*c3739801SMiguel Ojeda     }
3331*c3739801SMiguel Ojeda }
3332*c3739801SMiguel Ojeda 
3333*c3739801SMiguel Ojeda #[inline(always)]
3334*c3739801SMiguel Ojeda fn swap<T, U>((t, u): (T, U)) -> (U, T) {
3335*c3739801SMiguel Ojeda     (u, t)
3336*c3739801SMiguel Ojeda }
3337*c3739801SMiguel Ojeda 
3338*c3739801SMiguel Ojeda /// # Safety
3339*c3739801SMiguel Ojeda ///
3340*c3739801SMiguel Ojeda /// All bytes of `candidate` must be initialized.
3341*c3739801SMiguel Ojeda #[inline(always)]
3342*c3739801SMiguel Ojeda unsafe fn try_read_from<S, T: TryFromBytes>(
3343*c3739801SMiguel Ojeda     source: S,
3344*c3739801SMiguel Ojeda     mut candidate: CoreMaybeUninit<T>,
3345*c3739801SMiguel Ojeda ) -> Result<T, TryReadError<S, T>> {
3346*c3739801SMiguel Ojeda     // We use `from_mut` despite not mutating via `c_ptr` so that we don't need
3347*c3739801SMiguel Ojeda     // to add a `T: Immutable` bound.
3348*c3739801SMiguel Ojeda     let c_ptr = Ptr::from_mut(&mut candidate);
3349*c3739801SMiguel Ojeda     // SAFETY: `c_ptr` has no uninitialized sub-ranges because it derived from
3350*c3739801SMiguel Ojeda     // `candidate`, which the caller promises is entirely initialized. Since
3351*c3739801SMiguel Ojeda     // `candidate` is a `MaybeUninit`, it has no validity requirements, and so
3352*c3739801SMiguel Ojeda     // no values written to an `Initialized` `c_ptr` can violate its validity.
3353*c3739801SMiguel Ojeda     // Since `c_ptr` has `Exclusive` aliasing, no mutations may happen except
3354*c3739801SMiguel Ojeda     // via `c_ptr` so long as it is live, so we don't need to worry about the
3355*c3739801SMiguel Ojeda     // fact that `c_ptr` may have more restricted validity than `candidate`.
3356*c3739801SMiguel Ojeda     let c_ptr = unsafe { c_ptr.assume_validity::<invariant::Initialized>() };
3357*c3739801SMiguel Ojeda     let mut c_ptr = c_ptr.cast::<_, crate::pointer::cast::CastSized, _>();
3358*c3739801SMiguel Ojeda 
3359*c3739801SMiguel Ojeda     // Since we don't have `T: KnownLayout`, we hack around that by using
3360*c3739801SMiguel Ojeda     // `Wrapping<T>`, which implements `KnownLayout` even if `T` doesn't.
3361*c3739801SMiguel Ojeda     //
3362*c3739801SMiguel Ojeda     // This call may panic. If that happens, it doesn't cause any soundness
3363*c3739801SMiguel Ojeda     // issues, as we have not generated any invalid state which we need to fix
3364*c3739801SMiguel Ojeda     // before returning.
3365*c3739801SMiguel Ojeda     if !Wrapping::<T>::is_bit_valid(c_ptr.reborrow_shared().forget_aligned()) {
3366*c3739801SMiguel Ojeda         return Err(ValidityError::new(source).into());
3367*c3739801SMiguel Ojeda     }
3368*c3739801SMiguel Ojeda 
3369*c3739801SMiguel Ojeda     fn _assert_same_size_and_validity<T>()
3370*c3739801SMiguel Ojeda     where
3371*c3739801SMiguel Ojeda         Wrapping<T>: pointer::TransmuteFrom<T, invariant::Valid, invariant::Valid>,
3372*c3739801SMiguel Ojeda         T: pointer::TransmuteFrom<Wrapping<T>, invariant::Valid, invariant::Valid>,
3373*c3739801SMiguel Ojeda     {
3374*c3739801SMiguel Ojeda     }
3375*c3739801SMiguel Ojeda 
3376*c3739801SMiguel Ojeda     _assert_same_size_and_validity::<T>();
3377*c3739801SMiguel Ojeda 
3378*c3739801SMiguel Ojeda     // SAFETY: We just validated that `candidate` contains a valid
3379*c3739801SMiguel Ojeda     // `Wrapping<T>`, which has the same size and bit validity as `T`, as
3380*c3739801SMiguel Ojeda     // guaranteed by the preceding type assertion.
3381*c3739801SMiguel Ojeda     Ok(unsafe { candidate.assume_init() })
3382*c3739801SMiguel Ojeda }
3383*c3739801SMiguel Ojeda 
3384*c3739801SMiguel Ojeda /// Types for which a sequence of `0` bytes is a valid instance.
3385*c3739801SMiguel Ojeda ///
3386*c3739801SMiguel Ojeda /// Any memory region of the appropriate length which is guaranteed to contain
3387*c3739801SMiguel Ojeda /// only zero bytes can be viewed as any `FromZeros` type with no runtime
3388*c3739801SMiguel Ojeda /// overhead. This is useful whenever memory is known to be in a zeroed state,
3389*c3739801SMiguel Ojeda /// such memory returned from some allocation routines.
3390*c3739801SMiguel Ojeda ///
3391*c3739801SMiguel Ojeda /// # Warning: Padding bytes
3392*c3739801SMiguel Ojeda ///
3393*c3739801SMiguel Ojeda /// Note that, when a value is moved or copied, only the non-padding bytes of
3394*c3739801SMiguel Ojeda /// that value are guaranteed to be preserved. It is unsound to assume that
3395*c3739801SMiguel Ojeda /// values written to padding bytes are preserved after a move or copy. For more
3396*c3739801SMiguel Ojeda /// details, see the [`FromBytes` docs][frombytes-warning-padding-bytes].
3397*c3739801SMiguel Ojeda ///
3398*c3739801SMiguel Ojeda /// [frombytes-warning-padding-bytes]: FromBytes#warning-padding-bytes
3399*c3739801SMiguel Ojeda ///
3400*c3739801SMiguel Ojeda /// # Implementation
3401*c3739801SMiguel Ojeda ///
3402*c3739801SMiguel Ojeda /// **Do not implement this trait yourself!** Instead, use
3403*c3739801SMiguel Ojeda /// [`#[derive(FromZeros)]`][derive]; e.g.:
3404*c3739801SMiguel Ojeda ///
3405*c3739801SMiguel Ojeda /// ```
3406*c3739801SMiguel Ojeda /// # use zerocopy_derive::{FromZeros, Immutable};
3407*c3739801SMiguel Ojeda /// #[derive(FromZeros)]
3408*c3739801SMiguel Ojeda /// struct MyStruct {
3409*c3739801SMiguel Ojeda /// # /*
3410*c3739801SMiguel Ojeda ///     ...
3411*c3739801SMiguel Ojeda /// # */
3412*c3739801SMiguel Ojeda /// }
3413*c3739801SMiguel Ojeda ///
3414*c3739801SMiguel Ojeda /// #[derive(FromZeros)]
3415*c3739801SMiguel Ojeda /// #[repr(u8)]
3416*c3739801SMiguel Ojeda /// enum MyEnum {
3417*c3739801SMiguel Ojeda /// #   Variant0,
3418*c3739801SMiguel Ojeda /// # /*
3419*c3739801SMiguel Ojeda ///     ...
3420*c3739801SMiguel Ojeda /// # */
3421*c3739801SMiguel Ojeda /// }
3422*c3739801SMiguel Ojeda ///
3423*c3739801SMiguel Ojeda /// #[derive(FromZeros, Immutable)]
3424*c3739801SMiguel Ojeda /// union MyUnion {
3425*c3739801SMiguel Ojeda /// #   variant: u8,
3426*c3739801SMiguel Ojeda /// # /*
3427*c3739801SMiguel Ojeda ///     ...
3428*c3739801SMiguel Ojeda /// # */
3429*c3739801SMiguel Ojeda /// }
3430*c3739801SMiguel Ojeda /// ```
3431*c3739801SMiguel Ojeda ///
3432*c3739801SMiguel Ojeda /// This derive performs a sophisticated, compile-time safety analysis to
3433*c3739801SMiguel Ojeda /// determine whether a type is `FromZeros`.
3434*c3739801SMiguel Ojeda ///
3435*c3739801SMiguel Ojeda /// # Safety
3436*c3739801SMiguel Ojeda ///
3437*c3739801SMiguel Ojeda /// *This section describes what is required in order for `T: FromZeros`, and
3438*c3739801SMiguel Ojeda /// what unsafe code may assume of such types. If you don't plan on implementing
3439*c3739801SMiguel Ojeda /// `FromZeros` manually, and you don't plan on writing unsafe code that
3440*c3739801SMiguel Ojeda /// operates on `FromZeros` types, then you don't need to read this section.*
3441*c3739801SMiguel Ojeda ///
3442*c3739801SMiguel Ojeda /// If `T: FromZeros`, then unsafe code may assume that it is sound to produce a
3443*c3739801SMiguel Ojeda /// `T` whose bytes are all initialized to zero. If a type is marked as
3444*c3739801SMiguel Ojeda /// `FromZeros` which violates this contract, it may cause undefined behavior.
3445*c3739801SMiguel Ojeda ///
3446*c3739801SMiguel Ojeda /// `#[derive(FromZeros)]` only permits [types which satisfy these
3447*c3739801SMiguel Ojeda /// requirements][derive-analysis].
3448*c3739801SMiguel Ojeda ///
3449*c3739801SMiguel Ojeda #[cfg_attr(
3450*c3739801SMiguel Ojeda     feature = "derive",
3451*c3739801SMiguel Ojeda     doc = "[derive]: zerocopy_derive::FromZeros",
3452*c3739801SMiguel Ojeda     doc = "[derive-analysis]: zerocopy_derive::FromZeros#analysis"
3453*c3739801SMiguel Ojeda )]
3454*c3739801SMiguel Ojeda #[cfg_attr(
3455*c3739801SMiguel Ojeda     not(feature = "derive"),
3456*c3739801SMiguel Ojeda     doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromZeros.html"),
3457*c3739801SMiguel Ojeda     doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromZeros.html#analysis"),
3458*c3739801SMiguel Ojeda )]
3459*c3739801SMiguel Ojeda #[cfg_attr(
3460*c3739801SMiguel Ojeda     not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
3461*c3739801SMiguel Ojeda     diagnostic::on_unimplemented(note = "Consider adding `#[derive(FromZeros)]` to `{Self}`")
3462*c3739801SMiguel Ojeda )]
3463*c3739801SMiguel Ojeda pub unsafe trait FromZeros: TryFromBytes {
3464*c3739801SMiguel Ojeda     // The `Self: Sized` bound makes it so that `FromZeros` is still object
3465*c3739801SMiguel Ojeda     // safe.
3466*c3739801SMiguel Ojeda     #[doc(hidden)]
3467*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
3468*c3739801SMiguel Ojeda     where
3469*c3739801SMiguel Ojeda         Self: Sized;
3470*c3739801SMiguel Ojeda 
3471*c3739801SMiguel Ojeda     /// Overwrites `self` with zeros.
3472*c3739801SMiguel Ojeda     ///
3473*c3739801SMiguel Ojeda     /// Sets every byte in `self` to 0. While this is similar to doing `*self =
3474*c3739801SMiguel Ojeda     /// Self::new_zeroed()`, it differs in that `zero` does not semantically
3475*c3739801SMiguel Ojeda     /// drop the current value and replace it with a new one — it simply
3476*c3739801SMiguel Ojeda     /// modifies the bytes of the existing value.
3477*c3739801SMiguel Ojeda     ///
3478*c3739801SMiguel Ojeda     /// # Examples
3479*c3739801SMiguel Ojeda     ///
3480*c3739801SMiguel Ojeda     /// ```
3481*c3739801SMiguel Ojeda     /// # use zerocopy::FromZeros;
3482*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
3483*c3739801SMiguel Ojeda     /// #
3484*c3739801SMiguel Ojeda     /// #[derive(FromZeros)]
3485*c3739801SMiguel Ojeda     /// #[repr(C)]
3486*c3739801SMiguel Ojeda     /// struct PacketHeader {
3487*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
3488*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
3489*c3739801SMiguel Ojeda     ///     length: [u8; 2],
3490*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
3491*c3739801SMiguel Ojeda     /// }
3492*c3739801SMiguel Ojeda     ///
3493*c3739801SMiguel Ojeda     /// let mut header = PacketHeader {
3494*c3739801SMiguel Ojeda     ///     src_port: 100u16.to_be_bytes(),
3495*c3739801SMiguel Ojeda     ///     dst_port: 200u16.to_be_bytes(),
3496*c3739801SMiguel Ojeda     ///     length: 300u16.to_be_bytes(),
3497*c3739801SMiguel Ojeda     ///     checksum: 400u16.to_be_bytes(),
3498*c3739801SMiguel Ojeda     /// };
3499*c3739801SMiguel Ojeda     ///
3500*c3739801SMiguel Ojeda     /// header.zero();
3501*c3739801SMiguel Ojeda     ///
3502*c3739801SMiguel Ojeda     /// assert_eq!(header.src_port, [0, 0]);
3503*c3739801SMiguel Ojeda     /// assert_eq!(header.dst_port, [0, 0]);
3504*c3739801SMiguel Ojeda     /// assert_eq!(header.length, [0, 0]);
3505*c3739801SMiguel Ojeda     /// assert_eq!(header.checksum, [0, 0]);
3506*c3739801SMiguel Ojeda     /// ```
3507*c3739801SMiguel Ojeda     ///
3508*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3509*c3739801SMiguel Ojeda         header = "h5",
3510*c3739801SMiguel Ojeda         bench = "zero",
3511*c3739801SMiguel Ojeda         format = "coco",
3512*c3739801SMiguel Ojeda         arity = 3,
3513*c3739801SMiguel Ojeda         [
3514*c3739801SMiguel Ojeda             open
3515*c3739801SMiguel Ojeda             @index 1
3516*c3739801SMiguel Ojeda             @title "Sized"
3517*c3739801SMiguel Ojeda             @variant "static_size"
3518*c3739801SMiguel Ojeda         ],
3519*c3739801SMiguel Ojeda         [
3520*c3739801SMiguel Ojeda             @index 2
3521*c3739801SMiguel Ojeda             @title "Unsized"
3522*c3739801SMiguel Ojeda             @variant "dynamic_size"
3523*c3739801SMiguel Ojeda         ],
3524*c3739801SMiguel Ojeda         [
3525*c3739801SMiguel Ojeda             @index 3
3526*c3739801SMiguel Ojeda             @title "Dynamically Padded"
3527*c3739801SMiguel Ojeda             @variant "dynamic_padding"
3528*c3739801SMiguel Ojeda         ]
3529*c3739801SMiguel Ojeda     )]
3530*c3739801SMiguel Ojeda     #[inline(always)]
3531*c3739801SMiguel Ojeda     fn zero(&mut self) {
3532*c3739801SMiguel Ojeda         let slf: *mut Self = self;
3533*c3739801SMiguel Ojeda         let len = mem::size_of_val(self);
3534*c3739801SMiguel Ojeda         // SAFETY:
3535*c3739801SMiguel Ojeda         // - `self` is guaranteed by the type system to be valid for writes of
3536*c3739801SMiguel Ojeda         //   size `size_of_val(self)`.
3537*c3739801SMiguel Ojeda         // - `u8`'s alignment is 1, and thus `self` is guaranteed to be aligned
3538*c3739801SMiguel Ojeda         //   as required by `u8`.
3539*c3739801SMiguel Ojeda         // - Since `Self: FromZeros`, the all-zeros instance is a valid instance
3540*c3739801SMiguel Ojeda         //   of `Self.`
3541*c3739801SMiguel Ojeda         //
3542*c3739801SMiguel Ojeda         // FIXME(#429): Add references to docs and quotes.
3543*c3739801SMiguel Ojeda         unsafe { ptr::write_bytes(slf.cast::<u8>(), 0, len) };
3544*c3739801SMiguel Ojeda     }
3545*c3739801SMiguel Ojeda 
3546*c3739801SMiguel Ojeda     /// Creates an instance of `Self` from zeroed bytes.
3547*c3739801SMiguel Ojeda     ///
3548*c3739801SMiguel Ojeda     /// # Examples
3549*c3739801SMiguel Ojeda     ///
3550*c3739801SMiguel Ojeda     /// ```
3551*c3739801SMiguel Ojeda     /// # use zerocopy::FromZeros;
3552*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
3553*c3739801SMiguel Ojeda     /// #
3554*c3739801SMiguel Ojeda     /// #[derive(FromZeros)]
3555*c3739801SMiguel Ojeda     /// #[repr(C)]
3556*c3739801SMiguel Ojeda     /// struct PacketHeader {
3557*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
3558*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
3559*c3739801SMiguel Ojeda     ///     length: [u8; 2],
3560*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
3561*c3739801SMiguel Ojeda     /// }
3562*c3739801SMiguel Ojeda     ///
3563*c3739801SMiguel Ojeda     /// let header: PacketHeader = FromZeros::new_zeroed();
3564*c3739801SMiguel Ojeda     ///
3565*c3739801SMiguel Ojeda     /// assert_eq!(header.src_port, [0, 0]);
3566*c3739801SMiguel Ojeda     /// assert_eq!(header.dst_port, [0, 0]);
3567*c3739801SMiguel Ojeda     /// assert_eq!(header.length, [0, 0]);
3568*c3739801SMiguel Ojeda     /// assert_eq!(header.checksum, [0, 0]);
3569*c3739801SMiguel Ojeda     /// ```
3570*c3739801SMiguel Ojeda     ///
3571*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3572*c3739801SMiguel Ojeda         header = "h5",
3573*c3739801SMiguel Ojeda         bench = "new_zeroed",
3574*c3739801SMiguel Ojeda         format = "coco_static_size",
3575*c3739801SMiguel Ojeda     )]
3576*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
3577*c3739801SMiguel Ojeda     #[inline(always)]
3578*c3739801SMiguel Ojeda     fn new_zeroed() -> Self
3579*c3739801SMiguel Ojeda     where
3580*c3739801SMiguel Ojeda         Self: Sized,
3581*c3739801SMiguel Ojeda     {
3582*c3739801SMiguel Ojeda         // SAFETY: `FromZeros` says that the all-zeros bit pattern is legal.
3583*c3739801SMiguel Ojeda         unsafe { mem::zeroed() }
3584*c3739801SMiguel Ojeda     }
3585*c3739801SMiguel Ojeda 
3586*c3739801SMiguel Ojeda     /// Creates a `Box<Self>` from zeroed bytes.
3587*c3739801SMiguel Ojeda     ///
3588*c3739801SMiguel Ojeda     /// This function is useful for allocating large values on the heap and
3589*c3739801SMiguel Ojeda     /// zero-initializing them, without ever creating a temporary instance of
3590*c3739801SMiguel Ojeda     /// `Self` on the stack. For example, `<[u8; 1048576]>::new_box_zeroed()`
3591*c3739801SMiguel Ojeda     /// will allocate `[u8; 1048576]` directly on the heap; it does not require
3592*c3739801SMiguel Ojeda     /// storing `[u8; 1048576]` in a temporary variable on the stack.
3593*c3739801SMiguel Ojeda     ///
3594*c3739801SMiguel Ojeda     /// On systems that use a heap implementation that supports allocating from
3595*c3739801SMiguel Ojeda     /// pre-zeroed memory, using `new_box_zeroed` (or related functions) may
3596*c3739801SMiguel Ojeda     /// have performance benefits.
3597*c3739801SMiguel Ojeda     ///
3598*c3739801SMiguel Ojeda     /// # Errors
3599*c3739801SMiguel Ojeda     ///
3600*c3739801SMiguel Ojeda     /// Returns an error on allocation failure. Allocation failure is guaranteed
3601*c3739801SMiguel Ojeda     /// never to cause a panic or an abort.
3602*c3739801SMiguel Ojeda     ///
3603*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3604*c3739801SMiguel Ojeda         header = "h5",
3605*c3739801SMiguel Ojeda         bench = "new_box_zeroed",
3606*c3739801SMiguel Ojeda         format = "coco_static_size",
3607*c3739801SMiguel Ojeda     )]
3608*c3739801SMiguel Ojeda     #[must_use = "has no side effects (other than allocation)"]
3609*c3739801SMiguel Ojeda     #[cfg(any(feature = "alloc", test))]
3610*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
3611*c3739801SMiguel Ojeda     #[inline]
3612*c3739801SMiguel Ojeda     fn new_box_zeroed() -> Result<Box<Self>, AllocError>
3613*c3739801SMiguel Ojeda     where
3614*c3739801SMiguel Ojeda         Self: Sized,
3615*c3739801SMiguel Ojeda     {
3616*c3739801SMiguel Ojeda         // If `T` is a ZST, then return a proper boxed instance of it. There is
3617*c3739801SMiguel Ojeda         // no allocation, but `Box` does require a correct dangling pointer.
3618*c3739801SMiguel Ojeda         let layout = Layout::new::<Self>();
3619*c3739801SMiguel Ojeda         if layout.size() == 0 {
3620*c3739801SMiguel Ojeda             // Construct the `Box` from a dangling pointer to avoid calling
3621*c3739801SMiguel Ojeda             // `Self::new_zeroed`. This ensures that stack space is never
3622*c3739801SMiguel Ojeda             // allocated for `Self` even on lower opt-levels where this branch
3623*c3739801SMiguel Ojeda             // might not get optimized out.
3624*c3739801SMiguel Ojeda 
3625*c3739801SMiguel Ojeda             // SAFETY: Per [1], when `T` is a ZST, `Box<T>`'s only validity
3626*c3739801SMiguel Ojeda             // requirements are that the pointer is non-null and sufficiently
3627*c3739801SMiguel Ojeda             // aligned. Per [2], `NonNull::dangling` produces a pointer which
3628*c3739801SMiguel Ojeda             // is sufficiently aligned. Since the produced pointer is a
3629*c3739801SMiguel Ojeda             // `NonNull`, it is non-null.
3630*c3739801SMiguel Ojeda             //
3631*c3739801SMiguel Ojeda             // [1] Per https://doc.rust-lang.org/1.81.0/std/boxed/index.html#memory-layout:
3632*c3739801SMiguel Ojeda             //
3633*c3739801SMiguel Ojeda             //   For zero-sized values, the `Box` pointer has to be non-null and sufficiently aligned.
3634*c3739801SMiguel Ojeda             //
3635*c3739801SMiguel Ojeda             // [2] Per https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.dangling:
3636*c3739801SMiguel Ojeda             //
3637*c3739801SMiguel Ojeda             //   Creates a new `NonNull` that is dangling, but well-aligned.
3638*c3739801SMiguel Ojeda             return Ok(unsafe { Box::from_raw(NonNull::dangling().as_ptr()) });
3639*c3739801SMiguel Ojeda         }
3640*c3739801SMiguel Ojeda 
3641*c3739801SMiguel Ojeda         // FIXME(#429): Add a "SAFETY" comment and remove this `allow`.
3642*c3739801SMiguel Ojeda         #[allow(clippy::undocumented_unsafe_blocks)]
3643*c3739801SMiguel Ojeda         let ptr = unsafe { alloc::alloc::alloc_zeroed(layout).cast::<Self>() };
3644*c3739801SMiguel Ojeda         if ptr.is_null() {
3645*c3739801SMiguel Ojeda             return Err(AllocError);
3646*c3739801SMiguel Ojeda         }
3647*c3739801SMiguel Ojeda         // FIXME(#429): Add a "SAFETY" comment and remove this `allow`.
3648*c3739801SMiguel Ojeda         #[allow(clippy::undocumented_unsafe_blocks)]
3649*c3739801SMiguel Ojeda         Ok(unsafe { Box::from_raw(ptr) })
3650*c3739801SMiguel Ojeda     }
3651*c3739801SMiguel Ojeda 
3652*c3739801SMiguel Ojeda     /// Creates a `Box<[Self]>` (a boxed slice) from zeroed bytes.
3653*c3739801SMiguel Ojeda     ///
3654*c3739801SMiguel Ojeda     /// This function is useful for allocating large values of `[Self]` on the
3655*c3739801SMiguel Ojeda     /// heap and zero-initializing them, without ever creating a temporary
3656*c3739801SMiguel Ojeda     /// instance of `[Self; _]` on the stack. For example,
3657*c3739801SMiguel Ojeda     /// `u8::new_box_slice_zeroed(1048576)` will allocate the slice directly on
3658*c3739801SMiguel Ojeda     /// the heap; it does not require storing the slice on the stack.
3659*c3739801SMiguel Ojeda     ///
3660*c3739801SMiguel Ojeda     /// On systems that use a heap implementation that supports allocating from
3661*c3739801SMiguel Ojeda     /// pre-zeroed memory, using `new_box_slice_zeroed` may have performance
3662*c3739801SMiguel Ojeda     /// benefits.
3663*c3739801SMiguel Ojeda     ///
3664*c3739801SMiguel Ojeda     /// If `Self` is a zero-sized type, then this function will return a
3665*c3739801SMiguel Ojeda     /// `Box<[Self]>` that has the correct `len`. Such a box cannot contain any
3666*c3739801SMiguel Ojeda     /// actual information, but its `len()` property will report the correct
3667*c3739801SMiguel Ojeda     /// value.
3668*c3739801SMiguel Ojeda     ///
3669*c3739801SMiguel Ojeda     /// # Errors
3670*c3739801SMiguel Ojeda     ///
3671*c3739801SMiguel Ojeda     /// Returns an error on allocation failure. Allocation failure is
3672*c3739801SMiguel Ojeda     /// guaranteed never to cause a panic or an abort.
3673*c3739801SMiguel Ojeda     ///
3674*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3675*c3739801SMiguel Ojeda         header = "h5",
3676*c3739801SMiguel Ojeda         bench = "new_box_zeroed_with_elems",
3677*c3739801SMiguel Ojeda         format = "coco",
3678*c3739801SMiguel Ojeda         arity = 2,
3679*c3739801SMiguel Ojeda         [
3680*c3739801SMiguel Ojeda             open
3681*c3739801SMiguel Ojeda             @index 1
3682*c3739801SMiguel Ojeda             @title "Unsized"
3683*c3739801SMiguel Ojeda             @variant "dynamic_size"
3684*c3739801SMiguel Ojeda         ],
3685*c3739801SMiguel Ojeda         [
3686*c3739801SMiguel Ojeda             @index 2
3687*c3739801SMiguel Ojeda             @title "Dynamically Padded"
3688*c3739801SMiguel Ojeda             @variant "dynamic_padding"
3689*c3739801SMiguel Ojeda         ]
3690*c3739801SMiguel Ojeda     )]
3691*c3739801SMiguel Ojeda     #[must_use = "has no side effects (other than allocation)"]
3692*c3739801SMiguel Ojeda     #[cfg(feature = "alloc")]
3693*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
3694*c3739801SMiguel Ojeda     #[inline]
3695*c3739801SMiguel Ojeda     fn new_box_zeroed_with_elems(count: usize) -> Result<Box<Self>, AllocError>
3696*c3739801SMiguel Ojeda     where
3697*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize>,
3698*c3739801SMiguel Ojeda     {
3699*c3739801SMiguel Ojeda         // SAFETY: `alloc::alloc::alloc_zeroed` is a valid argument of
3700*c3739801SMiguel Ojeda         // `new_box`. The referent of the pointer returned by `alloc_zeroed`
3701*c3739801SMiguel Ojeda         // (and, consequently, the `Box` derived from it) is a valid instance of
3702*c3739801SMiguel Ojeda         // `Self`, because `Self` is `FromZeros`.
3703*c3739801SMiguel Ojeda         unsafe { crate::util::new_box(count, alloc::alloc::alloc_zeroed) }
3704*c3739801SMiguel Ojeda     }
3705*c3739801SMiguel Ojeda 
3706*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "renamed to `FromZeros::new_box_zeroed_with_elems`")]
3707*c3739801SMiguel Ojeda     #[doc(hidden)]
3708*c3739801SMiguel Ojeda     #[cfg(feature = "alloc")]
3709*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
3710*c3739801SMiguel Ojeda     #[must_use = "has no side effects (other than allocation)"]
3711*c3739801SMiguel Ojeda     #[inline(always)]
3712*c3739801SMiguel Ojeda     fn new_box_slice_zeroed(len: usize) -> Result<Box<[Self]>, AllocError>
3713*c3739801SMiguel Ojeda     where
3714*c3739801SMiguel Ojeda         Self: Sized,
3715*c3739801SMiguel Ojeda     {
3716*c3739801SMiguel Ojeda         <[Self]>::new_box_zeroed_with_elems(len)
3717*c3739801SMiguel Ojeda     }
3718*c3739801SMiguel Ojeda 
3719*c3739801SMiguel Ojeda     /// Creates a `Vec<Self>` from zeroed bytes.
3720*c3739801SMiguel Ojeda     ///
3721*c3739801SMiguel Ojeda     /// This function is useful for allocating large values of `Vec`s and
3722*c3739801SMiguel Ojeda     /// zero-initializing them, without ever creating a temporary instance of
3723*c3739801SMiguel Ojeda     /// `[Self; _]` (or many temporary instances of `Self`) on the stack. For
3724*c3739801SMiguel Ojeda     /// example, `u8::new_vec_zeroed(1048576)` will allocate directly on the
3725*c3739801SMiguel Ojeda     /// heap; it does not require storing intermediate values on the stack.
3726*c3739801SMiguel Ojeda     ///
3727*c3739801SMiguel Ojeda     /// On systems that use a heap implementation that supports allocating from
3728*c3739801SMiguel Ojeda     /// pre-zeroed memory, using `new_vec_zeroed` may have performance benefits.
3729*c3739801SMiguel Ojeda     ///
3730*c3739801SMiguel Ojeda     /// If `Self` is a zero-sized type, then this function will return a
3731*c3739801SMiguel Ojeda     /// `Vec<Self>` that has the correct `len`. Such a `Vec` cannot contain any
3732*c3739801SMiguel Ojeda     /// actual information, but its `len()` property will report the correct
3733*c3739801SMiguel Ojeda     /// value.
3734*c3739801SMiguel Ojeda     ///
3735*c3739801SMiguel Ojeda     /// # Errors
3736*c3739801SMiguel Ojeda     ///
3737*c3739801SMiguel Ojeda     /// Returns an error on allocation failure. Allocation failure is
3738*c3739801SMiguel Ojeda     /// guaranteed never to cause a panic or an abort.
3739*c3739801SMiguel Ojeda     ///
3740*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3741*c3739801SMiguel Ojeda         header = "h5",
3742*c3739801SMiguel Ojeda         bench = "new_vec_zeroed",
3743*c3739801SMiguel Ojeda         format = "coco_static_size",
3744*c3739801SMiguel Ojeda     )]
3745*c3739801SMiguel Ojeda     #[must_use = "has no side effects (other than allocation)"]
3746*c3739801SMiguel Ojeda     #[cfg(feature = "alloc")]
3747*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
3748*c3739801SMiguel Ojeda     #[inline(always)]
3749*c3739801SMiguel Ojeda     fn new_vec_zeroed(len: usize) -> Result<Vec<Self>, AllocError>
3750*c3739801SMiguel Ojeda     where
3751*c3739801SMiguel Ojeda         Self: Sized,
3752*c3739801SMiguel Ojeda     {
3753*c3739801SMiguel Ojeda         <[Self]>::new_box_zeroed_with_elems(len).map(Into::into)
3754*c3739801SMiguel Ojeda     }
3755*c3739801SMiguel Ojeda 
3756*c3739801SMiguel Ojeda     /// Extends a `Vec<Self>` by pushing `additional` new items onto the end of
3757*c3739801SMiguel Ojeda     /// the vector. The new items are initialized with zeros.
3758*c3739801SMiguel Ojeda     ///
3759*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3760*c3739801SMiguel Ojeda         header = "h5",
3761*c3739801SMiguel Ojeda         bench = "extend_vec_zeroed",
3762*c3739801SMiguel Ojeda         format = "coco_static_size",
3763*c3739801SMiguel Ojeda     )]
3764*c3739801SMiguel Ojeda     #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
3765*c3739801SMiguel Ojeda     #[cfg(feature = "alloc")]
3766*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.57.0", feature = "alloc"))))]
3767*c3739801SMiguel Ojeda     #[inline(always)]
3768*c3739801SMiguel Ojeda     fn extend_vec_zeroed(v: &mut Vec<Self>, additional: usize) -> Result<(), AllocError>
3769*c3739801SMiguel Ojeda     where
3770*c3739801SMiguel Ojeda         Self: Sized,
3771*c3739801SMiguel Ojeda     {
3772*c3739801SMiguel Ojeda         // PANICS: We pass `v.len()` for `position`, so the `position > v.len()`
3773*c3739801SMiguel Ojeda         // panic condition is not satisfied.
3774*c3739801SMiguel Ojeda         <Self as FromZeros>::insert_vec_zeroed(v, v.len(), additional)
3775*c3739801SMiguel Ojeda     }
3776*c3739801SMiguel Ojeda 
3777*c3739801SMiguel Ojeda     /// Inserts `additional` new items into `Vec<Self>` at `position`. The new
3778*c3739801SMiguel Ojeda     /// items are initialized with zeros.
3779*c3739801SMiguel Ojeda     ///
3780*c3739801SMiguel Ojeda     /// # Panics
3781*c3739801SMiguel Ojeda     ///
3782*c3739801SMiguel Ojeda     /// Panics if `position > v.len()`.
3783*c3739801SMiguel Ojeda     ///
3784*c3739801SMiguel Ojeda     #[doc = codegen_section!(
3785*c3739801SMiguel Ojeda         header = "h5",
3786*c3739801SMiguel Ojeda         bench = "insert_vec_zeroed",
3787*c3739801SMiguel Ojeda         format = "coco_static_size",
3788*c3739801SMiguel Ojeda     )]
3789*c3739801SMiguel Ojeda     #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
3790*c3739801SMiguel Ojeda     #[cfg(feature = "alloc")]
3791*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(all(rust = "1.57.0", feature = "alloc"))))]
3792*c3739801SMiguel Ojeda     #[inline]
3793*c3739801SMiguel Ojeda     fn insert_vec_zeroed(
3794*c3739801SMiguel Ojeda         v: &mut Vec<Self>,
3795*c3739801SMiguel Ojeda         position: usize,
3796*c3739801SMiguel Ojeda         additional: usize,
3797*c3739801SMiguel Ojeda     ) -> Result<(), AllocError>
3798*c3739801SMiguel Ojeda     where
3799*c3739801SMiguel Ojeda         Self: Sized,
3800*c3739801SMiguel Ojeda     {
3801*c3739801SMiguel Ojeda         assert!(position <= v.len());
3802*c3739801SMiguel Ojeda         // We only conditionally compile on versions on which `try_reserve` is
3803*c3739801SMiguel Ojeda         // stable; the Clippy lint is a false positive.
3804*c3739801SMiguel Ojeda         v.try_reserve(additional).map_err(|_| AllocError)?;
3805*c3739801SMiguel Ojeda         // SAFETY: The `try_reserve` call guarantees that these cannot overflow:
3806*c3739801SMiguel Ojeda         // * `ptr.add(position)`
3807*c3739801SMiguel Ojeda         // * `position + additional`
3808*c3739801SMiguel Ojeda         // * `v.len() + additional`
3809*c3739801SMiguel Ojeda         //
3810*c3739801SMiguel Ojeda         // `v.len() - position` cannot overflow because we asserted that
3811*c3739801SMiguel Ojeda         // `position <= v.len()`.
3812*c3739801SMiguel Ojeda         #[allow(clippy::multiple_unsafe_ops_per_block)]
3813*c3739801SMiguel Ojeda         unsafe {
3814*c3739801SMiguel Ojeda             // This is a potentially overlapping copy.
3815*c3739801SMiguel Ojeda             let ptr = v.as_mut_ptr();
3816*c3739801SMiguel Ojeda             #[allow(clippy::arithmetic_side_effects)]
3817*c3739801SMiguel Ojeda             ptr.add(position).copy_to(ptr.add(position + additional), v.len() - position);
3818*c3739801SMiguel Ojeda             ptr.add(position).write_bytes(0, additional);
3819*c3739801SMiguel Ojeda             #[allow(clippy::arithmetic_side_effects)]
3820*c3739801SMiguel Ojeda             v.set_len(v.len() + additional);
3821*c3739801SMiguel Ojeda         }
3822*c3739801SMiguel Ojeda 
3823*c3739801SMiguel Ojeda         Ok(())
3824*c3739801SMiguel Ojeda     }
3825*c3739801SMiguel Ojeda }
3826*c3739801SMiguel Ojeda 
3827*c3739801SMiguel Ojeda /// Analyzes whether a type is [`FromBytes`].
3828*c3739801SMiguel Ojeda ///
3829*c3739801SMiguel Ojeda /// This derive analyzes, at compile time, whether the annotated type satisfies
3830*c3739801SMiguel Ojeda /// the [safety conditions] of `FromBytes` and implements `FromBytes` and its
3831*c3739801SMiguel Ojeda /// supertraits if it is sound to do so. This derive can be applied to structs,
3832*c3739801SMiguel Ojeda /// enums, and unions;
3833*c3739801SMiguel Ojeda /// e.g.:
3834*c3739801SMiguel Ojeda ///
3835*c3739801SMiguel Ojeda /// ```
3836*c3739801SMiguel Ojeda /// # use zerocopy_derive::{FromBytes, FromZeros, Immutable};
3837*c3739801SMiguel Ojeda /// #[derive(FromBytes)]
3838*c3739801SMiguel Ojeda /// struct MyStruct {
3839*c3739801SMiguel Ojeda /// # /*
3840*c3739801SMiguel Ojeda ///     ...
3841*c3739801SMiguel Ojeda /// # */
3842*c3739801SMiguel Ojeda /// }
3843*c3739801SMiguel Ojeda ///
3844*c3739801SMiguel Ojeda /// #[derive(FromBytes)]
3845*c3739801SMiguel Ojeda /// #[repr(u8)]
3846*c3739801SMiguel Ojeda /// enum MyEnum {
3847*c3739801SMiguel Ojeda /// #   V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, V0A, V0B, V0C, V0D, V0E,
3848*c3739801SMiguel Ojeda /// #   V0F, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V1A, V1B, V1C, V1D,
3849*c3739801SMiguel Ojeda /// #   V1E, V1F, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V2A, V2B, V2C,
3850*c3739801SMiguel Ojeda /// #   V2D, V2E, V2F, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V3A, V3B,
3851*c3739801SMiguel Ojeda /// #   V3C, V3D, V3E, V3F, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V4A,
3852*c3739801SMiguel Ojeda /// #   V4B, V4C, V4D, V4E, V4F, V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
3853*c3739801SMiguel Ojeda /// #   V5A, V5B, V5C, V5D, V5E, V5F, V60, V61, V62, V63, V64, V65, V66, V67, V68,
3854*c3739801SMiguel Ojeda /// #   V69, V6A, V6B, V6C, V6D, V6E, V6F, V70, V71, V72, V73, V74, V75, V76, V77,
3855*c3739801SMiguel Ojeda /// #   V78, V79, V7A, V7B, V7C, V7D, V7E, V7F, V80, V81, V82, V83, V84, V85, V86,
3856*c3739801SMiguel Ojeda /// #   V87, V88, V89, V8A, V8B, V8C, V8D, V8E, V8F, V90, V91, V92, V93, V94, V95,
3857*c3739801SMiguel Ojeda /// #   V96, V97, V98, V99, V9A, V9B, V9C, V9D, V9E, V9F, VA0, VA1, VA2, VA3, VA4,
3858*c3739801SMiguel Ojeda /// #   VA5, VA6, VA7, VA8, VA9, VAA, VAB, VAC, VAD, VAE, VAF, VB0, VB1, VB2, VB3,
3859*c3739801SMiguel Ojeda /// #   VB4, VB5, VB6, VB7, VB8, VB9, VBA, VBB, VBC, VBD, VBE, VBF, VC0, VC1, VC2,
3860*c3739801SMiguel Ojeda /// #   VC3, VC4, VC5, VC6, VC7, VC8, VC9, VCA, VCB, VCC, VCD, VCE, VCF, VD0, VD1,
3861*c3739801SMiguel Ojeda /// #   VD2, VD3, VD4, VD5, VD6, VD7, VD8, VD9, VDA, VDB, VDC, VDD, VDE, VDF, VE0,
3862*c3739801SMiguel Ojeda /// #   VE1, VE2, VE3, VE4, VE5, VE6, VE7, VE8, VE9, VEA, VEB, VEC, VED, VEE, VEF,
3863*c3739801SMiguel Ojeda /// #   VF0, VF1, VF2, VF3, VF4, VF5, VF6, VF7, VF8, VF9, VFA, VFB, VFC, VFD, VFE,
3864*c3739801SMiguel Ojeda /// #   VFF,
3865*c3739801SMiguel Ojeda /// # /*
3866*c3739801SMiguel Ojeda ///     ...
3867*c3739801SMiguel Ojeda /// # */
3868*c3739801SMiguel Ojeda /// }
3869*c3739801SMiguel Ojeda ///
3870*c3739801SMiguel Ojeda /// #[derive(FromBytes, Immutable)]
3871*c3739801SMiguel Ojeda /// union MyUnion {
3872*c3739801SMiguel Ojeda /// #   variant: u8,
3873*c3739801SMiguel Ojeda /// # /*
3874*c3739801SMiguel Ojeda ///     ...
3875*c3739801SMiguel Ojeda /// # */
3876*c3739801SMiguel Ojeda /// }
3877*c3739801SMiguel Ojeda /// ```
3878*c3739801SMiguel Ojeda ///
3879*c3739801SMiguel Ojeda /// [safety conditions]: trait@FromBytes#safety
3880*c3739801SMiguel Ojeda ///
3881*c3739801SMiguel Ojeda /// # Analysis
3882*c3739801SMiguel Ojeda ///
3883*c3739801SMiguel Ojeda /// *This section describes, roughly, the analysis performed by this derive to
3884*c3739801SMiguel Ojeda /// determine whether it is sound to implement `FromBytes` for a given type.
3885*c3739801SMiguel Ojeda /// Unless you are modifying the implementation of this derive, or attempting to
3886*c3739801SMiguel Ojeda /// manually implement `FromBytes` for a type yourself, you don't need to read
3887*c3739801SMiguel Ojeda /// this section.*
3888*c3739801SMiguel Ojeda ///
3889*c3739801SMiguel Ojeda /// If a type has the following properties, then this derive can implement
3890*c3739801SMiguel Ojeda /// `FromBytes` for that type:
3891*c3739801SMiguel Ojeda ///
3892*c3739801SMiguel Ojeda /// - If the type is a struct, all of its fields must be `FromBytes`.
3893*c3739801SMiguel Ojeda /// - If the type is an enum:
3894*c3739801SMiguel Ojeda ///   - It must have a defined representation which is one of `u8`, `u16`, `i8`,
3895*c3739801SMiguel Ojeda ///     or `i16`.
3896*c3739801SMiguel Ojeda ///   - The maximum number of discriminants must be used (so that every possible
3897*c3739801SMiguel Ojeda ///     bit pattern is a valid one).
3898*c3739801SMiguel Ojeda ///   - Its fields must be `FromBytes`.
3899*c3739801SMiguel Ojeda ///
3900*c3739801SMiguel Ojeda /// This analysis is subject to change. Unsafe code may *only* rely on the
3901*c3739801SMiguel Ojeda /// documented [safety conditions] of `FromBytes`, and must *not* rely on the
3902*c3739801SMiguel Ojeda /// implementation details of this derive.
3903*c3739801SMiguel Ojeda ///
3904*c3739801SMiguel Ojeda /// ## Why isn't an explicit representation required for structs?
3905*c3739801SMiguel Ojeda ///
3906*c3739801SMiguel Ojeda /// Neither this derive, nor the [safety conditions] of `FromBytes`, requires
3907*c3739801SMiguel Ojeda /// that structs are marked with `#[repr(C)]`.
3908*c3739801SMiguel Ojeda ///
3909*c3739801SMiguel Ojeda /// Per the [Rust reference](reference),
3910*c3739801SMiguel Ojeda ///
3911*c3739801SMiguel Ojeda /// > The representation of a type can change the padding between fields, but
3912*c3739801SMiguel Ojeda /// > does not change the layout of the fields themselves.
3913*c3739801SMiguel Ojeda ///
3914*c3739801SMiguel Ojeda /// [reference]: https://doc.rust-lang.org/reference/type-layout.html#representations
3915*c3739801SMiguel Ojeda ///
3916*c3739801SMiguel Ojeda /// Since the layout of structs only consists of padding bytes and field bytes,
3917*c3739801SMiguel Ojeda /// a struct is soundly `FromBytes` if:
3918*c3739801SMiguel Ojeda /// 1. its padding is soundly `FromBytes`, and
3919*c3739801SMiguel Ojeda /// 2. its fields are soundly `FromBytes`.
3920*c3739801SMiguel Ojeda ///
3921*c3739801SMiguel Ojeda /// The answer to the first question is always yes: padding bytes do not have
3922*c3739801SMiguel Ojeda /// any validity constraints. A [discussion] of this question in the Unsafe Code
3923*c3739801SMiguel Ojeda /// Guidelines Working Group concluded that it would be virtually unimaginable
3924*c3739801SMiguel Ojeda /// for future versions of rustc to add validity constraints to padding bytes.
3925*c3739801SMiguel Ojeda ///
3926*c3739801SMiguel Ojeda /// [discussion]: https://github.com/rust-lang/unsafe-code-guidelines/issues/174
3927*c3739801SMiguel Ojeda ///
3928*c3739801SMiguel Ojeda /// Whether a struct is soundly `FromBytes` therefore solely depends on whether
3929*c3739801SMiguel Ojeda /// its fields are `FromBytes`.
3930*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
3931*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
3932*c3739801SMiguel Ojeda pub use zerocopy_derive::FromBytes;
3933*c3739801SMiguel Ojeda 
3934*c3739801SMiguel Ojeda /// Types for which any bit pattern is valid.
3935*c3739801SMiguel Ojeda ///
3936*c3739801SMiguel Ojeda /// Any memory region of the appropriate length which contains initialized bytes
3937*c3739801SMiguel Ojeda /// can be viewed as any `FromBytes` type with no runtime overhead. This is
3938*c3739801SMiguel Ojeda /// useful for efficiently parsing bytes as structured data.
3939*c3739801SMiguel Ojeda ///
3940*c3739801SMiguel Ojeda /// # Warning: Padding bytes
3941*c3739801SMiguel Ojeda ///
3942*c3739801SMiguel Ojeda /// Note that, when a value is moved or copied, only the non-padding bytes of
3943*c3739801SMiguel Ojeda /// that value are guaranteed to be preserved. It is unsound to assume that
3944*c3739801SMiguel Ojeda /// values written to padding bytes are preserved after a move or copy. For
3945*c3739801SMiguel Ojeda /// example, the following is unsound:
3946*c3739801SMiguel Ojeda ///
3947*c3739801SMiguel Ojeda /// ```rust,no_run
3948*c3739801SMiguel Ojeda /// use core::mem::{size_of, transmute};
3949*c3739801SMiguel Ojeda /// use zerocopy::FromZeros;
3950*c3739801SMiguel Ojeda /// # use zerocopy_derive::*;
3951*c3739801SMiguel Ojeda ///
3952*c3739801SMiguel Ojeda /// // Assume `Foo` is a type with padding bytes.
3953*c3739801SMiguel Ojeda /// #[derive(FromZeros, Default)]
3954*c3739801SMiguel Ojeda /// struct Foo {
3955*c3739801SMiguel Ojeda /// # /*
3956*c3739801SMiguel Ojeda ///     ...
3957*c3739801SMiguel Ojeda /// # */
3958*c3739801SMiguel Ojeda /// }
3959*c3739801SMiguel Ojeda ///
3960*c3739801SMiguel Ojeda /// let mut foo: Foo = Foo::default();
3961*c3739801SMiguel Ojeda /// FromZeros::zero(&mut foo);
3962*c3739801SMiguel Ojeda /// // UNSOUND: Although `FromZeros::zero` writes zeros to all bytes of `foo`,
3963*c3739801SMiguel Ojeda /// // those writes are not guaranteed to be preserved in padding bytes when
3964*c3739801SMiguel Ojeda /// // `foo` is moved, so this may expose padding bytes as `u8`s.
3965*c3739801SMiguel Ojeda /// let foo_bytes: [u8; size_of::<Foo>()] = unsafe { transmute(foo) };
3966*c3739801SMiguel Ojeda /// ```
3967*c3739801SMiguel Ojeda ///
3968*c3739801SMiguel Ojeda /// # Implementation
3969*c3739801SMiguel Ojeda ///
3970*c3739801SMiguel Ojeda /// **Do not implement this trait yourself!** Instead, use
3971*c3739801SMiguel Ojeda /// [`#[derive(FromBytes)]`][derive]; e.g.:
3972*c3739801SMiguel Ojeda ///
3973*c3739801SMiguel Ojeda /// ```
3974*c3739801SMiguel Ojeda /// # use zerocopy_derive::{FromBytes, Immutable};
3975*c3739801SMiguel Ojeda /// #[derive(FromBytes)]
3976*c3739801SMiguel Ojeda /// struct MyStruct {
3977*c3739801SMiguel Ojeda /// # /*
3978*c3739801SMiguel Ojeda ///     ...
3979*c3739801SMiguel Ojeda /// # */
3980*c3739801SMiguel Ojeda /// }
3981*c3739801SMiguel Ojeda ///
3982*c3739801SMiguel Ojeda /// #[derive(FromBytes)]
3983*c3739801SMiguel Ojeda /// #[repr(u8)]
3984*c3739801SMiguel Ojeda /// enum MyEnum {
3985*c3739801SMiguel Ojeda /// #   V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, V0A, V0B, V0C, V0D, V0E,
3986*c3739801SMiguel Ojeda /// #   V0F, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V1A, V1B, V1C, V1D,
3987*c3739801SMiguel Ojeda /// #   V1E, V1F, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V2A, V2B, V2C,
3988*c3739801SMiguel Ojeda /// #   V2D, V2E, V2F, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V3A, V3B,
3989*c3739801SMiguel Ojeda /// #   V3C, V3D, V3E, V3F, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V4A,
3990*c3739801SMiguel Ojeda /// #   V4B, V4C, V4D, V4E, V4F, V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
3991*c3739801SMiguel Ojeda /// #   V5A, V5B, V5C, V5D, V5E, V5F, V60, V61, V62, V63, V64, V65, V66, V67, V68,
3992*c3739801SMiguel Ojeda /// #   V69, V6A, V6B, V6C, V6D, V6E, V6F, V70, V71, V72, V73, V74, V75, V76, V77,
3993*c3739801SMiguel Ojeda /// #   V78, V79, V7A, V7B, V7C, V7D, V7E, V7F, V80, V81, V82, V83, V84, V85, V86,
3994*c3739801SMiguel Ojeda /// #   V87, V88, V89, V8A, V8B, V8C, V8D, V8E, V8F, V90, V91, V92, V93, V94, V95,
3995*c3739801SMiguel Ojeda /// #   V96, V97, V98, V99, V9A, V9B, V9C, V9D, V9E, V9F, VA0, VA1, VA2, VA3, VA4,
3996*c3739801SMiguel Ojeda /// #   VA5, VA6, VA7, VA8, VA9, VAA, VAB, VAC, VAD, VAE, VAF, VB0, VB1, VB2, VB3,
3997*c3739801SMiguel Ojeda /// #   VB4, VB5, VB6, VB7, VB8, VB9, VBA, VBB, VBC, VBD, VBE, VBF, VC0, VC1, VC2,
3998*c3739801SMiguel Ojeda /// #   VC3, VC4, VC5, VC6, VC7, VC8, VC9, VCA, VCB, VCC, VCD, VCE, VCF, VD0, VD1,
3999*c3739801SMiguel Ojeda /// #   VD2, VD3, VD4, VD5, VD6, VD7, VD8, VD9, VDA, VDB, VDC, VDD, VDE, VDF, VE0,
4000*c3739801SMiguel Ojeda /// #   VE1, VE2, VE3, VE4, VE5, VE6, VE7, VE8, VE9, VEA, VEB, VEC, VED, VEE, VEF,
4001*c3739801SMiguel Ojeda /// #   VF0, VF1, VF2, VF3, VF4, VF5, VF6, VF7, VF8, VF9, VFA, VFB, VFC, VFD, VFE,
4002*c3739801SMiguel Ojeda /// #   VFF,
4003*c3739801SMiguel Ojeda /// # /*
4004*c3739801SMiguel Ojeda ///     ...
4005*c3739801SMiguel Ojeda /// # */
4006*c3739801SMiguel Ojeda /// }
4007*c3739801SMiguel Ojeda ///
4008*c3739801SMiguel Ojeda /// #[derive(FromBytes, Immutable)]
4009*c3739801SMiguel Ojeda /// union MyUnion {
4010*c3739801SMiguel Ojeda /// #   variant: u8,
4011*c3739801SMiguel Ojeda /// # /*
4012*c3739801SMiguel Ojeda ///     ...
4013*c3739801SMiguel Ojeda /// # */
4014*c3739801SMiguel Ojeda /// }
4015*c3739801SMiguel Ojeda /// ```
4016*c3739801SMiguel Ojeda ///
4017*c3739801SMiguel Ojeda /// This derive performs a sophisticated, compile-time safety analysis to
4018*c3739801SMiguel Ojeda /// determine whether a type is `FromBytes`.
4019*c3739801SMiguel Ojeda ///
4020*c3739801SMiguel Ojeda /// # Safety
4021*c3739801SMiguel Ojeda ///
4022*c3739801SMiguel Ojeda /// *This section describes what is required in order for `T: FromBytes`, and
4023*c3739801SMiguel Ojeda /// what unsafe code may assume of such types. If you don't plan on implementing
4024*c3739801SMiguel Ojeda /// `FromBytes` manually, and you don't plan on writing unsafe code that
4025*c3739801SMiguel Ojeda /// operates on `FromBytes` types, then you don't need to read this section.*
4026*c3739801SMiguel Ojeda ///
4027*c3739801SMiguel Ojeda /// If `T: FromBytes`, then unsafe code may assume that it is sound to produce a
4028*c3739801SMiguel Ojeda /// `T` whose bytes are initialized to any sequence of valid `u8`s (in other
4029*c3739801SMiguel Ojeda /// words, any byte value which is not uninitialized). If a type is marked as
4030*c3739801SMiguel Ojeda /// `FromBytes` which violates this contract, it may cause undefined behavior.
4031*c3739801SMiguel Ojeda ///
4032*c3739801SMiguel Ojeda /// `#[derive(FromBytes)]` only permits [types which satisfy these
4033*c3739801SMiguel Ojeda /// requirements][derive-analysis].
4034*c3739801SMiguel Ojeda ///
4035*c3739801SMiguel Ojeda #[cfg_attr(
4036*c3739801SMiguel Ojeda     feature = "derive",
4037*c3739801SMiguel Ojeda     doc = "[derive]: zerocopy_derive::FromBytes",
4038*c3739801SMiguel Ojeda     doc = "[derive-analysis]: zerocopy_derive::FromBytes#analysis"
4039*c3739801SMiguel Ojeda )]
4040*c3739801SMiguel Ojeda #[cfg_attr(
4041*c3739801SMiguel Ojeda     not(feature = "derive"),
4042*c3739801SMiguel Ojeda     doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromBytes.html"),
4043*c3739801SMiguel Ojeda     doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.FromBytes.html#analysis"),
4044*c3739801SMiguel Ojeda )]
4045*c3739801SMiguel Ojeda #[cfg_attr(
4046*c3739801SMiguel Ojeda     not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
4047*c3739801SMiguel Ojeda     diagnostic::on_unimplemented(note = "Consider adding `#[derive(FromBytes)]` to `{Self}`")
4048*c3739801SMiguel Ojeda )]
4049*c3739801SMiguel Ojeda pub unsafe trait FromBytes: FromZeros {
4050*c3739801SMiguel Ojeda     // The `Self: Sized` bound makes it so that `FromBytes` is still object
4051*c3739801SMiguel Ojeda     // safe.
4052*c3739801SMiguel Ojeda     #[doc(hidden)]
4053*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
4054*c3739801SMiguel Ojeda     where
4055*c3739801SMiguel Ojeda         Self: Sized;
4056*c3739801SMiguel Ojeda 
4057*c3739801SMiguel Ojeda     /// Interprets the given `source` as a `&Self`.
4058*c3739801SMiguel Ojeda     ///
4059*c3739801SMiguel Ojeda     /// This method attempts to return a reference to `source` interpreted as a
4060*c3739801SMiguel Ojeda     /// `Self`. If the length of `source` is not a [valid size of
4061*c3739801SMiguel Ojeda     /// `Self`][valid-size], or if `source` is not appropriately aligned, this
4062*c3739801SMiguel Ojeda     /// returns `Err`. If [`Self: Unaligned`][self-unaligned], you can
4063*c3739801SMiguel Ojeda     /// [infallibly discard the alignment error][size-error-from].
4064*c3739801SMiguel Ojeda     ///
4065*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
4066*c3739801SMiguel Ojeda     ///
4067*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
4068*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4069*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4070*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
4071*c3739801SMiguel Ojeda     ///
4072*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
4073*c3739801SMiguel Ojeda     ///
4074*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
4075*c3739801SMiguel Ojeda     /// component is zero-sized. Attempting to use this method on such types
4076*c3739801SMiguel Ojeda     /// results in a compile-time assertion error; e.g.:
4077*c3739801SMiguel Ojeda     ///
4078*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
4079*c3739801SMiguel Ojeda     /// use zerocopy::*;
4080*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4081*c3739801SMiguel Ojeda     ///
4082*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, KnownLayout)]
4083*c3739801SMiguel Ojeda     /// #[repr(C)]
4084*c3739801SMiguel Ojeda     /// struct ZSTy {
4085*c3739801SMiguel Ojeda     ///     leading_sized: u16,
4086*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4087*c3739801SMiguel Ojeda     /// }
4088*c3739801SMiguel Ojeda     ///
4089*c3739801SMiguel Ojeda     /// let _ = ZSTy::ref_from_bytes(0u16.as_bytes()); // ⚠ Compile Error!
4090*c3739801SMiguel Ojeda     /// ```
4091*c3739801SMiguel Ojeda     ///
4092*c3739801SMiguel Ojeda     /// # Examples
4093*c3739801SMiguel Ojeda     ///
4094*c3739801SMiguel Ojeda     /// ```
4095*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4096*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4097*c3739801SMiguel Ojeda     ///
4098*c3739801SMiguel Ojeda     /// #[derive(FromBytes, KnownLayout, Immutable)]
4099*c3739801SMiguel Ojeda     /// #[repr(C)]
4100*c3739801SMiguel Ojeda     /// struct PacketHeader {
4101*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
4102*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
4103*c3739801SMiguel Ojeda     ///     length: [u8; 2],
4104*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
4105*c3739801SMiguel Ojeda     /// }
4106*c3739801SMiguel Ojeda     ///
4107*c3739801SMiguel Ojeda     /// #[derive(FromBytes, KnownLayout, Immutable)]
4108*c3739801SMiguel Ojeda     /// #[repr(C)]
4109*c3739801SMiguel Ojeda     /// struct Packet {
4110*c3739801SMiguel Ojeda     ///     header: PacketHeader,
4111*c3739801SMiguel Ojeda     ///     body: [u8],
4112*c3739801SMiguel Ojeda     /// }
4113*c3739801SMiguel Ojeda     ///
4114*c3739801SMiguel Ojeda     /// // These bytes encode a `Packet`.
4115*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11][..];
4116*c3739801SMiguel Ojeda     ///
4117*c3739801SMiguel Ojeda     /// let packet = Packet::ref_from_bytes(bytes).unwrap();
4118*c3739801SMiguel Ojeda     ///
4119*c3739801SMiguel Ojeda     /// assert_eq!(packet.header.src_port, [0, 1]);
4120*c3739801SMiguel Ojeda     /// assert_eq!(packet.header.dst_port, [2, 3]);
4121*c3739801SMiguel Ojeda     /// assert_eq!(packet.header.length, [4, 5]);
4122*c3739801SMiguel Ojeda     /// assert_eq!(packet.header.checksum, [6, 7]);
4123*c3739801SMiguel Ojeda     /// assert_eq!(packet.body, [8, 9, 10, 11]);
4124*c3739801SMiguel Ojeda     /// ```
4125*c3739801SMiguel Ojeda     ///
4126*c3739801SMiguel Ojeda     #[doc = codegen_section!(
4127*c3739801SMiguel Ojeda         header = "h5",
4128*c3739801SMiguel Ojeda         bench = "ref_from_bytes",
4129*c3739801SMiguel Ojeda         format = "coco",
4130*c3739801SMiguel Ojeda         arity = 3,
4131*c3739801SMiguel Ojeda         [
4132*c3739801SMiguel Ojeda             open
4133*c3739801SMiguel Ojeda             @index 1
4134*c3739801SMiguel Ojeda             @title "Sized"
4135*c3739801SMiguel Ojeda             @variant "static_size"
4136*c3739801SMiguel Ojeda         ],
4137*c3739801SMiguel Ojeda         [
4138*c3739801SMiguel Ojeda             @index 2
4139*c3739801SMiguel Ojeda             @title "Unsized"
4140*c3739801SMiguel Ojeda             @variant "dynamic_size"
4141*c3739801SMiguel Ojeda         ],
4142*c3739801SMiguel Ojeda         [
4143*c3739801SMiguel Ojeda             @index 3
4144*c3739801SMiguel Ojeda             @title "Dynamically Padded"
4145*c3739801SMiguel Ojeda             @variant "dynamic_padding"
4146*c3739801SMiguel Ojeda         ]
4147*c3739801SMiguel Ojeda     )]
4148*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4149*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4150*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4151*c3739801SMiguel Ojeda     fn ref_from_bytes(source: &[u8]) -> Result<&Self, CastError<&[u8], Self>>
4152*c3739801SMiguel Ojeda     where
4153*c3739801SMiguel Ojeda         Self: KnownLayout + Immutable,
4154*c3739801SMiguel Ojeda     {
4155*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
4156*c3739801SMiguel Ojeda         match Ptr::from_ref(source).try_cast_into_no_leftover::<_, BecauseImmutable>(None) {
4157*c3739801SMiguel Ojeda             Ok(ptr) => Ok(ptr.recall_validity().as_ref()),
4158*c3739801SMiguel Ojeda             Err(err) => Err(err.map_src(|src| src.as_ref())),
4159*c3739801SMiguel Ojeda         }
4160*c3739801SMiguel Ojeda     }
4161*c3739801SMiguel Ojeda 
4162*c3739801SMiguel Ojeda     /// Interprets the prefix of the given `source` as a `&Self` without
4163*c3739801SMiguel Ojeda     /// copying.
4164*c3739801SMiguel Ojeda     ///
4165*c3739801SMiguel Ojeda     /// This method computes the [largest possible size of `Self`][valid-size]
4166*c3739801SMiguel Ojeda     /// that can fit in the leading bytes of `source`, then attempts to return
4167*c3739801SMiguel Ojeda     /// both a reference to those bytes interpreted as a `Self`, and a reference
4168*c3739801SMiguel Ojeda     /// to the remaining bytes. If there are insufficient bytes, or if `source`
4169*c3739801SMiguel Ojeda     /// is not appropriately aligned, this returns `Err`. If [`Self:
4170*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
4171*c3739801SMiguel Ojeda     /// error][size-error-from].
4172*c3739801SMiguel Ojeda     ///
4173*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
4174*c3739801SMiguel Ojeda     ///
4175*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
4176*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4177*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4178*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
4179*c3739801SMiguel Ojeda     ///
4180*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
4181*c3739801SMiguel Ojeda     ///
4182*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
4183*c3739801SMiguel Ojeda     /// component is zero-sized. See [`ref_from_prefix_with_elems`], which does
4184*c3739801SMiguel Ojeda     /// support such types. Attempting to use this method on such types results
4185*c3739801SMiguel Ojeda     /// in a compile-time assertion error; e.g.:
4186*c3739801SMiguel Ojeda     ///
4187*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
4188*c3739801SMiguel Ojeda     /// use zerocopy::*;
4189*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4190*c3739801SMiguel Ojeda     ///
4191*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, KnownLayout)]
4192*c3739801SMiguel Ojeda     /// #[repr(C)]
4193*c3739801SMiguel Ojeda     /// struct ZSTy {
4194*c3739801SMiguel Ojeda     ///     leading_sized: u16,
4195*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4196*c3739801SMiguel Ojeda     /// }
4197*c3739801SMiguel Ojeda     ///
4198*c3739801SMiguel Ojeda     /// let _ = ZSTy::ref_from_prefix(0u16.as_bytes()); // ⚠ Compile Error!
4199*c3739801SMiguel Ojeda     /// ```
4200*c3739801SMiguel Ojeda     ///
4201*c3739801SMiguel Ojeda     /// [`ref_from_prefix_with_elems`]: FromBytes::ref_from_prefix_with_elems
4202*c3739801SMiguel Ojeda     ///
4203*c3739801SMiguel Ojeda     /// # Examples
4204*c3739801SMiguel Ojeda     ///
4205*c3739801SMiguel Ojeda     /// ```
4206*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4207*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4208*c3739801SMiguel Ojeda     ///
4209*c3739801SMiguel Ojeda     /// #[derive(FromBytes, KnownLayout, Immutable)]
4210*c3739801SMiguel Ojeda     /// #[repr(C)]
4211*c3739801SMiguel Ojeda     /// struct PacketHeader {
4212*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
4213*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
4214*c3739801SMiguel Ojeda     ///     length: [u8; 2],
4215*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
4216*c3739801SMiguel Ojeda     /// }
4217*c3739801SMiguel Ojeda     ///
4218*c3739801SMiguel Ojeda     /// #[derive(FromBytes, KnownLayout, Immutable)]
4219*c3739801SMiguel Ojeda     /// #[repr(C)]
4220*c3739801SMiguel Ojeda     /// struct Packet {
4221*c3739801SMiguel Ojeda     ///     header: PacketHeader,
4222*c3739801SMiguel Ojeda     ///     body: [[u8; 2]],
4223*c3739801SMiguel Ojeda     /// }
4224*c3739801SMiguel Ojeda     ///
4225*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `Packet`.
4226*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14][..];
4227*c3739801SMiguel Ojeda     ///
4228*c3739801SMiguel Ojeda     /// let (packet, suffix) = Packet::ref_from_prefix(bytes).unwrap();
4229*c3739801SMiguel Ojeda     ///
4230*c3739801SMiguel Ojeda     /// assert_eq!(packet.header.src_port, [0, 1]);
4231*c3739801SMiguel Ojeda     /// assert_eq!(packet.header.dst_port, [2, 3]);
4232*c3739801SMiguel Ojeda     /// assert_eq!(packet.header.length, [4, 5]);
4233*c3739801SMiguel Ojeda     /// assert_eq!(packet.header.checksum, [6, 7]);
4234*c3739801SMiguel Ojeda     /// assert_eq!(packet.body, [[8, 9], [10, 11], [12, 13]]);
4235*c3739801SMiguel Ojeda     /// assert_eq!(suffix, &[14u8][..]);
4236*c3739801SMiguel Ojeda     /// ```
4237*c3739801SMiguel Ojeda     ///
4238*c3739801SMiguel Ojeda     #[doc = codegen_section!(
4239*c3739801SMiguel Ojeda         header = "h5",
4240*c3739801SMiguel Ojeda         bench = "ref_from_prefix",
4241*c3739801SMiguel Ojeda         format = "coco",
4242*c3739801SMiguel Ojeda         arity = 3,
4243*c3739801SMiguel Ojeda         [
4244*c3739801SMiguel Ojeda             open
4245*c3739801SMiguel Ojeda             @index 1
4246*c3739801SMiguel Ojeda             @title "Sized"
4247*c3739801SMiguel Ojeda             @variant "static_size"
4248*c3739801SMiguel Ojeda         ],
4249*c3739801SMiguel Ojeda         [
4250*c3739801SMiguel Ojeda             @index 2
4251*c3739801SMiguel Ojeda             @title "Unsized"
4252*c3739801SMiguel Ojeda             @variant "dynamic_size"
4253*c3739801SMiguel Ojeda         ],
4254*c3739801SMiguel Ojeda         [
4255*c3739801SMiguel Ojeda             @index 3
4256*c3739801SMiguel Ojeda             @title "Dynamically Padded"
4257*c3739801SMiguel Ojeda             @variant "dynamic_padding"
4258*c3739801SMiguel Ojeda         ]
4259*c3739801SMiguel Ojeda     )]
4260*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4261*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4262*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4263*c3739801SMiguel Ojeda     fn ref_from_prefix(source: &[u8]) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>
4264*c3739801SMiguel Ojeda     where
4265*c3739801SMiguel Ojeda         Self: KnownLayout + Immutable,
4266*c3739801SMiguel Ojeda     {
4267*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
4268*c3739801SMiguel Ojeda         ref_from_prefix_suffix(source, None, CastType::Prefix)
4269*c3739801SMiguel Ojeda     }
4270*c3739801SMiguel Ojeda 
4271*c3739801SMiguel Ojeda     /// Interprets the suffix of the given bytes as a `&Self`.
4272*c3739801SMiguel Ojeda     ///
4273*c3739801SMiguel Ojeda     /// This method computes the [largest possible size of `Self`][valid-size]
4274*c3739801SMiguel Ojeda     /// that can fit in the trailing bytes of `source`, then attempts to return
4275*c3739801SMiguel Ojeda     /// both a reference to those bytes interpreted as a `Self`, and a reference
4276*c3739801SMiguel Ojeda     /// to the preceding bytes. If there are insufficient bytes, or if that
4277*c3739801SMiguel Ojeda     /// suffix of `source` is not appropriately aligned, this returns `Err`. If
4278*c3739801SMiguel Ojeda     /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
4279*c3739801SMiguel Ojeda     /// alignment error][size-error-from].
4280*c3739801SMiguel Ojeda     ///
4281*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
4282*c3739801SMiguel Ojeda     ///
4283*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
4284*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4285*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4286*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
4287*c3739801SMiguel Ojeda     ///
4288*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
4289*c3739801SMiguel Ojeda     ///
4290*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
4291*c3739801SMiguel Ojeda     /// component is zero-sized. See [`ref_from_suffix_with_elems`], which does
4292*c3739801SMiguel Ojeda     /// support such types. Attempting to use this method on such types results
4293*c3739801SMiguel Ojeda     /// in a compile-time assertion error; e.g.:
4294*c3739801SMiguel Ojeda     ///
4295*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
4296*c3739801SMiguel Ojeda     /// use zerocopy::*;
4297*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4298*c3739801SMiguel Ojeda     ///
4299*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, KnownLayout)]
4300*c3739801SMiguel Ojeda     /// #[repr(C)]
4301*c3739801SMiguel Ojeda     /// struct ZSTy {
4302*c3739801SMiguel Ojeda     ///     leading_sized: u16,
4303*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4304*c3739801SMiguel Ojeda     /// }
4305*c3739801SMiguel Ojeda     ///
4306*c3739801SMiguel Ojeda     /// let _ = ZSTy::ref_from_suffix(0u16.as_bytes()); // ⚠ Compile Error!
4307*c3739801SMiguel Ojeda     /// ```
4308*c3739801SMiguel Ojeda     ///
4309*c3739801SMiguel Ojeda     /// [`ref_from_suffix_with_elems`]: FromBytes::ref_from_suffix_with_elems
4310*c3739801SMiguel Ojeda     ///
4311*c3739801SMiguel Ojeda     /// # Examples
4312*c3739801SMiguel Ojeda     ///
4313*c3739801SMiguel Ojeda     /// ```
4314*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4315*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4316*c3739801SMiguel Ojeda     ///
4317*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, KnownLayout)]
4318*c3739801SMiguel Ojeda     /// #[repr(C)]
4319*c3739801SMiguel Ojeda     /// struct PacketTrailer {
4320*c3739801SMiguel Ojeda     ///     frame_check_sequence: [u8; 4],
4321*c3739801SMiguel Ojeda     /// }
4322*c3739801SMiguel Ojeda     ///
4323*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `PacketTrailer`.
4324*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4325*c3739801SMiguel Ojeda     ///
4326*c3739801SMiguel Ojeda     /// let (prefix, trailer) = PacketTrailer::ref_from_suffix(bytes).unwrap();
4327*c3739801SMiguel Ojeda     ///
4328*c3739801SMiguel Ojeda     /// assert_eq!(prefix, &[0, 1, 2, 3, 4, 5][..]);
4329*c3739801SMiguel Ojeda     /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
4330*c3739801SMiguel Ojeda     /// ```
4331*c3739801SMiguel Ojeda     ///
4332*c3739801SMiguel Ojeda     #[doc = codegen_section!(
4333*c3739801SMiguel Ojeda         header = "h5",
4334*c3739801SMiguel Ojeda         bench = "ref_from_suffix",
4335*c3739801SMiguel Ojeda         format = "coco",
4336*c3739801SMiguel Ojeda         arity = 3,
4337*c3739801SMiguel Ojeda         [
4338*c3739801SMiguel Ojeda             open
4339*c3739801SMiguel Ojeda             @index 1
4340*c3739801SMiguel Ojeda             @title "Sized"
4341*c3739801SMiguel Ojeda             @variant "static_size"
4342*c3739801SMiguel Ojeda         ],
4343*c3739801SMiguel Ojeda         [
4344*c3739801SMiguel Ojeda             @index 2
4345*c3739801SMiguel Ojeda             @title "Unsized"
4346*c3739801SMiguel Ojeda             @variant "dynamic_size"
4347*c3739801SMiguel Ojeda         ],
4348*c3739801SMiguel Ojeda         [
4349*c3739801SMiguel Ojeda             @index 3
4350*c3739801SMiguel Ojeda             @title "Dynamically Padded"
4351*c3739801SMiguel Ojeda             @variant "dynamic_padding"
4352*c3739801SMiguel Ojeda         ]
4353*c3739801SMiguel Ojeda     )]
4354*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4355*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4356*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4357*c3739801SMiguel Ojeda     fn ref_from_suffix(source: &[u8]) -> Result<(&[u8], &Self), CastError<&[u8], Self>>
4358*c3739801SMiguel Ojeda     where
4359*c3739801SMiguel Ojeda         Self: Immutable + KnownLayout,
4360*c3739801SMiguel Ojeda     {
4361*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
4362*c3739801SMiguel Ojeda         ref_from_prefix_suffix(source, None, CastType::Suffix).map(swap)
4363*c3739801SMiguel Ojeda     }
4364*c3739801SMiguel Ojeda 
4365*c3739801SMiguel Ojeda     /// Interprets the given `source` as a `&mut Self`.
4366*c3739801SMiguel Ojeda     ///
4367*c3739801SMiguel Ojeda     /// This method attempts to return a reference to `source` interpreted as a
4368*c3739801SMiguel Ojeda     /// `Self`. If the length of `source` is not a [valid size of
4369*c3739801SMiguel Ojeda     /// `Self`][valid-size], or if `source` is not appropriately aligned, this
4370*c3739801SMiguel Ojeda     /// returns `Err`. If [`Self: Unaligned`][self-unaligned], you can
4371*c3739801SMiguel Ojeda     /// [infallibly discard the alignment error][size-error-from].
4372*c3739801SMiguel Ojeda     ///
4373*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
4374*c3739801SMiguel Ojeda     ///
4375*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
4376*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4377*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4378*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
4379*c3739801SMiguel Ojeda     ///
4380*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
4381*c3739801SMiguel Ojeda     ///
4382*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
4383*c3739801SMiguel Ojeda     /// component is zero-sized. See [`mut_from_prefix_with_elems`], which does
4384*c3739801SMiguel Ojeda     /// support such types. Attempting to use this method on such types results
4385*c3739801SMiguel Ojeda     /// in a compile-time assertion error; e.g.:
4386*c3739801SMiguel Ojeda     ///
4387*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
4388*c3739801SMiguel Ojeda     /// use zerocopy::*;
4389*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4390*c3739801SMiguel Ojeda     ///
4391*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
4392*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
4393*c3739801SMiguel Ojeda     /// struct ZSTy {
4394*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
4395*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4396*c3739801SMiguel Ojeda     /// }
4397*c3739801SMiguel Ojeda     ///
4398*c3739801SMiguel Ojeda     /// let mut source = [85, 85];
4399*c3739801SMiguel Ojeda     /// let _ = ZSTy::mut_from_bytes(&mut source[..]); // ⚠ Compile Error!
4400*c3739801SMiguel Ojeda     /// ```
4401*c3739801SMiguel Ojeda     ///
4402*c3739801SMiguel Ojeda     /// [`mut_from_prefix_with_elems`]: FromBytes::mut_from_prefix_with_elems
4403*c3739801SMiguel Ojeda     ///
4404*c3739801SMiguel Ojeda     /// # Examples
4405*c3739801SMiguel Ojeda     ///
4406*c3739801SMiguel Ojeda     /// ```
4407*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4408*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4409*c3739801SMiguel Ojeda     ///
4410*c3739801SMiguel Ojeda     /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
4411*c3739801SMiguel Ojeda     /// #[repr(C)]
4412*c3739801SMiguel Ojeda     /// struct PacketHeader {
4413*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
4414*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
4415*c3739801SMiguel Ojeda     ///     length: [u8; 2],
4416*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
4417*c3739801SMiguel Ojeda     /// }
4418*c3739801SMiguel Ojeda     ///
4419*c3739801SMiguel Ojeda     /// // These bytes encode a `PacketHeader`.
4420*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..];
4421*c3739801SMiguel Ojeda     ///
4422*c3739801SMiguel Ojeda     /// let header = PacketHeader::mut_from_bytes(bytes).unwrap();
4423*c3739801SMiguel Ojeda     ///
4424*c3739801SMiguel Ojeda     /// assert_eq!(header.src_port, [0, 1]);
4425*c3739801SMiguel Ojeda     /// assert_eq!(header.dst_port, [2, 3]);
4426*c3739801SMiguel Ojeda     /// assert_eq!(header.length, [4, 5]);
4427*c3739801SMiguel Ojeda     /// assert_eq!(header.checksum, [6, 7]);
4428*c3739801SMiguel Ojeda     ///
4429*c3739801SMiguel Ojeda     /// header.checksum = [0, 0];
4430*c3739801SMiguel Ojeda     ///
4431*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0]);
4432*c3739801SMiguel Ojeda     ///
4433*c3739801SMiguel Ojeda     /// ```
4434*c3739801SMiguel Ojeda     ///
4435*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "mut_from_bytes")]
4436*c3739801SMiguel Ojeda     ///
4437*c3739801SMiguel Ojeda     /// See [`FromBytes::ref_from_bytes`](#method.ref_from_bytes.codegen).
4438*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4439*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4440*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4441*c3739801SMiguel Ojeda     fn mut_from_bytes(source: &mut [u8]) -> Result<&mut Self, CastError<&mut [u8], Self>>
4442*c3739801SMiguel Ojeda     where
4443*c3739801SMiguel Ojeda         Self: IntoBytes + KnownLayout,
4444*c3739801SMiguel Ojeda     {
4445*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
4446*c3739801SMiguel Ojeda         match Ptr::from_mut(source).try_cast_into_no_leftover::<_, BecauseExclusive>(None) {
4447*c3739801SMiguel Ojeda             Ok(ptr) => Ok(ptr.recall_validity::<_, (_, (_, _))>().as_mut()),
4448*c3739801SMiguel Ojeda             Err(err) => Err(err.map_src(|src| src.as_mut())),
4449*c3739801SMiguel Ojeda         }
4450*c3739801SMiguel Ojeda     }
4451*c3739801SMiguel Ojeda 
4452*c3739801SMiguel Ojeda     /// Interprets the prefix of the given `source` as a `&mut Self` without
4453*c3739801SMiguel Ojeda     /// copying.
4454*c3739801SMiguel Ojeda     ///
4455*c3739801SMiguel Ojeda     /// This method computes the [largest possible size of `Self`][valid-size]
4456*c3739801SMiguel Ojeda     /// that can fit in the leading bytes of `source`, then attempts to return
4457*c3739801SMiguel Ojeda     /// both a reference to those bytes interpreted as a `Self`, and a reference
4458*c3739801SMiguel Ojeda     /// to the remaining bytes. If there are insufficient bytes, or if `source`
4459*c3739801SMiguel Ojeda     /// is not appropriately aligned, this returns `Err`. If [`Self:
4460*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
4461*c3739801SMiguel Ojeda     /// error][size-error-from].
4462*c3739801SMiguel Ojeda     ///
4463*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
4464*c3739801SMiguel Ojeda     ///
4465*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
4466*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4467*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4468*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
4469*c3739801SMiguel Ojeda     ///
4470*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
4471*c3739801SMiguel Ojeda     ///
4472*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
4473*c3739801SMiguel Ojeda     /// component is zero-sized. See [`mut_from_suffix_with_elems`], which does
4474*c3739801SMiguel Ojeda     /// support such types. Attempting to use this method on such types results
4475*c3739801SMiguel Ojeda     /// in a compile-time assertion error; e.g.:
4476*c3739801SMiguel Ojeda     ///
4477*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
4478*c3739801SMiguel Ojeda     /// use zerocopy::*;
4479*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4480*c3739801SMiguel Ojeda     ///
4481*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
4482*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
4483*c3739801SMiguel Ojeda     /// struct ZSTy {
4484*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
4485*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4486*c3739801SMiguel Ojeda     /// }
4487*c3739801SMiguel Ojeda     ///
4488*c3739801SMiguel Ojeda     /// let mut source = [85, 85];
4489*c3739801SMiguel Ojeda     /// let _ = ZSTy::mut_from_prefix(&mut source[..]); // ⚠ Compile Error!
4490*c3739801SMiguel Ojeda     /// ```
4491*c3739801SMiguel Ojeda     ///
4492*c3739801SMiguel Ojeda     /// [`mut_from_suffix_with_elems`]: FromBytes::mut_from_suffix_with_elems
4493*c3739801SMiguel Ojeda     ///
4494*c3739801SMiguel Ojeda     /// # Examples
4495*c3739801SMiguel Ojeda     ///
4496*c3739801SMiguel Ojeda     /// ```
4497*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4498*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4499*c3739801SMiguel Ojeda     ///
4500*c3739801SMiguel Ojeda     /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
4501*c3739801SMiguel Ojeda     /// #[repr(C)]
4502*c3739801SMiguel Ojeda     /// struct PacketHeader {
4503*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
4504*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
4505*c3739801SMiguel Ojeda     ///     length: [u8; 2],
4506*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
4507*c3739801SMiguel Ojeda     /// }
4508*c3739801SMiguel Ojeda     ///
4509*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `PacketHeader`.
4510*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4511*c3739801SMiguel Ojeda     ///
4512*c3739801SMiguel Ojeda     /// let (header, body) = PacketHeader::mut_from_prefix(bytes).unwrap();
4513*c3739801SMiguel Ojeda     ///
4514*c3739801SMiguel Ojeda     /// assert_eq!(header.src_port, [0, 1]);
4515*c3739801SMiguel Ojeda     /// assert_eq!(header.dst_port, [2, 3]);
4516*c3739801SMiguel Ojeda     /// assert_eq!(header.length, [4, 5]);
4517*c3739801SMiguel Ojeda     /// assert_eq!(header.checksum, [6, 7]);
4518*c3739801SMiguel Ojeda     /// assert_eq!(body, &[8, 9][..]);
4519*c3739801SMiguel Ojeda     ///
4520*c3739801SMiguel Ojeda     /// header.checksum = [0, 0];
4521*c3739801SMiguel Ojeda     /// body.fill(1);
4522*c3739801SMiguel Ojeda     ///
4523*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 0, 0, 1, 1]);
4524*c3739801SMiguel Ojeda     /// ```
4525*c3739801SMiguel Ojeda     ///
4526*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "mut_from_prefix")]
4527*c3739801SMiguel Ojeda     ///
4528*c3739801SMiguel Ojeda     /// See [`FromBytes::ref_from_prefix`](#method.ref_from_prefix.codegen).
4529*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4530*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4531*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4532*c3739801SMiguel Ojeda     fn mut_from_prefix(
4533*c3739801SMiguel Ojeda         source: &mut [u8],
4534*c3739801SMiguel Ojeda     ) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>
4535*c3739801SMiguel Ojeda     where
4536*c3739801SMiguel Ojeda         Self: IntoBytes + KnownLayout,
4537*c3739801SMiguel Ojeda     {
4538*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
4539*c3739801SMiguel Ojeda         mut_from_prefix_suffix(source, None, CastType::Prefix)
4540*c3739801SMiguel Ojeda     }
4541*c3739801SMiguel Ojeda 
4542*c3739801SMiguel Ojeda     /// Interprets the suffix of the given `source` as a `&mut Self` without
4543*c3739801SMiguel Ojeda     /// copying.
4544*c3739801SMiguel Ojeda     ///
4545*c3739801SMiguel Ojeda     /// This method computes the [largest possible size of `Self`][valid-size]
4546*c3739801SMiguel Ojeda     /// that can fit in the trailing bytes of `source`, then attempts to return
4547*c3739801SMiguel Ojeda     /// both a reference to those bytes interpreted as a `Self`, and a reference
4548*c3739801SMiguel Ojeda     /// to the preceding bytes. If there are insufficient bytes, or if that
4549*c3739801SMiguel Ojeda     /// suffix of `source` is not appropriately aligned, this returns `Err`. If
4550*c3739801SMiguel Ojeda     /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
4551*c3739801SMiguel Ojeda     /// alignment error][size-error-from].
4552*c3739801SMiguel Ojeda     ///
4553*c3739801SMiguel Ojeda     /// `Self` may be a sized type, a slice, or a [slice DST][slice-dst].
4554*c3739801SMiguel Ojeda     ///
4555*c3739801SMiguel Ojeda     /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
4556*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4557*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4558*c3739801SMiguel Ojeda     /// [slice-dst]: KnownLayout#dynamically-sized-types
4559*c3739801SMiguel Ojeda     ///
4560*c3739801SMiguel Ojeda     /// # Compile-Time Assertions
4561*c3739801SMiguel Ojeda     ///
4562*c3739801SMiguel Ojeda     /// This method cannot yet be used on unsized types whose dynamically-sized
4563*c3739801SMiguel Ojeda     /// component is zero-sized. Attempting to use this method on such types
4564*c3739801SMiguel Ojeda     /// results in a compile-time assertion error; e.g.:
4565*c3739801SMiguel Ojeda     ///
4566*c3739801SMiguel Ojeda     /// ```compile_fail,E0080
4567*c3739801SMiguel Ojeda     /// use zerocopy::*;
4568*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4569*c3739801SMiguel Ojeda     ///
4570*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, IntoBytes, KnownLayout)]
4571*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
4572*c3739801SMiguel Ojeda     /// struct ZSTy {
4573*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
4574*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4575*c3739801SMiguel Ojeda     /// }
4576*c3739801SMiguel Ojeda     ///
4577*c3739801SMiguel Ojeda     /// let mut source = [85, 85];
4578*c3739801SMiguel Ojeda     /// let _ = ZSTy::mut_from_suffix(&mut source[..]); // ⚠ Compile Error!
4579*c3739801SMiguel Ojeda     /// ```
4580*c3739801SMiguel Ojeda     ///
4581*c3739801SMiguel Ojeda     /// # Examples
4582*c3739801SMiguel Ojeda     ///
4583*c3739801SMiguel Ojeda     /// ```
4584*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4585*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4586*c3739801SMiguel Ojeda     ///
4587*c3739801SMiguel Ojeda     /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable)]
4588*c3739801SMiguel Ojeda     /// #[repr(C)]
4589*c3739801SMiguel Ojeda     /// struct PacketTrailer {
4590*c3739801SMiguel Ojeda     ///     frame_check_sequence: [u8; 4],
4591*c3739801SMiguel Ojeda     /// }
4592*c3739801SMiguel Ojeda     ///
4593*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `PacketTrailer`.
4594*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4595*c3739801SMiguel Ojeda     ///
4596*c3739801SMiguel Ojeda     /// let (prefix, trailer) = PacketTrailer::mut_from_suffix(bytes).unwrap();
4597*c3739801SMiguel Ojeda     ///
4598*c3739801SMiguel Ojeda     /// assert_eq!(prefix, &[0u8, 1, 2, 3, 4, 5][..]);
4599*c3739801SMiguel Ojeda     /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
4600*c3739801SMiguel Ojeda     ///
4601*c3739801SMiguel Ojeda     /// prefix.fill(0);
4602*c3739801SMiguel Ojeda     /// trailer.frame_check_sequence.fill(1);
4603*c3739801SMiguel Ojeda     ///
4604*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 0, 0, 0, 0, 0, 1, 1, 1, 1]);
4605*c3739801SMiguel Ojeda     /// ```
4606*c3739801SMiguel Ojeda     ///
4607*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "mut_from_suffix")]
4608*c3739801SMiguel Ojeda     ///
4609*c3739801SMiguel Ojeda     /// See [`FromBytes::ref_from_suffix`](#method.ref_from_suffix.codegen).
4610*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4611*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4612*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4613*c3739801SMiguel Ojeda     fn mut_from_suffix(
4614*c3739801SMiguel Ojeda         source: &mut [u8],
4615*c3739801SMiguel Ojeda     ) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>
4616*c3739801SMiguel Ojeda     where
4617*c3739801SMiguel Ojeda         Self: IntoBytes + KnownLayout,
4618*c3739801SMiguel Ojeda     {
4619*c3739801SMiguel Ojeda         static_assert_dst_is_not_zst!(Self);
4620*c3739801SMiguel Ojeda         mut_from_prefix_suffix(source, None, CastType::Suffix).map(swap)
4621*c3739801SMiguel Ojeda     }
4622*c3739801SMiguel Ojeda 
4623*c3739801SMiguel Ojeda     /// Interprets the given `source` as a `&Self` with a DST length equal to
4624*c3739801SMiguel Ojeda     /// `count`.
4625*c3739801SMiguel Ojeda     ///
4626*c3739801SMiguel Ojeda     /// This method attempts to return a reference to `source` interpreted as a
4627*c3739801SMiguel Ojeda     /// `Self` with `count` trailing elements. If the length of `source` is not
4628*c3739801SMiguel Ojeda     /// equal to the size of `Self` with `count` elements, or if `source` is not
4629*c3739801SMiguel Ojeda     /// appropriately aligned, this returns `Err`. If [`Self:
4630*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
4631*c3739801SMiguel Ojeda     /// error][size-error-from].
4632*c3739801SMiguel Ojeda     ///
4633*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4634*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4635*c3739801SMiguel Ojeda     ///
4636*c3739801SMiguel Ojeda     /// # Examples
4637*c3739801SMiguel Ojeda     ///
4638*c3739801SMiguel Ojeda     /// ```
4639*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4640*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4641*c3739801SMiguel Ojeda     ///
4642*c3739801SMiguel Ojeda     /// # #[derive(Debug, PartialEq, Eq)]
4643*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable)]
4644*c3739801SMiguel Ojeda     /// #[repr(C)]
4645*c3739801SMiguel Ojeda     /// struct Pixel {
4646*c3739801SMiguel Ojeda     ///     r: u8,
4647*c3739801SMiguel Ojeda     ///     g: u8,
4648*c3739801SMiguel Ojeda     ///     b: u8,
4649*c3739801SMiguel Ojeda     ///     a: u8,
4650*c3739801SMiguel Ojeda     /// }
4651*c3739801SMiguel Ojeda     ///
4652*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..];
4653*c3739801SMiguel Ojeda     ///
4654*c3739801SMiguel Ojeda     /// let pixels = <[Pixel]>::ref_from_bytes_with_elems(bytes, 2).unwrap();
4655*c3739801SMiguel Ojeda     ///
4656*c3739801SMiguel Ojeda     /// assert_eq!(pixels, &[
4657*c3739801SMiguel Ojeda     ///     Pixel { r: 0, g: 1, b: 2, a: 3 },
4658*c3739801SMiguel Ojeda     ///     Pixel { r: 4, g: 5, b: 6, a: 7 },
4659*c3739801SMiguel Ojeda     /// ]);
4660*c3739801SMiguel Ojeda     ///
4661*c3739801SMiguel Ojeda     /// ```
4662*c3739801SMiguel Ojeda     ///
4663*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
4664*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`ref_from_bytes`]
4665*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
4666*c3739801SMiguel Ojeda     ///
4667*c3739801SMiguel Ojeda     /// ```
4668*c3739801SMiguel Ojeda     /// use zerocopy::*;
4669*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4670*c3739801SMiguel Ojeda     ///
4671*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, KnownLayout)]
4672*c3739801SMiguel Ojeda     /// #[repr(C)]
4673*c3739801SMiguel Ojeda     /// struct ZSTy {
4674*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
4675*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4676*c3739801SMiguel Ojeda     /// }
4677*c3739801SMiguel Ojeda     ///
4678*c3739801SMiguel Ojeda     /// let src = &[85, 85][..];
4679*c3739801SMiguel Ojeda     /// let zsty = ZSTy::ref_from_bytes_with_elems(src, 42).unwrap();
4680*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
4681*c3739801SMiguel Ojeda     /// ```
4682*c3739801SMiguel Ojeda     ///
4683*c3739801SMiguel Ojeda     /// [`ref_from_bytes`]: FromBytes::ref_from_bytes
4684*c3739801SMiguel Ojeda     ///
4685*c3739801SMiguel Ojeda     #[doc = codegen_section!(
4686*c3739801SMiguel Ojeda         header = "h5",
4687*c3739801SMiguel Ojeda         bench = "ref_from_bytes_with_elems",
4688*c3739801SMiguel Ojeda         format = "coco",
4689*c3739801SMiguel Ojeda         arity = 2,
4690*c3739801SMiguel Ojeda         [
4691*c3739801SMiguel Ojeda             open
4692*c3739801SMiguel Ojeda             @index 1
4693*c3739801SMiguel Ojeda             @title "Unsized"
4694*c3739801SMiguel Ojeda             @variant "dynamic_size"
4695*c3739801SMiguel Ojeda         ],
4696*c3739801SMiguel Ojeda         [
4697*c3739801SMiguel Ojeda             @index 2
4698*c3739801SMiguel Ojeda             @title "Dynamically Padded"
4699*c3739801SMiguel Ojeda             @variant "dynamic_padding"
4700*c3739801SMiguel Ojeda         ]
4701*c3739801SMiguel Ojeda     )]
4702*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4703*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4704*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4705*c3739801SMiguel Ojeda     fn ref_from_bytes_with_elems(
4706*c3739801SMiguel Ojeda         source: &[u8],
4707*c3739801SMiguel Ojeda         count: usize,
4708*c3739801SMiguel Ojeda     ) -> Result<&Self, CastError<&[u8], Self>>
4709*c3739801SMiguel Ojeda     where
4710*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize> + Immutable,
4711*c3739801SMiguel Ojeda     {
4712*c3739801SMiguel Ojeda         let source = Ptr::from_ref(source);
4713*c3739801SMiguel Ojeda         let maybe_slf = source.try_cast_into_no_leftover::<_, BecauseImmutable>(Some(count));
4714*c3739801SMiguel Ojeda         match maybe_slf {
4715*c3739801SMiguel Ojeda             Ok(slf) => Ok(slf.recall_validity().as_ref()),
4716*c3739801SMiguel Ojeda             Err(err) => Err(err.map_src(|s| s.as_ref())),
4717*c3739801SMiguel Ojeda         }
4718*c3739801SMiguel Ojeda     }
4719*c3739801SMiguel Ojeda 
4720*c3739801SMiguel Ojeda     /// Interprets the prefix of the given `source` as a DST `&Self` with length
4721*c3739801SMiguel Ojeda     /// equal to `count`.
4722*c3739801SMiguel Ojeda     ///
4723*c3739801SMiguel Ojeda     /// This method attempts to return a reference to the prefix of `source`
4724*c3739801SMiguel Ojeda     /// interpreted as a `Self` with `count` trailing elements, and a reference
4725*c3739801SMiguel Ojeda     /// to the remaining bytes. If there are insufficient bytes, or if `source`
4726*c3739801SMiguel Ojeda     /// is not appropriately aligned, this returns `Err`. If [`Self:
4727*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
4728*c3739801SMiguel Ojeda     /// error][size-error-from].
4729*c3739801SMiguel Ojeda     ///
4730*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4731*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4732*c3739801SMiguel Ojeda     ///
4733*c3739801SMiguel Ojeda     /// # Examples
4734*c3739801SMiguel Ojeda     ///
4735*c3739801SMiguel Ojeda     /// ```
4736*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4737*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4738*c3739801SMiguel Ojeda     ///
4739*c3739801SMiguel Ojeda     /// # #[derive(Debug, PartialEq, Eq)]
4740*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable)]
4741*c3739801SMiguel Ojeda     /// #[repr(C)]
4742*c3739801SMiguel Ojeda     /// struct Pixel {
4743*c3739801SMiguel Ojeda     ///     r: u8,
4744*c3739801SMiguel Ojeda     ///     g: u8,
4745*c3739801SMiguel Ojeda     ///     b: u8,
4746*c3739801SMiguel Ojeda     ///     a: u8,
4747*c3739801SMiguel Ojeda     /// }
4748*c3739801SMiguel Ojeda     ///
4749*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode two `Pixel`s.
4750*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4751*c3739801SMiguel Ojeda     ///
4752*c3739801SMiguel Ojeda     /// let (pixels, suffix) = <[Pixel]>::ref_from_prefix_with_elems(bytes, 2).unwrap();
4753*c3739801SMiguel Ojeda     ///
4754*c3739801SMiguel Ojeda     /// assert_eq!(pixels, &[
4755*c3739801SMiguel Ojeda     ///     Pixel { r: 0, g: 1, b: 2, a: 3 },
4756*c3739801SMiguel Ojeda     ///     Pixel { r: 4, g: 5, b: 6, a: 7 },
4757*c3739801SMiguel Ojeda     /// ]);
4758*c3739801SMiguel Ojeda     ///
4759*c3739801SMiguel Ojeda     /// assert_eq!(suffix, &[8, 9]);
4760*c3739801SMiguel Ojeda     /// ```
4761*c3739801SMiguel Ojeda     ///
4762*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
4763*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`ref_from_prefix`]
4764*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
4765*c3739801SMiguel Ojeda     ///
4766*c3739801SMiguel Ojeda     /// ```
4767*c3739801SMiguel Ojeda     /// use zerocopy::*;
4768*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4769*c3739801SMiguel Ojeda     ///
4770*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, KnownLayout)]
4771*c3739801SMiguel Ojeda     /// #[repr(C)]
4772*c3739801SMiguel Ojeda     /// struct ZSTy {
4773*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
4774*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4775*c3739801SMiguel Ojeda     /// }
4776*c3739801SMiguel Ojeda     ///
4777*c3739801SMiguel Ojeda     /// let src = &[85, 85][..];
4778*c3739801SMiguel Ojeda     /// let (zsty, _) = ZSTy::ref_from_prefix_with_elems(src, 42).unwrap();
4779*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
4780*c3739801SMiguel Ojeda     /// ```
4781*c3739801SMiguel Ojeda     ///
4782*c3739801SMiguel Ojeda     /// [`ref_from_prefix`]: FromBytes::ref_from_prefix
4783*c3739801SMiguel Ojeda     ///
4784*c3739801SMiguel Ojeda     #[doc = codegen_section!(
4785*c3739801SMiguel Ojeda         header = "h5",
4786*c3739801SMiguel Ojeda         bench = "ref_from_prefix_with_elems",
4787*c3739801SMiguel Ojeda         format = "coco",
4788*c3739801SMiguel Ojeda         arity = 2,
4789*c3739801SMiguel Ojeda         [
4790*c3739801SMiguel Ojeda             open
4791*c3739801SMiguel Ojeda             @index 1
4792*c3739801SMiguel Ojeda             @title "Unsized"
4793*c3739801SMiguel Ojeda             @variant "dynamic_size"
4794*c3739801SMiguel Ojeda         ],
4795*c3739801SMiguel Ojeda         [
4796*c3739801SMiguel Ojeda             @index 2
4797*c3739801SMiguel Ojeda             @title "Dynamically Padded"
4798*c3739801SMiguel Ojeda             @variant "dynamic_padding"
4799*c3739801SMiguel Ojeda         ]
4800*c3739801SMiguel Ojeda     )]
4801*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4802*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4803*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4804*c3739801SMiguel Ojeda     fn ref_from_prefix_with_elems(
4805*c3739801SMiguel Ojeda         source: &[u8],
4806*c3739801SMiguel Ojeda         count: usize,
4807*c3739801SMiguel Ojeda     ) -> Result<(&Self, &[u8]), CastError<&[u8], Self>>
4808*c3739801SMiguel Ojeda     where
4809*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize> + Immutable,
4810*c3739801SMiguel Ojeda     {
4811*c3739801SMiguel Ojeda         ref_from_prefix_suffix(source, Some(count), CastType::Prefix)
4812*c3739801SMiguel Ojeda     }
4813*c3739801SMiguel Ojeda 
4814*c3739801SMiguel Ojeda     /// Interprets the suffix of the given `source` as a DST `&Self` with length
4815*c3739801SMiguel Ojeda     /// equal to `count`.
4816*c3739801SMiguel Ojeda     ///
4817*c3739801SMiguel Ojeda     /// This method attempts to return a reference to the suffix of `source`
4818*c3739801SMiguel Ojeda     /// interpreted as a `Self` with `count` trailing elements, and a reference
4819*c3739801SMiguel Ojeda     /// to the preceding bytes. If there are insufficient bytes, or if that
4820*c3739801SMiguel Ojeda     /// suffix of `source` is not appropriately aligned, this returns `Err`. If
4821*c3739801SMiguel Ojeda     /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
4822*c3739801SMiguel Ojeda     /// alignment error][size-error-from].
4823*c3739801SMiguel Ojeda     ///
4824*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4825*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4826*c3739801SMiguel Ojeda     ///
4827*c3739801SMiguel Ojeda     /// # Examples
4828*c3739801SMiguel Ojeda     ///
4829*c3739801SMiguel Ojeda     /// ```
4830*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4831*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4832*c3739801SMiguel Ojeda     ///
4833*c3739801SMiguel Ojeda     /// # #[derive(Debug, PartialEq, Eq)]
4834*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable)]
4835*c3739801SMiguel Ojeda     /// #[repr(C)]
4836*c3739801SMiguel Ojeda     /// struct Pixel {
4837*c3739801SMiguel Ojeda     ///     r: u8,
4838*c3739801SMiguel Ojeda     ///     g: u8,
4839*c3739801SMiguel Ojeda     ///     b: u8,
4840*c3739801SMiguel Ojeda     ///     a: u8,
4841*c3739801SMiguel Ojeda     /// }
4842*c3739801SMiguel Ojeda     ///
4843*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode two `Pixel`s.
4844*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
4845*c3739801SMiguel Ojeda     ///
4846*c3739801SMiguel Ojeda     /// let (prefix, pixels) = <[Pixel]>::ref_from_suffix_with_elems(bytes, 2).unwrap();
4847*c3739801SMiguel Ojeda     ///
4848*c3739801SMiguel Ojeda     /// assert_eq!(prefix, &[0, 1]);
4849*c3739801SMiguel Ojeda     ///
4850*c3739801SMiguel Ojeda     /// assert_eq!(pixels, &[
4851*c3739801SMiguel Ojeda     ///     Pixel { r: 2, g: 3, b: 4, a: 5 },
4852*c3739801SMiguel Ojeda     ///     Pixel { r: 6, g: 7, b: 8, a: 9 },
4853*c3739801SMiguel Ojeda     /// ]);
4854*c3739801SMiguel Ojeda     /// ```
4855*c3739801SMiguel Ojeda     ///
4856*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
4857*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`ref_from_suffix`]
4858*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
4859*c3739801SMiguel Ojeda     ///
4860*c3739801SMiguel Ojeda     /// ```
4861*c3739801SMiguel Ojeda     /// use zerocopy::*;
4862*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4863*c3739801SMiguel Ojeda     ///
4864*c3739801SMiguel Ojeda     /// #[derive(FromBytes, Immutable, KnownLayout)]
4865*c3739801SMiguel Ojeda     /// #[repr(C)]
4866*c3739801SMiguel Ojeda     /// struct ZSTy {
4867*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
4868*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4869*c3739801SMiguel Ojeda     /// }
4870*c3739801SMiguel Ojeda     ///
4871*c3739801SMiguel Ojeda     /// let src = &[85, 85][..];
4872*c3739801SMiguel Ojeda     /// let (_, zsty) = ZSTy::ref_from_suffix_with_elems(src, 42).unwrap();
4873*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
4874*c3739801SMiguel Ojeda     /// ```
4875*c3739801SMiguel Ojeda     ///
4876*c3739801SMiguel Ojeda     /// [`ref_from_suffix`]: FromBytes::ref_from_suffix
4877*c3739801SMiguel Ojeda     ///
4878*c3739801SMiguel Ojeda     #[doc = codegen_section!(
4879*c3739801SMiguel Ojeda         header = "h5",
4880*c3739801SMiguel Ojeda         bench = "ref_from_suffix_with_elems",
4881*c3739801SMiguel Ojeda         format = "coco",
4882*c3739801SMiguel Ojeda         arity = 2,
4883*c3739801SMiguel Ojeda         [
4884*c3739801SMiguel Ojeda             open
4885*c3739801SMiguel Ojeda             @index 1
4886*c3739801SMiguel Ojeda             @title "Unsized"
4887*c3739801SMiguel Ojeda             @variant "dynamic_size"
4888*c3739801SMiguel Ojeda         ],
4889*c3739801SMiguel Ojeda         [
4890*c3739801SMiguel Ojeda             @index 2
4891*c3739801SMiguel Ojeda             @title "Dynamically Padded"
4892*c3739801SMiguel Ojeda             @variant "dynamic_padding"
4893*c3739801SMiguel Ojeda         ]
4894*c3739801SMiguel Ojeda     )]
4895*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4896*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4897*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4898*c3739801SMiguel Ojeda     fn ref_from_suffix_with_elems(
4899*c3739801SMiguel Ojeda         source: &[u8],
4900*c3739801SMiguel Ojeda         count: usize,
4901*c3739801SMiguel Ojeda     ) -> Result<(&[u8], &Self), CastError<&[u8], Self>>
4902*c3739801SMiguel Ojeda     where
4903*c3739801SMiguel Ojeda         Self: KnownLayout<PointerMetadata = usize> + Immutable,
4904*c3739801SMiguel Ojeda     {
4905*c3739801SMiguel Ojeda         ref_from_prefix_suffix(source, Some(count), CastType::Suffix).map(swap)
4906*c3739801SMiguel Ojeda     }
4907*c3739801SMiguel Ojeda 
4908*c3739801SMiguel Ojeda     /// Interprets the given `source` as a `&mut Self` with a DST length equal
4909*c3739801SMiguel Ojeda     /// to `count`.
4910*c3739801SMiguel Ojeda     ///
4911*c3739801SMiguel Ojeda     /// This method attempts to return a reference to `source` interpreted as a
4912*c3739801SMiguel Ojeda     /// `Self` with `count` trailing elements. If the length of `source` is not
4913*c3739801SMiguel Ojeda     /// equal to the size of `Self` with `count` elements, or if `source` is not
4914*c3739801SMiguel Ojeda     /// appropriately aligned, this returns `Err`. If [`Self:
4915*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
4916*c3739801SMiguel Ojeda     /// error][size-error-from].
4917*c3739801SMiguel Ojeda     ///
4918*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
4919*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
4920*c3739801SMiguel Ojeda     ///
4921*c3739801SMiguel Ojeda     /// # Examples
4922*c3739801SMiguel Ojeda     ///
4923*c3739801SMiguel Ojeda     /// ```
4924*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
4925*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4926*c3739801SMiguel Ojeda     ///
4927*c3739801SMiguel Ojeda     /// # #[derive(Debug, PartialEq, Eq)]
4928*c3739801SMiguel Ojeda     /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
4929*c3739801SMiguel Ojeda     /// #[repr(C)]
4930*c3739801SMiguel Ojeda     /// struct Pixel {
4931*c3739801SMiguel Ojeda     ///     r: u8,
4932*c3739801SMiguel Ojeda     ///     g: u8,
4933*c3739801SMiguel Ojeda     ///     b: u8,
4934*c3739801SMiguel Ojeda     ///     a: u8,
4935*c3739801SMiguel Ojeda     /// }
4936*c3739801SMiguel Ojeda     ///
4937*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7][..];
4938*c3739801SMiguel Ojeda     ///
4939*c3739801SMiguel Ojeda     /// let pixels = <[Pixel]>::mut_from_bytes_with_elems(bytes, 2).unwrap();
4940*c3739801SMiguel Ojeda     ///
4941*c3739801SMiguel Ojeda     /// assert_eq!(pixels, &[
4942*c3739801SMiguel Ojeda     ///     Pixel { r: 0, g: 1, b: 2, a: 3 },
4943*c3739801SMiguel Ojeda     ///     Pixel { r: 4, g: 5, b: 6, a: 7 },
4944*c3739801SMiguel Ojeda     /// ]);
4945*c3739801SMiguel Ojeda     ///
4946*c3739801SMiguel Ojeda     /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
4947*c3739801SMiguel Ojeda     ///
4948*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0]);
4949*c3739801SMiguel Ojeda     /// ```
4950*c3739801SMiguel Ojeda     ///
4951*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
4952*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`mut_from_bytes`]
4953*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
4954*c3739801SMiguel Ojeda     ///
4955*c3739801SMiguel Ojeda     /// ```
4956*c3739801SMiguel Ojeda     /// use zerocopy::*;
4957*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
4958*c3739801SMiguel Ojeda     ///
4959*c3739801SMiguel Ojeda     /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
4960*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
4961*c3739801SMiguel Ojeda     /// struct ZSTy {
4962*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
4963*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
4964*c3739801SMiguel Ojeda     /// }
4965*c3739801SMiguel Ojeda     ///
4966*c3739801SMiguel Ojeda     /// let src = &mut [85, 85][..];
4967*c3739801SMiguel Ojeda     /// let zsty = ZSTy::mut_from_bytes_with_elems(src, 42).unwrap();
4968*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
4969*c3739801SMiguel Ojeda     /// ```
4970*c3739801SMiguel Ojeda     ///
4971*c3739801SMiguel Ojeda     /// [`mut_from_bytes`]: FromBytes::mut_from_bytes
4972*c3739801SMiguel Ojeda     ///
4973*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "mut_from_bytes_with_elems")]
4974*c3739801SMiguel Ojeda     ///
4975*c3739801SMiguel Ojeda     /// See [`TryFromBytes::ref_from_bytes_with_elems`](#method.ref_from_bytes_with_elems.codegen).
4976*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
4977*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
4978*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
4979*c3739801SMiguel Ojeda     fn mut_from_bytes_with_elems(
4980*c3739801SMiguel Ojeda         source: &mut [u8],
4981*c3739801SMiguel Ojeda         count: usize,
4982*c3739801SMiguel Ojeda     ) -> Result<&mut Self, CastError<&mut [u8], Self>>
4983*c3739801SMiguel Ojeda     where
4984*c3739801SMiguel Ojeda         Self: IntoBytes + KnownLayout<PointerMetadata = usize> + Immutable,
4985*c3739801SMiguel Ojeda     {
4986*c3739801SMiguel Ojeda         let source = Ptr::from_mut(source);
4987*c3739801SMiguel Ojeda         let maybe_slf = source.try_cast_into_no_leftover::<_, BecauseImmutable>(Some(count));
4988*c3739801SMiguel Ojeda         match maybe_slf {
4989*c3739801SMiguel Ojeda             Ok(slf) => Ok(slf.recall_validity::<_, (_, (_, BecauseExclusive))>().as_mut()),
4990*c3739801SMiguel Ojeda             Err(err) => Err(err.map_src(|s| s.as_mut())),
4991*c3739801SMiguel Ojeda         }
4992*c3739801SMiguel Ojeda     }
4993*c3739801SMiguel Ojeda 
4994*c3739801SMiguel Ojeda     /// Interprets the prefix of the given `source` as a `&mut Self` with DST
4995*c3739801SMiguel Ojeda     /// length equal to `count`.
4996*c3739801SMiguel Ojeda     ///
4997*c3739801SMiguel Ojeda     /// This method attempts to return a reference to the prefix of `source`
4998*c3739801SMiguel Ojeda     /// interpreted as a `Self` with `count` trailing elements, and a reference
4999*c3739801SMiguel Ojeda     /// to the preceding bytes. If there are insufficient bytes, or if `source`
5000*c3739801SMiguel Ojeda     /// is not appropriately aligned, this returns `Err`. If [`Self:
5001*c3739801SMiguel Ojeda     /// Unaligned`][self-unaligned], you can [infallibly discard the alignment
5002*c3739801SMiguel Ojeda     /// error][size-error-from].
5003*c3739801SMiguel Ojeda     ///
5004*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
5005*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
5006*c3739801SMiguel Ojeda     ///
5007*c3739801SMiguel Ojeda     /// # Examples
5008*c3739801SMiguel Ojeda     ///
5009*c3739801SMiguel Ojeda     /// ```
5010*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
5011*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5012*c3739801SMiguel Ojeda     ///
5013*c3739801SMiguel Ojeda     /// # #[derive(Debug, PartialEq, Eq)]
5014*c3739801SMiguel Ojeda     /// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
5015*c3739801SMiguel Ojeda     /// #[repr(C)]
5016*c3739801SMiguel Ojeda     /// struct Pixel {
5017*c3739801SMiguel Ojeda     ///     r: u8,
5018*c3739801SMiguel Ojeda     ///     g: u8,
5019*c3739801SMiguel Ojeda     ///     b: u8,
5020*c3739801SMiguel Ojeda     ///     a: u8,
5021*c3739801SMiguel Ojeda     /// }
5022*c3739801SMiguel Ojeda     ///
5023*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode two `Pixel`s.
5024*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
5025*c3739801SMiguel Ojeda     ///
5026*c3739801SMiguel Ojeda     /// let (pixels, suffix) = <[Pixel]>::mut_from_prefix_with_elems(bytes, 2).unwrap();
5027*c3739801SMiguel Ojeda     ///
5028*c3739801SMiguel Ojeda     /// assert_eq!(pixels, &[
5029*c3739801SMiguel Ojeda     ///     Pixel { r: 0, g: 1, b: 2, a: 3 },
5030*c3739801SMiguel Ojeda     ///     Pixel { r: 4, g: 5, b: 6, a: 7 },
5031*c3739801SMiguel Ojeda     /// ]);
5032*c3739801SMiguel Ojeda     ///
5033*c3739801SMiguel Ojeda     /// assert_eq!(suffix, &[8, 9]);
5034*c3739801SMiguel Ojeda     ///
5035*c3739801SMiguel Ojeda     /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
5036*c3739801SMiguel Ojeda     /// suffix.fill(1);
5037*c3739801SMiguel Ojeda     ///
5038*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 1, 2, 3, 0, 0, 0, 0, 1, 1]);
5039*c3739801SMiguel Ojeda     /// ```
5040*c3739801SMiguel Ojeda     ///
5041*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
5042*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`mut_from_prefix`]
5043*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
5044*c3739801SMiguel Ojeda     ///
5045*c3739801SMiguel Ojeda     /// ```
5046*c3739801SMiguel Ojeda     /// use zerocopy::*;
5047*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5048*c3739801SMiguel Ojeda     ///
5049*c3739801SMiguel Ojeda     /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
5050*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
5051*c3739801SMiguel Ojeda     /// struct ZSTy {
5052*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
5053*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
5054*c3739801SMiguel Ojeda     /// }
5055*c3739801SMiguel Ojeda     ///
5056*c3739801SMiguel Ojeda     /// let src = &mut [85, 85][..];
5057*c3739801SMiguel Ojeda     /// let (zsty, _) = ZSTy::mut_from_prefix_with_elems(src, 42).unwrap();
5058*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
5059*c3739801SMiguel Ojeda     /// ```
5060*c3739801SMiguel Ojeda     ///
5061*c3739801SMiguel Ojeda     /// [`mut_from_prefix`]: FromBytes::mut_from_prefix
5062*c3739801SMiguel Ojeda     ///
5063*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "mut_from_prefix_with_elems")]
5064*c3739801SMiguel Ojeda     ///
5065*c3739801SMiguel Ojeda     /// See [`TryFromBytes::ref_from_prefix_with_elems`](#method.ref_from_prefix_with_elems.codegen).
5066*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5067*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
5068*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
5069*c3739801SMiguel Ojeda     fn mut_from_prefix_with_elems(
5070*c3739801SMiguel Ojeda         source: &mut [u8],
5071*c3739801SMiguel Ojeda         count: usize,
5072*c3739801SMiguel Ojeda     ) -> Result<(&mut Self, &mut [u8]), CastError<&mut [u8], Self>>
5073*c3739801SMiguel Ojeda     where
5074*c3739801SMiguel Ojeda         Self: IntoBytes + KnownLayout<PointerMetadata = usize>,
5075*c3739801SMiguel Ojeda     {
5076*c3739801SMiguel Ojeda         mut_from_prefix_suffix(source, Some(count), CastType::Prefix)
5077*c3739801SMiguel Ojeda     }
5078*c3739801SMiguel Ojeda 
5079*c3739801SMiguel Ojeda     /// Interprets the suffix of the given `source` as a `&mut Self` with DST
5080*c3739801SMiguel Ojeda     /// length equal to `count`.
5081*c3739801SMiguel Ojeda     ///
5082*c3739801SMiguel Ojeda     /// This method attempts to return a reference to the suffix of `source`
5083*c3739801SMiguel Ojeda     /// interpreted as a `Self` with `count` trailing elements, and a reference
5084*c3739801SMiguel Ojeda     /// to the remaining bytes. If there are insufficient bytes, or if that
5085*c3739801SMiguel Ojeda     /// suffix of `source` is not appropriately aligned, this returns `Err`. If
5086*c3739801SMiguel Ojeda     /// [`Self: Unaligned`][self-unaligned], you can [infallibly discard the
5087*c3739801SMiguel Ojeda     /// alignment error][size-error-from].
5088*c3739801SMiguel Ojeda     ///
5089*c3739801SMiguel Ojeda     /// [self-unaligned]: Unaligned
5090*c3739801SMiguel Ojeda     /// [size-error-from]: error/struct.SizeError.html#method.from-1
5091*c3739801SMiguel Ojeda     ///
5092*c3739801SMiguel Ojeda     /// # Examples
5093*c3739801SMiguel Ojeda     ///
5094*c3739801SMiguel Ojeda     /// ```
5095*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
5096*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5097*c3739801SMiguel Ojeda     ///
5098*c3739801SMiguel Ojeda     /// # #[derive(Debug, PartialEq, Eq)]
5099*c3739801SMiguel Ojeda     /// #[derive(FromBytes, IntoBytes, Immutable)]
5100*c3739801SMiguel Ojeda     /// #[repr(C)]
5101*c3739801SMiguel Ojeda     /// struct Pixel {
5102*c3739801SMiguel Ojeda     ///     r: u8,
5103*c3739801SMiguel Ojeda     ///     g: u8,
5104*c3739801SMiguel Ojeda     ///     b: u8,
5105*c3739801SMiguel Ojeda     ///     a: u8,
5106*c3739801SMiguel Ojeda     /// }
5107*c3739801SMiguel Ojeda     ///
5108*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode two `Pixel`s.
5109*c3739801SMiguel Ojeda     /// let bytes = &mut [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
5110*c3739801SMiguel Ojeda     ///
5111*c3739801SMiguel Ojeda     /// let (prefix, pixels) = <[Pixel]>::mut_from_suffix_with_elems(bytes, 2).unwrap();
5112*c3739801SMiguel Ojeda     ///
5113*c3739801SMiguel Ojeda     /// assert_eq!(prefix, &[0, 1]);
5114*c3739801SMiguel Ojeda     ///
5115*c3739801SMiguel Ojeda     /// assert_eq!(pixels, &[
5116*c3739801SMiguel Ojeda     ///     Pixel { r: 2, g: 3, b: 4, a: 5 },
5117*c3739801SMiguel Ojeda     ///     Pixel { r: 6, g: 7, b: 8, a: 9 },
5118*c3739801SMiguel Ojeda     /// ]);
5119*c3739801SMiguel Ojeda     ///
5120*c3739801SMiguel Ojeda     /// prefix.fill(9);
5121*c3739801SMiguel Ojeda     /// pixels[1] = Pixel { r: 0, g: 0, b: 0, a: 0 };
5122*c3739801SMiguel Ojeda     ///
5123*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [9, 9, 2, 3, 4, 5, 0, 0, 0, 0]);
5124*c3739801SMiguel Ojeda     /// ```
5125*c3739801SMiguel Ojeda     ///
5126*c3739801SMiguel Ojeda     /// Since an explicit `count` is provided, this method supports types with
5127*c3739801SMiguel Ojeda     /// zero-sized trailing slice elements. Methods such as [`mut_from_suffix`]
5128*c3739801SMiguel Ojeda     /// which do not take an explicit count do not support such types.
5129*c3739801SMiguel Ojeda     ///
5130*c3739801SMiguel Ojeda     /// ```
5131*c3739801SMiguel Ojeda     /// use zerocopy::*;
5132*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5133*c3739801SMiguel Ojeda     ///
5134*c3739801SMiguel Ojeda     /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
5135*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
5136*c3739801SMiguel Ojeda     /// struct ZSTy {
5137*c3739801SMiguel Ojeda     ///     leading_sized: [u8; 2],
5138*c3739801SMiguel Ojeda     ///     trailing_dst: [()],
5139*c3739801SMiguel Ojeda     /// }
5140*c3739801SMiguel Ojeda     ///
5141*c3739801SMiguel Ojeda     /// let src = &mut [85, 85][..];
5142*c3739801SMiguel Ojeda     /// let (_, zsty) = ZSTy::mut_from_suffix_with_elems(src, 42).unwrap();
5143*c3739801SMiguel Ojeda     /// assert_eq!(zsty.trailing_dst.len(), 42);
5144*c3739801SMiguel Ojeda     /// ```
5145*c3739801SMiguel Ojeda     ///
5146*c3739801SMiguel Ojeda     /// [`mut_from_suffix`]: FromBytes::mut_from_suffix
5147*c3739801SMiguel Ojeda     ///
5148*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "mut_from_suffix_with_elems")]
5149*c3739801SMiguel Ojeda     ///
5150*c3739801SMiguel Ojeda     /// See [`TryFromBytes::ref_from_suffix_with_elems`](#method.ref_from_suffix_with_elems.codegen).
5151*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5152*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
5153*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
5154*c3739801SMiguel Ojeda     fn mut_from_suffix_with_elems(
5155*c3739801SMiguel Ojeda         source: &mut [u8],
5156*c3739801SMiguel Ojeda         count: usize,
5157*c3739801SMiguel Ojeda     ) -> Result<(&mut [u8], &mut Self), CastError<&mut [u8], Self>>
5158*c3739801SMiguel Ojeda     where
5159*c3739801SMiguel Ojeda         Self: IntoBytes + KnownLayout<PointerMetadata = usize>,
5160*c3739801SMiguel Ojeda     {
5161*c3739801SMiguel Ojeda         mut_from_prefix_suffix(source, Some(count), CastType::Suffix).map(swap)
5162*c3739801SMiguel Ojeda     }
5163*c3739801SMiguel Ojeda 
5164*c3739801SMiguel Ojeda     /// Reads a copy of `Self` from the given `source`.
5165*c3739801SMiguel Ojeda     ///
5166*c3739801SMiguel Ojeda     /// If `source.len() != size_of::<Self>()`, `read_from_bytes` returns `Err`.
5167*c3739801SMiguel Ojeda     ///
5168*c3739801SMiguel Ojeda     /// # Examples
5169*c3739801SMiguel Ojeda     ///
5170*c3739801SMiguel Ojeda     /// ```
5171*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
5172*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5173*c3739801SMiguel Ojeda     ///
5174*c3739801SMiguel Ojeda     /// #[derive(FromBytes)]
5175*c3739801SMiguel Ojeda     /// #[repr(C)]
5176*c3739801SMiguel Ojeda     /// struct PacketHeader {
5177*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
5178*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
5179*c3739801SMiguel Ojeda     ///     length: [u8; 2],
5180*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
5181*c3739801SMiguel Ojeda     /// }
5182*c3739801SMiguel Ojeda     ///
5183*c3739801SMiguel Ojeda     /// // These bytes encode a `PacketHeader`.
5184*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..];
5185*c3739801SMiguel Ojeda     ///
5186*c3739801SMiguel Ojeda     /// let header = PacketHeader::read_from_bytes(bytes).unwrap();
5187*c3739801SMiguel Ojeda     ///
5188*c3739801SMiguel Ojeda     /// assert_eq!(header.src_port, [0, 1]);
5189*c3739801SMiguel Ojeda     /// assert_eq!(header.dst_port, [2, 3]);
5190*c3739801SMiguel Ojeda     /// assert_eq!(header.length, [4, 5]);
5191*c3739801SMiguel Ojeda     /// assert_eq!(header.checksum, [6, 7]);
5192*c3739801SMiguel Ojeda     /// ```
5193*c3739801SMiguel Ojeda     ///
5194*c3739801SMiguel Ojeda     #[doc = codegen_section!(
5195*c3739801SMiguel Ojeda         header = "h5",
5196*c3739801SMiguel Ojeda         bench = "read_from_bytes",
5197*c3739801SMiguel Ojeda         format = "coco_static_size",
5198*c3739801SMiguel Ojeda     )]
5199*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5200*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
5201*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
5202*c3739801SMiguel Ojeda     fn read_from_bytes(source: &[u8]) -> Result<Self, SizeError<&[u8], Self>>
5203*c3739801SMiguel Ojeda     where
5204*c3739801SMiguel Ojeda         Self: Sized,
5205*c3739801SMiguel Ojeda     {
5206*c3739801SMiguel Ojeda         match Ref::<_, Unalign<Self>>::sized_from(source) {
5207*c3739801SMiguel Ojeda             Ok(r) => Ok(Ref::read(&r).into_inner()),
5208*c3739801SMiguel Ojeda             Err(CastError::Size(e)) => Err(e.with_dst()),
5209*c3739801SMiguel Ojeda             Err(CastError::Alignment(_)) => {
5210*c3739801SMiguel Ojeda                 // SAFETY: `Unalign<Self>` is trivially aligned, so
5211*c3739801SMiguel Ojeda                 // `Ref::sized_from` cannot fail due to unmet alignment
5212*c3739801SMiguel Ojeda                 // requirements.
5213*c3739801SMiguel Ojeda                 unsafe { core::hint::unreachable_unchecked() }
5214*c3739801SMiguel Ojeda             }
5215*c3739801SMiguel Ojeda             Err(CastError::Validity(i)) => match i {},
5216*c3739801SMiguel Ojeda         }
5217*c3739801SMiguel Ojeda     }
5218*c3739801SMiguel Ojeda 
5219*c3739801SMiguel Ojeda     /// Reads a copy of `Self` from the prefix of the given `source`.
5220*c3739801SMiguel Ojeda     ///
5221*c3739801SMiguel Ojeda     /// This attempts to read a `Self` from the first `size_of::<Self>()` bytes
5222*c3739801SMiguel Ojeda     /// of `source`, returning that `Self` and any remaining bytes. If
5223*c3739801SMiguel Ojeda     /// `source.len() < size_of::<Self>()`, it returns `Err`.
5224*c3739801SMiguel Ojeda     ///
5225*c3739801SMiguel Ojeda     /// # Examples
5226*c3739801SMiguel Ojeda     ///
5227*c3739801SMiguel Ojeda     /// ```
5228*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
5229*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5230*c3739801SMiguel Ojeda     ///
5231*c3739801SMiguel Ojeda     /// #[derive(FromBytes)]
5232*c3739801SMiguel Ojeda     /// #[repr(C)]
5233*c3739801SMiguel Ojeda     /// struct PacketHeader {
5234*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
5235*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
5236*c3739801SMiguel Ojeda     ///     length: [u8; 2],
5237*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
5238*c3739801SMiguel Ojeda     /// }
5239*c3739801SMiguel Ojeda     ///
5240*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `PacketHeader`.
5241*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
5242*c3739801SMiguel Ojeda     ///
5243*c3739801SMiguel Ojeda     /// let (header, body) = PacketHeader::read_from_prefix(bytes).unwrap();
5244*c3739801SMiguel Ojeda     ///
5245*c3739801SMiguel Ojeda     /// assert_eq!(header.src_port, [0, 1]);
5246*c3739801SMiguel Ojeda     /// assert_eq!(header.dst_port, [2, 3]);
5247*c3739801SMiguel Ojeda     /// assert_eq!(header.length, [4, 5]);
5248*c3739801SMiguel Ojeda     /// assert_eq!(header.checksum, [6, 7]);
5249*c3739801SMiguel Ojeda     /// assert_eq!(body, [8, 9]);
5250*c3739801SMiguel Ojeda     /// ```
5251*c3739801SMiguel Ojeda     ///
5252*c3739801SMiguel Ojeda     #[doc = codegen_section!(
5253*c3739801SMiguel Ojeda         header = "h5",
5254*c3739801SMiguel Ojeda         bench = "read_from_prefix",
5255*c3739801SMiguel Ojeda         format = "coco_static_size",
5256*c3739801SMiguel Ojeda     )]
5257*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5258*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
5259*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
5260*c3739801SMiguel Ojeda     fn read_from_prefix(source: &[u8]) -> Result<(Self, &[u8]), SizeError<&[u8], Self>>
5261*c3739801SMiguel Ojeda     where
5262*c3739801SMiguel Ojeda         Self: Sized,
5263*c3739801SMiguel Ojeda     {
5264*c3739801SMiguel Ojeda         match Ref::<_, Unalign<Self>>::sized_from_prefix(source) {
5265*c3739801SMiguel Ojeda             Ok((r, suffix)) => Ok((Ref::read(&r).into_inner(), suffix)),
5266*c3739801SMiguel Ojeda             Err(CastError::Size(e)) => Err(e.with_dst()),
5267*c3739801SMiguel Ojeda             Err(CastError::Alignment(_)) => {
5268*c3739801SMiguel Ojeda                 // SAFETY: `Unalign<Self>` is trivially aligned, so
5269*c3739801SMiguel Ojeda                 // `Ref::sized_from_prefix` cannot fail due to unmet alignment
5270*c3739801SMiguel Ojeda                 // requirements.
5271*c3739801SMiguel Ojeda                 unsafe { core::hint::unreachable_unchecked() }
5272*c3739801SMiguel Ojeda             }
5273*c3739801SMiguel Ojeda             Err(CastError::Validity(i)) => match i {},
5274*c3739801SMiguel Ojeda         }
5275*c3739801SMiguel Ojeda     }
5276*c3739801SMiguel Ojeda 
5277*c3739801SMiguel Ojeda     /// Reads a copy of `Self` from the suffix of the given `source`.
5278*c3739801SMiguel Ojeda     ///
5279*c3739801SMiguel Ojeda     /// This attempts to read a `Self` from the last `size_of::<Self>()` bytes
5280*c3739801SMiguel Ojeda     /// of `source`, returning that `Self` and any preceding bytes. If
5281*c3739801SMiguel Ojeda     /// `source.len() < size_of::<Self>()`, it returns `Err`.
5282*c3739801SMiguel Ojeda     ///
5283*c3739801SMiguel Ojeda     /// # Examples
5284*c3739801SMiguel Ojeda     ///
5285*c3739801SMiguel Ojeda     /// ```
5286*c3739801SMiguel Ojeda     /// use zerocopy::FromBytes;
5287*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5288*c3739801SMiguel Ojeda     ///
5289*c3739801SMiguel Ojeda     /// #[derive(FromBytes)]
5290*c3739801SMiguel Ojeda     /// #[repr(C)]
5291*c3739801SMiguel Ojeda     /// struct PacketTrailer {
5292*c3739801SMiguel Ojeda     ///     frame_check_sequence: [u8; 4],
5293*c3739801SMiguel Ojeda     /// }
5294*c3739801SMiguel Ojeda     ///
5295*c3739801SMiguel Ojeda     /// // These are more bytes than are needed to encode a `PacketTrailer`.
5296*c3739801SMiguel Ojeda     /// let bytes = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][..];
5297*c3739801SMiguel Ojeda     ///
5298*c3739801SMiguel Ojeda     /// let (prefix, trailer) = PacketTrailer::read_from_suffix(bytes).unwrap();
5299*c3739801SMiguel Ojeda     ///
5300*c3739801SMiguel Ojeda     /// assert_eq!(prefix, [0, 1, 2, 3, 4, 5]);
5301*c3739801SMiguel Ojeda     /// assert_eq!(trailer.frame_check_sequence, [6, 7, 8, 9]);
5302*c3739801SMiguel Ojeda     /// ```
5303*c3739801SMiguel Ojeda     ///
5304*c3739801SMiguel Ojeda     #[doc = codegen_section!(
5305*c3739801SMiguel Ojeda         header = "h5",
5306*c3739801SMiguel Ojeda         bench = "read_from_suffix",
5307*c3739801SMiguel Ojeda         format = "coco_static_size",
5308*c3739801SMiguel Ojeda     )]
5309*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5310*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
5311*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
5312*c3739801SMiguel Ojeda     fn read_from_suffix(source: &[u8]) -> Result<(&[u8], Self), SizeError<&[u8], Self>>
5313*c3739801SMiguel Ojeda     where
5314*c3739801SMiguel Ojeda         Self: Sized,
5315*c3739801SMiguel Ojeda     {
5316*c3739801SMiguel Ojeda         match Ref::<_, Unalign<Self>>::sized_from_suffix(source) {
5317*c3739801SMiguel Ojeda             Ok((prefix, r)) => Ok((prefix, Ref::read(&r).into_inner())),
5318*c3739801SMiguel Ojeda             Err(CastError::Size(e)) => Err(e.with_dst()),
5319*c3739801SMiguel Ojeda             Err(CastError::Alignment(_)) => {
5320*c3739801SMiguel Ojeda                 // SAFETY: `Unalign<Self>` is trivially aligned, so
5321*c3739801SMiguel Ojeda                 // `Ref::sized_from_suffix` cannot fail due to unmet alignment
5322*c3739801SMiguel Ojeda                 // requirements.
5323*c3739801SMiguel Ojeda                 unsafe { core::hint::unreachable_unchecked() }
5324*c3739801SMiguel Ojeda             }
5325*c3739801SMiguel Ojeda             Err(CastError::Validity(i)) => match i {},
5326*c3739801SMiguel Ojeda         }
5327*c3739801SMiguel Ojeda     }
5328*c3739801SMiguel Ojeda 
5329*c3739801SMiguel Ojeda     /// Reads a copy of `self` from an `io::Read`.
5330*c3739801SMiguel Ojeda     ///
5331*c3739801SMiguel Ojeda     /// This is useful for interfacing with operating system byte sinks (files,
5332*c3739801SMiguel Ojeda     /// sockets, etc.).
5333*c3739801SMiguel Ojeda     ///
5334*c3739801SMiguel Ojeda     /// # Examples
5335*c3739801SMiguel Ojeda     ///
5336*c3739801SMiguel Ojeda     /// ```no_run
5337*c3739801SMiguel Ojeda     /// use zerocopy::{byteorder::big_endian::*, FromBytes};
5338*c3739801SMiguel Ojeda     /// use std::fs::File;
5339*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5340*c3739801SMiguel Ojeda     ///
5341*c3739801SMiguel Ojeda     /// #[derive(FromBytes)]
5342*c3739801SMiguel Ojeda     /// #[repr(C)]
5343*c3739801SMiguel Ojeda     /// struct BitmapFileHeader {
5344*c3739801SMiguel Ojeda     ///     signature: [u8; 2],
5345*c3739801SMiguel Ojeda     ///     size: U32,
5346*c3739801SMiguel Ojeda     ///     reserved: U64,
5347*c3739801SMiguel Ojeda     ///     offset: U64,
5348*c3739801SMiguel Ojeda     /// }
5349*c3739801SMiguel Ojeda     ///
5350*c3739801SMiguel Ojeda     /// let mut file = File::open("image.bin").unwrap();
5351*c3739801SMiguel Ojeda     /// let header = BitmapFileHeader::read_from_io(&mut file).unwrap();
5352*c3739801SMiguel Ojeda     /// ```
5353*c3739801SMiguel Ojeda     #[cfg(feature = "std")]
5354*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
5355*c3739801SMiguel Ojeda     #[inline(always)]
5356*c3739801SMiguel Ojeda     fn read_from_io<R>(mut src: R) -> io::Result<Self>
5357*c3739801SMiguel Ojeda     where
5358*c3739801SMiguel Ojeda         Self: Sized,
5359*c3739801SMiguel Ojeda         R: io::Read,
5360*c3739801SMiguel Ojeda     {
5361*c3739801SMiguel Ojeda         // NOTE(#2319, #2320): We do `buf.zero()` separately rather than
5362*c3739801SMiguel Ojeda         // constructing `let buf = CoreMaybeUninit::zeroed()` because, if `Self`
5363*c3739801SMiguel Ojeda         // contains padding bytes, then a typed copy of `CoreMaybeUninit<Self>`
5364*c3739801SMiguel Ojeda         // will not necessarily preserve zeros written to those padding byte
5365*c3739801SMiguel Ojeda         // locations, and so `buf` could contain uninitialized bytes.
5366*c3739801SMiguel Ojeda         let mut buf = CoreMaybeUninit::<Self>::uninit();
5367*c3739801SMiguel Ojeda         buf.zero();
5368*c3739801SMiguel Ojeda 
5369*c3739801SMiguel Ojeda         let ptr = Ptr::from_mut(&mut buf);
5370*c3739801SMiguel Ojeda         // SAFETY: After `buf.zero()`, `buf` consists entirely of initialized,
5371*c3739801SMiguel Ojeda         // zeroed bytes. Since `MaybeUninit` has no validity requirements, `ptr`
5372*c3739801SMiguel Ojeda         // cannot be used to write values which will violate `buf`'s bit
5373*c3739801SMiguel Ojeda         // validity. Since `ptr` has `Exclusive` aliasing, nothing other than
5374*c3739801SMiguel Ojeda         // `ptr` may be used to mutate `ptr`'s referent, and so its bit validity
5375*c3739801SMiguel Ojeda         // cannot be violated even though `buf` may have more permissive bit
5376*c3739801SMiguel Ojeda         // validity than `ptr`.
5377*c3739801SMiguel Ojeda         let ptr = unsafe { ptr.assume_validity::<invariant::Initialized>() };
5378*c3739801SMiguel Ojeda         let ptr = ptr.as_bytes();
5379*c3739801SMiguel Ojeda         src.read_exact(ptr.as_mut())?;
5380*c3739801SMiguel Ojeda         // SAFETY: `buf` entirely consists of initialized bytes, and `Self` is
5381*c3739801SMiguel Ojeda         // `FromBytes`.
5382*c3739801SMiguel Ojeda         Ok(unsafe { buf.assume_init() })
5383*c3739801SMiguel Ojeda     }
5384*c3739801SMiguel Ojeda 
5385*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::ref_from_bytes`")]
5386*c3739801SMiguel Ojeda     #[doc(hidden)]
5387*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5388*c3739801SMiguel Ojeda     #[inline(always)]
5389*c3739801SMiguel Ojeda     fn ref_from(source: &[u8]) -> Option<&Self>
5390*c3739801SMiguel Ojeda     where
5391*c3739801SMiguel Ojeda         Self: KnownLayout + Immutable,
5392*c3739801SMiguel Ojeda     {
5393*c3739801SMiguel Ojeda         Self::ref_from_bytes(source).ok()
5394*c3739801SMiguel Ojeda     }
5395*c3739801SMiguel Ojeda 
5396*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::mut_from_bytes`")]
5397*c3739801SMiguel Ojeda     #[doc(hidden)]
5398*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5399*c3739801SMiguel Ojeda     #[inline(always)]
5400*c3739801SMiguel Ojeda     fn mut_from(source: &mut [u8]) -> Option<&mut Self>
5401*c3739801SMiguel Ojeda     where
5402*c3739801SMiguel Ojeda         Self: KnownLayout + IntoBytes,
5403*c3739801SMiguel Ojeda     {
5404*c3739801SMiguel Ojeda         Self::mut_from_bytes(source).ok()
5405*c3739801SMiguel Ojeda     }
5406*c3739801SMiguel Ojeda 
5407*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::ref_from_prefix_with_elems`")]
5408*c3739801SMiguel Ojeda     #[doc(hidden)]
5409*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5410*c3739801SMiguel Ojeda     #[inline(always)]
5411*c3739801SMiguel Ojeda     fn slice_from_prefix(source: &[u8], count: usize) -> Option<(&[Self], &[u8])>
5412*c3739801SMiguel Ojeda     where
5413*c3739801SMiguel Ojeda         Self: Sized + Immutable,
5414*c3739801SMiguel Ojeda     {
5415*c3739801SMiguel Ojeda         <[Self]>::ref_from_prefix_with_elems(source, count).ok()
5416*c3739801SMiguel Ojeda     }
5417*c3739801SMiguel Ojeda 
5418*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::ref_from_suffix_with_elems`")]
5419*c3739801SMiguel Ojeda     #[doc(hidden)]
5420*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5421*c3739801SMiguel Ojeda     #[inline(always)]
5422*c3739801SMiguel Ojeda     fn slice_from_suffix(source: &[u8], count: usize) -> Option<(&[u8], &[Self])>
5423*c3739801SMiguel Ojeda     where
5424*c3739801SMiguel Ojeda         Self: Sized + Immutable,
5425*c3739801SMiguel Ojeda     {
5426*c3739801SMiguel Ojeda         <[Self]>::ref_from_suffix_with_elems(source, count).ok()
5427*c3739801SMiguel Ojeda     }
5428*c3739801SMiguel Ojeda 
5429*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::mut_from_prefix_with_elems`")]
5430*c3739801SMiguel Ojeda     #[doc(hidden)]
5431*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5432*c3739801SMiguel Ojeda     #[inline(always)]
5433*c3739801SMiguel Ojeda     fn mut_slice_from_prefix(source: &mut [u8], count: usize) -> Option<(&mut [Self], &mut [u8])>
5434*c3739801SMiguel Ojeda     where
5435*c3739801SMiguel Ojeda         Self: Sized + IntoBytes,
5436*c3739801SMiguel Ojeda     {
5437*c3739801SMiguel Ojeda         <[Self]>::mut_from_prefix_with_elems(source, count).ok()
5438*c3739801SMiguel Ojeda     }
5439*c3739801SMiguel Ojeda 
5440*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::mut_from_suffix_with_elems`")]
5441*c3739801SMiguel Ojeda     #[doc(hidden)]
5442*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5443*c3739801SMiguel Ojeda     #[inline(always)]
5444*c3739801SMiguel Ojeda     fn mut_slice_from_suffix(source: &mut [u8], count: usize) -> Option<(&mut [u8], &mut [Self])>
5445*c3739801SMiguel Ojeda     where
5446*c3739801SMiguel Ojeda         Self: Sized + IntoBytes,
5447*c3739801SMiguel Ojeda     {
5448*c3739801SMiguel Ojeda         <[Self]>::mut_from_suffix_with_elems(source, count).ok()
5449*c3739801SMiguel Ojeda     }
5450*c3739801SMiguel Ojeda 
5451*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "renamed to `FromBytes::read_from_bytes`")]
5452*c3739801SMiguel Ojeda     #[doc(hidden)]
5453*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5454*c3739801SMiguel Ojeda     #[inline(always)]
5455*c3739801SMiguel Ojeda     fn read_from(source: &[u8]) -> Option<Self>
5456*c3739801SMiguel Ojeda     where
5457*c3739801SMiguel Ojeda         Self: Sized,
5458*c3739801SMiguel Ojeda     {
5459*c3739801SMiguel Ojeda         Self::read_from_bytes(source).ok()
5460*c3739801SMiguel Ojeda     }
5461*c3739801SMiguel Ojeda }
5462*c3739801SMiguel Ojeda 
5463*c3739801SMiguel Ojeda /// Interprets the given affix of the given bytes as a `&Self`.
5464*c3739801SMiguel Ojeda ///
5465*c3739801SMiguel Ojeda /// This method computes the largest possible size of `Self` that can fit in the
5466*c3739801SMiguel Ojeda /// prefix or suffix bytes of `source`, then attempts to return both a reference
5467*c3739801SMiguel Ojeda /// to those bytes interpreted as a `Self`, and a reference to the excess bytes.
5468*c3739801SMiguel Ojeda /// If there are insufficient bytes, or if that affix of `source` is not
5469*c3739801SMiguel Ojeda /// appropriately aligned, this returns `Err`.
5470*c3739801SMiguel Ojeda #[inline(always)]
5471*c3739801SMiguel Ojeda fn ref_from_prefix_suffix<T: FromBytes + KnownLayout + Immutable + ?Sized>(
5472*c3739801SMiguel Ojeda     source: &[u8],
5473*c3739801SMiguel Ojeda     meta: Option<T::PointerMetadata>,
5474*c3739801SMiguel Ojeda     cast_type: CastType,
5475*c3739801SMiguel Ojeda ) -> Result<(&T, &[u8]), CastError<&[u8], T>> {
5476*c3739801SMiguel Ojeda     let (slf, prefix_suffix) = Ptr::from_ref(source)
5477*c3739801SMiguel Ojeda         .try_cast_into::<_, BecauseImmutable>(cast_type, meta)
5478*c3739801SMiguel Ojeda         .map_err(|err| err.map_src(|s| s.as_ref()))?;
5479*c3739801SMiguel Ojeda     Ok((slf.recall_validity().as_ref(), prefix_suffix.as_ref()))
5480*c3739801SMiguel Ojeda }
5481*c3739801SMiguel Ojeda 
5482*c3739801SMiguel Ojeda /// Interprets the given affix of the given bytes as a `&mut Self` without
5483*c3739801SMiguel Ojeda /// copying.
5484*c3739801SMiguel Ojeda ///
5485*c3739801SMiguel Ojeda /// This method computes the largest possible size of `Self` that can fit in the
5486*c3739801SMiguel Ojeda /// prefix or suffix bytes of `source`, then attempts to return both a reference
5487*c3739801SMiguel Ojeda /// to those bytes interpreted as a `Self`, and a reference to the excess bytes.
5488*c3739801SMiguel Ojeda /// If there are insufficient bytes, or if that affix of `source` is not
5489*c3739801SMiguel Ojeda /// appropriately aligned, this returns `Err`.
5490*c3739801SMiguel Ojeda #[inline(always)]
5491*c3739801SMiguel Ojeda fn mut_from_prefix_suffix<T: FromBytes + IntoBytes + KnownLayout + ?Sized>(
5492*c3739801SMiguel Ojeda     source: &mut [u8],
5493*c3739801SMiguel Ojeda     meta: Option<T::PointerMetadata>,
5494*c3739801SMiguel Ojeda     cast_type: CastType,
5495*c3739801SMiguel Ojeda ) -> Result<(&mut T, &mut [u8]), CastError<&mut [u8], T>> {
5496*c3739801SMiguel Ojeda     let (slf, prefix_suffix) = Ptr::from_mut(source)
5497*c3739801SMiguel Ojeda         .try_cast_into::<_, BecauseExclusive>(cast_type, meta)
5498*c3739801SMiguel Ojeda         .map_err(|err| err.map_src(|s| s.as_mut()))?;
5499*c3739801SMiguel Ojeda     Ok((slf.recall_validity::<_, (_, (_, _))>().as_mut(), prefix_suffix.as_mut()))
5500*c3739801SMiguel Ojeda }
5501*c3739801SMiguel Ojeda 
5502*c3739801SMiguel Ojeda /// Analyzes whether a type is [`IntoBytes`].
5503*c3739801SMiguel Ojeda ///
5504*c3739801SMiguel Ojeda /// This derive analyzes, at compile time, whether the annotated type satisfies
5505*c3739801SMiguel Ojeda /// the [safety conditions] of `IntoBytes` and implements `IntoBytes` if it is
5506*c3739801SMiguel Ojeda /// sound to do so. This derive can be applied to structs and enums (see below
5507*c3739801SMiguel Ojeda /// for union support); e.g.:
5508*c3739801SMiguel Ojeda ///
5509*c3739801SMiguel Ojeda /// ```
5510*c3739801SMiguel Ojeda /// # use zerocopy_derive::{IntoBytes};
5511*c3739801SMiguel Ojeda /// #[derive(IntoBytes)]
5512*c3739801SMiguel Ojeda /// #[repr(C)]
5513*c3739801SMiguel Ojeda /// struct MyStruct {
5514*c3739801SMiguel Ojeda /// # /*
5515*c3739801SMiguel Ojeda ///     ...
5516*c3739801SMiguel Ojeda /// # */
5517*c3739801SMiguel Ojeda /// }
5518*c3739801SMiguel Ojeda ///
5519*c3739801SMiguel Ojeda /// #[derive(IntoBytes)]
5520*c3739801SMiguel Ojeda /// #[repr(u8)]
5521*c3739801SMiguel Ojeda /// enum MyEnum {
5522*c3739801SMiguel Ojeda /// #   Variant,
5523*c3739801SMiguel Ojeda /// # /*
5524*c3739801SMiguel Ojeda ///     ...
5525*c3739801SMiguel Ojeda /// # */
5526*c3739801SMiguel Ojeda /// }
5527*c3739801SMiguel Ojeda /// ```
5528*c3739801SMiguel Ojeda ///
5529*c3739801SMiguel Ojeda /// [safety conditions]: trait@IntoBytes#safety
5530*c3739801SMiguel Ojeda ///
5531*c3739801SMiguel Ojeda /// # Error Messages
5532*c3739801SMiguel Ojeda ///
5533*c3739801SMiguel Ojeda /// On Rust toolchains prior to 1.78.0, due to the way that the custom derive
5534*c3739801SMiguel Ojeda /// for `IntoBytes` is implemented, you may get an error like this:
5535*c3739801SMiguel Ojeda ///
5536*c3739801SMiguel Ojeda /// ```text
5537*c3739801SMiguel Ojeda /// error[E0277]: the trait bound `(): PaddingFree<Foo, true>` is not satisfied
5538*c3739801SMiguel Ojeda ///   --> lib.rs:23:10
5539*c3739801SMiguel Ojeda ///    |
5540*c3739801SMiguel Ojeda ///  1 | #[derive(IntoBytes)]
5541*c3739801SMiguel Ojeda ///    |          ^^^^^^^^^ the trait `PaddingFree<Foo, true>` is not implemented for `()`
5542*c3739801SMiguel Ojeda ///    |
5543*c3739801SMiguel Ojeda ///    = help: the following implementations were found:
5544*c3739801SMiguel Ojeda ///                   <() as PaddingFree<T, false>>
5545*c3739801SMiguel Ojeda /// ```
5546*c3739801SMiguel Ojeda ///
5547*c3739801SMiguel Ojeda /// This error indicates that the type being annotated has padding bytes, which
5548*c3739801SMiguel Ojeda /// is illegal for `IntoBytes` types. Consider reducing the alignment of some
5549*c3739801SMiguel Ojeda /// fields by using types in the [`byteorder`] module, wrapping field types in
5550*c3739801SMiguel Ojeda /// [`Unalign`], adding explicit struct fields where those padding bytes would
5551*c3739801SMiguel Ojeda /// be, or using `#[repr(packed)]`. See the Rust Reference's page on [type
5552*c3739801SMiguel Ojeda /// layout] for more information about type layout and padding.
5553*c3739801SMiguel Ojeda ///
5554*c3739801SMiguel Ojeda /// [type layout]: https://doc.rust-lang.org/reference/type-layout.html
5555*c3739801SMiguel Ojeda ///
5556*c3739801SMiguel Ojeda /// # Unions
5557*c3739801SMiguel Ojeda ///
5558*c3739801SMiguel Ojeda /// Currently, union bit validity is [up in the air][union-validity], and so
5559*c3739801SMiguel Ojeda /// zerocopy does not support `#[derive(IntoBytes)]` on unions by default.
5560*c3739801SMiguel Ojeda /// However, implementing `IntoBytes` on a union type is likely sound on all
5561*c3739801SMiguel Ojeda /// existing Rust toolchains - it's just that it may become unsound in the
5562*c3739801SMiguel Ojeda /// future. You can opt-in to `#[derive(IntoBytes)]` support on unions by
5563*c3739801SMiguel Ojeda /// passing the unstable `zerocopy_derive_union_into_bytes` cfg:
5564*c3739801SMiguel Ojeda ///
5565*c3739801SMiguel Ojeda /// ```shell
5566*c3739801SMiguel Ojeda /// $ RUSTFLAGS='--cfg zerocopy_derive_union_into_bytes' cargo build
5567*c3739801SMiguel Ojeda /// ```
5568*c3739801SMiguel Ojeda ///
5569*c3739801SMiguel Ojeda /// However, it is your responsibility to ensure that this derive is sound on
5570*c3739801SMiguel Ojeda /// the specific versions of the Rust toolchain you are using! We make no
5571*c3739801SMiguel Ojeda /// stability or soundness guarantees regarding this cfg, and may remove it at
5572*c3739801SMiguel Ojeda /// any point.
5573*c3739801SMiguel Ojeda ///
5574*c3739801SMiguel Ojeda /// We are actively working with Rust to stabilize the necessary language
5575*c3739801SMiguel Ojeda /// guarantees to support this in a forwards-compatible way, which will enable
5576*c3739801SMiguel Ojeda /// us to remove the cfg gate. As part of this effort, we need to know how much
5577*c3739801SMiguel Ojeda /// demand there is for this feature. If you would like to use `IntoBytes` on
5578*c3739801SMiguel Ojeda /// unions, [please let us know][discussion].
5579*c3739801SMiguel Ojeda ///
5580*c3739801SMiguel Ojeda /// [union-validity]: https://github.com/rust-lang/unsafe-code-guidelines/issues/438
5581*c3739801SMiguel Ojeda /// [discussion]: https://github.com/google/zerocopy/discussions/1802
5582*c3739801SMiguel Ojeda ///
5583*c3739801SMiguel Ojeda /// # Analysis
5584*c3739801SMiguel Ojeda ///
5585*c3739801SMiguel Ojeda /// *This section describes, roughly, the analysis performed by this derive to
5586*c3739801SMiguel Ojeda /// determine whether it is sound to implement `IntoBytes` for a given type.
5587*c3739801SMiguel Ojeda /// Unless you are modifying the implementation of this derive, or attempting to
5588*c3739801SMiguel Ojeda /// manually implement `IntoBytes` for a type yourself, you don't need to read
5589*c3739801SMiguel Ojeda /// this section.*
5590*c3739801SMiguel Ojeda ///
5591*c3739801SMiguel Ojeda /// If a type has the following properties, then this derive can implement
5592*c3739801SMiguel Ojeda /// `IntoBytes` for that type:
5593*c3739801SMiguel Ojeda ///
5594*c3739801SMiguel Ojeda /// - If the type is a struct, its fields must be [`IntoBytes`]. Additionally:
5595*c3739801SMiguel Ojeda ///     - if the type is `repr(transparent)` or `repr(packed)`, it is
5596*c3739801SMiguel Ojeda ///       [`IntoBytes`] if its fields are [`IntoBytes`]; else,
5597*c3739801SMiguel Ojeda ///     - if the type is `repr(C)` with at most one field, it is [`IntoBytes`]
5598*c3739801SMiguel Ojeda ///       if its field is [`IntoBytes`]; else,
5599*c3739801SMiguel Ojeda ///     - if the type has no generic parameters, it is [`IntoBytes`] if the type
5600*c3739801SMiguel Ojeda ///       is sized and has no padding bytes; else,
5601*c3739801SMiguel Ojeda ///     - if the type is `repr(C)`, its fields must be [`Unaligned`].
5602*c3739801SMiguel Ojeda /// - If the type is an enum:
5603*c3739801SMiguel Ojeda ///   - It must have a defined representation (`repr`s `C`, `u8`, `u16`, `u32`,
5604*c3739801SMiguel Ojeda ///     `u64`, `usize`, `i8`, `i16`, `i32`, `i64`, or `isize`).
5605*c3739801SMiguel Ojeda ///   - It must have no padding bytes.
5606*c3739801SMiguel Ojeda ///   - Its fields must be [`IntoBytes`].
5607*c3739801SMiguel Ojeda ///
5608*c3739801SMiguel Ojeda /// This analysis is subject to change. Unsafe code may *only* rely on the
5609*c3739801SMiguel Ojeda /// documented [safety conditions] of `FromBytes`, and must *not* rely on the
5610*c3739801SMiguel Ojeda /// implementation details of this derive.
5611*c3739801SMiguel Ojeda ///
5612*c3739801SMiguel Ojeda /// [Rust Reference]: https://doc.rust-lang.org/reference/type-layout.html
5613*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
5614*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
5615*c3739801SMiguel Ojeda pub use zerocopy_derive::IntoBytes;
5616*c3739801SMiguel Ojeda 
5617*c3739801SMiguel Ojeda /// Types that can be converted to an immutable slice of initialized bytes.
5618*c3739801SMiguel Ojeda ///
5619*c3739801SMiguel Ojeda /// Any `IntoBytes` type can be converted to a slice of initialized bytes of the
5620*c3739801SMiguel Ojeda /// same size. This is useful for efficiently serializing structured data as raw
5621*c3739801SMiguel Ojeda /// bytes.
5622*c3739801SMiguel Ojeda ///
5623*c3739801SMiguel Ojeda /// # Implementation
5624*c3739801SMiguel Ojeda ///
5625*c3739801SMiguel Ojeda /// **Do not implement this trait yourself!** Instead, use
5626*c3739801SMiguel Ojeda /// [`#[derive(IntoBytes)]`][derive]; e.g.:
5627*c3739801SMiguel Ojeda ///
5628*c3739801SMiguel Ojeda /// ```
5629*c3739801SMiguel Ojeda /// # use zerocopy_derive::IntoBytes;
5630*c3739801SMiguel Ojeda /// #[derive(IntoBytes)]
5631*c3739801SMiguel Ojeda /// #[repr(C)]
5632*c3739801SMiguel Ojeda /// struct MyStruct {
5633*c3739801SMiguel Ojeda /// # /*
5634*c3739801SMiguel Ojeda ///     ...
5635*c3739801SMiguel Ojeda /// # */
5636*c3739801SMiguel Ojeda /// }
5637*c3739801SMiguel Ojeda ///
5638*c3739801SMiguel Ojeda /// #[derive(IntoBytes)]
5639*c3739801SMiguel Ojeda /// #[repr(u8)]
5640*c3739801SMiguel Ojeda /// enum MyEnum {
5641*c3739801SMiguel Ojeda /// #   Variant0,
5642*c3739801SMiguel Ojeda /// # /*
5643*c3739801SMiguel Ojeda ///     ...
5644*c3739801SMiguel Ojeda /// # */
5645*c3739801SMiguel Ojeda /// }
5646*c3739801SMiguel Ojeda /// ```
5647*c3739801SMiguel Ojeda ///
5648*c3739801SMiguel Ojeda /// This derive performs a sophisticated, compile-time safety analysis to
5649*c3739801SMiguel Ojeda /// determine whether a type is `IntoBytes`. See the [derive
5650*c3739801SMiguel Ojeda /// documentation][derive] for guidance on how to interpret error messages
5651*c3739801SMiguel Ojeda /// produced by the derive's analysis.
5652*c3739801SMiguel Ojeda ///
5653*c3739801SMiguel Ojeda /// # Safety
5654*c3739801SMiguel Ojeda ///
5655*c3739801SMiguel Ojeda /// *This section describes what is required in order for `T: IntoBytes`, and
5656*c3739801SMiguel Ojeda /// what unsafe code may assume of such types. If you don't plan on implementing
5657*c3739801SMiguel Ojeda /// `IntoBytes` manually, and you don't plan on writing unsafe code that
5658*c3739801SMiguel Ojeda /// operates on `IntoBytes` types, then you don't need to read this section.*
5659*c3739801SMiguel Ojeda ///
5660*c3739801SMiguel Ojeda /// If `T: IntoBytes`, then unsafe code may assume that it is sound to treat any
5661*c3739801SMiguel Ojeda /// `t: T` as an immutable `[u8]` of length `size_of_val(t)`. If a type is
5662*c3739801SMiguel Ojeda /// marked as `IntoBytes` which violates this contract, it may cause undefined
5663*c3739801SMiguel Ojeda /// behavior.
5664*c3739801SMiguel Ojeda ///
5665*c3739801SMiguel Ojeda /// `#[derive(IntoBytes)]` only permits [types which satisfy these
5666*c3739801SMiguel Ojeda /// requirements][derive-analysis].
5667*c3739801SMiguel Ojeda ///
5668*c3739801SMiguel Ojeda #[cfg_attr(
5669*c3739801SMiguel Ojeda     feature = "derive",
5670*c3739801SMiguel Ojeda     doc = "[derive]: zerocopy_derive::IntoBytes",
5671*c3739801SMiguel Ojeda     doc = "[derive-analysis]: zerocopy_derive::IntoBytes#analysis"
5672*c3739801SMiguel Ojeda )]
5673*c3739801SMiguel Ojeda #[cfg_attr(
5674*c3739801SMiguel Ojeda     not(feature = "derive"),
5675*c3739801SMiguel Ojeda     doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.IntoBytes.html"),
5676*c3739801SMiguel Ojeda     doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.IntoBytes.html#analysis"),
5677*c3739801SMiguel Ojeda )]
5678*c3739801SMiguel Ojeda #[cfg_attr(
5679*c3739801SMiguel Ojeda     not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
5680*c3739801SMiguel Ojeda     diagnostic::on_unimplemented(note = "Consider adding `#[derive(IntoBytes)]` to `{Self}`")
5681*c3739801SMiguel Ojeda )]
5682*c3739801SMiguel Ojeda pub unsafe trait IntoBytes {
5683*c3739801SMiguel Ojeda     // The `Self: Sized` bound makes it so that this function doesn't prevent
5684*c3739801SMiguel Ojeda     // `IntoBytes` from being object safe. Note that other `IntoBytes` methods
5685*c3739801SMiguel Ojeda     // prevent object safety, but those provide a benefit in exchange for object
5686*c3739801SMiguel Ojeda     // safety. If at some point we remove those methods, change their type
5687*c3739801SMiguel Ojeda     // signatures, or move them out of this trait so that `IntoBytes` is object
5688*c3739801SMiguel Ojeda     // safe again, it's important that this function not prevent object safety.
5689*c3739801SMiguel Ojeda     #[doc(hidden)]
5690*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
5691*c3739801SMiguel Ojeda     where
5692*c3739801SMiguel Ojeda         Self: Sized;
5693*c3739801SMiguel Ojeda 
5694*c3739801SMiguel Ojeda     /// Gets the bytes of this value.
5695*c3739801SMiguel Ojeda     ///
5696*c3739801SMiguel Ojeda     /// # Examples
5697*c3739801SMiguel Ojeda     ///
5698*c3739801SMiguel Ojeda     /// ```
5699*c3739801SMiguel Ojeda     /// use zerocopy::IntoBytes;
5700*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5701*c3739801SMiguel Ojeda     ///
5702*c3739801SMiguel Ojeda     /// #[derive(IntoBytes, Immutable)]
5703*c3739801SMiguel Ojeda     /// #[repr(C)]
5704*c3739801SMiguel Ojeda     /// struct PacketHeader {
5705*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
5706*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
5707*c3739801SMiguel Ojeda     ///     length: [u8; 2],
5708*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
5709*c3739801SMiguel Ojeda     /// }
5710*c3739801SMiguel Ojeda     ///
5711*c3739801SMiguel Ojeda     /// let header = PacketHeader {
5712*c3739801SMiguel Ojeda     ///     src_port: [0, 1],
5713*c3739801SMiguel Ojeda     ///     dst_port: [2, 3],
5714*c3739801SMiguel Ojeda     ///     length: [4, 5],
5715*c3739801SMiguel Ojeda     ///     checksum: [6, 7],
5716*c3739801SMiguel Ojeda     /// };
5717*c3739801SMiguel Ojeda     ///
5718*c3739801SMiguel Ojeda     /// let bytes = header.as_bytes();
5719*c3739801SMiguel Ojeda     ///
5720*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]);
5721*c3739801SMiguel Ojeda     /// ```
5722*c3739801SMiguel Ojeda     ///
5723*c3739801SMiguel Ojeda     #[doc = codegen_section!(
5724*c3739801SMiguel Ojeda         header = "h5",
5725*c3739801SMiguel Ojeda         bench = "as_bytes",
5726*c3739801SMiguel Ojeda         format = "coco",
5727*c3739801SMiguel Ojeda         arity = 2,
5728*c3739801SMiguel Ojeda         [
5729*c3739801SMiguel Ojeda             open
5730*c3739801SMiguel Ojeda             @index 1
5731*c3739801SMiguel Ojeda             @title "Sized"
5732*c3739801SMiguel Ojeda             @variant "static_size"
5733*c3739801SMiguel Ojeda         ],
5734*c3739801SMiguel Ojeda         [
5735*c3739801SMiguel Ojeda             @index 2
5736*c3739801SMiguel Ojeda             @title "Unsized"
5737*c3739801SMiguel Ojeda             @variant "dynamic_size"
5738*c3739801SMiguel Ojeda         ]
5739*c3739801SMiguel Ojeda     )]
5740*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5741*c3739801SMiguel Ojeda     #[inline(always)]
5742*c3739801SMiguel Ojeda     fn as_bytes(&self) -> &[u8]
5743*c3739801SMiguel Ojeda     where
5744*c3739801SMiguel Ojeda         Self: Immutable,
5745*c3739801SMiguel Ojeda     {
5746*c3739801SMiguel Ojeda         // Note that this method does not have a `Self: Sized` bound;
5747*c3739801SMiguel Ojeda         // `size_of_val` works for unsized values too.
5748*c3739801SMiguel Ojeda         let len = mem::size_of_val(self);
5749*c3739801SMiguel Ojeda         let slf: *const Self = self;
5750*c3739801SMiguel Ojeda 
5751*c3739801SMiguel Ojeda         // SAFETY:
5752*c3739801SMiguel Ojeda         // - `slf.cast::<u8>()` is valid for reads for `len * size_of::<u8>()`
5753*c3739801SMiguel Ojeda         //   many bytes because...
5754*c3739801SMiguel Ojeda         //   - `slf` is the same pointer as `self`, and `self` is a reference
5755*c3739801SMiguel Ojeda         //     which points to an object whose size is `len`. Thus...
5756*c3739801SMiguel Ojeda         //     - The entire region of `len` bytes starting at `slf` is contained
5757*c3739801SMiguel Ojeda         //       within a single allocation.
5758*c3739801SMiguel Ojeda         //     - `slf` is non-null.
5759*c3739801SMiguel Ojeda         //   - `slf` is trivially aligned to `align_of::<u8>() == 1`.
5760*c3739801SMiguel Ojeda         // - `Self: IntoBytes` ensures that all of the bytes of `slf` are
5761*c3739801SMiguel Ojeda         //   initialized.
5762*c3739801SMiguel Ojeda         // - Since `slf` is derived from `self`, and `self` is an immutable
5763*c3739801SMiguel Ojeda         //   reference, the only other references to this memory region that
5764*c3739801SMiguel Ojeda         //   could exist are other immutable references, which by `Self:
5765*c3739801SMiguel Ojeda         //   Immutable` don't permit mutation.
5766*c3739801SMiguel Ojeda         // - The total size of the resulting slice is no larger than
5767*c3739801SMiguel Ojeda         //   `isize::MAX` because no allocation produced by safe code can be
5768*c3739801SMiguel Ojeda         //   larger than `isize::MAX`.
5769*c3739801SMiguel Ojeda         //
5770*c3739801SMiguel Ojeda         // FIXME(#429): Add references to docs and quotes.
5771*c3739801SMiguel Ojeda         unsafe { slice::from_raw_parts(slf.cast::<u8>(), len) }
5772*c3739801SMiguel Ojeda     }
5773*c3739801SMiguel Ojeda 
5774*c3739801SMiguel Ojeda     /// Gets the bytes of this value mutably.
5775*c3739801SMiguel Ojeda     ///
5776*c3739801SMiguel Ojeda     /// # Examples
5777*c3739801SMiguel Ojeda     ///
5778*c3739801SMiguel Ojeda     /// ```
5779*c3739801SMiguel Ojeda     /// use zerocopy::IntoBytes;
5780*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5781*c3739801SMiguel Ojeda     ///
5782*c3739801SMiguel Ojeda     /// # #[derive(Eq, PartialEq, Debug)]
5783*c3739801SMiguel Ojeda     /// #[derive(FromBytes, IntoBytes, Immutable)]
5784*c3739801SMiguel Ojeda     /// #[repr(C)]
5785*c3739801SMiguel Ojeda     /// struct PacketHeader {
5786*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
5787*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
5788*c3739801SMiguel Ojeda     ///     length: [u8; 2],
5789*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
5790*c3739801SMiguel Ojeda     /// }
5791*c3739801SMiguel Ojeda     ///
5792*c3739801SMiguel Ojeda     /// let mut header = PacketHeader {
5793*c3739801SMiguel Ojeda     ///     src_port: [0, 1],
5794*c3739801SMiguel Ojeda     ///     dst_port: [2, 3],
5795*c3739801SMiguel Ojeda     ///     length: [4, 5],
5796*c3739801SMiguel Ojeda     ///     checksum: [6, 7],
5797*c3739801SMiguel Ojeda     /// };
5798*c3739801SMiguel Ojeda     ///
5799*c3739801SMiguel Ojeda     /// let bytes = header.as_mut_bytes();
5800*c3739801SMiguel Ojeda     ///
5801*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]);
5802*c3739801SMiguel Ojeda     ///
5803*c3739801SMiguel Ojeda     /// bytes.reverse();
5804*c3739801SMiguel Ojeda     ///
5805*c3739801SMiguel Ojeda     /// assert_eq!(header, PacketHeader {
5806*c3739801SMiguel Ojeda     ///     src_port: [7, 6],
5807*c3739801SMiguel Ojeda     ///     dst_port: [5, 4],
5808*c3739801SMiguel Ojeda     ///     length: [3, 2],
5809*c3739801SMiguel Ojeda     ///     checksum: [1, 0],
5810*c3739801SMiguel Ojeda     /// });
5811*c3739801SMiguel Ojeda     /// ```
5812*c3739801SMiguel Ojeda     ///
5813*c3739801SMiguel Ojeda     #[doc = codegen_header!("h5", "as_mut_bytes")]
5814*c3739801SMiguel Ojeda     ///
5815*c3739801SMiguel Ojeda     /// See [`IntoBytes::as_bytes`](#method.as_bytes.codegen).
5816*c3739801SMiguel Ojeda     #[must_use = "has no side effects"]
5817*c3739801SMiguel Ojeda     #[inline(always)]
5818*c3739801SMiguel Ojeda     fn as_mut_bytes(&mut self) -> &mut [u8]
5819*c3739801SMiguel Ojeda     where
5820*c3739801SMiguel Ojeda         Self: FromBytes,
5821*c3739801SMiguel Ojeda     {
5822*c3739801SMiguel Ojeda         // Note that this method does not have a `Self: Sized` bound;
5823*c3739801SMiguel Ojeda         // `size_of_val` works for unsized values too.
5824*c3739801SMiguel Ojeda         let len = mem::size_of_val(self);
5825*c3739801SMiguel Ojeda         let slf: *mut Self = self;
5826*c3739801SMiguel Ojeda 
5827*c3739801SMiguel Ojeda         // SAFETY:
5828*c3739801SMiguel Ojeda         // - `slf.cast::<u8>()` is valid for reads and writes for `len *
5829*c3739801SMiguel Ojeda         //   size_of::<u8>()` many bytes because...
5830*c3739801SMiguel Ojeda         //   - `slf` is the same pointer as `self`, and `self` is a reference
5831*c3739801SMiguel Ojeda         //     which points to an object whose size is `len`. Thus...
5832*c3739801SMiguel Ojeda         //     - The entire region of `len` bytes starting at `slf` is contained
5833*c3739801SMiguel Ojeda         //       within a single allocation.
5834*c3739801SMiguel Ojeda         //     - `slf` is non-null.
5835*c3739801SMiguel Ojeda         //   - `slf` is trivially aligned to `align_of::<u8>() == 1`.
5836*c3739801SMiguel Ojeda         // - `Self: IntoBytes` ensures that all of the bytes of `slf` are
5837*c3739801SMiguel Ojeda         //   initialized.
5838*c3739801SMiguel Ojeda         // - `Self: FromBytes` ensures that no write to this memory region
5839*c3739801SMiguel Ojeda         //   could result in it containing an invalid `Self`.
5840*c3739801SMiguel Ojeda         // - Since `slf` is derived from `self`, and `self` is a mutable
5841*c3739801SMiguel Ojeda         //   reference, no other references to this memory region can exist.
5842*c3739801SMiguel Ojeda         // - The total size of the resulting slice is no larger than
5843*c3739801SMiguel Ojeda         //   `isize::MAX` because no allocation produced by safe code can be
5844*c3739801SMiguel Ojeda         //   larger than `isize::MAX`.
5845*c3739801SMiguel Ojeda         //
5846*c3739801SMiguel Ojeda         // FIXME(#429): Add references to docs and quotes.
5847*c3739801SMiguel Ojeda         unsafe { slice::from_raw_parts_mut(slf.cast::<u8>(), len) }
5848*c3739801SMiguel Ojeda     }
5849*c3739801SMiguel Ojeda 
5850*c3739801SMiguel Ojeda     /// Writes a copy of `self` to `dst`.
5851*c3739801SMiguel Ojeda     ///
5852*c3739801SMiguel Ojeda     /// If `dst.len() != size_of_val(self)`, `write_to` returns `Err`.
5853*c3739801SMiguel Ojeda     ///
5854*c3739801SMiguel Ojeda     /// # Examples
5855*c3739801SMiguel Ojeda     ///
5856*c3739801SMiguel Ojeda     /// ```
5857*c3739801SMiguel Ojeda     /// use zerocopy::IntoBytes;
5858*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5859*c3739801SMiguel Ojeda     ///
5860*c3739801SMiguel Ojeda     /// #[derive(IntoBytes, Immutable)]
5861*c3739801SMiguel Ojeda     /// #[repr(C)]
5862*c3739801SMiguel Ojeda     /// struct PacketHeader {
5863*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
5864*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
5865*c3739801SMiguel Ojeda     ///     length: [u8; 2],
5866*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
5867*c3739801SMiguel Ojeda     /// }
5868*c3739801SMiguel Ojeda     ///
5869*c3739801SMiguel Ojeda     /// let header = PacketHeader {
5870*c3739801SMiguel Ojeda     ///     src_port: [0, 1],
5871*c3739801SMiguel Ojeda     ///     dst_port: [2, 3],
5872*c3739801SMiguel Ojeda     ///     length: [4, 5],
5873*c3739801SMiguel Ojeda     ///     checksum: [6, 7],
5874*c3739801SMiguel Ojeda     /// };
5875*c3739801SMiguel Ojeda     ///
5876*c3739801SMiguel Ojeda     /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0];
5877*c3739801SMiguel Ojeda     ///
5878*c3739801SMiguel Ojeda     /// header.write_to(&mut bytes[..]);
5879*c3739801SMiguel Ojeda     ///
5880*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7]);
5881*c3739801SMiguel Ojeda     /// ```
5882*c3739801SMiguel Ojeda     ///
5883*c3739801SMiguel Ojeda     /// If too many or too few target bytes are provided, `write_to` returns
5884*c3739801SMiguel Ojeda     /// `Err` and leaves the target bytes unmodified:
5885*c3739801SMiguel Ojeda     ///
5886*c3739801SMiguel Ojeda     /// ```
5887*c3739801SMiguel Ojeda     /// # use zerocopy::IntoBytes;
5888*c3739801SMiguel Ojeda     /// # let header = u128::MAX;
5889*c3739801SMiguel Ojeda     /// let mut excessive_bytes = &mut [0u8; 128][..];
5890*c3739801SMiguel Ojeda     ///
5891*c3739801SMiguel Ojeda     /// let write_result = header.write_to(excessive_bytes);
5892*c3739801SMiguel Ojeda     ///
5893*c3739801SMiguel Ojeda     /// assert!(write_result.is_err());
5894*c3739801SMiguel Ojeda     /// assert_eq!(excessive_bytes, [0u8; 128]);
5895*c3739801SMiguel Ojeda     /// ```
5896*c3739801SMiguel Ojeda     ///
5897*c3739801SMiguel Ojeda     #[doc = codegen_section!(
5898*c3739801SMiguel Ojeda         header = "h5",
5899*c3739801SMiguel Ojeda         bench = "write_to",
5900*c3739801SMiguel Ojeda         format = "coco",
5901*c3739801SMiguel Ojeda         arity = 2,
5902*c3739801SMiguel Ojeda         [
5903*c3739801SMiguel Ojeda             open
5904*c3739801SMiguel Ojeda             @index 1
5905*c3739801SMiguel Ojeda             @title "Sized"
5906*c3739801SMiguel Ojeda             @variant "static_size"
5907*c3739801SMiguel Ojeda         ],
5908*c3739801SMiguel Ojeda         [
5909*c3739801SMiguel Ojeda             @index 2
5910*c3739801SMiguel Ojeda             @title "Unsized"
5911*c3739801SMiguel Ojeda             @variant "dynamic_size"
5912*c3739801SMiguel Ojeda         ]
5913*c3739801SMiguel Ojeda     )]
5914*c3739801SMiguel Ojeda     #[must_use = "callers should check the return value to see if the operation succeeded"]
5915*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
5916*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
5917*c3739801SMiguel Ojeda     #[allow(clippy::mut_from_ref)] // False positive: `&self -> &mut [u8]`
5918*c3739801SMiguel Ojeda     fn write_to(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>>
5919*c3739801SMiguel Ojeda     where
5920*c3739801SMiguel Ojeda         Self: Immutable,
5921*c3739801SMiguel Ojeda     {
5922*c3739801SMiguel Ojeda         let src = self.as_bytes();
5923*c3739801SMiguel Ojeda         if dst.len() == src.len() {
5924*c3739801SMiguel Ojeda             // SAFETY: Within this branch of the conditional, we have ensured
5925*c3739801SMiguel Ojeda             // that `dst.len()` is equal to `src.len()`. Neither the size of the
5926*c3739801SMiguel Ojeda             // source nor the size of the destination change between the above
5927*c3739801SMiguel Ojeda             // size check and the invocation of `copy_unchecked`.
5928*c3739801SMiguel Ojeda             unsafe { util::copy_unchecked(src, dst) }
5929*c3739801SMiguel Ojeda             Ok(())
5930*c3739801SMiguel Ojeda         } else {
5931*c3739801SMiguel Ojeda             Err(SizeError::new(self))
5932*c3739801SMiguel Ojeda         }
5933*c3739801SMiguel Ojeda     }
5934*c3739801SMiguel Ojeda 
5935*c3739801SMiguel Ojeda     /// Writes a copy of `self` to the prefix of `dst`.
5936*c3739801SMiguel Ojeda     ///
5937*c3739801SMiguel Ojeda     /// `write_to_prefix` writes `self` to the first `size_of_val(self)` bytes
5938*c3739801SMiguel Ojeda     /// of `dst`. If `dst.len() < size_of_val(self)`, it returns `Err`.
5939*c3739801SMiguel Ojeda     ///
5940*c3739801SMiguel Ojeda     /// # Examples
5941*c3739801SMiguel Ojeda     ///
5942*c3739801SMiguel Ojeda     /// ```
5943*c3739801SMiguel Ojeda     /// use zerocopy::IntoBytes;
5944*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
5945*c3739801SMiguel Ojeda     ///
5946*c3739801SMiguel Ojeda     /// #[derive(IntoBytes, Immutable)]
5947*c3739801SMiguel Ojeda     /// #[repr(C)]
5948*c3739801SMiguel Ojeda     /// struct PacketHeader {
5949*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
5950*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
5951*c3739801SMiguel Ojeda     ///     length: [u8; 2],
5952*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
5953*c3739801SMiguel Ojeda     /// }
5954*c3739801SMiguel Ojeda     ///
5955*c3739801SMiguel Ojeda     /// let header = PacketHeader {
5956*c3739801SMiguel Ojeda     ///     src_port: [0, 1],
5957*c3739801SMiguel Ojeda     ///     dst_port: [2, 3],
5958*c3739801SMiguel Ojeda     ///     length: [4, 5],
5959*c3739801SMiguel Ojeda     ///     checksum: [6, 7],
5960*c3739801SMiguel Ojeda     /// };
5961*c3739801SMiguel Ojeda     ///
5962*c3739801SMiguel Ojeda     /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
5963*c3739801SMiguel Ojeda     ///
5964*c3739801SMiguel Ojeda     /// header.write_to_prefix(&mut bytes[..]);
5965*c3739801SMiguel Ojeda     ///
5966*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7, 0, 0]);
5967*c3739801SMiguel Ojeda     /// ```
5968*c3739801SMiguel Ojeda     ///
5969*c3739801SMiguel Ojeda     /// If insufficient target bytes are provided, `write_to_prefix` returns
5970*c3739801SMiguel Ojeda     /// `Err` and leaves the target bytes unmodified:
5971*c3739801SMiguel Ojeda     ///
5972*c3739801SMiguel Ojeda     /// ```
5973*c3739801SMiguel Ojeda     /// # use zerocopy::IntoBytes;
5974*c3739801SMiguel Ojeda     /// # let header = u128::MAX;
5975*c3739801SMiguel Ojeda     /// let mut insufficient_bytes = &mut [0, 0][..];
5976*c3739801SMiguel Ojeda     ///
5977*c3739801SMiguel Ojeda     /// let write_result = header.write_to_suffix(insufficient_bytes);
5978*c3739801SMiguel Ojeda     ///
5979*c3739801SMiguel Ojeda     /// assert!(write_result.is_err());
5980*c3739801SMiguel Ojeda     /// assert_eq!(insufficient_bytes, [0, 0]);
5981*c3739801SMiguel Ojeda     /// ```
5982*c3739801SMiguel Ojeda     ///
5983*c3739801SMiguel Ojeda     #[doc = codegen_section!(
5984*c3739801SMiguel Ojeda         header = "h5",
5985*c3739801SMiguel Ojeda         bench = "write_to_prefix",
5986*c3739801SMiguel Ojeda         format = "coco",
5987*c3739801SMiguel Ojeda         arity = 2,
5988*c3739801SMiguel Ojeda         [
5989*c3739801SMiguel Ojeda             open
5990*c3739801SMiguel Ojeda             @index 1
5991*c3739801SMiguel Ojeda             @title "Sized"
5992*c3739801SMiguel Ojeda             @variant "static_size"
5993*c3739801SMiguel Ojeda         ],
5994*c3739801SMiguel Ojeda         [
5995*c3739801SMiguel Ojeda             @index 2
5996*c3739801SMiguel Ojeda             @title "Unsized"
5997*c3739801SMiguel Ojeda             @variant "dynamic_size"
5998*c3739801SMiguel Ojeda         ]
5999*c3739801SMiguel Ojeda     )]
6000*c3739801SMiguel Ojeda     #[must_use = "callers should check the return value to see if the operation succeeded"]
6001*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
6002*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
6003*c3739801SMiguel Ojeda     #[allow(clippy::mut_from_ref)] // False positive: `&self -> &mut [u8]`
6004*c3739801SMiguel Ojeda     fn write_to_prefix(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>>
6005*c3739801SMiguel Ojeda     where
6006*c3739801SMiguel Ojeda         Self: Immutable,
6007*c3739801SMiguel Ojeda     {
6008*c3739801SMiguel Ojeda         let src = self.as_bytes();
6009*c3739801SMiguel Ojeda         match dst.get_mut(..src.len()) {
6010*c3739801SMiguel Ojeda             Some(dst) => {
6011*c3739801SMiguel Ojeda                 // SAFETY: Within this branch of the `match`, we have ensured
6012*c3739801SMiguel Ojeda                 // through fallible subslicing that `dst.len()` is equal to
6013*c3739801SMiguel Ojeda                 // `src.len()`. Neither the size of the source nor the size of
6014*c3739801SMiguel Ojeda                 // the destination change between the above subslicing operation
6015*c3739801SMiguel Ojeda                 // and the invocation of `copy_unchecked`.
6016*c3739801SMiguel Ojeda                 unsafe { util::copy_unchecked(src, dst) }
6017*c3739801SMiguel Ojeda                 Ok(())
6018*c3739801SMiguel Ojeda             }
6019*c3739801SMiguel Ojeda             None => Err(SizeError::new(self)),
6020*c3739801SMiguel Ojeda         }
6021*c3739801SMiguel Ojeda     }
6022*c3739801SMiguel Ojeda 
6023*c3739801SMiguel Ojeda     /// Writes a copy of `self` to the suffix of `dst`.
6024*c3739801SMiguel Ojeda     ///
6025*c3739801SMiguel Ojeda     /// `write_to_suffix` writes `self` to the last `size_of_val(self)` bytes of
6026*c3739801SMiguel Ojeda     /// `dst`. If `dst.len() < size_of_val(self)`, it returns `Err`.
6027*c3739801SMiguel Ojeda     ///
6028*c3739801SMiguel Ojeda     /// # Examples
6029*c3739801SMiguel Ojeda     ///
6030*c3739801SMiguel Ojeda     /// ```
6031*c3739801SMiguel Ojeda     /// use zerocopy::IntoBytes;
6032*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
6033*c3739801SMiguel Ojeda     ///
6034*c3739801SMiguel Ojeda     /// #[derive(IntoBytes, Immutable)]
6035*c3739801SMiguel Ojeda     /// #[repr(C)]
6036*c3739801SMiguel Ojeda     /// struct PacketHeader {
6037*c3739801SMiguel Ojeda     ///     src_port: [u8; 2],
6038*c3739801SMiguel Ojeda     ///     dst_port: [u8; 2],
6039*c3739801SMiguel Ojeda     ///     length: [u8; 2],
6040*c3739801SMiguel Ojeda     ///     checksum: [u8; 2],
6041*c3739801SMiguel Ojeda     /// }
6042*c3739801SMiguel Ojeda     ///
6043*c3739801SMiguel Ojeda     /// let header = PacketHeader {
6044*c3739801SMiguel Ojeda     ///     src_port: [0, 1],
6045*c3739801SMiguel Ojeda     ///     dst_port: [2, 3],
6046*c3739801SMiguel Ojeda     ///     length: [4, 5],
6047*c3739801SMiguel Ojeda     ///     checksum: [6, 7],
6048*c3739801SMiguel Ojeda     /// };
6049*c3739801SMiguel Ojeda     ///
6050*c3739801SMiguel Ojeda     /// let mut bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
6051*c3739801SMiguel Ojeda     ///
6052*c3739801SMiguel Ojeda     /// header.write_to_suffix(&mut bytes[..]);
6053*c3739801SMiguel Ojeda     ///
6054*c3739801SMiguel Ojeda     /// assert_eq!(bytes, [0, 0, 0, 1, 2, 3, 4, 5, 6, 7]);
6055*c3739801SMiguel Ojeda     ///
6056*c3739801SMiguel Ojeda     /// let mut insufficient_bytes = &mut [0, 0][..];
6057*c3739801SMiguel Ojeda     ///
6058*c3739801SMiguel Ojeda     /// let write_result = header.write_to_suffix(insufficient_bytes);
6059*c3739801SMiguel Ojeda     ///
6060*c3739801SMiguel Ojeda     /// assert!(write_result.is_err());
6061*c3739801SMiguel Ojeda     /// assert_eq!(insufficient_bytes, [0, 0]);
6062*c3739801SMiguel Ojeda     /// ```
6063*c3739801SMiguel Ojeda     ///
6064*c3739801SMiguel Ojeda     /// If insufficient target bytes are provided, `write_to_suffix` returns
6065*c3739801SMiguel Ojeda     /// `Err` and leaves the target bytes unmodified:
6066*c3739801SMiguel Ojeda     ///
6067*c3739801SMiguel Ojeda     /// ```
6068*c3739801SMiguel Ojeda     /// # use zerocopy::IntoBytes;
6069*c3739801SMiguel Ojeda     /// # let header = u128::MAX;
6070*c3739801SMiguel Ojeda     /// let mut insufficient_bytes = &mut [0, 0][..];
6071*c3739801SMiguel Ojeda     ///
6072*c3739801SMiguel Ojeda     /// let write_result = header.write_to_suffix(insufficient_bytes);
6073*c3739801SMiguel Ojeda     ///
6074*c3739801SMiguel Ojeda     /// assert!(write_result.is_err());
6075*c3739801SMiguel Ojeda     /// assert_eq!(insufficient_bytes, [0, 0]);
6076*c3739801SMiguel Ojeda     /// ```
6077*c3739801SMiguel Ojeda     ///
6078*c3739801SMiguel Ojeda     #[doc = codegen_section!(
6079*c3739801SMiguel Ojeda         header = "h5",
6080*c3739801SMiguel Ojeda         bench = "write_to_suffix",
6081*c3739801SMiguel Ojeda         format = "coco",
6082*c3739801SMiguel Ojeda         arity = 2,
6083*c3739801SMiguel Ojeda         [
6084*c3739801SMiguel Ojeda             open
6085*c3739801SMiguel Ojeda             @index 1
6086*c3739801SMiguel Ojeda             @title "Sized"
6087*c3739801SMiguel Ojeda             @variant "static_size"
6088*c3739801SMiguel Ojeda         ],
6089*c3739801SMiguel Ojeda         [
6090*c3739801SMiguel Ojeda             @index 2
6091*c3739801SMiguel Ojeda             @title "Unsized"
6092*c3739801SMiguel Ojeda             @variant "dynamic_size"
6093*c3739801SMiguel Ojeda         ]
6094*c3739801SMiguel Ojeda     )]
6095*c3739801SMiguel Ojeda     #[must_use = "callers should check the return value to see if the operation succeeded"]
6096*c3739801SMiguel Ojeda     #[cfg_attr(zerocopy_inline_always, inline(always))]
6097*c3739801SMiguel Ojeda     #[cfg_attr(not(zerocopy_inline_always), inline)]
6098*c3739801SMiguel Ojeda     #[allow(clippy::mut_from_ref)] // False positive: `&self -> &mut [u8]`
6099*c3739801SMiguel Ojeda     fn write_to_suffix(&self, dst: &mut [u8]) -> Result<(), SizeError<&Self, &mut [u8]>>
6100*c3739801SMiguel Ojeda     where
6101*c3739801SMiguel Ojeda         Self: Immutable,
6102*c3739801SMiguel Ojeda     {
6103*c3739801SMiguel Ojeda         let src = self.as_bytes();
6104*c3739801SMiguel Ojeda         let start = if let Some(start) = dst.len().checked_sub(src.len()) {
6105*c3739801SMiguel Ojeda             start
6106*c3739801SMiguel Ojeda         } else {
6107*c3739801SMiguel Ojeda             return Err(SizeError::new(self));
6108*c3739801SMiguel Ojeda         };
6109*c3739801SMiguel Ojeda         let dst = if let Some(dst) = dst.get_mut(start..) {
6110*c3739801SMiguel Ojeda             dst
6111*c3739801SMiguel Ojeda         } else {
6112*c3739801SMiguel Ojeda             // get_mut() should never return None here. We return a `SizeError`
6113*c3739801SMiguel Ojeda             // rather than .unwrap() because in the event the branch is not
6114*c3739801SMiguel Ojeda             // optimized away, returning a value is generally lighter-weight
6115*c3739801SMiguel Ojeda             // than panicking.
6116*c3739801SMiguel Ojeda             return Err(SizeError::new(self));
6117*c3739801SMiguel Ojeda         };
6118*c3739801SMiguel Ojeda         // SAFETY: Through fallible subslicing of `dst`, we have ensured that
6119*c3739801SMiguel Ojeda         // `dst.len()` is equal to `src.len()`. Neither the size of the source
6120*c3739801SMiguel Ojeda         // nor the size of the destination change between the above subslicing
6121*c3739801SMiguel Ojeda         // operation and the invocation of `copy_unchecked`.
6122*c3739801SMiguel Ojeda         unsafe {
6123*c3739801SMiguel Ojeda             util::copy_unchecked(src, dst);
6124*c3739801SMiguel Ojeda         }
6125*c3739801SMiguel Ojeda         Ok(())
6126*c3739801SMiguel Ojeda     }
6127*c3739801SMiguel Ojeda 
6128*c3739801SMiguel Ojeda     /// Writes a copy of `self` to an `io::Write`.
6129*c3739801SMiguel Ojeda     ///
6130*c3739801SMiguel Ojeda     /// This is a shorthand for `dst.write_all(self.as_bytes())`, and is useful
6131*c3739801SMiguel Ojeda     /// for interfacing with operating system byte sinks (files, sockets, etc.).
6132*c3739801SMiguel Ojeda     ///
6133*c3739801SMiguel Ojeda     /// # Examples
6134*c3739801SMiguel Ojeda     ///
6135*c3739801SMiguel Ojeda     /// ```no_run
6136*c3739801SMiguel Ojeda     /// use zerocopy::{byteorder::big_endian::U16, FromBytes, IntoBytes};
6137*c3739801SMiguel Ojeda     /// use std::fs::File;
6138*c3739801SMiguel Ojeda     /// # use zerocopy_derive::*;
6139*c3739801SMiguel Ojeda     ///
6140*c3739801SMiguel Ojeda     /// #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
6141*c3739801SMiguel Ojeda     /// #[repr(C, packed)]
6142*c3739801SMiguel Ojeda     /// struct GrayscaleImage {
6143*c3739801SMiguel Ojeda     ///     height: U16,
6144*c3739801SMiguel Ojeda     ///     width: U16,
6145*c3739801SMiguel Ojeda     ///     pixels: [U16],
6146*c3739801SMiguel Ojeda     /// }
6147*c3739801SMiguel Ojeda     ///
6148*c3739801SMiguel Ojeda     /// let image = GrayscaleImage::ref_from_bytes(&[0, 0, 0, 0][..]).unwrap();
6149*c3739801SMiguel Ojeda     /// let mut file = File::create("image.bin").unwrap();
6150*c3739801SMiguel Ojeda     /// image.write_to_io(&mut file).unwrap();
6151*c3739801SMiguel Ojeda     /// ```
6152*c3739801SMiguel Ojeda     ///
6153*c3739801SMiguel Ojeda     /// If the write fails, `write_to_io` returns `Err` and a partial write may
6154*c3739801SMiguel Ojeda     /// have occurred; e.g.:
6155*c3739801SMiguel Ojeda     ///
6156*c3739801SMiguel Ojeda     /// ```
6157*c3739801SMiguel Ojeda     /// # use zerocopy::IntoBytes;
6158*c3739801SMiguel Ojeda     ///
6159*c3739801SMiguel Ojeda     /// let src = u128::MAX;
6160*c3739801SMiguel Ojeda     /// let mut dst = [0u8; 2];
6161*c3739801SMiguel Ojeda     ///
6162*c3739801SMiguel Ojeda     /// let write_result = src.write_to_io(&mut dst[..]);
6163*c3739801SMiguel Ojeda     ///
6164*c3739801SMiguel Ojeda     /// assert!(write_result.is_err());
6165*c3739801SMiguel Ojeda     /// assert_eq!(dst, [255, 255]);
6166*c3739801SMiguel Ojeda     /// ```
6167*c3739801SMiguel Ojeda     #[cfg(feature = "std")]
6168*c3739801SMiguel Ojeda     #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
6169*c3739801SMiguel Ojeda     #[inline(always)]
6170*c3739801SMiguel Ojeda     fn write_to_io<W>(&self, mut dst: W) -> io::Result<()>
6171*c3739801SMiguel Ojeda     where
6172*c3739801SMiguel Ojeda         Self: Immutable,
6173*c3739801SMiguel Ojeda         W: io::Write,
6174*c3739801SMiguel Ojeda     {
6175*c3739801SMiguel Ojeda         dst.write_all(self.as_bytes())
6176*c3739801SMiguel Ojeda     }
6177*c3739801SMiguel Ojeda 
6178*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "`IntoBytes::as_bytes_mut` was renamed to `as_mut_bytes`")]
6179*c3739801SMiguel Ojeda     #[doc(hidden)]
6180*c3739801SMiguel Ojeda     #[inline]
6181*c3739801SMiguel Ojeda     fn as_bytes_mut(&mut self) -> &mut [u8]
6182*c3739801SMiguel Ojeda     where
6183*c3739801SMiguel Ojeda         Self: FromBytes,
6184*c3739801SMiguel Ojeda     {
6185*c3739801SMiguel Ojeda         self.as_mut_bytes()
6186*c3739801SMiguel Ojeda     }
6187*c3739801SMiguel Ojeda }
6188*c3739801SMiguel Ojeda 
6189*c3739801SMiguel Ojeda /// Analyzes whether a type is [`Unaligned`].
6190*c3739801SMiguel Ojeda ///
6191*c3739801SMiguel Ojeda /// This derive analyzes, at compile time, whether the annotated type satisfies
6192*c3739801SMiguel Ojeda /// the [safety conditions] of `Unaligned` and implements `Unaligned` if it is
6193*c3739801SMiguel Ojeda /// sound to do so. This derive can be applied to structs, enums, and unions;
6194*c3739801SMiguel Ojeda /// e.g.:
6195*c3739801SMiguel Ojeda ///
6196*c3739801SMiguel Ojeda /// ```
6197*c3739801SMiguel Ojeda /// # use zerocopy_derive::Unaligned;
6198*c3739801SMiguel Ojeda /// #[derive(Unaligned)]
6199*c3739801SMiguel Ojeda /// #[repr(C)]
6200*c3739801SMiguel Ojeda /// struct MyStruct {
6201*c3739801SMiguel Ojeda /// # /*
6202*c3739801SMiguel Ojeda ///     ...
6203*c3739801SMiguel Ojeda /// # */
6204*c3739801SMiguel Ojeda /// }
6205*c3739801SMiguel Ojeda ///
6206*c3739801SMiguel Ojeda /// #[derive(Unaligned)]
6207*c3739801SMiguel Ojeda /// #[repr(u8)]
6208*c3739801SMiguel Ojeda /// enum MyEnum {
6209*c3739801SMiguel Ojeda /// #   Variant0,
6210*c3739801SMiguel Ojeda /// # /*
6211*c3739801SMiguel Ojeda ///     ...
6212*c3739801SMiguel Ojeda /// # */
6213*c3739801SMiguel Ojeda /// }
6214*c3739801SMiguel Ojeda ///
6215*c3739801SMiguel Ojeda /// #[derive(Unaligned)]
6216*c3739801SMiguel Ojeda /// #[repr(packed)]
6217*c3739801SMiguel Ojeda /// union MyUnion {
6218*c3739801SMiguel Ojeda /// #   variant: u8,
6219*c3739801SMiguel Ojeda /// # /*
6220*c3739801SMiguel Ojeda ///     ...
6221*c3739801SMiguel Ojeda /// # */
6222*c3739801SMiguel Ojeda /// }
6223*c3739801SMiguel Ojeda /// ```
6224*c3739801SMiguel Ojeda ///
6225*c3739801SMiguel Ojeda /// # Analysis
6226*c3739801SMiguel Ojeda ///
6227*c3739801SMiguel Ojeda /// *This section describes, roughly, the analysis performed by this derive to
6228*c3739801SMiguel Ojeda /// determine whether it is sound to implement `Unaligned` for a given type.
6229*c3739801SMiguel Ojeda /// Unless you are modifying the implementation of this derive, or attempting to
6230*c3739801SMiguel Ojeda /// manually implement `Unaligned` for a type yourself, you don't need to read
6231*c3739801SMiguel Ojeda /// this section.*
6232*c3739801SMiguel Ojeda ///
6233*c3739801SMiguel Ojeda /// If a type has the following properties, then this derive can implement
6234*c3739801SMiguel Ojeda /// `Unaligned` for that type:
6235*c3739801SMiguel Ojeda ///
6236*c3739801SMiguel Ojeda /// - If the type is a struct or union:
6237*c3739801SMiguel Ojeda ///   - If `repr(align(N))` is provided, `N` must equal 1.
6238*c3739801SMiguel Ojeda ///   - If the type is `repr(C)` or `repr(transparent)`, all fields must be
6239*c3739801SMiguel Ojeda ///     [`Unaligned`].
6240*c3739801SMiguel Ojeda ///   - If the type is not `repr(C)` or `repr(transparent)`, it must be
6241*c3739801SMiguel Ojeda ///     `repr(packed)` or `repr(packed(1))`.
6242*c3739801SMiguel Ojeda /// - If the type is an enum:
6243*c3739801SMiguel Ojeda ///   - If `repr(align(N))` is provided, `N` must equal 1.
6244*c3739801SMiguel Ojeda ///   - It must be a field-less enum (meaning that all variants have no fields).
6245*c3739801SMiguel Ojeda ///   - It must be `repr(i8)` or `repr(u8)`.
6246*c3739801SMiguel Ojeda ///
6247*c3739801SMiguel Ojeda /// [safety conditions]: trait@Unaligned#safety
6248*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
6249*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
6250*c3739801SMiguel Ojeda pub use zerocopy_derive::Unaligned;
6251*c3739801SMiguel Ojeda 
6252*c3739801SMiguel Ojeda /// Types with no alignment requirement.
6253*c3739801SMiguel Ojeda ///
6254*c3739801SMiguel Ojeda /// If `T: Unaligned`, then `align_of::<T>() == 1`.
6255*c3739801SMiguel Ojeda ///
6256*c3739801SMiguel Ojeda /// # Implementation
6257*c3739801SMiguel Ojeda ///
6258*c3739801SMiguel Ojeda /// **Do not implement this trait yourself!** Instead, use
6259*c3739801SMiguel Ojeda /// [`#[derive(Unaligned)]`][derive]; e.g.:
6260*c3739801SMiguel Ojeda ///
6261*c3739801SMiguel Ojeda /// ```
6262*c3739801SMiguel Ojeda /// # use zerocopy_derive::Unaligned;
6263*c3739801SMiguel Ojeda /// #[derive(Unaligned)]
6264*c3739801SMiguel Ojeda /// #[repr(C)]
6265*c3739801SMiguel Ojeda /// struct MyStruct {
6266*c3739801SMiguel Ojeda /// # /*
6267*c3739801SMiguel Ojeda ///     ...
6268*c3739801SMiguel Ojeda /// # */
6269*c3739801SMiguel Ojeda /// }
6270*c3739801SMiguel Ojeda ///
6271*c3739801SMiguel Ojeda /// #[derive(Unaligned)]
6272*c3739801SMiguel Ojeda /// #[repr(u8)]
6273*c3739801SMiguel Ojeda /// enum MyEnum {
6274*c3739801SMiguel Ojeda /// #   Variant0,
6275*c3739801SMiguel Ojeda /// # /*
6276*c3739801SMiguel Ojeda ///     ...
6277*c3739801SMiguel Ojeda /// # */
6278*c3739801SMiguel Ojeda /// }
6279*c3739801SMiguel Ojeda ///
6280*c3739801SMiguel Ojeda /// #[derive(Unaligned)]
6281*c3739801SMiguel Ojeda /// #[repr(packed)]
6282*c3739801SMiguel Ojeda /// union MyUnion {
6283*c3739801SMiguel Ojeda /// #   variant: u8,
6284*c3739801SMiguel Ojeda /// # /*
6285*c3739801SMiguel Ojeda ///     ...
6286*c3739801SMiguel Ojeda /// # */
6287*c3739801SMiguel Ojeda /// }
6288*c3739801SMiguel Ojeda /// ```
6289*c3739801SMiguel Ojeda ///
6290*c3739801SMiguel Ojeda /// This derive performs a sophisticated, compile-time safety analysis to
6291*c3739801SMiguel Ojeda /// determine whether a type is `Unaligned`.
6292*c3739801SMiguel Ojeda ///
6293*c3739801SMiguel Ojeda /// # Safety
6294*c3739801SMiguel Ojeda ///
6295*c3739801SMiguel Ojeda /// *This section describes what is required in order for `T: Unaligned`, and
6296*c3739801SMiguel Ojeda /// what unsafe code may assume of such types. If you don't plan on implementing
6297*c3739801SMiguel Ojeda /// `Unaligned` manually, and you don't plan on writing unsafe code that
6298*c3739801SMiguel Ojeda /// operates on `Unaligned` types, then you don't need to read this section.*
6299*c3739801SMiguel Ojeda ///
6300*c3739801SMiguel Ojeda /// If `T: Unaligned`, then unsafe code may assume that it is sound to produce a
6301*c3739801SMiguel Ojeda /// reference to `T` at any memory location regardless of alignment. If a type
6302*c3739801SMiguel Ojeda /// is marked as `Unaligned` which violates this contract, it may cause
6303*c3739801SMiguel Ojeda /// undefined behavior.
6304*c3739801SMiguel Ojeda ///
6305*c3739801SMiguel Ojeda /// `#[derive(Unaligned)]` only permits [types which satisfy these
6306*c3739801SMiguel Ojeda /// requirements][derive-analysis].
6307*c3739801SMiguel Ojeda ///
6308*c3739801SMiguel Ojeda #[cfg_attr(
6309*c3739801SMiguel Ojeda     feature = "derive",
6310*c3739801SMiguel Ojeda     doc = "[derive]: zerocopy_derive::Unaligned",
6311*c3739801SMiguel Ojeda     doc = "[derive-analysis]: zerocopy_derive::Unaligned#analysis"
6312*c3739801SMiguel Ojeda )]
6313*c3739801SMiguel Ojeda #[cfg_attr(
6314*c3739801SMiguel Ojeda     not(feature = "derive"),
6315*c3739801SMiguel Ojeda     doc = concat!("[derive]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Unaligned.html"),
6316*c3739801SMiguel Ojeda     doc = concat!("[derive-analysis]: https://docs.rs/zerocopy/", env!("CARGO_PKG_VERSION"), "/zerocopy/derive.Unaligned.html#analysis"),
6317*c3739801SMiguel Ojeda )]
6318*c3739801SMiguel Ojeda #[cfg_attr(
6319*c3739801SMiguel Ojeda     not(no_zerocopy_diagnostic_on_unimplemented_1_78_0),
6320*c3739801SMiguel Ojeda     diagnostic::on_unimplemented(note = "Consider adding `#[derive(Unaligned)]` to `{Self}`")
6321*c3739801SMiguel Ojeda )]
6322*c3739801SMiguel Ojeda pub unsafe trait Unaligned {
6323*c3739801SMiguel Ojeda     // The `Self: Sized` bound makes it so that `Unaligned` is still object
6324*c3739801SMiguel Ojeda     // safe.
6325*c3739801SMiguel Ojeda     #[doc(hidden)]
6326*c3739801SMiguel Ojeda     fn only_derive_is_allowed_to_implement_this_trait()
6327*c3739801SMiguel Ojeda     where
6328*c3739801SMiguel Ojeda         Self: Sized;
6329*c3739801SMiguel Ojeda }
6330*c3739801SMiguel Ojeda 
6331*c3739801SMiguel Ojeda /// Derives optimized [`PartialEq`] and [`Eq`] implementations.
6332*c3739801SMiguel Ojeda ///
6333*c3739801SMiguel Ojeda /// This derive can be applied to structs and enums implementing both
6334*c3739801SMiguel Ojeda /// [`Immutable`] and [`IntoBytes`]; e.g.:
6335*c3739801SMiguel Ojeda ///
6336*c3739801SMiguel Ojeda /// ```
6337*c3739801SMiguel Ojeda /// # use zerocopy_derive::{ByteEq, Immutable, IntoBytes};
6338*c3739801SMiguel Ojeda /// #[derive(ByteEq, Immutable, IntoBytes)]
6339*c3739801SMiguel Ojeda /// #[repr(C)]
6340*c3739801SMiguel Ojeda /// struct MyStruct {
6341*c3739801SMiguel Ojeda /// # /*
6342*c3739801SMiguel Ojeda ///     ...
6343*c3739801SMiguel Ojeda /// # */
6344*c3739801SMiguel Ojeda /// }
6345*c3739801SMiguel Ojeda ///
6346*c3739801SMiguel Ojeda /// #[derive(ByteEq, Immutable, IntoBytes)]
6347*c3739801SMiguel Ojeda /// #[repr(u8)]
6348*c3739801SMiguel Ojeda /// enum MyEnum {
6349*c3739801SMiguel Ojeda /// #   Variant,
6350*c3739801SMiguel Ojeda /// # /*
6351*c3739801SMiguel Ojeda ///     ...
6352*c3739801SMiguel Ojeda /// # */
6353*c3739801SMiguel Ojeda /// }
6354*c3739801SMiguel Ojeda /// ```
6355*c3739801SMiguel Ojeda ///
6356*c3739801SMiguel Ojeda /// The standard library's [`derive(Eq, PartialEq)`][derive@PartialEq] computes
6357*c3739801SMiguel Ojeda /// equality by individually comparing each field. Instead, the implementation
6358*c3739801SMiguel Ojeda /// of [`PartialEq::eq`] emitted by `derive(ByteHash)` converts the entirety of
6359*c3739801SMiguel Ojeda /// `self` and `other` to byte slices and compares those slices for equality.
6360*c3739801SMiguel Ojeda /// This may have performance advantages.
6361*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
6362*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
6363*c3739801SMiguel Ojeda pub use zerocopy_derive::ByteEq;
6364*c3739801SMiguel Ojeda /// Derives an optimized [`Hash`] implementation.
6365*c3739801SMiguel Ojeda ///
6366*c3739801SMiguel Ojeda /// This derive can be applied to structs and enums implementing both
6367*c3739801SMiguel Ojeda /// [`Immutable`] and [`IntoBytes`]; e.g.:
6368*c3739801SMiguel Ojeda ///
6369*c3739801SMiguel Ojeda /// ```
6370*c3739801SMiguel Ojeda /// # use zerocopy_derive::{ByteHash, Immutable, IntoBytes};
6371*c3739801SMiguel Ojeda /// #[derive(ByteHash, Immutable, IntoBytes)]
6372*c3739801SMiguel Ojeda /// #[repr(C)]
6373*c3739801SMiguel Ojeda /// struct MyStruct {
6374*c3739801SMiguel Ojeda /// # /*
6375*c3739801SMiguel Ojeda ///     ...
6376*c3739801SMiguel Ojeda /// # */
6377*c3739801SMiguel Ojeda /// }
6378*c3739801SMiguel Ojeda ///
6379*c3739801SMiguel Ojeda /// #[derive(ByteHash, Immutable, IntoBytes)]
6380*c3739801SMiguel Ojeda /// #[repr(u8)]
6381*c3739801SMiguel Ojeda /// enum MyEnum {
6382*c3739801SMiguel Ojeda /// #   Variant,
6383*c3739801SMiguel Ojeda /// # /*
6384*c3739801SMiguel Ojeda ///     ...
6385*c3739801SMiguel Ojeda /// # */
6386*c3739801SMiguel Ojeda /// }
6387*c3739801SMiguel Ojeda /// ```
6388*c3739801SMiguel Ojeda ///
6389*c3739801SMiguel Ojeda /// The standard library's [`derive(Hash)`][derive@Hash] produces hashes by
6390*c3739801SMiguel Ojeda /// individually hashing each field and combining the results. Instead, the
6391*c3739801SMiguel Ojeda /// implementations of [`Hash::hash()`] and [`Hash::hash_slice()`] generated by
6392*c3739801SMiguel Ojeda /// `derive(ByteHash)` convert the entirety of `self` to a byte slice and hashes
6393*c3739801SMiguel Ojeda /// it in a single call to [`Hasher::write()`]. This may have performance
6394*c3739801SMiguel Ojeda /// advantages.
6395*c3739801SMiguel Ojeda ///
6396*c3739801SMiguel Ojeda /// [`Hash`]: core::hash::Hash
6397*c3739801SMiguel Ojeda /// [`Hash::hash()`]: core::hash::Hash::hash()
6398*c3739801SMiguel Ojeda /// [`Hash::hash_slice()`]: core::hash::Hash::hash_slice()
6399*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
6400*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
6401*c3739801SMiguel Ojeda pub use zerocopy_derive::ByteHash;
6402*c3739801SMiguel Ojeda /// Implements [`SplitAt`].
6403*c3739801SMiguel Ojeda ///
6404*c3739801SMiguel Ojeda /// This derive can be applied to structs; e.g.:
6405*c3739801SMiguel Ojeda ///
6406*c3739801SMiguel Ojeda /// ```
6407*c3739801SMiguel Ojeda /// # use zerocopy_derive::{ByteEq, Immutable, IntoBytes};
6408*c3739801SMiguel Ojeda /// #[derive(ByteEq, Immutable, IntoBytes)]
6409*c3739801SMiguel Ojeda /// #[repr(C)]
6410*c3739801SMiguel Ojeda /// struct MyStruct {
6411*c3739801SMiguel Ojeda /// # /*
6412*c3739801SMiguel Ojeda ///     ...
6413*c3739801SMiguel Ojeda /// # */
6414*c3739801SMiguel Ojeda /// }
6415*c3739801SMiguel Ojeda /// ```
6416*c3739801SMiguel Ojeda #[cfg(any(feature = "derive", test))]
6417*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))]
6418*c3739801SMiguel Ojeda pub use zerocopy_derive::SplitAt;
6419*c3739801SMiguel Ojeda 
6420*c3739801SMiguel Ojeda #[cfg(feature = "alloc")]
6421*c3739801SMiguel Ojeda #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
6422*c3739801SMiguel Ojeda #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
6423*c3739801SMiguel Ojeda mod alloc_support {
6424*c3739801SMiguel Ojeda     use super::*;
6425*c3739801SMiguel Ojeda 
6426*c3739801SMiguel Ojeda     /// Extends a `Vec<T>` by pushing `additional` new items onto the end of the
6427*c3739801SMiguel Ojeda     /// vector. The new items are initialized with zeros.
6428*c3739801SMiguel Ojeda     #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
6429*c3739801SMiguel Ojeda     #[doc(hidden)]
6430*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "moved to `FromZeros`")]
6431*c3739801SMiguel Ojeda     #[inline(always)]
6432*c3739801SMiguel Ojeda     pub fn extend_vec_zeroed<T: FromZeros>(
6433*c3739801SMiguel Ojeda         v: &mut Vec<T>,
6434*c3739801SMiguel Ojeda         additional: usize,
6435*c3739801SMiguel Ojeda     ) -> Result<(), AllocError> {
6436*c3739801SMiguel Ojeda         <T as FromZeros>::extend_vec_zeroed(v, additional)
6437*c3739801SMiguel Ojeda     }
6438*c3739801SMiguel Ojeda 
6439*c3739801SMiguel Ojeda     /// Inserts `additional` new items into `Vec<T>` at `position`. The new
6440*c3739801SMiguel Ojeda     /// items are initialized with zeros.
6441*c3739801SMiguel Ojeda     ///
6442*c3739801SMiguel Ojeda     /// # Panics
6443*c3739801SMiguel Ojeda     ///
6444*c3739801SMiguel Ojeda     /// Panics if `position > v.len()`.
6445*c3739801SMiguel Ojeda     #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
6446*c3739801SMiguel Ojeda     #[doc(hidden)]
6447*c3739801SMiguel Ojeda     #[deprecated(since = "0.8.0", note = "moved to `FromZeros`")]
6448*c3739801SMiguel Ojeda     #[inline(always)]
6449*c3739801SMiguel Ojeda     pub fn insert_vec_zeroed<T: FromZeros>(
6450*c3739801SMiguel Ojeda         v: &mut Vec<T>,
6451*c3739801SMiguel Ojeda         position: usize,
6452*c3739801SMiguel Ojeda         additional: usize,
6453*c3739801SMiguel Ojeda     ) -> Result<(), AllocError> {
6454*c3739801SMiguel Ojeda         <T as FromZeros>::insert_vec_zeroed(v, position, additional)
6455*c3739801SMiguel Ojeda     }
6456*c3739801SMiguel Ojeda }
6457*c3739801SMiguel Ojeda 
6458*c3739801SMiguel Ojeda #[cfg(feature = "alloc")]
6459*c3739801SMiguel Ojeda #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
6460*c3739801SMiguel Ojeda #[doc(hidden)]
6461*c3739801SMiguel Ojeda pub use alloc_support::*;
6462*c3739801SMiguel Ojeda 
6463*c3739801SMiguel Ojeda #[cfg(test)]
6464*c3739801SMiguel Ojeda #[allow(clippy::assertions_on_result_states, clippy::unreadable_literal)]
6465*c3739801SMiguel Ojeda mod tests {
6466*c3739801SMiguel Ojeda     use static_assertions::assert_impl_all;
6467*c3739801SMiguel Ojeda 
6468*c3739801SMiguel Ojeda     use super::*;
6469*c3739801SMiguel Ojeda     use crate::util::testutil::*;
6470*c3739801SMiguel Ojeda 
6471*c3739801SMiguel Ojeda     // An unsized type.
6472*c3739801SMiguel Ojeda     //
6473*c3739801SMiguel Ojeda     // This is used to test the custom derives of our traits. The `[u8]` type
6474*c3739801SMiguel Ojeda     // gets a hand-rolled impl, so it doesn't exercise our custom derives.
6475*c3739801SMiguel Ojeda     #[derive(Debug, Eq, PartialEq, FromBytes, IntoBytes, Unaligned, Immutable)]
6476*c3739801SMiguel Ojeda     #[repr(transparent)]
6477*c3739801SMiguel Ojeda     struct Unsized([u8]);
6478*c3739801SMiguel Ojeda 
6479*c3739801SMiguel Ojeda     impl Unsized {
6480*c3739801SMiguel Ojeda         fn from_mut_slice(slc: &mut [u8]) -> &mut Unsized {
6481*c3739801SMiguel Ojeda             // SAFETY: This *probably* sound - since the layouts of `[u8]` and
6482*c3739801SMiguel Ojeda             // `Unsized` are the same, so are the layouts of `&mut [u8]` and
6483*c3739801SMiguel Ojeda             // `&mut Unsized`. [1] Even if it turns out that this isn't actually
6484*c3739801SMiguel Ojeda             // guaranteed by the language spec, we can just change this since
6485*c3739801SMiguel Ojeda             // it's in test code.
6486*c3739801SMiguel Ojeda             //
6487*c3739801SMiguel Ojeda             // [1] https://github.com/rust-lang/unsafe-code-guidelines/issues/375
6488*c3739801SMiguel Ojeda             unsafe { mem::transmute(slc) }
6489*c3739801SMiguel Ojeda         }
6490*c3739801SMiguel Ojeda     }
6491*c3739801SMiguel Ojeda 
6492*c3739801SMiguel Ojeda     #[test]
6493*c3739801SMiguel Ojeda     fn test_known_layout() {
6494*c3739801SMiguel Ojeda         // Test that `$ty` and `ManuallyDrop<$ty>` have the expected layout.
6495*c3739801SMiguel Ojeda         // Test that `PhantomData<$ty>` has the same layout as `()` regardless
6496*c3739801SMiguel Ojeda         // of `$ty`.
6497*c3739801SMiguel Ojeda         macro_rules! test {
6498*c3739801SMiguel Ojeda             ($ty:ty, $expect:expr) => {
6499*c3739801SMiguel Ojeda                 let expect = $expect;
6500*c3739801SMiguel Ojeda                 assert_eq!(<$ty as KnownLayout>::LAYOUT, expect);
6501*c3739801SMiguel Ojeda                 assert_eq!(<ManuallyDrop<$ty> as KnownLayout>::LAYOUT, expect);
6502*c3739801SMiguel Ojeda                 assert_eq!(<PhantomData<$ty> as KnownLayout>::LAYOUT, <() as KnownLayout>::LAYOUT);
6503*c3739801SMiguel Ojeda             };
6504*c3739801SMiguel Ojeda         }
6505*c3739801SMiguel Ojeda 
6506*c3739801SMiguel Ojeda         let layout =
6507*c3739801SMiguel Ojeda             |offset, align, trailing_slice_elem_size, statically_shallow_unpadded| DstLayout {
6508*c3739801SMiguel Ojeda                 align: NonZeroUsize::new(align).unwrap(),
6509*c3739801SMiguel Ojeda                 size_info: match trailing_slice_elem_size {
6510*c3739801SMiguel Ojeda                     None => SizeInfo::Sized { size: offset },
6511*c3739801SMiguel Ojeda                     Some(elem_size) => {
6512*c3739801SMiguel Ojeda                         SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size })
6513*c3739801SMiguel Ojeda                     }
6514*c3739801SMiguel Ojeda                 },
6515*c3739801SMiguel Ojeda                 statically_shallow_unpadded,
6516*c3739801SMiguel Ojeda             };
6517*c3739801SMiguel Ojeda 
6518*c3739801SMiguel Ojeda         test!((), layout(0, 1, None, false));
6519*c3739801SMiguel Ojeda         test!(u8, layout(1, 1, None, false));
6520*c3739801SMiguel Ojeda         // Use `align_of` because `u64` alignment may be smaller than 8 on some
6521*c3739801SMiguel Ojeda         // platforms.
6522*c3739801SMiguel Ojeda         test!(u64, layout(8, mem::align_of::<u64>(), None, false));
6523*c3739801SMiguel Ojeda         test!(AU64, layout(8, 8, None, false));
6524*c3739801SMiguel Ojeda 
6525*c3739801SMiguel Ojeda         test!(Option<&'static ()>, usize::LAYOUT);
6526*c3739801SMiguel Ojeda 
6527*c3739801SMiguel Ojeda         test!([()], layout(0, 1, Some(0), true));
6528*c3739801SMiguel Ojeda         test!([u8], layout(0, 1, Some(1), true));
6529*c3739801SMiguel Ojeda         test!(str, layout(0, 1, Some(1), true));
6530*c3739801SMiguel Ojeda     }
6531*c3739801SMiguel Ojeda 
6532*c3739801SMiguel Ojeda     #[cfg(feature = "derive")]
6533*c3739801SMiguel Ojeda     #[test]
6534*c3739801SMiguel Ojeda     fn test_known_layout_derive() {
6535*c3739801SMiguel Ojeda         // In this and other files (`late_compile_pass.rs`,
6536*c3739801SMiguel Ojeda         // `mid_compile_pass.rs`, and `struct.rs`), we test success and failure
6537*c3739801SMiguel Ojeda         // modes of `derive(KnownLayout)` for the following combination of
6538*c3739801SMiguel Ojeda         // properties:
6539*c3739801SMiguel Ojeda         //
6540*c3739801SMiguel Ojeda         // +------------+--------------------------------------+-----------+
6541*c3739801SMiguel Ojeda         // |            |      trailing field properties       |           |
6542*c3739801SMiguel Ojeda         // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
6543*c3739801SMiguel Ojeda         // |------------+----------+----------------+----------+-----------|
6544*c3739801SMiguel Ojeda         // |          N |        N |              N |        N |      KL00 |
6545*c3739801SMiguel Ojeda         // |          N |        N |              N |        Y |      KL01 |
6546*c3739801SMiguel Ojeda         // |          N |        N |              Y |        N |      KL02 |
6547*c3739801SMiguel Ojeda         // |          N |        N |              Y |        Y |      KL03 |
6548*c3739801SMiguel Ojeda         // |          N |        Y |              N |        N |      KL04 |
6549*c3739801SMiguel Ojeda         // |          N |        Y |              N |        Y |      KL05 |
6550*c3739801SMiguel Ojeda         // |          N |        Y |              Y |        N |      KL06 |
6551*c3739801SMiguel Ojeda         // |          N |        Y |              Y |        Y |      KL07 |
6552*c3739801SMiguel Ojeda         // |          Y |        N |              N |        N |      KL08 |
6553*c3739801SMiguel Ojeda         // |          Y |        N |              N |        Y |      KL09 |
6554*c3739801SMiguel Ojeda         // |          Y |        N |              Y |        N |      KL10 |
6555*c3739801SMiguel Ojeda         // |          Y |        N |              Y |        Y |      KL11 |
6556*c3739801SMiguel Ojeda         // |          Y |        Y |              N |        N |      KL12 |
6557*c3739801SMiguel Ojeda         // |          Y |        Y |              N |        Y |      KL13 |
6558*c3739801SMiguel Ojeda         // |          Y |        Y |              Y |        N |      KL14 |
6559*c3739801SMiguel Ojeda         // |          Y |        Y |              Y |        Y |      KL15 |
6560*c3739801SMiguel Ojeda         // +------------+----------+----------------+----------+-----------+
6561*c3739801SMiguel Ojeda 
6562*c3739801SMiguel Ojeda         struct NotKnownLayout<T = ()> {
6563*c3739801SMiguel Ojeda             _t: T,
6564*c3739801SMiguel Ojeda         }
6565*c3739801SMiguel Ojeda 
6566*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6567*c3739801SMiguel Ojeda         #[repr(C)]
6568*c3739801SMiguel Ojeda         struct AlignSize<const ALIGN: usize, const SIZE: usize>
6569*c3739801SMiguel Ojeda         where
6570*c3739801SMiguel Ojeda             elain::Align<ALIGN>: elain::Alignment,
6571*c3739801SMiguel Ojeda         {
6572*c3739801SMiguel Ojeda             _align: elain::Align<ALIGN>,
6573*c3739801SMiguel Ojeda             size: [u8; SIZE],
6574*c3739801SMiguel Ojeda         }
6575*c3739801SMiguel Ojeda 
6576*c3739801SMiguel Ojeda         type AU16 = AlignSize<2, 2>;
6577*c3739801SMiguel Ojeda         type AU32 = AlignSize<4, 4>;
6578*c3739801SMiguel Ojeda 
6579*c3739801SMiguel Ojeda         fn _assert_kl<T: ?Sized + KnownLayout>(_: &T) {}
6580*c3739801SMiguel Ojeda 
6581*c3739801SMiguel Ojeda         let sized_layout = |align, size| DstLayout {
6582*c3739801SMiguel Ojeda             align: NonZeroUsize::new(align).unwrap(),
6583*c3739801SMiguel Ojeda             size_info: SizeInfo::Sized { size },
6584*c3739801SMiguel Ojeda             statically_shallow_unpadded: false,
6585*c3739801SMiguel Ojeda         };
6586*c3739801SMiguel Ojeda 
6587*c3739801SMiguel Ojeda         let unsized_layout = |align, elem_size, offset, statically_shallow_unpadded| DstLayout {
6588*c3739801SMiguel Ojeda             align: NonZeroUsize::new(align).unwrap(),
6589*c3739801SMiguel Ojeda             size_info: SizeInfo::SliceDst(TrailingSliceLayout { offset, elem_size }),
6590*c3739801SMiguel Ojeda             statically_shallow_unpadded,
6591*c3739801SMiguel Ojeda         };
6592*c3739801SMiguel Ojeda 
6593*c3739801SMiguel Ojeda         // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
6594*c3739801SMiguel Ojeda         // |          N |        N |              N |        Y |      KL01 |
6595*c3739801SMiguel Ojeda         #[allow(dead_code)]
6596*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6597*c3739801SMiguel Ojeda         struct KL01(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
6598*c3739801SMiguel Ojeda 
6599*c3739801SMiguel Ojeda         let expected = DstLayout::for_type::<KL01>();
6600*c3739801SMiguel Ojeda 
6601*c3739801SMiguel Ojeda         assert_eq!(<KL01 as KnownLayout>::LAYOUT, expected);
6602*c3739801SMiguel Ojeda         assert_eq!(<KL01 as KnownLayout>::LAYOUT, sized_layout(4, 8));
6603*c3739801SMiguel Ojeda 
6604*c3739801SMiguel Ojeda         // ...with `align(N)`:
6605*c3739801SMiguel Ojeda         #[allow(dead_code)]
6606*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6607*c3739801SMiguel Ojeda         #[repr(align(64))]
6608*c3739801SMiguel Ojeda         struct KL01Align(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
6609*c3739801SMiguel Ojeda 
6610*c3739801SMiguel Ojeda         let expected = DstLayout::for_type::<KL01Align>();
6611*c3739801SMiguel Ojeda 
6612*c3739801SMiguel Ojeda         assert_eq!(<KL01Align as KnownLayout>::LAYOUT, expected);
6613*c3739801SMiguel Ojeda         assert_eq!(<KL01Align as KnownLayout>::LAYOUT, sized_layout(64, 64));
6614*c3739801SMiguel Ojeda 
6615*c3739801SMiguel Ojeda         // ...with `packed`:
6616*c3739801SMiguel Ojeda         #[allow(dead_code)]
6617*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6618*c3739801SMiguel Ojeda         #[repr(packed)]
6619*c3739801SMiguel Ojeda         struct KL01Packed(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
6620*c3739801SMiguel Ojeda 
6621*c3739801SMiguel Ojeda         let expected = DstLayout::for_type::<KL01Packed>();
6622*c3739801SMiguel Ojeda 
6623*c3739801SMiguel Ojeda         assert_eq!(<KL01Packed as KnownLayout>::LAYOUT, expected);
6624*c3739801SMiguel Ojeda         assert_eq!(<KL01Packed as KnownLayout>::LAYOUT, sized_layout(1, 6));
6625*c3739801SMiguel Ojeda 
6626*c3739801SMiguel Ojeda         // ...with `packed(N)`:
6627*c3739801SMiguel Ojeda         #[allow(dead_code)]
6628*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6629*c3739801SMiguel Ojeda         #[repr(packed(2))]
6630*c3739801SMiguel Ojeda         struct KL01PackedN(NotKnownLayout<AU32>, NotKnownLayout<AU16>);
6631*c3739801SMiguel Ojeda 
6632*c3739801SMiguel Ojeda         assert_impl_all!(KL01PackedN: KnownLayout);
6633*c3739801SMiguel Ojeda 
6634*c3739801SMiguel Ojeda         let expected = DstLayout::for_type::<KL01PackedN>();
6635*c3739801SMiguel Ojeda 
6636*c3739801SMiguel Ojeda         assert_eq!(<KL01PackedN as KnownLayout>::LAYOUT, expected);
6637*c3739801SMiguel Ojeda         assert_eq!(<KL01PackedN as KnownLayout>::LAYOUT, sized_layout(2, 6));
6638*c3739801SMiguel Ojeda 
6639*c3739801SMiguel Ojeda         // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
6640*c3739801SMiguel Ojeda         // |          N |        N |              Y |        Y |      KL03 |
6641*c3739801SMiguel Ojeda         #[allow(dead_code)]
6642*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6643*c3739801SMiguel Ojeda         struct KL03(NotKnownLayout, u8);
6644*c3739801SMiguel Ojeda 
6645*c3739801SMiguel Ojeda         let expected = DstLayout::for_type::<KL03>();
6646*c3739801SMiguel Ojeda 
6647*c3739801SMiguel Ojeda         assert_eq!(<KL03 as KnownLayout>::LAYOUT, expected);
6648*c3739801SMiguel Ojeda         assert_eq!(<KL03 as KnownLayout>::LAYOUT, sized_layout(1, 1));
6649*c3739801SMiguel Ojeda 
6650*c3739801SMiguel Ojeda         // ... with `align(N)`
6651*c3739801SMiguel Ojeda         #[allow(dead_code)]
6652*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6653*c3739801SMiguel Ojeda         #[repr(align(64))]
6654*c3739801SMiguel Ojeda         struct KL03Align(NotKnownLayout<AU32>, u8);
6655*c3739801SMiguel Ojeda 
6656*c3739801SMiguel Ojeda         let expected = DstLayout::for_type::<KL03Align>();
6657*c3739801SMiguel Ojeda 
6658*c3739801SMiguel Ojeda         assert_eq!(<KL03Align as KnownLayout>::LAYOUT, expected);
6659*c3739801SMiguel Ojeda         assert_eq!(<KL03Align as KnownLayout>::LAYOUT, sized_layout(64, 64));
6660*c3739801SMiguel Ojeda 
6661*c3739801SMiguel Ojeda         // ... with `packed`:
6662*c3739801SMiguel Ojeda         #[allow(dead_code)]
6663*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6664*c3739801SMiguel Ojeda         #[repr(packed)]
6665*c3739801SMiguel Ojeda         struct KL03Packed(NotKnownLayout<AU32>, u8);
6666*c3739801SMiguel Ojeda 
6667*c3739801SMiguel Ojeda         let expected = DstLayout::for_type::<KL03Packed>();
6668*c3739801SMiguel Ojeda 
6669*c3739801SMiguel Ojeda         assert_eq!(<KL03Packed as KnownLayout>::LAYOUT, expected);
6670*c3739801SMiguel Ojeda         assert_eq!(<KL03Packed as KnownLayout>::LAYOUT, sized_layout(1, 5));
6671*c3739801SMiguel Ojeda 
6672*c3739801SMiguel Ojeda         // ... with `packed(N)`
6673*c3739801SMiguel Ojeda         #[allow(dead_code)]
6674*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6675*c3739801SMiguel Ojeda         #[repr(packed(2))]
6676*c3739801SMiguel Ojeda         struct KL03PackedN(NotKnownLayout<AU32>, u8);
6677*c3739801SMiguel Ojeda 
6678*c3739801SMiguel Ojeda         assert_impl_all!(KL03PackedN: KnownLayout);
6679*c3739801SMiguel Ojeda 
6680*c3739801SMiguel Ojeda         let expected = DstLayout::for_type::<KL03PackedN>();
6681*c3739801SMiguel Ojeda 
6682*c3739801SMiguel Ojeda         assert_eq!(<KL03PackedN as KnownLayout>::LAYOUT, expected);
6683*c3739801SMiguel Ojeda         assert_eq!(<KL03PackedN as KnownLayout>::LAYOUT, sized_layout(2, 6));
6684*c3739801SMiguel Ojeda 
6685*c3739801SMiguel Ojeda         // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
6686*c3739801SMiguel Ojeda         // |          N |        Y |              N |        Y |      KL05 |
6687*c3739801SMiguel Ojeda         #[allow(dead_code)]
6688*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6689*c3739801SMiguel Ojeda         struct KL05<T>(u8, T);
6690*c3739801SMiguel Ojeda 
6691*c3739801SMiguel Ojeda         fn _test_kl05<T>(t: T) -> impl KnownLayout {
6692*c3739801SMiguel Ojeda             KL05(0u8, t)
6693*c3739801SMiguel Ojeda         }
6694*c3739801SMiguel Ojeda 
6695*c3739801SMiguel Ojeda         // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
6696*c3739801SMiguel Ojeda         // |          N |        Y |              Y |        Y |      KL07 |
6697*c3739801SMiguel Ojeda         #[allow(dead_code)]
6698*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6699*c3739801SMiguel Ojeda         struct KL07<T: KnownLayout>(u8, T);
6700*c3739801SMiguel Ojeda 
6701*c3739801SMiguel Ojeda         fn _test_kl07<T: KnownLayout>(t: T) -> impl KnownLayout {
6702*c3739801SMiguel Ojeda             let _ = KL07(0u8, t);
6703*c3739801SMiguel Ojeda         }
6704*c3739801SMiguel Ojeda 
6705*c3739801SMiguel Ojeda         // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
6706*c3739801SMiguel Ojeda         // |          Y |        N |              Y |        N |      KL10 |
6707*c3739801SMiguel Ojeda         #[allow(dead_code)]
6708*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6709*c3739801SMiguel Ojeda         #[repr(C)]
6710*c3739801SMiguel Ojeda         struct KL10(NotKnownLayout<AU32>, [u8]);
6711*c3739801SMiguel Ojeda 
6712*c3739801SMiguel Ojeda         let expected = DstLayout::new_zst(None)
6713*c3739801SMiguel Ojeda             .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), None)
6714*c3739801SMiguel Ojeda             .extend(<[u8] as KnownLayout>::LAYOUT, None)
6715*c3739801SMiguel Ojeda             .pad_to_align();
6716*c3739801SMiguel Ojeda 
6717*c3739801SMiguel Ojeda         assert_eq!(<KL10 as KnownLayout>::LAYOUT, expected);
6718*c3739801SMiguel Ojeda         assert_eq!(<KL10 as KnownLayout>::LAYOUT, unsized_layout(4, 1, 4, false));
6719*c3739801SMiguel Ojeda 
6720*c3739801SMiguel Ojeda         // ...with `align(N)`:
6721*c3739801SMiguel Ojeda         #[allow(dead_code)]
6722*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6723*c3739801SMiguel Ojeda         #[repr(C, align(64))]
6724*c3739801SMiguel Ojeda         struct KL10Align(NotKnownLayout<AU32>, [u8]);
6725*c3739801SMiguel Ojeda 
6726*c3739801SMiguel Ojeda         let repr_align = NonZeroUsize::new(64);
6727*c3739801SMiguel Ojeda 
6728*c3739801SMiguel Ojeda         let expected = DstLayout::new_zst(repr_align)
6729*c3739801SMiguel Ojeda             .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), None)
6730*c3739801SMiguel Ojeda             .extend(<[u8] as KnownLayout>::LAYOUT, None)
6731*c3739801SMiguel Ojeda             .pad_to_align();
6732*c3739801SMiguel Ojeda 
6733*c3739801SMiguel Ojeda         assert_eq!(<KL10Align as KnownLayout>::LAYOUT, expected);
6734*c3739801SMiguel Ojeda         assert_eq!(<KL10Align as KnownLayout>::LAYOUT, unsized_layout(64, 1, 4, false));
6735*c3739801SMiguel Ojeda 
6736*c3739801SMiguel Ojeda         // ...with `packed`:
6737*c3739801SMiguel Ojeda         #[allow(dead_code)]
6738*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6739*c3739801SMiguel Ojeda         #[repr(C, packed)]
6740*c3739801SMiguel Ojeda         struct KL10Packed(NotKnownLayout<AU32>, [u8]);
6741*c3739801SMiguel Ojeda 
6742*c3739801SMiguel Ojeda         let repr_packed = NonZeroUsize::new(1);
6743*c3739801SMiguel Ojeda 
6744*c3739801SMiguel Ojeda         let expected = DstLayout::new_zst(None)
6745*c3739801SMiguel Ojeda             .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), repr_packed)
6746*c3739801SMiguel Ojeda             .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed)
6747*c3739801SMiguel Ojeda             .pad_to_align();
6748*c3739801SMiguel Ojeda 
6749*c3739801SMiguel Ojeda         assert_eq!(<KL10Packed as KnownLayout>::LAYOUT, expected);
6750*c3739801SMiguel Ojeda         assert_eq!(<KL10Packed as KnownLayout>::LAYOUT, unsized_layout(1, 1, 4, false));
6751*c3739801SMiguel Ojeda 
6752*c3739801SMiguel Ojeda         // ...with `packed(N)`:
6753*c3739801SMiguel Ojeda         #[allow(dead_code)]
6754*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6755*c3739801SMiguel Ojeda         #[repr(C, packed(2))]
6756*c3739801SMiguel Ojeda         struct KL10PackedN(NotKnownLayout<AU32>, [u8]);
6757*c3739801SMiguel Ojeda 
6758*c3739801SMiguel Ojeda         let repr_packed = NonZeroUsize::new(2);
6759*c3739801SMiguel Ojeda 
6760*c3739801SMiguel Ojeda         let expected = DstLayout::new_zst(None)
6761*c3739801SMiguel Ojeda             .extend(DstLayout::for_type::<NotKnownLayout<AU32>>(), repr_packed)
6762*c3739801SMiguel Ojeda             .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed)
6763*c3739801SMiguel Ojeda             .pad_to_align();
6764*c3739801SMiguel Ojeda 
6765*c3739801SMiguel Ojeda         assert_eq!(<KL10PackedN as KnownLayout>::LAYOUT, expected);
6766*c3739801SMiguel Ojeda         assert_eq!(<KL10PackedN as KnownLayout>::LAYOUT, unsized_layout(2, 1, 4, false));
6767*c3739801SMiguel Ojeda 
6768*c3739801SMiguel Ojeda         // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
6769*c3739801SMiguel Ojeda         // |          Y |        N |              Y |        Y |      KL11 |
6770*c3739801SMiguel Ojeda         #[allow(dead_code)]
6771*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6772*c3739801SMiguel Ojeda         #[repr(C)]
6773*c3739801SMiguel Ojeda         struct KL11(NotKnownLayout<AU64>, u8);
6774*c3739801SMiguel Ojeda 
6775*c3739801SMiguel Ojeda         let expected = DstLayout::new_zst(None)
6776*c3739801SMiguel Ojeda             .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), None)
6777*c3739801SMiguel Ojeda             .extend(<u8 as KnownLayout>::LAYOUT, None)
6778*c3739801SMiguel Ojeda             .pad_to_align();
6779*c3739801SMiguel Ojeda 
6780*c3739801SMiguel Ojeda         assert_eq!(<KL11 as KnownLayout>::LAYOUT, expected);
6781*c3739801SMiguel Ojeda         assert_eq!(<KL11 as KnownLayout>::LAYOUT, sized_layout(8, 16));
6782*c3739801SMiguel Ojeda 
6783*c3739801SMiguel Ojeda         // ...with `align(N)`:
6784*c3739801SMiguel Ojeda         #[allow(dead_code)]
6785*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6786*c3739801SMiguel Ojeda         #[repr(C, align(64))]
6787*c3739801SMiguel Ojeda         struct KL11Align(NotKnownLayout<AU64>, u8);
6788*c3739801SMiguel Ojeda 
6789*c3739801SMiguel Ojeda         let repr_align = NonZeroUsize::new(64);
6790*c3739801SMiguel Ojeda 
6791*c3739801SMiguel Ojeda         let expected = DstLayout::new_zst(repr_align)
6792*c3739801SMiguel Ojeda             .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), None)
6793*c3739801SMiguel Ojeda             .extend(<u8 as KnownLayout>::LAYOUT, None)
6794*c3739801SMiguel Ojeda             .pad_to_align();
6795*c3739801SMiguel Ojeda 
6796*c3739801SMiguel Ojeda         assert_eq!(<KL11Align as KnownLayout>::LAYOUT, expected);
6797*c3739801SMiguel Ojeda         assert_eq!(<KL11Align as KnownLayout>::LAYOUT, sized_layout(64, 64));
6798*c3739801SMiguel Ojeda 
6799*c3739801SMiguel Ojeda         // ...with `packed`:
6800*c3739801SMiguel Ojeda         #[allow(dead_code)]
6801*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6802*c3739801SMiguel Ojeda         #[repr(C, packed)]
6803*c3739801SMiguel Ojeda         struct KL11Packed(NotKnownLayout<AU64>, u8);
6804*c3739801SMiguel Ojeda 
6805*c3739801SMiguel Ojeda         let repr_packed = NonZeroUsize::new(1);
6806*c3739801SMiguel Ojeda 
6807*c3739801SMiguel Ojeda         let expected = DstLayout::new_zst(None)
6808*c3739801SMiguel Ojeda             .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), repr_packed)
6809*c3739801SMiguel Ojeda             .extend(<u8 as KnownLayout>::LAYOUT, repr_packed)
6810*c3739801SMiguel Ojeda             .pad_to_align();
6811*c3739801SMiguel Ojeda 
6812*c3739801SMiguel Ojeda         assert_eq!(<KL11Packed as KnownLayout>::LAYOUT, expected);
6813*c3739801SMiguel Ojeda         assert_eq!(<KL11Packed as KnownLayout>::LAYOUT, sized_layout(1, 9));
6814*c3739801SMiguel Ojeda 
6815*c3739801SMiguel Ojeda         // ...with `packed(N)`:
6816*c3739801SMiguel Ojeda         #[allow(dead_code)]
6817*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6818*c3739801SMiguel Ojeda         #[repr(C, packed(2))]
6819*c3739801SMiguel Ojeda         struct KL11PackedN(NotKnownLayout<AU64>, u8);
6820*c3739801SMiguel Ojeda 
6821*c3739801SMiguel Ojeda         let repr_packed = NonZeroUsize::new(2);
6822*c3739801SMiguel Ojeda 
6823*c3739801SMiguel Ojeda         let expected = DstLayout::new_zst(None)
6824*c3739801SMiguel Ojeda             .extend(DstLayout::for_type::<NotKnownLayout<AU64>>(), repr_packed)
6825*c3739801SMiguel Ojeda             .extend(<u8 as KnownLayout>::LAYOUT, repr_packed)
6826*c3739801SMiguel Ojeda             .pad_to_align();
6827*c3739801SMiguel Ojeda 
6828*c3739801SMiguel Ojeda         assert_eq!(<KL11PackedN as KnownLayout>::LAYOUT, expected);
6829*c3739801SMiguel Ojeda         assert_eq!(<KL11PackedN as KnownLayout>::LAYOUT, sized_layout(2, 10));
6830*c3739801SMiguel Ojeda 
6831*c3739801SMiguel Ojeda         // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
6832*c3739801SMiguel Ojeda         // |          Y |        Y |              Y |        N |      KL14 |
6833*c3739801SMiguel Ojeda         #[allow(dead_code)]
6834*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6835*c3739801SMiguel Ojeda         #[repr(C)]
6836*c3739801SMiguel Ojeda         struct KL14<T: ?Sized + KnownLayout>(u8, T);
6837*c3739801SMiguel Ojeda 
6838*c3739801SMiguel Ojeda         fn _test_kl14<T: ?Sized + KnownLayout>(kl: &KL14<T>) {
6839*c3739801SMiguel Ojeda             _assert_kl(kl)
6840*c3739801SMiguel Ojeda         }
6841*c3739801SMiguel Ojeda 
6842*c3739801SMiguel Ojeda         // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name |
6843*c3739801SMiguel Ojeda         // |          Y |        Y |              Y |        Y |      KL15 |
6844*c3739801SMiguel Ojeda         #[allow(dead_code)]
6845*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6846*c3739801SMiguel Ojeda         #[repr(C)]
6847*c3739801SMiguel Ojeda         struct KL15<T: KnownLayout>(u8, T);
6848*c3739801SMiguel Ojeda 
6849*c3739801SMiguel Ojeda         fn _test_kl15<T: KnownLayout>(t: T) -> impl KnownLayout {
6850*c3739801SMiguel Ojeda             let _ = KL15(0u8, t);
6851*c3739801SMiguel Ojeda         }
6852*c3739801SMiguel Ojeda 
6853*c3739801SMiguel Ojeda         // Test a variety of combinations of field types:
6854*c3739801SMiguel Ojeda         //  - ()
6855*c3739801SMiguel Ojeda         //  - u8
6856*c3739801SMiguel Ojeda         //  - AU16
6857*c3739801SMiguel Ojeda         //  - [()]
6858*c3739801SMiguel Ojeda         //  - [u8]
6859*c3739801SMiguel Ojeda         //  - [AU16]
6860*c3739801SMiguel Ojeda 
6861*c3739801SMiguel Ojeda         #[allow(clippy::upper_case_acronyms, dead_code)]
6862*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6863*c3739801SMiguel Ojeda         #[repr(C)]
6864*c3739801SMiguel Ojeda         struct KLTU<T, U: ?Sized>(T, U);
6865*c3739801SMiguel Ojeda 
6866*c3739801SMiguel Ojeda         assert_eq!(<KLTU<(), ()> as KnownLayout>::LAYOUT, sized_layout(1, 0));
6867*c3739801SMiguel Ojeda 
6868*c3739801SMiguel Ojeda         assert_eq!(<KLTU<(), u8> as KnownLayout>::LAYOUT, sized_layout(1, 1));
6869*c3739801SMiguel Ojeda 
6870*c3739801SMiguel Ojeda         assert_eq!(<KLTU<(), AU16> as KnownLayout>::LAYOUT, sized_layout(2, 2));
6871*c3739801SMiguel Ojeda 
6872*c3739801SMiguel Ojeda         assert_eq!(<KLTU<(), [()]> as KnownLayout>::LAYOUT, unsized_layout(1, 0, 0, false));
6873*c3739801SMiguel Ojeda 
6874*c3739801SMiguel Ojeda         assert_eq!(<KLTU<(), [u8]> as KnownLayout>::LAYOUT, unsized_layout(1, 1, 0, false));
6875*c3739801SMiguel Ojeda 
6876*c3739801SMiguel Ojeda         assert_eq!(<KLTU<(), [AU16]> as KnownLayout>::LAYOUT, unsized_layout(2, 2, 0, false));
6877*c3739801SMiguel Ojeda 
6878*c3739801SMiguel Ojeda         assert_eq!(<KLTU<u8, ()> as KnownLayout>::LAYOUT, sized_layout(1, 1));
6879*c3739801SMiguel Ojeda 
6880*c3739801SMiguel Ojeda         assert_eq!(<KLTU<u8, u8> as KnownLayout>::LAYOUT, sized_layout(1, 2));
6881*c3739801SMiguel Ojeda 
6882*c3739801SMiguel Ojeda         assert_eq!(<KLTU<u8, AU16> as KnownLayout>::LAYOUT, sized_layout(2, 4));
6883*c3739801SMiguel Ojeda 
6884*c3739801SMiguel Ojeda         assert_eq!(<KLTU<u8, [()]> as KnownLayout>::LAYOUT, unsized_layout(1, 0, 1, false));
6885*c3739801SMiguel Ojeda 
6886*c3739801SMiguel Ojeda         assert_eq!(<KLTU<u8, [u8]> as KnownLayout>::LAYOUT, unsized_layout(1, 1, 1, false));
6887*c3739801SMiguel Ojeda 
6888*c3739801SMiguel Ojeda         assert_eq!(<KLTU<u8, [AU16]> as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2, false));
6889*c3739801SMiguel Ojeda 
6890*c3739801SMiguel Ojeda         assert_eq!(<KLTU<AU16, ()> as KnownLayout>::LAYOUT, sized_layout(2, 2));
6891*c3739801SMiguel Ojeda 
6892*c3739801SMiguel Ojeda         assert_eq!(<KLTU<AU16, u8> as KnownLayout>::LAYOUT, sized_layout(2, 4));
6893*c3739801SMiguel Ojeda 
6894*c3739801SMiguel Ojeda         assert_eq!(<KLTU<AU16, AU16> as KnownLayout>::LAYOUT, sized_layout(2, 4));
6895*c3739801SMiguel Ojeda 
6896*c3739801SMiguel Ojeda         assert_eq!(<KLTU<AU16, [()]> as KnownLayout>::LAYOUT, unsized_layout(2, 0, 2, false));
6897*c3739801SMiguel Ojeda 
6898*c3739801SMiguel Ojeda         assert_eq!(<KLTU<AU16, [u8]> as KnownLayout>::LAYOUT, unsized_layout(2, 1, 2, false));
6899*c3739801SMiguel Ojeda 
6900*c3739801SMiguel Ojeda         assert_eq!(<KLTU<AU16, [AU16]> as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2, false));
6901*c3739801SMiguel Ojeda 
6902*c3739801SMiguel Ojeda         // Test a variety of field counts.
6903*c3739801SMiguel Ojeda 
6904*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6905*c3739801SMiguel Ojeda         #[repr(C)]
6906*c3739801SMiguel Ojeda         struct KLF0;
6907*c3739801SMiguel Ojeda 
6908*c3739801SMiguel Ojeda         assert_eq!(<KLF0 as KnownLayout>::LAYOUT, sized_layout(1, 0));
6909*c3739801SMiguel Ojeda 
6910*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6911*c3739801SMiguel Ojeda         #[repr(C)]
6912*c3739801SMiguel Ojeda         struct KLF1([u8]);
6913*c3739801SMiguel Ojeda 
6914*c3739801SMiguel Ojeda         assert_eq!(<KLF1 as KnownLayout>::LAYOUT, unsized_layout(1, 1, 0, true));
6915*c3739801SMiguel Ojeda 
6916*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6917*c3739801SMiguel Ojeda         #[repr(C)]
6918*c3739801SMiguel Ojeda         struct KLF2(NotKnownLayout<u8>, [u8]);
6919*c3739801SMiguel Ojeda 
6920*c3739801SMiguel Ojeda         assert_eq!(<KLF2 as KnownLayout>::LAYOUT, unsized_layout(1, 1, 1, false));
6921*c3739801SMiguel Ojeda 
6922*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6923*c3739801SMiguel Ojeda         #[repr(C)]
6924*c3739801SMiguel Ojeda         struct KLF3(NotKnownLayout<u8>, NotKnownLayout<AU16>, [u8]);
6925*c3739801SMiguel Ojeda 
6926*c3739801SMiguel Ojeda         assert_eq!(<KLF3 as KnownLayout>::LAYOUT, unsized_layout(2, 1, 4, false));
6927*c3739801SMiguel Ojeda 
6928*c3739801SMiguel Ojeda         #[derive(KnownLayout)]
6929*c3739801SMiguel Ojeda         #[repr(C)]
6930*c3739801SMiguel Ojeda         struct KLF4(NotKnownLayout<u8>, NotKnownLayout<AU16>, NotKnownLayout<AU32>, [u8]);
6931*c3739801SMiguel Ojeda 
6932*c3739801SMiguel Ojeda         assert_eq!(<KLF4 as KnownLayout>::LAYOUT, unsized_layout(4, 1, 8, false));
6933*c3739801SMiguel Ojeda     }
6934*c3739801SMiguel Ojeda 
6935*c3739801SMiguel Ojeda     #[test]
6936*c3739801SMiguel Ojeda     fn test_object_safety() {
6937*c3739801SMiguel Ojeda         fn _takes_immutable(_: &dyn Immutable) {}
6938*c3739801SMiguel Ojeda         fn _takes_unaligned(_: &dyn Unaligned) {}
6939*c3739801SMiguel Ojeda     }
6940*c3739801SMiguel Ojeda 
6941*c3739801SMiguel Ojeda     #[test]
6942*c3739801SMiguel Ojeda     fn test_from_zeros_only() {
6943*c3739801SMiguel Ojeda         // Test types that implement `FromZeros` but not `FromBytes`.
6944*c3739801SMiguel Ojeda 
6945*c3739801SMiguel Ojeda         assert!(!bool::new_zeroed());
6946*c3739801SMiguel Ojeda         assert_eq!(char::new_zeroed(), '\0');
6947*c3739801SMiguel Ojeda 
6948*c3739801SMiguel Ojeda         #[cfg(feature = "alloc")]
6949*c3739801SMiguel Ojeda         {
6950*c3739801SMiguel Ojeda             assert_eq!(bool::new_box_zeroed(), Ok(Box::new(false)));
6951*c3739801SMiguel Ojeda             assert_eq!(char::new_box_zeroed(), Ok(Box::new('\0')));
6952*c3739801SMiguel Ojeda 
6953*c3739801SMiguel Ojeda             assert_eq!(
6954*c3739801SMiguel Ojeda                 <[bool]>::new_box_zeroed_with_elems(3).unwrap().as_ref(),
6955*c3739801SMiguel Ojeda                 [false, false, false]
6956*c3739801SMiguel Ojeda             );
6957*c3739801SMiguel Ojeda             assert_eq!(
6958*c3739801SMiguel Ojeda                 <[char]>::new_box_zeroed_with_elems(3).unwrap().as_ref(),
6959*c3739801SMiguel Ojeda                 ['\0', '\0', '\0']
6960*c3739801SMiguel Ojeda             );
6961*c3739801SMiguel Ojeda 
6962*c3739801SMiguel Ojeda             assert_eq!(bool::new_vec_zeroed(3).unwrap().as_ref(), [false, false, false]);
6963*c3739801SMiguel Ojeda             assert_eq!(char::new_vec_zeroed(3).unwrap().as_ref(), ['\0', '\0', '\0']);
6964*c3739801SMiguel Ojeda         }
6965*c3739801SMiguel Ojeda 
6966*c3739801SMiguel Ojeda         let mut string = "hello".to_string();
6967*c3739801SMiguel Ojeda         let s: &mut str = string.as_mut();
6968*c3739801SMiguel Ojeda         assert_eq!(s, "hello");
6969*c3739801SMiguel Ojeda         s.zero();
6970*c3739801SMiguel Ojeda         assert_eq!(s, "\0\0\0\0\0");
6971*c3739801SMiguel Ojeda     }
6972*c3739801SMiguel Ojeda 
6973*c3739801SMiguel Ojeda     #[test]
6974*c3739801SMiguel Ojeda     fn test_zst_count_preserved() {
6975*c3739801SMiguel Ojeda         // Test that, when an explicit count is provided to for a type with a
6976*c3739801SMiguel Ojeda         // ZST trailing slice element, that count is preserved. This is
6977*c3739801SMiguel Ojeda         // important since, for such types, all element counts result in objects
6978*c3739801SMiguel Ojeda         // of the same size, and so the correct behavior is ambiguous. However,
6979*c3739801SMiguel Ojeda         // preserving the count as requested by the user is the behavior that we
6980*c3739801SMiguel Ojeda         // document publicly.
6981*c3739801SMiguel Ojeda 
6982*c3739801SMiguel Ojeda         // FromZeros methods
6983*c3739801SMiguel Ojeda         #[cfg(feature = "alloc")]
6984*c3739801SMiguel Ojeda         assert_eq!(<[()]>::new_box_zeroed_with_elems(3).unwrap().len(), 3);
6985*c3739801SMiguel Ojeda         #[cfg(feature = "alloc")]
6986*c3739801SMiguel Ojeda         assert_eq!(<()>::new_vec_zeroed(3).unwrap().len(), 3);
6987*c3739801SMiguel Ojeda 
6988*c3739801SMiguel Ojeda         // FromBytes methods
6989*c3739801SMiguel Ojeda         assert_eq!(<[()]>::ref_from_bytes_with_elems(&[][..], 3).unwrap().len(), 3);
6990*c3739801SMiguel Ojeda         assert_eq!(<[()]>::ref_from_prefix_with_elems(&[][..], 3).unwrap().0.len(), 3);
6991*c3739801SMiguel Ojeda         assert_eq!(<[()]>::ref_from_suffix_with_elems(&[][..], 3).unwrap().1.len(), 3);
6992*c3739801SMiguel Ojeda         assert_eq!(<[()]>::mut_from_bytes_with_elems(&mut [][..], 3).unwrap().len(), 3);
6993*c3739801SMiguel Ojeda         assert_eq!(<[()]>::mut_from_prefix_with_elems(&mut [][..], 3).unwrap().0.len(), 3);
6994*c3739801SMiguel Ojeda         assert_eq!(<[()]>::mut_from_suffix_with_elems(&mut [][..], 3).unwrap().1.len(), 3);
6995*c3739801SMiguel Ojeda     }
6996*c3739801SMiguel Ojeda 
6997*c3739801SMiguel Ojeda     #[test]
6998*c3739801SMiguel Ojeda     fn test_read_write() {
6999*c3739801SMiguel Ojeda         const VAL: u64 = 0x12345678;
7000*c3739801SMiguel Ojeda         #[cfg(target_endian = "big")]
7001*c3739801SMiguel Ojeda         const VAL_BYTES: [u8; 8] = VAL.to_be_bytes();
7002*c3739801SMiguel Ojeda         #[cfg(target_endian = "little")]
7003*c3739801SMiguel Ojeda         const VAL_BYTES: [u8; 8] = VAL.to_le_bytes();
7004*c3739801SMiguel Ojeda         const ZEROS: [u8; 8] = [0u8; 8];
7005*c3739801SMiguel Ojeda 
7006*c3739801SMiguel Ojeda         // Test `FromBytes::{read_from, read_from_prefix, read_from_suffix}`.
7007*c3739801SMiguel Ojeda 
7008*c3739801SMiguel Ojeda         assert_eq!(u64::read_from_bytes(&VAL_BYTES[..]), Ok(VAL));
7009*c3739801SMiguel Ojeda         // The first 8 bytes are from `VAL_BYTES` and the second 8 bytes are all
7010*c3739801SMiguel Ojeda         // zeros.
7011*c3739801SMiguel Ojeda         let bytes_with_prefix: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]);
7012*c3739801SMiguel Ojeda         assert_eq!(u64::read_from_prefix(&bytes_with_prefix[..]), Ok((VAL, &ZEROS[..])));
7013*c3739801SMiguel Ojeda         assert_eq!(u64::read_from_suffix(&bytes_with_prefix[..]), Ok((&VAL_BYTES[..], 0)));
7014*c3739801SMiguel Ojeda         // The first 8 bytes are all zeros and the second 8 bytes are from
7015*c3739801SMiguel Ojeda         // `VAL_BYTES`
7016*c3739801SMiguel Ojeda         let bytes_with_suffix: [u8; 16] = transmute!([[0; 8], VAL_BYTES]);
7017*c3739801SMiguel Ojeda         assert_eq!(u64::read_from_prefix(&bytes_with_suffix[..]), Ok((0, &VAL_BYTES[..])));
7018*c3739801SMiguel Ojeda         assert_eq!(u64::read_from_suffix(&bytes_with_suffix[..]), Ok((&ZEROS[..], VAL)));
7019*c3739801SMiguel Ojeda 
7020*c3739801SMiguel Ojeda         // Test `IntoBytes::{write_to, write_to_prefix, write_to_suffix}`.
7021*c3739801SMiguel Ojeda 
7022*c3739801SMiguel Ojeda         let mut bytes = [0u8; 8];
7023*c3739801SMiguel Ojeda         assert_eq!(VAL.write_to(&mut bytes[..]), Ok(()));
7024*c3739801SMiguel Ojeda         assert_eq!(bytes, VAL_BYTES);
7025*c3739801SMiguel Ojeda         let mut bytes = [0u8; 16];
7026*c3739801SMiguel Ojeda         assert_eq!(VAL.write_to_prefix(&mut bytes[..]), Ok(()));
7027*c3739801SMiguel Ojeda         let want: [u8; 16] = transmute!([VAL_BYTES, [0; 8]]);
7028*c3739801SMiguel Ojeda         assert_eq!(bytes, want);
7029*c3739801SMiguel Ojeda         let mut bytes = [0u8; 16];
7030*c3739801SMiguel Ojeda         assert_eq!(VAL.write_to_suffix(&mut bytes[..]), Ok(()));
7031*c3739801SMiguel Ojeda         let want: [u8; 16] = transmute!([[0; 8], VAL_BYTES]);
7032*c3739801SMiguel Ojeda         assert_eq!(bytes, want);
7033*c3739801SMiguel Ojeda     }
7034*c3739801SMiguel Ojeda 
7035*c3739801SMiguel Ojeda     #[test]
7036*c3739801SMiguel Ojeda     #[cfg(feature = "std")]
7037*c3739801SMiguel Ojeda     fn test_read_io_with_padding_soundness() {
7038*c3739801SMiguel Ojeda         // This test is designed to exhibit potential UB in
7039*c3739801SMiguel Ojeda         // `FromBytes::read_from_io`. (see #2319, #2320).
7040*c3739801SMiguel Ojeda 
7041*c3739801SMiguel Ojeda         // On most platforms (where `align_of::<u16>() == 2`), `WithPadding`
7042*c3739801SMiguel Ojeda         // will have inter-field padding between `x` and `y`.
7043*c3739801SMiguel Ojeda         #[derive(FromBytes)]
7044*c3739801SMiguel Ojeda         #[repr(C)]
7045*c3739801SMiguel Ojeda         struct WithPadding {
7046*c3739801SMiguel Ojeda             x: u8,
7047*c3739801SMiguel Ojeda             y: u16,
7048*c3739801SMiguel Ojeda         }
7049*c3739801SMiguel Ojeda         struct ReadsInRead;
7050*c3739801SMiguel Ojeda         impl std::io::Read for ReadsInRead {
7051*c3739801SMiguel Ojeda             fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
7052*c3739801SMiguel Ojeda                 // This body branches on every byte of `buf`, ensuring that it
7053*c3739801SMiguel Ojeda                 // exhibits UB if any byte of `buf` is uninitialized.
7054*c3739801SMiguel Ojeda                 if buf.iter().all(|&x| x == 0) {
7055*c3739801SMiguel Ojeda                     Ok(buf.len())
7056*c3739801SMiguel Ojeda                 } else {
7057*c3739801SMiguel Ojeda                     buf.iter_mut().for_each(|x| *x = 0);
7058*c3739801SMiguel Ojeda                     Ok(buf.len())
7059*c3739801SMiguel Ojeda                 }
7060*c3739801SMiguel Ojeda             }
7061*c3739801SMiguel Ojeda         }
7062*c3739801SMiguel Ojeda         assert!(matches!(WithPadding::read_from_io(ReadsInRead), Ok(WithPadding { x: 0, y: 0 })));
7063*c3739801SMiguel Ojeda     }
7064*c3739801SMiguel Ojeda 
7065*c3739801SMiguel Ojeda     #[test]
7066*c3739801SMiguel Ojeda     #[cfg(feature = "std")]
7067*c3739801SMiguel Ojeda     fn test_read_write_io() {
7068*c3739801SMiguel Ojeda         let mut long_buffer = [0, 0, 0, 0];
7069*c3739801SMiguel Ojeda         assert!(matches!(u16::MAX.write_to_io(&mut long_buffer[..]), Ok(())));
7070*c3739801SMiguel Ojeda         assert_eq!(long_buffer, [255, 255, 0, 0]);
7071*c3739801SMiguel Ojeda         assert!(matches!(u16::read_from_io(&long_buffer[..]), Ok(u16::MAX)));
7072*c3739801SMiguel Ojeda 
7073*c3739801SMiguel Ojeda         let mut short_buffer = [0, 0];
7074*c3739801SMiguel Ojeda         assert!(u32::MAX.write_to_io(&mut short_buffer[..]).is_err());
7075*c3739801SMiguel Ojeda         assert_eq!(short_buffer, [255, 255]);
7076*c3739801SMiguel Ojeda         assert!(u32::read_from_io(&short_buffer[..]).is_err());
7077*c3739801SMiguel Ojeda     }
7078*c3739801SMiguel Ojeda 
7079*c3739801SMiguel Ojeda     #[test]
7080*c3739801SMiguel Ojeda     fn test_try_from_bytes_try_read_from() {
7081*c3739801SMiguel Ojeda         assert_eq!(<bool as TryFromBytes>::try_read_from_bytes(&[0]), Ok(false));
7082*c3739801SMiguel Ojeda         assert_eq!(<bool as TryFromBytes>::try_read_from_bytes(&[1]), Ok(true));
7083*c3739801SMiguel Ojeda 
7084*c3739801SMiguel Ojeda         assert_eq!(<bool as TryFromBytes>::try_read_from_prefix(&[0, 2]), Ok((false, &[2][..])));
7085*c3739801SMiguel Ojeda         assert_eq!(<bool as TryFromBytes>::try_read_from_prefix(&[1, 2]), Ok((true, &[2][..])));
7086*c3739801SMiguel Ojeda 
7087*c3739801SMiguel Ojeda         assert_eq!(<bool as TryFromBytes>::try_read_from_suffix(&[2, 0]), Ok((&[2][..], false)));
7088*c3739801SMiguel Ojeda         assert_eq!(<bool as TryFromBytes>::try_read_from_suffix(&[2, 1]), Ok((&[2][..], true)));
7089*c3739801SMiguel Ojeda 
7090*c3739801SMiguel Ojeda         // If we don't pass enough bytes, it fails.
7091*c3739801SMiguel Ojeda         assert!(matches!(
7092*c3739801SMiguel Ojeda             <u8 as TryFromBytes>::try_read_from_bytes(&[]),
7093*c3739801SMiguel Ojeda             Err(TryReadError::Size(_))
7094*c3739801SMiguel Ojeda         ));
7095*c3739801SMiguel Ojeda         assert!(matches!(
7096*c3739801SMiguel Ojeda             <u8 as TryFromBytes>::try_read_from_prefix(&[]),
7097*c3739801SMiguel Ojeda             Err(TryReadError::Size(_))
7098*c3739801SMiguel Ojeda         ));
7099*c3739801SMiguel Ojeda         assert!(matches!(
7100*c3739801SMiguel Ojeda             <u8 as TryFromBytes>::try_read_from_suffix(&[]),
7101*c3739801SMiguel Ojeda             Err(TryReadError::Size(_))
7102*c3739801SMiguel Ojeda         ));
7103*c3739801SMiguel Ojeda 
7104*c3739801SMiguel Ojeda         // If we pass too many bytes, it fails.
7105*c3739801SMiguel Ojeda         assert!(matches!(
7106*c3739801SMiguel Ojeda             <u8 as TryFromBytes>::try_read_from_bytes(&[0, 0]),
7107*c3739801SMiguel Ojeda             Err(TryReadError::Size(_))
7108*c3739801SMiguel Ojeda         ));
7109*c3739801SMiguel Ojeda 
7110*c3739801SMiguel Ojeda         // If we pass an invalid value, it fails.
7111*c3739801SMiguel Ojeda         assert!(matches!(
7112*c3739801SMiguel Ojeda             <bool as TryFromBytes>::try_read_from_bytes(&[2]),
7113*c3739801SMiguel Ojeda             Err(TryReadError::Validity(_))
7114*c3739801SMiguel Ojeda         ));
7115*c3739801SMiguel Ojeda         assert!(matches!(
7116*c3739801SMiguel Ojeda             <bool as TryFromBytes>::try_read_from_prefix(&[2, 0]),
7117*c3739801SMiguel Ojeda             Err(TryReadError::Validity(_))
7118*c3739801SMiguel Ojeda         ));
7119*c3739801SMiguel Ojeda         assert!(matches!(
7120*c3739801SMiguel Ojeda             <bool as TryFromBytes>::try_read_from_suffix(&[0, 2]),
7121*c3739801SMiguel Ojeda             Err(TryReadError::Validity(_))
7122*c3739801SMiguel Ojeda         ));
7123*c3739801SMiguel Ojeda 
7124*c3739801SMiguel Ojeda         // Reading from a misaligned buffer should still succeed. Since `AU64`'s
7125*c3739801SMiguel Ojeda         // alignment is 8, and since we read from two adjacent addresses one
7126*c3739801SMiguel Ojeda         // byte apart, it is guaranteed that at least one of them (though
7127*c3739801SMiguel Ojeda         // possibly both) will be misaligned.
7128*c3739801SMiguel Ojeda         let bytes: [u8; 9] = [0, 0, 0, 0, 0, 0, 0, 0, 0];
7129*c3739801SMiguel Ojeda         assert_eq!(<AU64 as TryFromBytes>::try_read_from_bytes(&bytes[..8]), Ok(AU64(0)));
7130*c3739801SMiguel Ojeda         assert_eq!(<AU64 as TryFromBytes>::try_read_from_bytes(&bytes[1..9]), Ok(AU64(0)));
7131*c3739801SMiguel Ojeda 
7132*c3739801SMiguel Ojeda         assert_eq!(
7133*c3739801SMiguel Ojeda             <AU64 as TryFromBytes>::try_read_from_prefix(&bytes[..8]),
7134*c3739801SMiguel Ojeda             Ok((AU64(0), &[][..]))
7135*c3739801SMiguel Ojeda         );
7136*c3739801SMiguel Ojeda         assert_eq!(
7137*c3739801SMiguel Ojeda             <AU64 as TryFromBytes>::try_read_from_prefix(&bytes[1..9]),
7138*c3739801SMiguel Ojeda             Ok((AU64(0), &[][..]))
7139*c3739801SMiguel Ojeda         );
7140*c3739801SMiguel Ojeda 
7141*c3739801SMiguel Ojeda         assert_eq!(
7142*c3739801SMiguel Ojeda             <AU64 as TryFromBytes>::try_read_from_suffix(&bytes[..8]),
7143*c3739801SMiguel Ojeda             Ok((&[][..], AU64(0)))
7144*c3739801SMiguel Ojeda         );
7145*c3739801SMiguel Ojeda         assert_eq!(
7146*c3739801SMiguel Ojeda             <AU64 as TryFromBytes>::try_read_from_suffix(&bytes[1..9]),
7147*c3739801SMiguel Ojeda             Ok((&[][..], AU64(0)))
7148*c3739801SMiguel Ojeda         );
7149*c3739801SMiguel Ojeda     }
7150*c3739801SMiguel Ojeda 
7151*c3739801SMiguel Ojeda     #[test]
7152*c3739801SMiguel Ojeda     fn test_ref_from_mut_from_bytes() {
7153*c3739801SMiguel Ojeda         // Test `FromBytes::{ref_from_bytes, mut_from_bytes}{,_prefix,Suffix}`
7154*c3739801SMiguel Ojeda         // success cases. Exhaustive coverage for these methods is covered by
7155*c3739801SMiguel Ojeda         // the `Ref` tests above, which these helper methods defer to.
7156*c3739801SMiguel Ojeda 
7157*c3739801SMiguel Ojeda         let mut buf =
7158*c3739801SMiguel Ojeda             Align::<[u8; 16], AU64>::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
7159*c3739801SMiguel Ojeda 
7160*c3739801SMiguel Ojeda         assert_eq!(
7161*c3739801SMiguel Ojeda             AU64::ref_from_bytes(&buf.t[8..]).unwrap().0.to_ne_bytes(),
7162*c3739801SMiguel Ojeda             [8, 9, 10, 11, 12, 13, 14, 15]
7163*c3739801SMiguel Ojeda         );
7164*c3739801SMiguel Ojeda         let suffix = AU64::mut_from_bytes(&mut buf.t[8..]).unwrap();
7165*c3739801SMiguel Ojeda         suffix.0 = 0x0101010101010101;
7166*c3739801SMiguel Ojeda         // The `[u8:9]` is a non-half size of the full buffer, which would catch
7167*c3739801SMiguel Ojeda         // `from_prefix` having the same implementation as `from_suffix` (issues #506, #511).
7168*c3739801SMiguel Ojeda         assert_eq!(
7169*c3739801SMiguel Ojeda             <[u8; 9]>::ref_from_suffix(&buf.t[..]).unwrap(),
7170*c3739801SMiguel Ojeda             (&[0, 1, 2, 3, 4, 5, 6][..], &[7u8, 1, 1, 1, 1, 1, 1, 1, 1])
7171*c3739801SMiguel Ojeda         );
7172*c3739801SMiguel Ojeda         let (prefix, suffix) = AU64::mut_from_suffix(&mut buf.t[1..]).unwrap();
7173*c3739801SMiguel Ojeda         assert_eq!(prefix, &mut [1u8, 2, 3, 4, 5, 6, 7][..]);
7174*c3739801SMiguel Ojeda         suffix.0 = 0x0202020202020202;
7175*c3739801SMiguel Ojeda         let (prefix, suffix) = <[u8; 10]>::mut_from_suffix(&mut buf.t[..]).unwrap();
7176*c3739801SMiguel Ojeda         assert_eq!(prefix, &mut [0u8, 1, 2, 3, 4, 5][..]);
7177*c3739801SMiguel Ojeda         suffix[0] = 42;
7178*c3739801SMiguel Ojeda         assert_eq!(
7179*c3739801SMiguel Ojeda             <[u8; 9]>::ref_from_prefix(&buf.t[..]).unwrap(),
7180*c3739801SMiguel Ojeda             (&[0u8, 1, 2, 3, 4, 5, 42, 7, 2], &[2u8, 2, 2, 2, 2, 2, 2][..])
7181*c3739801SMiguel Ojeda         );
7182*c3739801SMiguel Ojeda         <[u8; 2]>::mut_from_prefix(&mut buf.t[..]).unwrap().0[1] = 30;
7183*c3739801SMiguel Ojeda         assert_eq!(buf.t, [0, 30, 2, 3, 4, 5, 42, 7, 2, 2, 2, 2, 2, 2, 2, 2]);
7184*c3739801SMiguel Ojeda     }
7185*c3739801SMiguel Ojeda 
7186*c3739801SMiguel Ojeda     #[test]
7187*c3739801SMiguel Ojeda     fn test_ref_from_mut_from_bytes_error() {
7188*c3739801SMiguel Ojeda         // Test `FromBytes::{ref_from_bytes, mut_from_bytes}{,_prefix,Suffix}`
7189*c3739801SMiguel Ojeda         // error cases.
7190*c3739801SMiguel Ojeda 
7191*c3739801SMiguel Ojeda         // Fail because the buffer is too large.
7192*c3739801SMiguel Ojeda         let mut buf = Align::<[u8; 16], AU64>::default();
7193*c3739801SMiguel Ojeda         // `buf.t` should be aligned to 8, so only the length check should fail.
7194*c3739801SMiguel Ojeda         assert!(AU64::ref_from_bytes(&buf.t[..]).is_err());
7195*c3739801SMiguel Ojeda         assert!(AU64::mut_from_bytes(&mut buf.t[..]).is_err());
7196*c3739801SMiguel Ojeda         assert!(<[u8; 8]>::ref_from_bytes(&buf.t[..]).is_err());
7197*c3739801SMiguel Ojeda         assert!(<[u8; 8]>::mut_from_bytes(&mut buf.t[..]).is_err());
7198*c3739801SMiguel Ojeda 
7199*c3739801SMiguel Ojeda         // Fail because the buffer is too small.
7200*c3739801SMiguel Ojeda         let mut buf = Align::<[u8; 4], AU64>::default();
7201*c3739801SMiguel Ojeda         assert!(AU64::ref_from_bytes(&buf.t[..]).is_err());
7202*c3739801SMiguel Ojeda         assert!(AU64::mut_from_bytes(&mut buf.t[..]).is_err());
7203*c3739801SMiguel Ojeda         assert!(<[u8; 8]>::ref_from_bytes(&buf.t[..]).is_err());
7204*c3739801SMiguel Ojeda         assert!(<[u8; 8]>::mut_from_bytes(&mut buf.t[..]).is_err());
7205*c3739801SMiguel Ojeda         assert!(AU64::ref_from_prefix(&buf.t[..]).is_err());
7206*c3739801SMiguel Ojeda         assert!(AU64::mut_from_prefix(&mut buf.t[..]).is_err());
7207*c3739801SMiguel Ojeda         assert!(AU64::ref_from_suffix(&buf.t[..]).is_err());
7208*c3739801SMiguel Ojeda         assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_err());
7209*c3739801SMiguel Ojeda         assert!(<[u8; 8]>::ref_from_prefix(&buf.t[..]).is_err());
7210*c3739801SMiguel Ojeda         assert!(<[u8; 8]>::mut_from_prefix(&mut buf.t[..]).is_err());
7211*c3739801SMiguel Ojeda         assert!(<[u8; 8]>::ref_from_suffix(&buf.t[..]).is_err());
7212*c3739801SMiguel Ojeda         assert!(<[u8; 8]>::mut_from_suffix(&mut buf.t[..]).is_err());
7213*c3739801SMiguel Ojeda 
7214*c3739801SMiguel Ojeda         // Fail because the alignment is insufficient.
7215*c3739801SMiguel Ojeda         let mut buf = Align::<[u8; 13], AU64>::default();
7216*c3739801SMiguel Ojeda         assert!(AU64::ref_from_bytes(&buf.t[1..]).is_err());
7217*c3739801SMiguel Ojeda         assert!(AU64::mut_from_bytes(&mut buf.t[1..]).is_err());
7218*c3739801SMiguel Ojeda         assert!(AU64::ref_from_bytes(&buf.t[1..]).is_err());
7219*c3739801SMiguel Ojeda         assert!(AU64::mut_from_bytes(&mut buf.t[1..]).is_err());
7220*c3739801SMiguel Ojeda         assert!(AU64::ref_from_prefix(&buf.t[1..]).is_err());
7221*c3739801SMiguel Ojeda         assert!(AU64::mut_from_prefix(&mut buf.t[1..]).is_err());
7222*c3739801SMiguel Ojeda         assert!(AU64::ref_from_suffix(&buf.t[..]).is_err());
7223*c3739801SMiguel Ojeda         assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_err());
7224*c3739801SMiguel Ojeda     }
7225*c3739801SMiguel Ojeda 
7226*c3739801SMiguel Ojeda     #[test]
7227*c3739801SMiguel Ojeda     fn test_to_methods() {
7228*c3739801SMiguel Ojeda         /// Run a series of tests by calling `IntoBytes` methods on `t`.
7229*c3739801SMiguel Ojeda         ///
7230*c3739801SMiguel Ojeda         /// `bytes` is the expected byte sequence returned from `t.as_bytes()`
7231*c3739801SMiguel Ojeda         /// before `t` has been modified. `post_mutation` is the expected
7232*c3739801SMiguel Ojeda         /// sequence returned from `t.as_bytes()` after `t.as_mut_bytes()[0]`
7233*c3739801SMiguel Ojeda         /// has had its bits flipped (by applying `^= 0xFF`).
7234*c3739801SMiguel Ojeda         ///
7235*c3739801SMiguel Ojeda         /// `N` is the size of `t` in bytes.
7236*c3739801SMiguel Ojeda         fn test<T: FromBytes + IntoBytes + Immutable + Debug + Eq + ?Sized, const N: usize>(
7237*c3739801SMiguel Ojeda             t: &mut T,
7238*c3739801SMiguel Ojeda             bytes: &[u8],
7239*c3739801SMiguel Ojeda             post_mutation: &T,
7240*c3739801SMiguel Ojeda         ) {
7241*c3739801SMiguel Ojeda             // Test that we can access the underlying bytes, and that we get the
7242*c3739801SMiguel Ojeda             // right bytes and the right number of bytes.
7243*c3739801SMiguel Ojeda             assert_eq!(t.as_bytes(), bytes);
7244*c3739801SMiguel Ojeda 
7245*c3739801SMiguel Ojeda             // Test that changes to the underlying byte slices are reflected in
7246*c3739801SMiguel Ojeda             // the original object.
7247*c3739801SMiguel Ojeda             t.as_mut_bytes()[0] ^= 0xFF;
7248*c3739801SMiguel Ojeda             assert_eq!(t, post_mutation);
7249*c3739801SMiguel Ojeda             t.as_mut_bytes()[0] ^= 0xFF;
7250*c3739801SMiguel Ojeda 
7251*c3739801SMiguel Ojeda             // `write_to` rejects slices that are too small or too large.
7252*c3739801SMiguel Ojeda             assert!(t.write_to(&mut vec![0; N - 1][..]).is_err());
7253*c3739801SMiguel Ojeda             assert!(t.write_to(&mut vec![0; N + 1][..]).is_err());
7254*c3739801SMiguel Ojeda 
7255*c3739801SMiguel Ojeda             // `write_to` works as expected.
7256*c3739801SMiguel Ojeda             let mut bytes = [0; N];
7257*c3739801SMiguel Ojeda             assert_eq!(t.write_to(&mut bytes[..]), Ok(()));
7258*c3739801SMiguel Ojeda             assert_eq!(bytes, t.as_bytes());
7259*c3739801SMiguel Ojeda 
7260*c3739801SMiguel Ojeda             // `write_to_prefix` rejects slices that are too small.
7261*c3739801SMiguel Ojeda             assert!(t.write_to_prefix(&mut vec![0; N - 1][..]).is_err());
7262*c3739801SMiguel Ojeda 
7263*c3739801SMiguel Ojeda             // `write_to_prefix` works with exact-sized slices.
7264*c3739801SMiguel Ojeda             let mut bytes = [0; N];
7265*c3739801SMiguel Ojeda             assert_eq!(t.write_to_prefix(&mut bytes[..]), Ok(()));
7266*c3739801SMiguel Ojeda             assert_eq!(bytes, t.as_bytes());
7267*c3739801SMiguel Ojeda 
7268*c3739801SMiguel Ojeda             // `write_to_prefix` works with too-large slices, and any bytes past
7269*c3739801SMiguel Ojeda             // the prefix aren't modified.
7270*c3739801SMiguel Ojeda             let mut too_many_bytes = vec![0; N + 1];
7271*c3739801SMiguel Ojeda             too_many_bytes[N] = 123;
7272*c3739801SMiguel Ojeda             assert_eq!(t.write_to_prefix(&mut too_many_bytes[..]), Ok(()));
7273*c3739801SMiguel Ojeda             assert_eq!(&too_many_bytes[..N], t.as_bytes());
7274*c3739801SMiguel Ojeda             assert_eq!(too_many_bytes[N], 123);
7275*c3739801SMiguel Ojeda 
7276*c3739801SMiguel Ojeda             // `write_to_suffix` rejects slices that are too small.
7277*c3739801SMiguel Ojeda             assert!(t.write_to_suffix(&mut vec![0; N - 1][..]).is_err());
7278*c3739801SMiguel Ojeda 
7279*c3739801SMiguel Ojeda             // `write_to_suffix` works with exact-sized slices.
7280*c3739801SMiguel Ojeda             let mut bytes = [0; N];
7281*c3739801SMiguel Ojeda             assert_eq!(t.write_to_suffix(&mut bytes[..]), Ok(()));
7282*c3739801SMiguel Ojeda             assert_eq!(bytes, t.as_bytes());
7283*c3739801SMiguel Ojeda 
7284*c3739801SMiguel Ojeda             // `write_to_suffix` works with too-large slices, and any bytes
7285*c3739801SMiguel Ojeda             // before the suffix aren't modified.
7286*c3739801SMiguel Ojeda             let mut too_many_bytes = vec![0; N + 1];
7287*c3739801SMiguel Ojeda             too_many_bytes[0] = 123;
7288*c3739801SMiguel Ojeda             assert_eq!(t.write_to_suffix(&mut too_many_bytes[..]), Ok(()));
7289*c3739801SMiguel Ojeda             assert_eq!(&too_many_bytes[1..], t.as_bytes());
7290*c3739801SMiguel Ojeda             assert_eq!(too_many_bytes[0], 123);
7291*c3739801SMiguel Ojeda         }
7292*c3739801SMiguel Ojeda 
7293*c3739801SMiguel Ojeda         #[derive(Debug, Eq, PartialEq, FromBytes, IntoBytes, Immutable)]
7294*c3739801SMiguel Ojeda         #[repr(C)]
7295*c3739801SMiguel Ojeda         struct Foo {
7296*c3739801SMiguel Ojeda             a: u32,
7297*c3739801SMiguel Ojeda             b: Wrapping<u32>,
7298*c3739801SMiguel Ojeda             c: Option<NonZeroU32>,
7299*c3739801SMiguel Ojeda         }
7300*c3739801SMiguel Ojeda 
7301*c3739801SMiguel Ojeda         let expected_bytes: Vec<u8> = if cfg!(target_endian = "little") {
7302*c3739801SMiguel Ojeda             vec![1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]
7303*c3739801SMiguel Ojeda         } else {
7304*c3739801SMiguel Ojeda             vec![0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0]
7305*c3739801SMiguel Ojeda         };
7306*c3739801SMiguel Ojeda         let post_mutation_expected_a =
7307*c3739801SMiguel Ojeda             if cfg!(target_endian = "little") { 0x00_00_00_FE } else { 0xFF_00_00_01 };
7308*c3739801SMiguel Ojeda         test::<_, 12>(
7309*c3739801SMiguel Ojeda             &mut Foo { a: 1, b: Wrapping(2), c: None },
7310*c3739801SMiguel Ojeda             expected_bytes.as_bytes(),
7311*c3739801SMiguel Ojeda             &Foo { a: post_mutation_expected_a, b: Wrapping(2), c: None },
7312*c3739801SMiguel Ojeda         );
7313*c3739801SMiguel Ojeda         test::<_, 3>(
7314*c3739801SMiguel Ojeda             Unsized::from_mut_slice(&mut [1, 2, 3]),
7315*c3739801SMiguel Ojeda             &[1, 2, 3],
7316*c3739801SMiguel Ojeda             Unsized::from_mut_slice(&mut [0xFE, 2, 3]),
7317*c3739801SMiguel Ojeda         );
7318*c3739801SMiguel Ojeda     }
7319*c3739801SMiguel Ojeda 
7320*c3739801SMiguel Ojeda     #[test]
7321*c3739801SMiguel Ojeda     fn test_array() {
7322*c3739801SMiguel Ojeda         #[derive(FromBytes, IntoBytes, Immutable)]
7323*c3739801SMiguel Ojeda         #[repr(C)]
7324*c3739801SMiguel Ojeda         struct Foo {
7325*c3739801SMiguel Ojeda             a: [u16; 33],
7326*c3739801SMiguel Ojeda         }
7327*c3739801SMiguel Ojeda 
7328*c3739801SMiguel Ojeda         let foo = Foo { a: [0xFFFF; 33] };
7329*c3739801SMiguel Ojeda         let expected = [0xFFu8; 66];
7330*c3739801SMiguel Ojeda         assert_eq!(foo.as_bytes(), &expected[..]);
7331*c3739801SMiguel Ojeda     }
7332*c3739801SMiguel Ojeda 
7333*c3739801SMiguel Ojeda     #[test]
7334*c3739801SMiguel Ojeda     fn test_new_zeroed() {
7335*c3739801SMiguel Ojeda         assert!(!bool::new_zeroed());
7336*c3739801SMiguel Ojeda         assert_eq!(u64::new_zeroed(), 0);
7337*c3739801SMiguel Ojeda         // This test exists in order to exercise unsafe code, especially when
7338*c3739801SMiguel Ojeda         // running under Miri.
7339*c3739801SMiguel Ojeda         #[allow(clippy::unit_cmp)]
7340*c3739801SMiguel Ojeda         {
7341*c3739801SMiguel Ojeda             assert_eq!(<()>::new_zeroed(), ());
7342*c3739801SMiguel Ojeda         }
7343*c3739801SMiguel Ojeda     }
7344*c3739801SMiguel Ojeda 
7345*c3739801SMiguel Ojeda     #[test]
7346*c3739801SMiguel Ojeda     fn test_transparent_packed_generic_struct() {
7347*c3739801SMiguel Ojeda         #[derive(IntoBytes, FromBytes, Unaligned)]
7348*c3739801SMiguel Ojeda         #[repr(transparent)]
7349*c3739801SMiguel Ojeda         #[allow(dead_code)] // We never construct this type
7350*c3739801SMiguel Ojeda         struct Foo<T> {
7351*c3739801SMiguel Ojeda             _t: T,
7352*c3739801SMiguel Ojeda             _phantom: PhantomData<()>,
7353*c3739801SMiguel Ojeda         }
7354*c3739801SMiguel Ojeda 
7355*c3739801SMiguel Ojeda         assert_impl_all!(Foo<u32>: FromZeros, FromBytes, IntoBytes);
7356*c3739801SMiguel Ojeda         assert_impl_all!(Foo<u8>: Unaligned);
7357*c3739801SMiguel Ojeda 
7358*c3739801SMiguel Ojeda         #[derive(IntoBytes, FromBytes, Unaligned)]
7359*c3739801SMiguel Ojeda         #[repr(C, packed)]
7360*c3739801SMiguel Ojeda         #[allow(dead_code)] // We never construct this type
7361*c3739801SMiguel Ojeda         struct Bar<T, U> {
7362*c3739801SMiguel Ojeda             _t: T,
7363*c3739801SMiguel Ojeda             _u: U,
7364*c3739801SMiguel Ojeda         }
7365*c3739801SMiguel Ojeda 
7366*c3739801SMiguel Ojeda         assert_impl_all!(Bar<u8, AU64>: FromZeros, FromBytes, IntoBytes, Unaligned);
7367*c3739801SMiguel Ojeda     }
7368*c3739801SMiguel Ojeda 
7369*c3739801SMiguel Ojeda     #[cfg(feature = "alloc")]
7370*c3739801SMiguel Ojeda     mod alloc {
7371*c3739801SMiguel Ojeda         use super::*;
7372*c3739801SMiguel Ojeda 
7373*c3739801SMiguel Ojeda         #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
7374*c3739801SMiguel Ojeda         #[test]
7375*c3739801SMiguel Ojeda         fn test_extend_vec_zeroed() {
7376*c3739801SMiguel Ojeda             // Test extending when there is an existing allocation.
7377*c3739801SMiguel Ojeda             let mut v = vec![100u16, 200, 300];
7378*c3739801SMiguel Ojeda             FromZeros::extend_vec_zeroed(&mut v, 3).unwrap();
7379*c3739801SMiguel Ojeda             assert_eq!(v.len(), 6);
7380*c3739801SMiguel Ojeda             assert_eq!(&*v, &[100, 200, 300, 0, 0, 0]);
7381*c3739801SMiguel Ojeda             drop(v);
7382*c3739801SMiguel Ojeda 
7383*c3739801SMiguel Ojeda             // Test extending when there is no existing allocation.
7384*c3739801SMiguel Ojeda             let mut v: Vec<u64> = Vec::new();
7385*c3739801SMiguel Ojeda             FromZeros::extend_vec_zeroed(&mut v, 3).unwrap();
7386*c3739801SMiguel Ojeda             assert_eq!(v.len(), 3);
7387*c3739801SMiguel Ojeda             assert_eq!(&*v, &[0, 0, 0]);
7388*c3739801SMiguel Ojeda             drop(v);
7389*c3739801SMiguel Ojeda         }
7390*c3739801SMiguel Ojeda 
7391*c3739801SMiguel Ojeda         #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
7392*c3739801SMiguel Ojeda         #[test]
7393*c3739801SMiguel Ojeda         fn test_extend_vec_zeroed_zst() {
7394*c3739801SMiguel Ojeda             // Test extending when there is an existing (fake) allocation.
7395*c3739801SMiguel Ojeda             let mut v = vec![(), (), ()];
7396*c3739801SMiguel Ojeda             <()>::extend_vec_zeroed(&mut v, 3).unwrap();
7397*c3739801SMiguel Ojeda             assert_eq!(v.len(), 6);
7398*c3739801SMiguel Ojeda             assert_eq!(&*v, &[(), (), (), (), (), ()]);
7399*c3739801SMiguel Ojeda             drop(v);
7400*c3739801SMiguel Ojeda 
7401*c3739801SMiguel Ojeda             // Test extending when there is no existing (fake) allocation.
7402*c3739801SMiguel Ojeda             let mut v: Vec<()> = Vec::new();
7403*c3739801SMiguel Ojeda             <()>::extend_vec_zeroed(&mut v, 3).unwrap();
7404*c3739801SMiguel Ojeda             assert_eq!(&*v, &[(), (), ()]);
7405*c3739801SMiguel Ojeda             drop(v);
7406*c3739801SMiguel Ojeda         }
7407*c3739801SMiguel Ojeda 
7408*c3739801SMiguel Ojeda         #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
7409*c3739801SMiguel Ojeda         #[test]
7410*c3739801SMiguel Ojeda         fn test_insert_vec_zeroed() {
7411*c3739801SMiguel Ojeda             // Insert at start (no existing allocation).
7412*c3739801SMiguel Ojeda             let mut v: Vec<u64> = Vec::new();
7413*c3739801SMiguel Ojeda             u64::insert_vec_zeroed(&mut v, 0, 2).unwrap();
7414*c3739801SMiguel Ojeda             assert_eq!(v.len(), 2);
7415*c3739801SMiguel Ojeda             assert_eq!(&*v, &[0, 0]);
7416*c3739801SMiguel Ojeda             drop(v);
7417*c3739801SMiguel Ojeda 
7418*c3739801SMiguel Ojeda             // Insert at start.
7419*c3739801SMiguel Ojeda             let mut v = vec![100u64, 200, 300];
7420*c3739801SMiguel Ojeda             u64::insert_vec_zeroed(&mut v, 0, 2).unwrap();
7421*c3739801SMiguel Ojeda             assert_eq!(v.len(), 5);
7422*c3739801SMiguel Ojeda             assert_eq!(&*v, &[0, 0, 100, 200, 300]);
7423*c3739801SMiguel Ojeda             drop(v);
7424*c3739801SMiguel Ojeda 
7425*c3739801SMiguel Ojeda             // Insert at middle.
7426*c3739801SMiguel Ojeda             let mut v = vec![100u64, 200, 300];
7427*c3739801SMiguel Ojeda             u64::insert_vec_zeroed(&mut v, 1, 1).unwrap();
7428*c3739801SMiguel Ojeda             assert_eq!(v.len(), 4);
7429*c3739801SMiguel Ojeda             assert_eq!(&*v, &[100, 0, 200, 300]);
7430*c3739801SMiguel Ojeda             drop(v);
7431*c3739801SMiguel Ojeda 
7432*c3739801SMiguel Ojeda             // Insert at end.
7433*c3739801SMiguel Ojeda             let mut v = vec![100u64, 200, 300];
7434*c3739801SMiguel Ojeda             u64::insert_vec_zeroed(&mut v, 3, 1).unwrap();
7435*c3739801SMiguel Ojeda             assert_eq!(v.len(), 4);
7436*c3739801SMiguel Ojeda             assert_eq!(&*v, &[100, 200, 300, 0]);
7437*c3739801SMiguel Ojeda             drop(v);
7438*c3739801SMiguel Ojeda         }
7439*c3739801SMiguel Ojeda 
7440*c3739801SMiguel Ojeda         #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
7441*c3739801SMiguel Ojeda         #[test]
7442*c3739801SMiguel Ojeda         fn test_insert_vec_zeroed_zst() {
7443*c3739801SMiguel Ojeda             // Insert at start (no existing fake allocation).
7444*c3739801SMiguel Ojeda             let mut v: Vec<()> = Vec::new();
7445*c3739801SMiguel Ojeda             <()>::insert_vec_zeroed(&mut v, 0, 2).unwrap();
7446*c3739801SMiguel Ojeda             assert_eq!(v.len(), 2);
7447*c3739801SMiguel Ojeda             assert_eq!(&*v, &[(), ()]);
7448*c3739801SMiguel Ojeda             drop(v);
7449*c3739801SMiguel Ojeda 
7450*c3739801SMiguel Ojeda             // Insert at start.
7451*c3739801SMiguel Ojeda             let mut v = vec![(), (), ()];
7452*c3739801SMiguel Ojeda             <()>::insert_vec_zeroed(&mut v, 0, 2).unwrap();
7453*c3739801SMiguel Ojeda             assert_eq!(v.len(), 5);
7454*c3739801SMiguel Ojeda             assert_eq!(&*v, &[(), (), (), (), ()]);
7455*c3739801SMiguel Ojeda             drop(v);
7456*c3739801SMiguel Ojeda 
7457*c3739801SMiguel Ojeda             // Insert at middle.
7458*c3739801SMiguel Ojeda             let mut v = vec![(), (), ()];
7459*c3739801SMiguel Ojeda             <()>::insert_vec_zeroed(&mut v, 1, 1).unwrap();
7460*c3739801SMiguel Ojeda             assert_eq!(v.len(), 4);
7461*c3739801SMiguel Ojeda             assert_eq!(&*v, &[(), (), (), ()]);
7462*c3739801SMiguel Ojeda             drop(v);
7463*c3739801SMiguel Ojeda 
7464*c3739801SMiguel Ojeda             // Insert at end.
7465*c3739801SMiguel Ojeda             let mut v = vec![(), (), ()];
7466*c3739801SMiguel Ojeda             <()>::insert_vec_zeroed(&mut v, 3, 1).unwrap();
7467*c3739801SMiguel Ojeda             assert_eq!(v.len(), 4);
7468*c3739801SMiguel Ojeda             assert_eq!(&*v, &[(), (), (), ()]);
7469*c3739801SMiguel Ojeda             drop(v);
7470*c3739801SMiguel Ojeda         }
7471*c3739801SMiguel Ojeda 
7472*c3739801SMiguel Ojeda         #[test]
7473*c3739801SMiguel Ojeda         fn test_new_box_zeroed() {
7474*c3739801SMiguel Ojeda             assert_eq!(u64::new_box_zeroed(), Ok(Box::new(0)));
7475*c3739801SMiguel Ojeda         }
7476*c3739801SMiguel Ojeda 
7477*c3739801SMiguel Ojeda         #[test]
7478*c3739801SMiguel Ojeda         fn test_new_box_zeroed_array() {
7479*c3739801SMiguel Ojeda             drop(<[u32; 0x1000]>::new_box_zeroed());
7480*c3739801SMiguel Ojeda         }
7481*c3739801SMiguel Ojeda 
7482*c3739801SMiguel Ojeda         #[test]
7483*c3739801SMiguel Ojeda         fn test_new_box_zeroed_zst() {
7484*c3739801SMiguel Ojeda             // This test exists in order to exercise unsafe code, especially
7485*c3739801SMiguel Ojeda             // when running under Miri.
7486*c3739801SMiguel Ojeda             #[allow(clippy::unit_cmp)]
7487*c3739801SMiguel Ojeda             {
7488*c3739801SMiguel Ojeda                 assert_eq!(<()>::new_box_zeroed(), Ok(Box::new(())));
7489*c3739801SMiguel Ojeda             }
7490*c3739801SMiguel Ojeda         }
7491*c3739801SMiguel Ojeda 
7492*c3739801SMiguel Ojeda         #[test]
7493*c3739801SMiguel Ojeda         fn test_new_box_zeroed_with_elems() {
7494*c3739801SMiguel Ojeda             let mut s: Box<[u64]> = <[u64]>::new_box_zeroed_with_elems(3).unwrap();
7495*c3739801SMiguel Ojeda             assert_eq!(s.len(), 3);
7496*c3739801SMiguel Ojeda             assert_eq!(&*s, &[0, 0, 0]);
7497*c3739801SMiguel Ojeda             s[1] = 3;
7498*c3739801SMiguel Ojeda             assert_eq!(&*s, &[0, 3, 0]);
7499*c3739801SMiguel Ojeda         }
7500*c3739801SMiguel Ojeda 
7501*c3739801SMiguel Ojeda         #[test]
7502*c3739801SMiguel Ojeda         fn test_new_box_zeroed_with_elems_empty() {
7503*c3739801SMiguel Ojeda             let s: Box<[u64]> = <[u64]>::new_box_zeroed_with_elems(0).unwrap();
7504*c3739801SMiguel Ojeda             assert_eq!(s.len(), 0);
7505*c3739801SMiguel Ojeda         }
7506*c3739801SMiguel Ojeda 
7507*c3739801SMiguel Ojeda         #[test]
7508*c3739801SMiguel Ojeda         fn test_new_box_zeroed_with_elems_zst() {
7509*c3739801SMiguel Ojeda             let mut s: Box<[()]> = <[()]>::new_box_zeroed_with_elems(3).unwrap();
7510*c3739801SMiguel Ojeda             assert_eq!(s.len(), 3);
7511*c3739801SMiguel Ojeda             assert!(s.get(10).is_none());
7512*c3739801SMiguel Ojeda             // This test exists in order to exercise unsafe code, especially
7513*c3739801SMiguel Ojeda             // when running under Miri.
7514*c3739801SMiguel Ojeda             #[allow(clippy::unit_cmp)]
7515*c3739801SMiguel Ojeda             {
7516*c3739801SMiguel Ojeda                 assert_eq!(s[1], ());
7517*c3739801SMiguel Ojeda             }
7518*c3739801SMiguel Ojeda             s[2] = ();
7519*c3739801SMiguel Ojeda         }
7520*c3739801SMiguel Ojeda 
7521*c3739801SMiguel Ojeda         #[test]
7522*c3739801SMiguel Ojeda         fn test_new_box_zeroed_with_elems_zst_empty() {
7523*c3739801SMiguel Ojeda             let s: Box<[()]> = <[()]>::new_box_zeroed_with_elems(0).unwrap();
7524*c3739801SMiguel Ojeda             assert_eq!(s.len(), 0);
7525*c3739801SMiguel Ojeda         }
7526*c3739801SMiguel Ojeda 
7527*c3739801SMiguel Ojeda         #[test]
7528*c3739801SMiguel Ojeda         fn new_box_zeroed_with_elems_errors() {
7529*c3739801SMiguel Ojeda             assert_eq!(<[u16]>::new_box_zeroed_with_elems(usize::MAX), Err(AllocError));
7530*c3739801SMiguel Ojeda 
7531*c3739801SMiguel Ojeda             let max = <usize as core::convert::TryFrom<_>>::try_from(isize::MAX).unwrap();
7532*c3739801SMiguel Ojeda             assert_eq!(
7533*c3739801SMiguel Ojeda                 <[u16]>::new_box_zeroed_with_elems((max / mem::size_of::<u16>()) + 1),
7534*c3739801SMiguel Ojeda                 Err(AllocError)
7535*c3739801SMiguel Ojeda             );
7536*c3739801SMiguel Ojeda         }
7537*c3739801SMiguel Ojeda     }
7538*c3739801SMiguel Ojeda 
7539*c3739801SMiguel Ojeda     #[test]
7540*c3739801SMiguel Ojeda     #[allow(deprecated)]
7541*c3739801SMiguel Ojeda     fn test_deprecated_from_bytes() {
7542*c3739801SMiguel Ojeda         let val = 0u32;
7543*c3739801SMiguel Ojeda         let bytes = val.as_bytes();
7544*c3739801SMiguel Ojeda 
7545*c3739801SMiguel Ojeda         assert!(u32::ref_from(bytes).is_some());
7546*c3739801SMiguel Ojeda         // mut_from needs mut bytes
7547*c3739801SMiguel Ojeda         let mut val = 0u32;
7548*c3739801SMiguel Ojeda         let mut_bytes = val.as_mut_bytes();
7549*c3739801SMiguel Ojeda         assert!(u32::mut_from(mut_bytes).is_some());
7550*c3739801SMiguel Ojeda 
7551*c3739801SMiguel Ojeda         assert!(u32::read_from(bytes).is_some());
7552*c3739801SMiguel Ojeda 
7553*c3739801SMiguel Ojeda         let (slc, rest) = <u32>::slice_from_prefix(bytes, 0).unwrap();
7554*c3739801SMiguel Ojeda         assert!(slc.is_empty());
7555*c3739801SMiguel Ojeda         assert_eq!(rest.len(), 4);
7556*c3739801SMiguel Ojeda 
7557*c3739801SMiguel Ojeda         let (rest, slc) = <u32>::slice_from_suffix(bytes, 0).unwrap();
7558*c3739801SMiguel Ojeda         assert!(slc.is_empty());
7559*c3739801SMiguel Ojeda         assert_eq!(rest.len(), 4);
7560*c3739801SMiguel Ojeda 
7561*c3739801SMiguel Ojeda         let (slc, rest) = <u32>::mut_slice_from_prefix(mut_bytes, 0).unwrap();
7562*c3739801SMiguel Ojeda         assert!(slc.is_empty());
7563*c3739801SMiguel Ojeda         assert_eq!(rest.len(), 4);
7564*c3739801SMiguel Ojeda 
7565*c3739801SMiguel Ojeda         let (rest, slc) = <u32>::mut_slice_from_suffix(mut_bytes, 0).unwrap();
7566*c3739801SMiguel Ojeda         assert!(slc.is_empty());
7567*c3739801SMiguel Ojeda         assert_eq!(rest.len(), 4);
7568*c3739801SMiguel Ojeda     }
7569*c3739801SMiguel Ojeda 
7570*c3739801SMiguel Ojeda     #[test]
7571*c3739801SMiguel Ojeda     fn test_try_ref_from_prefix_suffix() {
7572*c3739801SMiguel Ojeda         use crate::util::testutil::Align;
7573*c3739801SMiguel Ojeda         let bytes = &Align::<[u8; 4], u32>::new([0u8; 4]).t[..];
7574*c3739801SMiguel Ojeda         let (r, rest): (&u32, &[u8]) = u32::try_ref_from_prefix(bytes).unwrap();
7575*c3739801SMiguel Ojeda         assert_eq!(*r, 0);
7576*c3739801SMiguel Ojeda         assert_eq!(rest.len(), 0);
7577*c3739801SMiguel Ojeda 
7578*c3739801SMiguel Ojeda         let (rest, r): (&[u8], &u32) = u32::try_ref_from_suffix(bytes).unwrap();
7579*c3739801SMiguel Ojeda         assert_eq!(*r, 0);
7580*c3739801SMiguel Ojeda         assert_eq!(rest.len(), 0);
7581*c3739801SMiguel Ojeda     }
7582*c3739801SMiguel Ojeda 
7583*c3739801SMiguel Ojeda     #[test]
7584*c3739801SMiguel Ojeda     fn test_raw_dangling() {
7585*c3739801SMiguel Ojeda         use crate::util::AsAddress;
7586*c3739801SMiguel Ojeda         let ptr: NonNull<u32> = u32::raw_dangling();
7587*c3739801SMiguel Ojeda         assert_eq!(AsAddress::addr(ptr), 1);
7588*c3739801SMiguel Ojeda 
7589*c3739801SMiguel Ojeda         let ptr: NonNull<[u32]> = <[u32]>::raw_dangling();
7590*c3739801SMiguel Ojeda         assert_eq!(AsAddress::addr(ptr), 1);
7591*c3739801SMiguel Ojeda     }
7592*c3739801SMiguel Ojeda 
7593*c3739801SMiguel Ojeda     #[test]
7594*c3739801SMiguel Ojeda     fn test_try_ref_from_prefix_with_elems() {
7595*c3739801SMiguel Ojeda         use crate::util::testutil::Align;
7596*c3739801SMiguel Ojeda         let bytes = &Align::<[u8; 8], u32>::new([0u8; 8]).t[..];
7597*c3739801SMiguel Ojeda         let (r, rest): (&[u32], &[u8]) = <[u32]>::try_ref_from_prefix_with_elems(bytes, 2).unwrap();
7598*c3739801SMiguel Ojeda         assert_eq!(r.len(), 2);
7599*c3739801SMiguel Ojeda         assert_eq!(rest.len(), 0);
7600*c3739801SMiguel Ojeda     }
7601*c3739801SMiguel Ojeda 
7602*c3739801SMiguel Ojeda     #[test]
7603*c3739801SMiguel Ojeda     fn test_try_ref_from_suffix_with_elems() {
7604*c3739801SMiguel Ojeda         use crate::util::testutil::Align;
7605*c3739801SMiguel Ojeda         let bytes = &Align::<[u8; 8], u32>::new([0u8; 8]).t[..];
7606*c3739801SMiguel Ojeda         let (rest, r): (&[u8], &[u32]) = <[u32]>::try_ref_from_suffix_with_elems(bytes, 2).unwrap();
7607*c3739801SMiguel Ojeda         assert_eq!(r.len(), 2);
7608*c3739801SMiguel Ojeda         assert_eq!(rest.len(), 0);
7609*c3739801SMiguel Ojeda     }
7610*c3739801SMiguel Ojeda }
7611