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