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