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