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