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