1 // Copyright 2024 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 /// Safely transmutes a value of one type to a value of another type of the same 11 /// size. 12 /// 13 /// This macro behaves like an invocation of this function: 14 /// 15 /// ```ignore 16 /// const fn transmute<Src, Dst>(src: Src) -> Dst 17 /// where 18 /// Src: IntoBytes, 19 /// Dst: FromBytes, 20 /// size_of::<Src>() == size_of::<Dst>(), 21 /// { 22 /// # /* 23 /// ... 24 /// # */ 25 /// } 26 /// ``` 27 /// 28 /// However, unlike a function, this macro can only be invoked when the types of 29 /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are 30 /// inferred from the calling context; they cannot be explicitly specified in 31 /// the macro invocation. 32 /// 33 /// Note that the `Src` produced by the expression `$e` will *not* be dropped. 34 /// Semantically, its bits will be copied into a new value of type `Dst`, the 35 /// original `Src` will be forgotten, and the value of type `Dst` will be 36 /// returned. 37 /// 38 /// # Examples 39 /// 40 /// ``` 41 /// # use zerocopy::transmute; 42 /// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; 43 /// 44 /// let two_dimensional: [[u8; 4]; 2] = transmute!(one_dimensional); 45 /// 46 /// assert_eq!(two_dimensional, [[0, 1, 2, 3], [4, 5, 6, 7]]); 47 /// ``` 48 /// 49 /// # Use in `const` contexts 50 /// 51 /// This macro can be invoked in `const` contexts. 52 #[macro_export] 53 macro_rules! transmute { 54 ($e:expr) => {{ 55 // NOTE: This must be a macro (rather than a function with trait bounds) 56 // because there's no way, in a generic context, to enforce that two 57 // types have the same size. `core::mem::transmute` uses compiler magic 58 // to enforce this so long as the types are concrete. 59 60 let e = $e; 61 if false { 62 // This branch, though never taken, ensures that the type of `e` is 63 // `IntoBytes` and that the type of this macro invocation expression 64 // is `FromBytes`. 65 66 struct AssertIsIntoBytes<T: $crate::IntoBytes>(T); 67 let _ = AssertIsIntoBytes(e); 68 69 struct AssertIsFromBytes<U: $crate::FromBytes>(U); 70 #[allow(unused, unreachable_code)] 71 let u = AssertIsFromBytes(loop {}); 72 u.0 73 } else { 74 // SAFETY: `core::mem::transmute` ensures that the type of `e` and 75 // the type of this macro invocation expression have the same size. 76 // We know this transmute is safe thanks to the `IntoBytes` and 77 // `FromBytes` bounds enforced by the `false` branch. 78 // 79 // We use this reexport of `core::mem::transmute` because we know it 80 // will always be available for crates which are using the 2015 81 // edition of Rust. By contrast, if we were to use 82 // `std::mem::transmute`, this macro would not work for such crates 83 // in `no_std` contexts, and if we were to use 84 // `core::mem::transmute`, this macro would not work in `std` 85 // contexts in which `core` was not manually imported. This is not a 86 // problem for 2018 edition crates. 87 let u = unsafe { 88 // Clippy: We can't annotate the types; this macro is designed 89 // to infer the types from the calling context. 90 #[allow(clippy::missing_transmute_annotations)] 91 $crate::util::macro_util::core_reexport::mem::transmute(e) 92 }; 93 $crate::util::macro_util::must_use(u) 94 } 95 }} 96 } 97 98 /// Safely transmutes a mutable or immutable reference of one type to an 99 /// immutable reference of another type of the same size and compatible 100 /// alignment. 101 /// 102 /// This macro behaves like an invocation of this function: 103 /// 104 /// ```ignore 105 /// const fn transmute_ref<'src, 'dst, Src, Dst>(src: &'src Src) -> &'dst Dst 106 /// where 107 /// 'src: 'dst, 108 /// Src: IntoBytes + Immutable, 109 /// Dst: FromBytes + Immutable, 110 /// size_of::<Src>() == size_of::<Dst>(), 111 /// align_of::<Src>() >= align_of::<Dst>(), 112 /// { 113 /// # /* 114 /// ... 115 /// # */ 116 /// } 117 /// ``` 118 /// 119 /// However, unlike a function, this macro can only be invoked when the types of 120 /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are 121 /// inferred from the calling context; they cannot be explicitly specified in 122 /// the macro invocation. 123 /// 124 /// # Examples 125 /// 126 /// ``` 127 /// # use zerocopy::transmute_ref; 128 /// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; 129 /// 130 /// let two_dimensional: &[[u8; 4]; 2] = transmute_ref!(&one_dimensional); 131 /// 132 /// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]); 133 /// ``` 134 /// 135 /// # Use in `const` contexts 136 /// 137 /// This macro can be invoked in `const` contexts. 138 /// 139 /// # Alignment increase error message 140 /// 141 /// Because of limitations on macros, the error message generated when 142 /// `transmute_ref!` is used to transmute from a type of lower alignment to a 143 /// type of higher alignment is somewhat confusing. For example, the following 144 /// code: 145 /// 146 /// ```compile_fail 147 /// const INCREASE_ALIGNMENT: &u16 = zerocopy::transmute_ref!(&[0u8; 2]); 148 /// ``` 149 /// 150 /// ...generates the following error: 151 /// 152 /// ```text 153 /// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types 154 /// --> src/lib.rs:1524:34 155 /// | 156 /// 5 | const INCREASE_ALIGNMENT: &u16 = zerocopy::transmute_ref!(&[0u8; 2]); 157 /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 158 /// | 159 /// = note: source type: `AlignOf<[u8; 2]>` (8 bits) 160 /// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits) 161 /// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) 162 /// ``` 163 /// 164 /// This is saying that `max(align_of::<T>(), align_of::<U>()) != 165 /// align_of::<T>()`, which is equivalent to `align_of::<T>() < 166 /// align_of::<U>()`. 167 #[macro_export] 168 macro_rules! transmute_ref { 169 ($e:expr) => {{ 170 // NOTE: This must be a macro (rather than a function with trait bounds) 171 // because there's no way, in a generic context, to enforce that two 172 // types have the same size or alignment. 173 174 // Ensure that the source type is a reference or a mutable reference 175 // (note that mutable references are implicitly reborrowed here). 176 let e: &_ = $e; 177 178 #[allow(unused, clippy::diverging_sub_expression)] 179 if false { 180 // This branch, though never taken, ensures that the type of `e` is 181 // `&T` where `T: 't + Sized + IntoBytes + Immutable`, that the type of 182 // this macro expression is `&U` where `U: 'u + Sized + FromBytes + 183 // Immutable`, and that `'t` outlives `'u`. 184 185 struct AssertSrcIsSized<'a, T: ::core::marker::Sized>(&'a T); 186 struct AssertSrcIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T); 187 struct AssertSrcIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T); 188 struct AssertDstIsSized<'a, T: ::core::marker::Sized>(&'a T); 189 struct AssertDstIsFromBytes<'a, U: ?::core::marker::Sized + $crate::FromBytes>(&'a U); 190 struct AssertDstIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T); 191 192 let _ = AssertSrcIsSized(e); 193 let _ = AssertSrcIsIntoBytes(e); 194 let _ = AssertSrcIsImmutable(e); 195 196 if true { 197 #[allow(unused, unreachable_code)] 198 let u = AssertDstIsSized(loop {}); 199 u.0 200 } else if true { 201 #[allow(unused, unreachable_code)] 202 let u = AssertDstIsFromBytes(loop {}); 203 u.0 204 } else { 205 #[allow(unused, unreachable_code)] 206 let u = AssertDstIsImmutable(loop {}); 207 u.0 208 } 209 } else if false { 210 // This branch, though never taken, ensures that `size_of::<T>() == 211 // size_of::<U>()` and that that `align_of::<T>() >= 212 // align_of::<U>()`. 213 214 // `t` is inferred to have type `T` because it's assigned to `e` (of 215 // type `&T`) as `&t`. 216 let mut t = loop {}; 217 e = &t; 218 219 // `u` is inferred to have type `U` because it's used as `&u` as the 220 // value returned from this branch. 221 let u; 222 223 $crate::assert_size_eq!(t, u); 224 $crate::assert_align_gt_eq!(t, u); 225 226 &u 227 } else { 228 // SAFETY: For source type `Src` and destination type `Dst`: 229 // - We know that `Src: IntoBytes + Immutable` and `Dst: FromBytes + 230 // Immutable` thanks to the uses of `AssertSrcIsIntoBytes`, 231 // `AssertSrcIsImmutable`, `AssertDstIsFromBytes`, and 232 // `AssertDstIsImmutable` above. 233 // - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to 234 // the use of `assert_size_eq!` above. 235 // - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to 236 // the use of `assert_align_gt_eq!` above. 237 let u = unsafe { $crate::util::macro_util::transmute_ref(e) }; 238 $crate::util::macro_util::must_use(u) 239 } 240 }} 241 } 242 243 /// Safely transmutes a mutable reference of one type to a mutable reference of 244 /// another type of the same size and compatible alignment. 245 /// 246 /// This macro behaves like an invocation of this function: 247 /// 248 /// ```ignore 249 /// const fn transmute_mut<'src, 'dst, Src, Dst>(src: &'src mut Src) -> &'dst mut Dst 250 /// where 251 /// 'src: 'dst, 252 /// Src: FromBytes + IntoBytes, 253 /// Dst: FromBytes + IntoBytes, 254 /// size_of::<Src>() == size_of::<Dst>(), 255 /// align_of::<Src>() >= align_of::<Dst>(), 256 /// { 257 /// # /* 258 /// ... 259 /// # */ 260 /// } 261 /// ``` 262 /// 263 /// However, unlike a function, this macro can only be invoked when the types of 264 /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are 265 /// inferred from the calling context; they cannot be explicitly specified in 266 /// the macro invocation. 267 /// 268 /// # Examples 269 /// 270 /// ``` 271 /// # use zerocopy::transmute_mut; 272 /// let mut one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; 273 /// 274 /// let two_dimensional: &mut [[u8; 4]; 2] = transmute_mut!(&mut one_dimensional); 275 /// 276 /// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]); 277 /// 278 /// two_dimensional.reverse(); 279 /// 280 /// assert_eq!(one_dimensional, [4, 5, 6, 7, 0, 1, 2, 3]); 281 /// ``` 282 /// 283 /// # Use in `const` contexts 284 /// 285 /// This macro can be invoked in `const` contexts. 286 /// 287 /// # Alignment increase error message 288 /// 289 /// Because of limitations on macros, the error message generated when 290 /// `transmute_mut!` is used to transmute from a type of lower alignment to a 291 /// type of higher alignment is somewhat confusing. For example, the following 292 /// code: 293 /// 294 /// ```compile_fail 295 /// const INCREASE_ALIGNMENT: &mut u16 = zerocopy::transmute_mut!(&mut [0u8; 2]); 296 /// ``` 297 /// 298 /// ...generates the following error: 299 /// 300 /// ```text 301 /// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types 302 /// --> src/lib.rs:1524:34 303 /// | 304 /// 5 | const INCREASE_ALIGNMENT: &mut u16 = zerocopy::transmute_mut!(&mut [0u8; 2]); 305 /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 306 /// | 307 /// = note: source type: `AlignOf<[u8; 2]>` (8 bits) 308 /// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits) 309 /// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) 310 /// ``` 311 /// 312 /// This is saying that `max(align_of::<T>(), align_of::<U>()) != 313 /// align_of::<T>()`, which is equivalent to `align_of::<T>() < 314 /// align_of::<U>()`. 315 #[macro_export] 316 macro_rules! transmute_mut { 317 ($e:expr) => {{ 318 // NOTE: This must be a macro (rather than a function with trait bounds) 319 // because there's no way, in a generic context, to enforce that two 320 // types have the same size or alignment. 321 322 // Ensure that the source type is a mutable reference. 323 let e: &mut _ = $e; 324 325 #[allow(unused, clippy::diverging_sub_expression)] 326 if false { 327 // This branch, though never taken, ensures that the type of `e` is 328 // `&mut T` where `T: 't + Sized + FromBytes + IntoBytes` and that 329 // the type of this macro expression is `&mut U` where `U: 'u + 330 // Sized + FromBytes + IntoBytes`. 331 332 // We use immutable references here rather than mutable so that, if 333 // this macro is used in a const context (in which, as of this 334 // writing, mutable references are banned), the error message 335 // appears to originate in the user's code rather than in the 336 // internals of this macro. 337 struct AssertSrcIsSized<'a, T: ::core::marker::Sized>(&'a T); 338 struct AssertSrcIsFromBytes<'a, T: ?::core::marker::Sized + $crate::FromBytes>(&'a T); 339 struct AssertSrcIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T); 340 struct AssertDstIsSized<'a, T: ::core::marker::Sized>(&'a T); 341 struct AssertDstIsFromBytes<'a, T: ?::core::marker::Sized + $crate::FromBytes>(&'a T); 342 struct AssertDstIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T); 343 344 if true { 345 let _ = AssertSrcIsSized(&*e); 346 } else if true { 347 let _ = AssertSrcIsFromBytes(&*e); 348 } else { 349 let _ = AssertSrcIsIntoBytes(&*e); 350 } 351 352 if true { 353 #[allow(unused, unreachable_code)] 354 let u = AssertDstIsSized(loop {}); 355 &mut *u.0 356 } else if true { 357 #[allow(unused, unreachable_code)] 358 let u = AssertDstIsFromBytes(loop {}); 359 &mut *u.0 360 } else { 361 #[allow(unused, unreachable_code)] 362 let u = AssertDstIsIntoBytes(loop {}); 363 &mut *u.0 364 } 365 } else if false { 366 // This branch, though never taken, ensures that `size_of::<T>() == 367 // size_of::<U>()` and that that `align_of::<T>() >= 368 // align_of::<U>()`. 369 370 // `t` is inferred to have type `T` because it's assigned to `e` (of 371 // type `&mut T`) as `&mut t`. 372 let mut t = loop {}; 373 e = &mut t; 374 375 // `u` is inferred to have type `U` because it's used as `&mut u` as 376 // the value returned from this branch. 377 let u; 378 379 $crate::assert_size_eq!(t, u); 380 $crate::assert_align_gt_eq!(t, u); 381 382 &mut u 383 } else { 384 // SAFETY: For source type `Src` and destination type `Dst`: 385 // - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to 386 // the use of `assert_size_eq!` above. 387 // - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to 388 // the use of `assert_align_gt_eq!` above. 389 let u = unsafe { $crate::util::macro_util::transmute_mut(e) }; 390 $crate::util::macro_util::must_use(u) 391 } 392 }} 393 } 394 395 /// Conditionally transmutes a value of one type to a value of another type of 396 /// the same size. 397 /// 398 /// This macro behaves like an invocation of this function: 399 /// 400 /// ```ignore 401 /// fn try_transmute<Src, Dst>(src: Src) -> Result<Dst, ValidityError<Src, Dst>> 402 /// where 403 /// Src: IntoBytes, 404 /// Dst: TryFromBytes, 405 /// size_of::<Src>() == size_of::<Dst>(), 406 /// { 407 /// # /* 408 /// ... 409 /// # */ 410 /// } 411 /// ``` 412 /// 413 /// However, unlike a function, this macro can only be invoked when the types of 414 /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are 415 /// inferred from the calling context; they cannot be explicitly specified in 416 /// the macro invocation. 417 /// 418 /// Note that the `Src` produced by the expression `$e` will *not* be dropped. 419 /// Semantically, its bits will be copied into a new value of type `Dst`, the 420 /// original `Src` will be forgotten, and the value of type `Dst` will be 421 /// returned. 422 /// 423 /// # Examples 424 /// 425 /// ``` 426 /// # use zerocopy::*; 427 /// // 0u8 → bool = false 428 /// assert_eq!(try_transmute!(0u8), Ok(false)); 429 /// 430 /// // 1u8 → bool = true 431 /// assert_eq!(try_transmute!(1u8), Ok(true)); 432 /// 433 /// // 2u8 → bool = error 434 /// assert!(matches!( 435 /// try_transmute!(2u8), 436 /// Result::<bool, _>::Err(ValidityError { .. }) 437 /// )); 438 /// ``` 439 #[macro_export] 440 macro_rules! try_transmute { 441 ($e:expr) => {{ 442 // NOTE: This must be a macro (rather than a function with trait bounds) 443 // because there's no way, in a generic context, to enforce that two 444 // types have the same size. `core::mem::transmute` uses compiler magic 445 // to enforce this so long as the types are concrete. 446 447 let e = $e; 448 if false { 449 // Check that the sizes of the source and destination types are 450 // equal. 451 452 // SAFETY: This code is never executed. 453 Ok(unsafe { 454 // Clippy: We can't annotate the types; this macro is designed 455 // to infer the types from the calling context. 456 #[allow(clippy::missing_transmute_annotations)] 457 $crate::util::macro_util::core_reexport::mem::transmute(e) 458 }) 459 } else { 460 $crate::util::macro_util::try_transmute::<_, _>(e) 461 } 462 }} 463 } 464 465 /// Conditionally transmutes a mutable or immutable reference of one type to an 466 /// immutable reference of another type of the same size and compatible 467 /// alignment. 468 /// 469 /// This macro behaves like an invocation of this function: 470 /// 471 /// ```ignore 472 /// fn try_transmute_ref<Src, Dst>(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>> 473 /// where 474 /// Src: IntoBytes + Immutable, 475 /// Dst: TryFromBytes + Immutable, 476 /// size_of::<Src>() == size_of::<Dst>(), 477 /// align_of::<Src>() >= align_of::<Dst>(), 478 /// { 479 /// # /* 480 /// ... 481 /// # */ 482 /// } 483 /// ``` 484 /// 485 /// However, unlike a function, this macro can only be invoked when the types of 486 /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are 487 /// inferred from the calling context; they cannot be explicitly specified in 488 /// the macro invocation. 489 /// 490 /// # Examples 491 /// 492 /// ``` 493 /// # use zerocopy::*; 494 /// // 0u8 → bool = false 495 /// assert_eq!(try_transmute_ref!(&0u8), Ok(&false)); 496 /// 497 /// // 1u8 → bool = true 498 /// assert_eq!(try_transmute_ref!(&1u8), Ok(&true)); 499 /// 500 /// // 2u8 → bool = error 501 /// assert!(matches!( 502 /// try_transmute_ref!(&2u8), 503 /// Result::<&bool, _>::Err(ValidityError { .. }) 504 /// )); 505 /// ``` 506 /// 507 /// # Alignment increase error message 508 /// 509 /// Because of limitations on macros, the error message generated when 510 /// `try_transmute_ref!` is used to transmute from a type of lower alignment to 511 /// a type of higher alignment is somewhat confusing. For example, the following 512 /// code: 513 /// 514 /// ```compile_fail 515 /// let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]); 516 /// ``` 517 /// 518 /// ...generates the following error: 519 /// 520 /// ```text 521 /// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types 522 /// --> example.rs:1:47 523 /// | 524 /// 1 | let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]); 525 /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 526 /// | 527 /// = note: source type: `AlignOf<[u8; 2]>` (8 bits) 528 /// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits) 529 /// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `zerocopy::try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)/// ``` 530 /// ``` 531 /// 532 /// This is saying that `max(align_of::<T>(), align_of::<U>()) != 533 /// align_of::<T>()`, which is equivalent to `align_of::<T>() < 534 /// align_of::<U>()`. 535 #[macro_export] 536 macro_rules! try_transmute_ref { 537 ($e:expr) => {{ 538 // NOTE: This must be a macro (rather than a function with trait bounds) 539 // because there's no way, in a generic context, to enforce that two 540 // types have the same size. `core::mem::transmute` uses compiler magic 541 // to enforce this so long as the types are concrete. 542 543 // Ensure that the source type is a reference or a mutable reference 544 // (note that mutable references are implicitly reborrowed here). 545 let e: &_ = $e; 546 547 #[allow(unreachable_code, unused, clippy::diverging_sub_expression)] 548 if false { 549 // This branch, though never taken, ensures that `size_of::<T>() == 550 // size_of::<U>()` and that that `align_of::<T>() >= 551 // align_of::<U>()`. 552 553 // `t` is inferred to have type `T` because it's assigned to `e` (of 554 // type `&T`) as `&t`. 555 let mut t = loop {}; 556 e = &t; 557 558 // `u` is inferred to have type `U` because it's used as `Ok(&u)` as 559 // the value returned from this branch. 560 let u; 561 562 $crate::assert_size_eq!(t, u); 563 $crate::assert_align_gt_eq!(t, u); 564 565 Ok(&u) 566 } else { 567 $crate::util::macro_util::try_transmute_ref::<_, _>(e) 568 } 569 }} 570 } 571 572 /// Conditionally transmutes a mutable reference of one type to a mutable 573 /// reference of another type of the same size and compatible alignment. 574 /// 575 /// This macro behaves like an invocation of this function: 576 /// 577 /// ```ignore 578 /// fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>> 579 /// where 580 /// Src: FromBytes + IntoBytes, 581 /// Dst: TryFromBytes + IntoBytes, 582 /// size_of::<Src>() == size_of::<Dst>(), 583 /// align_of::<Src>() >= align_of::<Dst>(), 584 /// { 585 /// # /* 586 /// ... 587 /// # */ 588 /// } 589 /// ``` 590 /// 591 /// However, unlike a function, this macro can only be invoked when the types of 592 /// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are 593 /// inferred from the calling context; they cannot be explicitly specified in 594 /// the macro invocation. 595 /// 596 /// # Examples 597 /// 598 /// ``` 599 /// # use zerocopy::*; 600 /// // 0u8 → bool = false 601 /// let src = &mut 0u8; 602 /// assert_eq!(try_transmute_mut!(src), Ok(&mut false)); 603 /// 604 /// // 1u8 → bool = true 605 /// let src = &mut 1u8; 606 /// assert_eq!(try_transmute_mut!(src), Ok(&mut true)); 607 /// 608 /// // 2u8 → bool = error 609 /// let src = &mut 2u8; 610 /// assert!(matches!( 611 /// try_transmute_mut!(src), 612 /// Result::<&mut bool, _>::Err(ValidityError { .. }) 613 /// )); 614 /// ``` 615 /// 616 /// # Alignment increase error message 617 /// 618 /// Because of limitations on macros, the error message generated when 619 /// `try_transmute_ref!` is used to transmute from a type of lower alignment to 620 /// a type of higher alignment is somewhat confusing. For example, the following 621 /// code: 622 /// 623 /// ```compile_fail 624 /// let src = &mut [0u8; 2]; 625 /// let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src); 626 /// ``` 627 /// 628 /// ...generates the following error: 629 /// 630 /// ```text 631 /// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types 632 /// --> example.rs:2:51 633 /// | 634 /// 2 | let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src); 635 /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 636 /// | 637 /// = note: source type: `AlignOf<[u8; 2]>` (8 bits) 638 /// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits) 639 /// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `zerocopy::try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) 640 /// ``` 641 /// 642 /// This is saying that `max(align_of::<T>(), align_of::<U>()) != 643 /// align_of::<T>()`, which is equivalent to `align_of::<T>() < 644 /// align_of::<U>()`. 645 #[macro_export] 646 macro_rules! try_transmute_mut { 647 ($e:expr) => {{ 648 // NOTE: This must be a macro (rather than a function with trait bounds) 649 // because there's no way, in a generic context, to enforce that two 650 // types have the same size. `core::mem::transmute` uses compiler magic 651 // to enforce this so long as the types are concrete. 652 653 // Ensure that the source type is a mutable reference. 654 let e: &mut _ = $e; 655 656 #[allow(unreachable_code, unused, clippy::diverging_sub_expression)] 657 if false { 658 // This branch, though never taken, ensures that `size_of::<T>() == 659 // size_of::<U>()` and that that `align_of::<T>() >= 660 // align_of::<U>()`. 661 662 // `t` is inferred to have type `T` because it's assigned to `e` (of 663 // type `&mut T`) as `&mut t`. 664 let mut t = loop {}; 665 e = &mut t; 666 667 // `u` is inferred to have type `U` because it's used as `Ok(&mut 668 // u)` as the value returned from this branch. 669 let u; 670 671 $crate::assert_size_eq!(t, u); 672 $crate::assert_align_gt_eq!(t, u); 673 674 Ok(&mut u) 675 } else { 676 $crate::util::macro_util::try_transmute_mut::<_, _>(e) 677 } 678 }} 679 } 680 681 /// Includes a file and safely transmutes it to a value of an arbitrary type. 682 /// 683 /// The file will be included as a byte array, `[u8; N]`, which will be 684 /// transmuted to another type, `T`. `T` is inferred from the calling context, 685 /// and must implement [`FromBytes`]. 686 /// 687 /// The file is located relative to the current file (similarly to how modules 688 /// are found). The provided path is interpreted in a platform-specific way at 689 /// compile time. So, for instance, an invocation with a Windows path containing 690 /// backslashes `\` would not compile correctly on Unix. 691 /// 692 /// `include_value!` is ignorant of byte order. For byte order-aware types, see 693 /// the [`byteorder`] module. 694 /// 695 /// [`FromBytes`]: crate::FromBytes 696 /// [`byteorder`]: crate::byteorder 697 /// 698 /// # Examples 699 /// 700 /// Assume there are two files in the same directory with the following 701 /// contents: 702 /// 703 /// File `data` (no trailing newline): 704 /// 705 /// ```text 706 /// abcd 707 /// ``` 708 /// 709 /// File `main.rs`: 710 /// 711 /// ```rust 712 /// use zerocopy::include_value; 713 /// # macro_rules! include_value { 714 /// # ($file:expr) => { zerocopy::include_value!(concat!("../testdata/include_value/", $file)) }; 715 /// # } 716 /// 717 /// fn main() { 718 /// let as_u32: u32 = include_value!("data"); 719 /// assert_eq!(as_u32, u32::from_ne_bytes([b'a', b'b', b'c', b'd'])); 720 /// let as_i32: i32 = include_value!("data"); 721 /// assert_eq!(as_i32, i32::from_ne_bytes([b'a', b'b', b'c', b'd'])); 722 /// } 723 /// ``` 724 /// 725 /// # Use in `const` contexts 726 /// 727 /// This macro can be invoked in `const` contexts. 728 #[doc(alias("include_bytes", "include_data", "include_type"))] 729 #[macro_export] 730 macro_rules! include_value { 731 ($file:expr $(,)?) => { 732 $crate::transmute!(*::core::include_bytes!($file)) 733 }; 734 } 735 736 #[doc(hidden)] 737 #[macro_export] 738 macro_rules! cryptocorrosion_derive_traits { 739 ( 740 #[repr($repr:ident)] 741 $(#[$attr:meta])* 742 $vis:vis struct $name:ident $(<$($tyvar:ident),*>)? 743 $( 744 ( 745 $($tuple_field_vis:vis $tuple_field_ty:ty),* 746 ); 747 )? 748 749 $( 750 { 751 $($field_vis:vis $field_name:ident: $field_ty:ty,)* 752 } 753 )? 754 ) => { 755 $crate::cryptocorrosion_derive_traits!(@assert_allowed_struct_repr #[repr($repr)]); 756 757 $(#[$attr])* 758 #[repr($repr)] 759 $vis struct $name $(<$($tyvar),*>)? 760 $( 761 ( 762 $($tuple_field_vis $tuple_field_ty),* 763 ); 764 )? 765 766 $( 767 { 768 $($field_vis $field_name: $field_ty,)* 769 } 770 )? 771 772 // SAFETY: See inline. 773 unsafe impl $(<$($tyvar),*>)? $crate::TryFromBytes for $name$(<$($tyvar),*>)? 774 where 775 $( 776 $($tuple_field_ty: $crate::FromBytes,)* 777 )? 778 779 $( 780 $($field_ty: $crate::FromBytes,)* 781 )? 782 { 783 fn is_bit_valid<A>(_c: $crate::Maybe<'_, Self, A>) -> bool 784 where 785 A: $crate::pointer::invariant::Reference 786 { 787 // SAFETY: This macro only accepts `#[repr(C)]` and 788 // `#[repr(transparent)]` structs, and this `impl` block 789 // requires all field types to be `FromBytes`. Thus, all 790 // initialized byte sequences constitutes valid instances of 791 // `Self`. 792 true 793 } 794 795 fn only_derive_is_allowed_to_implement_this_trait() {} 796 } 797 798 // SAFETY: This macro only accepts `#[repr(C)]` and 799 // `#[repr(transparent)]` structs, and this `impl` block requires all 800 // field types to be `FromBytes`, which is a sub-trait of `FromZeros`. 801 unsafe impl $(<$($tyvar),*>)? $crate::FromZeros for $name$(<$($tyvar),*>)? 802 where 803 $( 804 $($tuple_field_ty: $crate::FromBytes,)* 805 )? 806 807 $( 808 $($field_ty: $crate::FromBytes,)* 809 )? 810 { 811 fn only_derive_is_allowed_to_implement_this_trait() {} 812 } 813 814 // SAFETY: This macro only accepts `#[repr(C)]` and 815 // `#[repr(transparent)]` structs, and this `impl` block requires all 816 // field types to be `FromBytes`. 817 unsafe impl $(<$($tyvar),*>)? $crate::FromBytes for $name$(<$($tyvar),*>)? 818 where 819 $( 820 $($tuple_field_ty: $crate::FromBytes,)* 821 )? 822 823 $( 824 $($field_ty: $crate::FromBytes,)* 825 )? 826 { 827 fn only_derive_is_allowed_to_implement_this_trait() {} 828 } 829 830 // SAFETY: This macro only accepts `#[repr(C)]` and 831 // `#[repr(transparent)]` structs, this `impl` block requires all field 832 // types to be `IntoBytes`, and a padding check is used to ensures that 833 // there are no padding bytes. 834 unsafe impl $(<$($tyvar),*>)? $crate::IntoBytes for $name$(<$($tyvar),*>)? 835 where 836 $( 837 $($tuple_field_ty: $crate::IntoBytes,)* 838 )? 839 840 $( 841 $($field_ty: $crate::IntoBytes,)* 842 )? 843 844 (): $crate::util::macro_util::PaddingFree< 845 Self, 846 { 847 $crate::cryptocorrosion_derive_traits!( 848 @struct_padding_check #[repr($repr)] 849 $(($($tuple_field_ty),*))? 850 $({$($field_ty),*})? 851 ) 852 }, 853 >, 854 { 855 fn only_derive_is_allowed_to_implement_this_trait() {} 856 } 857 858 // SAFETY: This macro only accepts `#[repr(C)]` and 859 // `#[repr(transparent)]` structs, and this `impl` block requires all 860 // field types to be `Immutable`. 861 unsafe impl $(<$($tyvar),*>)? $crate::Immutable for $name$(<$($tyvar),*>)? 862 where 863 $( 864 $($tuple_field_ty: $crate::Immutable,)* 865 )? 866 867 $( 868 $($field_ty: $crate::Immutable,)* 869 )? 870 { 871 fn only_derive_is_allowed_to_implement_this_trait() {} 872 } 873 }; 874 (@assert_allowed_struct_repr #[repr(transparent)]) => {}; 875 (@assert_allowed_struct_repr #[repr(C)]) => {}; 876 (@assert_allowed_struct_repr #[$_attr:meta]) => { 877 compile_error!("repr must be `#[repr(transparent)]` or `#[repr(C)]`"); 878 }; 879 ( 880 @struct_padding_check #[repr(transparent)] 881 $(($($tuple_field_ty:ty),*))? 882 $({$($field_ty:ty),*})? 883 ) => { 884 // SAFETY: `#[repr(transparent)]` structs cannot have the same layout as 885 // their single non-zero-sized field, and so cannot have any padding 886 // outside of that field. 887 false 888 }; 889 ( 890 @struct_padding_check #[repr(C)] 891 $(($($tuple_field_ty:ty),*))? 892 $({$($field_ty:ty),*})? 893 ) => { 894 $crate::struct_has_padding!( 895 Self, 896 [ 897 $($($tuple_field_ty),*)? 898 $($($field_ty),*)? 899 ] 900 ) 901 }; 902 ( 903 #[repr(C)] 904 $(#[$attr:meta])* 905 $vis:vis union $name:ident { 906 $( 907 $field_name:ident: $field_ty:ty, 908 )* 909 } 910 ) => { 911 $(#[$attr])* 912 #[repr(C)] 913 $vis union $name { 914 $( 915 $field_name: $field_ty, 916 )* 917 } 918 919 // SAFETY: See inline. 920 unsafe impl $crate::TryFromBytes for $name 921 where 922 $( 923 $field_ty: $crate::FromBytes, 924 )* 925 { 926 fn is_bit_valid<A>(_c: $crate::Maybe<'_, Self, A>) -> bool 927 where 928 A: $crate::pointer::invariant::Reference 929 { 930 // SAFETY: This macro only accepts `#[repr(C)]` unions, and this 931 // `impl` block requires all field types to be `FromBytes`. 932 // Thus, all initialized byte sequences constitutes valid 933 // instances of `Self`. 934 true 935 } 936 937 fn only_derive_is_allowed_to_implement_this_trait() {} 938 } 939 940 // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl` 941 // block requires all field types to be `FromBytes`, which is a 942 // sub-trait of `FromZeros`. 943 unsafe impl $crate::FromZeros for $name 944 where 945 $( 946 $field_ty: $crate::FromBytes, 947 )* 948 { 949 fn only_derive_is_allowed_to_implement_this_trait() {} 950 } 951 952 // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl` 953 // block requires all field types to be `FromBytes`. 954 unsafe impl $crate::FromBytes for $name 955 where 956 $( 957 $field_ty: $crate::FromBytes, 958 )* 959 { 960 fn only_derive_is_allowed_to_implement_this_trait() {} 961 } 962 963 // SAFETY: This macro only accepts `#[repr(C)]` unions, this `impl` 964 // block requires all field types to be `IntoBytes`, and a padding check 965 // is used to ensures that there are no padding bytes before or after 966 // any field. 967 unsafe impl $crate::IntoBytes for $name 968 where 969 $( 970 $field_ty: $crate::IntoBytes, 971 )* 972 (): $crate::util::macro_util::PaddingFree< 973 Self, 974 { 975 $crate::union_has_padding!( 976 Self, 977 [$($field_ty),*] 978 ) 979 }, 980 >, 981 { 982 fn only_derive_is_allowed_to_implement_this_trait() {} 983 } 984 985 // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl` 986 // block requires all field types to be `Immutable`. 987 unsafe impl $crate::Immutable for $name 988 where 989 $( 990 $field_ty: $crate::Immutable, 991 )* 992 { 993 fn only_derive_is_allowed_to_implement_this_trait() {} 994 } 995 }; 996 } 997 998 #[cfg(test)] 999 mod tests { 1000 use crate::util::testutil::*; 1001 use crate::*; 1002 1003 #[test] test_transmute()1004 fn test_transmute() { 1005 // Test that memory is transmuted as expected. 1006 let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7]; 1007 let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]]; 1008 let x: [[u8; 2]; 4] = transmute!(array_of_u8s); 1009 assert_eq!(x, array_of_arrays); 1010 let x: [u8; 8] = transmute!(array_of_arrays); 1011 assert_eq!(x, array_of_u8s); 1012 1013 // Test that the source expression's value is forgotten rather than 1014 // dropped. 1015 #[derive(IntoBytes)] 1016 #[repr(transparent)] 1017 struct PanicOnDrop(()); 1018 impl Drop for PanicOnDrop { 1019 fn drop(&mut self) { 1020 panic!("PanicOnDrop::drop"); 1021 } 1022 } 1023 #[allow(clippy::let_unit_value)] 1024 let _: () = transmute!(PanicOnDrop(())); 1025 1026 // Test that `transmute!` is legal in a const context. 1027 const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7]; 1028 const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]]; 1029 const X: [[u8; 2]; 4] = transmute!(ARRAY_OF_U8S); 1030 assert_eq!(X, ARRAY_OF_ARRAYS); 1031 1032 // Test that `transmute!` works with `!Immutable` types. 1033 let x: usize = transmute!(UnsafeCell::new(1usize)); 1034 assert_eq!(x, 1); 1035 let x: UnsafeCell<usize> = transmute!(1usize); 1036 assert_eq!(x.into_inner(), 1); 1037 let x: UnsafeCell<isize> = transmute!(UnsafeCell::new(1usize)); 1038 assert_eq!(x.into_inner(), 1); 1039 } 1040 1041 #[test] test_transmute_ref()1042 fn test_transmute_ref() { 1043 // Test that memory is transmuted as expected. 1044 let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7]; 1045 let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]]; 1046 let x: &[[u8; 2]; 4] = transmute_ref!(&array_of_u8s); 1047 assert_eq!(*x, array_of_arrays); 1048 let x: &[u8; 8] = transmute_ref!(&array_of_arrays); 1049 assert_eq!(*x, array_of_u8s); 1050 1051 // Test that `transmute_ref!` is legal in a const context. 1052 const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7]; 1053 const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]]; 1054 #[allow(clippy::redundant_static_lifetimes)] 1055 const X: &'static [[u8; 2]; 4] = transmute_ref!(&ARRAY_OF_U8S); 1056 assert_eq!(*X, ARRAY_OF_ARRAYS); 1057 1058 // Test that it's legal to transmute a reference while shrinking the 1059 // lifetime (note that `X` has the lifetime `'static`). 1060 let x: &[u8; 8] = transmute_ref!(X); 1061 assert_eq!(*x, ARRAY_OF_U8S); 1062 1063 // Test that `transmute_ref!` supports decreasing alignment. 1064 let u = AU64(0); 1065 let array = [0, 0, 0, 0, 0, 0, 0, 0]; 1066 let x: &[u8; 8] = transmute_ref!(&u); 1067 assert_eq!(*x, array); 1068 1069 // Test that a mutable reference can be turned into an immutable one. 1070 let mut x = 0u8; 1071 #[allow(clippy::useless_transmute)] 1072 let y: &u8 = transmute_ref!(&mut x); 1073 assert_eq!(*y, 0); 1074 } 1075 1076 #[test] test_try_transmute()1077 fn test_try_transmute() { 1078 // Test that memory is transmuted with `try_transmute` as expected. 1079 let array_of_bools = [false, true, false, true, false, true, false, true]; 1080 let array_of_arrays = [[0, 1], [0, 1], [0, 1], [0, 1]]; 1081 let x: Result<[[u8; 2]; 4], _> = try_transmute!(array_of_bools); 1082 assert_eq!(x, Ok(array_of_arrays)); 1083 let x: Result<[bool; 8], _> = try_transmute!(array_of_arrays); 1084 assert_eq!(x, Ok(array_of_bools)); 1085 1086 // Test that `try_transmute!` works with `!Immutable` types. 1087 let x: Result<usize, _> = try_transmute!(UnsafeCell::new(1usize)); 1088 assert_eq!(x.unwrap(), 1); 1089 let x: Result<UnsafeCell<usize>, _> = try_transmute!(1usize); 1090 assert_eq!(x.unwrap().into_inner(), 1); 1091 let x: Result<UnsafeCell<isize>, _> = try_transmute!(UnsafeCell::new(1usize)); 1092 assert_eq!(x.unwrap().into_inner(), 1); 1093 1094 #[derive(FromBytes, IntoBytes, Debug, PartialEq)] 1095 #[repr(transparent)] 1096 struct PanicOnDrop<T>(T); 1097 1098 impl<T> Drop for PanicOnDrop<T> { 1099 fn drop(&mut self) { 1100 panic!("PanicOnDrop dropped"); 1101 } 1102 } 1103 1104 // Since `try_transmute!` semantically moves its argument on failure, 1105 // the `PanicOnDrop` is not dropped, and thus this shouldn't panic. 1106 let x: Result<usize, _> = try_transmute!(PanicOnDrop(1usize)); 1107 assert_eq!(x, Ok(1)); 1108 1109 // Since `try_transmute!` semantically returns ownership of its argument 1110 // on failure, the `PanicOnDrop` is returned rather than dropped, and 1111 // thus this shouldn't panic. 1112 let y: Result<bool, _> = try_transmute!(PanicOnDrop(2u8)); 1113 // We have to use `map_err` instead of comparing against 1114 // `Err(PanicOnDrop(2u8))` because the latter would create and then drop 1115 // its `PanicOnDrop` temporary, which would cause a panic. 1116 assert_eq!(y.as_ref().map_err(|p| &p.src.0), Err::<&bool, _>(&2u8)); 1117 mem::forget(y); 1118 } 1119 1120 #[test] test_try_transmute_ref()1121 fn test_try_transmute_ref() { 1122 // Test that memory is transmuted with `try_transmute_ref` as expected. 1123 let array_of_bools = &[false, true, false, true, false, true, false, true]; 1124 let array_of_arrays = &[[0, 1], [0, 1], [0, 1], [0, 1]]; 1125 let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools); 1126 assert_eq!(x, Ok(array_of_arrays)); 1127 let x: Result<&[bool; 8], _> = try_transmute_ref!(array_of_arrays); 1128 assert_eq!(x, Ok(array_of_bools)); 1129 1130 // Test that it's legal to transmute a reference while shrinking the 1131 // lifetime. 1132 { 1133 let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools); 1134 assert_eq!(x, Ok(array_of_arrays)); 1135 } 1136 1137 // Test that `try_transmute_ref!` supports decreasing alignment. 1138 let u = AU64(0); 1139 let array = [0u8, 0, 0, 0, 0, 0, 0, 0]; 1140 let x: Result<&[u8; 8], _> = try_transmute_ref!(&u); 1141 assert_eq!(x, Ok(&array)); 1142 1143 // Test that a mutable reference can be turned into an immutable one. 1144 let mut x = 0u8; 1145 #[allow(clippy::useless_transmute)] 1146 let y: Result<&u8, _> = try_transmute_ref!(&mut x); 1147 assert_eq!(y, Ok(&0)); 1148 } 1149 1150 #[test] test_try_transmute_mut()1151 fn test_try_transmute_mut() { 1152 // Test that memory is transmuted with `try_transmute_mut` as expected. 1153 let array_of_u8s = &mut [0u8, 1, 0, 1, 0, 1, 0, 1]; 1154 let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]]; 1155 let x: Result<&mut [[u8; 2]; 4], _> = try_transmute_mut!(array_of_u8s); 1156 assert_eq!(x, Ok(array_of_arrays)); 1157 1158 let array_of_bools = &mut [false, true, false, true, false, true, false, true]; 1159 let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]]; 1160 let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays); 1161 assert_eq!(x, Ok(array_of_bools)); 1162 1163 // Test that it's legal to transmute a reference while shrinking the 1164 // lifetime. 1165 let array_of_bools = &mut [false, true, false, true, false, true, false, true]; 1166 let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]]; 1167 { 1168 let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays); 1169 assert_eq!(x, Ok(array_of_bools)); 1170 } 1171 1172 // Test that `try_transmute_mut!` supports decreasing alignment. 1173 let u = &mut AU64(0); 1174 let array = &mut [0u8, 0, 0, 0, 0, 0, 0, 0]; 1175 let x: Result<&mut [u8; 8], _> = try_transmute_mut!(u); 1176 assert_eq!(x, Ok(array)); 1177 1178 // Test that a mutable reference can be turned into an immutable one. 1179 let mut x = 0u8; 1180 #[allow(clippy::useless_transmute)] 1181 let y: Result<&mut u8, _> = try_transmute_mut!(&mut x); 1182 assert_eq!(y, Ok(&mut 0)); 1183 } 1184 1185 #[test] test_transmute_mut()1186 fn test_transmute_mut() { 1187 // Test that memory is transmuted as expected. 1188 let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7]; 1189 let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]]; 1190 let x: &mut [[u8; 2]; 4] = transmute_mut!(&mut array_of_u8s); 1191 assert_eq!(*x, array_of_arrays); 1192 let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays); 1193 assert_eq!(*x, array_of_u8s); 1194 1195 { 1196 // Test that it's legal to transmute a reference while shrinking the 1197 // lifetime. 1198 let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays); 1199 assert_eq!(*x, array_of_u8s); 1200 } 1201 // Test that `transmute_mut!` supports decreasing alignment. 1202 let mut u = AU64(0); 1203 let array = [0, 0, 0, 0, 0, 0, 0, 0]; 1204 let x: &[u8; 8] = transmute_mut!(&mut u); 1205 assert_eq!(*x, array); 1206 1207 // Test that a mutable reference can be turned into an immutable one. 1208 let mut x = 0u8; 1209 #[allow(clippy::useless_transmute)] 1210 let y: &u8 = transmute_mut!(&mut x); 1211 assert_eq!(*y, 0); 1212 } 1213 1214 #[test] test_macros_evaluate_args_once()1215 fn test_macros_evaluate_args_once() { 1216 let mut ctr = 0; 1217 #[allow(clippy::useless_transmute)] 1218 let _: usize = transmute!({ 1219 ctr += 1; 1220 0usize 1221 }); 1222 assert_eq!(ctr, 1); 1223 1224 let mut ctr = 0; 1225 let _: &usize = transmute_ref!({ 1226 ctr += 1; 1227 &0usize 1228 }); 1229 assert_eq!(ctr, 1); 1230 1231 let mut ctr: usize = 0; 1232 let _: &mut usize = transmute_mut!({ 1233 ctr += 1; 1234 &mut ctr 1235 }); 1236 assert_eq!(ctr, 1); 1237 1238 let mut ctr = 0; 1239 #[allow(clippy::useless_transmute)] 1240 let _: usize = try_transmute!({ 1241 ctr += 1; 1242 0usize 1243 }) 1244 .unwrap(); 1245 assert_eq!(ctr, 1); 1246 } 1247 1248 #[test] test_include_value()1249 fn test_include_value() { 1250 const AS_U32: u32 = include_value!("../testdata/include_value/data"); 1251 assert_eq!(AS_U32, u32::from_ne_bytes([b'a', b'b', b'c', b'd'])); 1252 const AS_I32: i32 = include_value!("../testdata/include_value/data"); 1253 assert_eq!(AS_I32, i32::from_ne_bytes([b'a', b'b', b'c', b'd'])); 1254 } 1255 1256 #[test] 1257 #[allow(non_camel_case_types, unreachable_pub, dead_code)] test_cryptocorrosion_derive_traits()1258 fn test_cryptocorrosion_derive_traits() { 1259 // Test the set of invocations added in 1260 // https://github.com/cryptocorrosion/cryptocorrosion/pull/85 1261 1262 fn assert_impls<T: FromBytes + IntoBytes + Immutable>() {} 1263 1264 cryptocorrosion_derive_traits! { 1265 #[repr(C)] 1266 #[derive(Clone, Copy)] 1267 pub union vec128_storage { 1268 d: [u32; 4], 1269 q: [u64; 2], 1270 } 1271 } 1272 1273 assert_impls::<vec128_storage>(); 1274 1275 cryptocorrosion_derive_traits! { 1276 #[repr(transparent)] 1277 #[derive(Copy, Clone, Debug, PartialEq)] 1278 pub struct u32x4_generic([u32; 4]); 1279 } 1280 1281 assert_impls::<u32x4_generic>(); 1282 1283 cryptocorrosion_derive_traits! { 1284 #[repr(transparent)] 1285 #[derive(Copy, Clone, Debug, PartialEq)] 1286 pub struct u64x2_generic([u64; 2]); 1287 } 1288 1289 assert_impls::<u64x2_generic>(); 1290 1291 cryptocorrosion_derive_traits! { 1292 #[repr(transparent)] 1293 #[derive(Copy, Clone, Debug, PartialEq)] 1294 pub struct u128x1_generic([u128; 1]); 1295 } 1296 1297 assert_impls::<u128x1_generic>(); 1298 1299 cryptocorrosion_derive_traits! { 1300 #[repr(transparent)] 1301 #[derive(Copy, Clone, Default)] 1302 #[allow(non_camel_case_types)] 1303 pub struct x2<W, G>(pub [W; 2], PhantomData<G>); 1304 } 1305 1306 enum NotZerocopy {} 1307 assert_impls::<x2<(), NotZerocopy>>(); 1308 1309 cryptocorrosion_derive_traits! { 1310 #[repr(transparent)] 1311 #[derive(Copy, Clone, Default)] 1312 #[allow(non_camel_case_types)] 1313 pub struct x4<W>(pub [W; 4]); 1314 } 1315 1316 assert_impls::<x4<()>>(); 1317 1318 #[cfg(feature = "simd")] 1319 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 1320 { 1321 #[cfg(target_arch = "x86")] 1322 use core::arch::x86::{__m128i, __m256i}; 1323 #[cfg(target_arch = "x86_64")] 1324 use core::arch::x86_64::{__m128i, __m256i}; 1325 1326 cryptocorrosion_derive_traits! { 1327 #[repr(C)] 1328 #[derive(Copy, Clone)] 1329 pub struct X4(__m128i, __m128i, __m128i, __m128i); 1330 } 1331 1332 assert_impls::<X4>(); 1333 1334 cryptocorrosion_derive_traits! { 1335 #[repr(C)] 1336 /// Generic wrapper for unparameterized storage of any of the possible impls. 1337 /// Converting into and out of this type should be essentially free, although it may be more 1338 /// aligned than a particular impl requires. 1339 #[allow(non_camel_case_types)] 1340 #[derive(Copy, Clone)] 1341 pub union vec128_storage { 1342 u32x4: [u32; 4], 1343 u64x2: [u64; 2], 1344 u128x1: [u128; 1], 1345 sse2: __m128i, 1346 } 1347 } 1348 1349 assert_impls::<vec128_storage>(); 1350 1351 cryptocorrosion_derive_traits! { 1352 #[repr(transparent)] 1353 #[allow(non_camel_case_types)] 1354 #[derive(Copy, Clone)] 1355 pub struct vec<S3, S4, NI> { 1356 x: __m128i, 1357 s3: PhantomData<S3>, 1358 s4: PhantomData<S4>, 1359 ni: PhantomData<NI>, 1360 } 1361 } 1362 1363 assert_impls::<vec<NotZerocopy, NotZerocopy, NotZerocopy>>(); 1364 1365 cryptocorrosion_derive_traits! { 1366 #[repr(transparent)] 1367 #[derive(Copy, Clone)] 1368 pub struct u32x4x2_avx2<NI> { 1369 x: __m256i, 1370 ni: PhantomData<NI>, 1371 } 1372 } 1373 1374 assert_impls::<u32x4x2_avx2<NotZerocopy>>(); 1375 } 1376 1377 // Make sure that our derive works for `#[repr(C)]` structs even though 1378 // cryptocorrosion doesn't currently have any. 1379 cryptocorrosion_derive_traits! { 1380 #[repr(C)] 1381 #[derive(Copy, Clone, Debug, PartialEq)] 1382 pub struct ReprC(u8, u8, u16); 1383 } 1384 } 1385 } 1386