1#![no_std]
2#![warn(missing_docs)]
3#![allow(clippy::match_like_matches_macro)]
4#![allow(clippy::uninlined_format_args)]
5#![cfg_attr(feature = "nightly_docs", feature(doc_cfg))]
6#![cfg_attr(feature = "nightly_portable_simd", feature(portable_simd))]
7#![cfg_attr(
8 all(
9 feature = "nightly_stdsimd",
10 any(target_arch = "x86_64", target_arch = "x86")
11 ),
12 feature(stdarch_x86_avx512)
13)]
14
15//! This crate gives small utilities for casting between plain data types.
16//!
17//! ## Basics
18//!
19//! Data comes in five basic forms in Rust, so we have five basic casting
20//! functions:
21//!
22//! * `T` uses [`cast`]
23//! * `&T` uses [`cast_ref`]
24//! * `&mut T` uses [`cast_mut`]
25//! * `&[T]` uses [`cast_slice`]
26//! * `&mut [T]` uses [`cast_slice_mut`]
27//!
28//! Depending on the function, the [`NoUninit`] and/or [`AnyBitPattern`] traits
29//! are used to maintain memory safety.
30//!
31//! **Historical Note:** When the crate first started the [`Pod`] trait was used
32//! instead, and so you may hear people refer to that, but it has the strongest
33//! requirements and people eventually wanted the more fine-grained system, so
34//! here we are. All types that impl `Pod` have a blanket impl to also support
35//! `NoUninit` and `AnyBitPattern`. The traits unfortunately do not have a
36//! perfectly clean hierarchy for semver reasons.
37//!
38//! ## Failures
39//!
40//! Some casts will never fail, and other casts might fail.
41//!
42//! * `cast::<u32, f32>` always works (and [`f32::from_bits`]).
43//! * `cast_ref::<[u8; 4], u32>` might fail if the specific array reference
44//! given at runtime doesn't have alignment 4.
45//!
46//! In addition to the "normal" forms of each function, which will panic on
47//! invalid input, there's also `try_` versions which will return a `Result`.
48//!
49//! If you would like to statically ensure that a cast will work at runtime you
50//! can use the `must_cast` crate feature and the `must_` casting functions. A
51//! "must cast" that can't be statically known to be valid will cause a
52//! compilation error (and sometimes a very hard to read compilation error).
53//!
54//! ## Using Your Own Types
55//!
56//! All the functions listed above are guarded by the [`Pod`] trait, which is a
57//! sub-trait of the [`Zeroable`] trait.
58//!
59//! If you enable the crate's `derive` feature then these traits can be derived
60//! on your own types. The derive macros will perform the necessary checks on
61//! your type declaration, and trigger an error if your type does not qualify.
62//!
63//! The derive macros might not cover all edge cases, and sometimes they will
64//! error when actually everything is fine. As a last resort you can impl these
65//! traits manually. However, these traits are `unsafe`, and you should
66//! carefully read the requirements before using a manual implementation.
67//!
68//! ## Cargo Features
69//!
70//! The crate supports Rust 1.34 when no features are enabled, and so there's
71//! cargo features for thing that you might consider "obvious".
72//!
73//! The cargo features **do not** promise any particular MSRV, and they may
74//! increase their MSRV in new versions.
75//!
76//! * `derive`: Provide derive macros for the various traits.
77//! * `extern_crate_alloc`: Provide utilities for `alloc` related types such as
78//! Box and Vec.
79//! * `zeroable_maybe_uninit` and `zeroable_atomics`: Provide more [`Zeroable`]
80//! impls.
81//! * `wasm_simd` and `aarch64_simd`: Support more SIMD types.
82//! * `min_const_generics`: Provides appropriate impls for arrays of all lengths
83//! instead of just for a select list of array lengths.
84//! * `must_cast`: Provides the `must_` functions, which will compile error if
85//! the requested cast can't be statically verified.
86
87#[cfg(all(target_arch = "aarch64", feature = "aarch64_simd"))]
88use core::arch::aarch64;
89#[cfg(all(target_arch = "wasm32", feature = "wasm_simd"))]
90use core::arch::wasm32;
91#[cfg(target_arch = "x86")]
92use core::arch::x86;
93#[cfg(target_arch = "x86_64")]
94use core::arch::x86_64;
95//
96use core::{marker::*, mem::*, num::*, ptr::*};
97
98// Used from macros to ensure we aren't using some locally defined name and
99// actually are referencing libcore. This also would allow pre-2018 edition
100// crates to use our macros, but I'm not sure how important that is.
101#[doc(hidden)]
102pub use ::core as __core;
103
104#[cfg(not(feature = "min_const_generics"))]
105macro_rules! impl_unsafe_marker_for_array {
106 ( $marker:ident , $( $n:expr ),* ) => {
107 $(unsafe impl<T> $marker for [T; $n] where T: $marker {})*
108 }
109}
110
111/// A macro to transmute between two types without requiring knowing size
112/// statically.
113macro_rules! transmute {
114 ($val:expr) => {
115 ::core::mem::transmute_copy(&::core::mem::ManuallyDrop::new($val))
116 };
117}
118
119/// A macro to implement marker traits for various simd types.
120/// #[allow(unused)] because the impls are only compiled on relevant platforms
121/// with relevant cargo features enabled.
122#[allow(unused)]
123macro_rules! impl_unsafe_marker_for_simd {
124 ($(#[cfg($cfg_predicate:meta)])? unsafe impl $trait:ident for $platform:ident :: {}) => {};
125 ($(#[cfg($cfg_predicate:meta)])? unsafe impl $trait:ident for $platform:ident :: { $first_type:ident $(, $types:ident)* $(,)? }) => {
126 $( #[cfg($cfg_predicate)] )?
127 $( #[cfg_attr(feature = "nightly_docs", doc(cfg($cfg_predicate)))] )?
128 unsafe impl $trait for $platform::$first_type {}
129 $( #[cfg($cfg_predicate)] )? // To prevent recursion errors if nothing is going to be expanded anyway.
130 impl_unsafe_marker_for_simd!($( #[cfg($cfg_predicate)] )? unsafe impl $trait for $platform::{ $( $types ),* });
131 };
132}
133
134#[cfg(feature = "extern_crate_std")]
135extern crate std;
136
137#[cfg(feature = "extern_crate_alloc")]
138extern crate alloc;
139#[cfg(feature = "extern_crate_alloc")]
140#[cfg_attr(feature = "nightly_docs", doc(cfg(feature = "extern_crate_alloc")))]
141pub mod allocation;
142#[cfg(feature = "extern_crate_alloc")]
143pub use allocation::*;
144
145mod anybitpattern;
146pub use anybitpattern::*;
147
148pub mod checked;
149pub use checked::CheckedBitPattern;
150
151mod internal;
152
153mod zeroable;
154pub use zeroable::*;
155mod zeroable_in_option;
156pub use zeroable_in_option::*;
157
158mod pod;
159pub use pod::*;
160mod pod_in_option;
161pub use pod_in_option::*;
162
163#[cfg(feature = "must_cast")]
164mod must;
165#[cfg(feature = "must_cast")]
166#[cfg_attr(feature = "nightly_docs", doc(cfg(feature = "must_cast")))]
167pub use must::*;
168
169mod no_uninit;
170pub use no_uninit::*;
171
172mod contiguous;
173pub use contiguous::*;
174
175mod offset_of;
176// ^ no import, the module only has a macro_rules, which are cursed and don't
177// follow normal import/export rules.
178
179mod transparent;
180pub use transparent::*;
181
182#[cfg(feature = "derive")]
183#[cfg_attr(feature = "nightly_docs", doc(cfg(feature = "derive")))]
184pub use bytemuck_derive::{
185 AnyBitPattern, ByteEq, ByteHash, CheckedBitPattern, Contiguous, NoUninit,
186 Pod, TransparentWrapper, Zeroable,
187};
188
189/// The things that can go wrong when casting between [`Pod`] data forms.
190#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
191pub enum PodCastError {
192 /// You tried to cast a slice to an element type with a higher alignment
193 /// requirement but the slice wasn't aligned.
194 TargetAlignmentGreaterAndInputNotAligned,
195 /// If the element size changes then the output slice changes length
196 /// accordingly. If the output slice wouldn't be a whole number of elements
197 /// then the conversion fails.
198 OutputSliceWouldHaveSlop,
199 /// When casting a slice you can't convert between ZST elements and non-ZST
200 /// elements. When casting an individual `T`, `&T`, or `&mut T` value the
201 /// source size and destination size must be an exact match.
202 SizeMismatch,
203 /// For this type of cast the alignments must be exactly the same and they
204 /// were not so now you're sad.
205 ///
206 /// This error is generated **only** by operations that cast allocated types
207 /// (such as `Box` and `Vec`), because in that case the alignment must stay
208 /// exact.
209 AlignmentMismatch,
210}
211#[cfg(not(target_arch = "spirv"))]
212impl core::fmt::Display for PodCastError {
213 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
214 write!(f, "{:?}", self)
215 }
216}
217#[cfg(feature = "extern_crate_std")]
218#[cfg_attr(feature = "nightly_docs", doc(cfg(feature = "extern_crate_std")))]
219impl std::error::Error for PodCastError {}
220
221/// Re-interprets `&T` as `&[u8]`.
222///
223/// Any ZST becomes an empty slice, and in that case the pointer value of that
224/// empty slice might not match the pointer value of the input reference.
225#[inline]
226pub fn bytes_of<T: NoUninit>(t: &T) -> &[u8] {
227 unsafe { internal::bytes_of(t) }
228}
229
230/// Re-interprets `&mut T` as `&mut [u8]`.
231///
232/// Any ZST becomes an empty slice, and in that case the pointer value of that
233/// empty slice might not match the pointer value of the input reference.
234#[inline]
235pub fn bytes_of_mut<T: NoUninit + AnyBitPattern>(t: &mut T) -> &mut [u8] {
236 unsafe { internal::bytes_of_mut(t) }
237}
238
239/// Re-interprets `&[u8]` as `&T`.
240///
241/// ## Panics
242///
243/// This is like [`try_from_bytes`] but will panic on error.
244#[inline]
245pub fn from_bytes<T: AnyBitPattern>(s: &[u8]) -> &T {
246 unsafe { internal::from_bytes(s) }
247}
248
249/// Re-interprets `&mut [u8]` as `&mut T`.
250///
251/// ## Panics
252///
253/// This is like [`try_from_bytes_mut`] but will panic on error.
254#[inline]
255pub fn from_bytes_mut<T: NoUninit + AnyBitPattern>(s: &mut [u8]) -> &mut T {
256 unsafe { internal::from_bytes_mut(s) }
257}
258
259/// Reads from the bytes as if they were a `T`.
260///
261/// Unlike [`from_bytes`], the slice doesn't need to respect alignment of `T`,
262/// only sizes must match.
263///
264/// ## Failure
265/// * If the `bytes` length is not equal to `size_of::<T>()`.
266#[inline]
267pub fn try_pod_read_unaligned<T: AnyBitPattern>(
268 bytes: &[u8],
269) -> Result<T, PodCastError> {
270 unsafe { internal::try_pod_read_unaligned(bytes) }
271}
272
273/// Reads the slice into a `T` value.
274///
275/// Unlike [`from_bytes`], the slice doesn't need to respect alignment of `T`,
276/// only sizes must match.
277///
278/// ## Panics
279/// * This is like `try_pod_read_unaligned` but will panic on failure.
280#[inline]
281pub fn pod_read_unaligned<T: AnyBitPattern>(bytes: &[u8]) -> T {
282 unsafe { internal::pod_read_unaligned(bytes) }
283}
284
285/// Re-interprets `&[u8]` as `&T`.
286///
287/// ## Failure
288///
289/// * If the slice isn't aligned for the new type
290/// * If the slice's length isn’t exactly the size of the new type
291#[inline]
292pub fn try_from_bytes<T: AnyBitPattern>(s: &[u8]) -> Result<&T, PodCastError> {
293 unsafe { internal::try_from_bytes(s) }
294}
295
296/// Re-interprets `&mut [u8]` as `&mut T`.
297///
298/// ## Failure
299///
300/// * If the slice isn't aligned for the new type
301/// * If the slice's length isn’t exactly the size of the new type
302#[inline]
303pub fn try_from_bytes_mut<T: NoUninit + AnyBitPattern>(
304 s: &mut [u8],
305) -> Result<&mut T, PodCastError> {
306 unsafe { internal::try_from_bytes_mut(s) }
307}
308
309/// Cast `T` into `U`
310///
311/// ## Panics
312///
313/// * This is like [`try_cast`], but will panic on a size mismatch.
314#[inline]
315pub fn cast<A: NoUninit, B: AnyBitPattern>(a: A) -> B {
316 unsafe { internal::cast(a) }
317}
318
319/// Cast `&mut T` into `&mut U`.
320///
321/// ## Panics
322///
323/// This is [`try_cast_mut`] but will panic on error.
324#[inline]
325pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + AnyBitPattern>(
326 a: &mut A,
327) -> &mut B {
328 unsafe { internal::cast_mut(a) }
329}
330
331/// Cast `&T` into `&U`.
332///
333/// ## Panics
334///
335/// This is [`try_cast_ref`] but will panic on error.
336#[inline]
337pub fn cast_ref<A: NoUninit, B: AnyBitPattern>(a: &A) -> &B {
338 unsafe { internal::cast_ref(a) }
339}
340
341/// Cast `&[A]` into `&[B]`.
342///
343/// ## Panics
344///
345/// This is [`try_cast_slice`] but will panic on error.
346#[inline]
347pub fn cast_slice<A: NoUninit, B: AnyBitPattern>(a: &[A]) -> &[B] {
348 unsafe { internal::cast_slice(a) }
349}
350
351/// Cast `&mut [T]` into `&mut [U]`.
352///
353/// ## Panics
354///
355/// This is [`try_cast_slice_mut`] but will panic on error.
356#[inline]
357pub fn cast_slice_mut<
358 A: NoUninit + AnyBitPattern,
359 B: NoUninit + AnyBitPattern,
360>(
361 a: &mut [A],
362) -> &mut [B] {
363 unsafe { internal::cast_slice_mut(a) }
364}
365
366/// As [`align_to`](https://doc.rust-lang.org/std/primitive.slice.html#method.align_to),
367/// but safe because of the [`Pod`] bound.
368#[inline]
369pub fn pod_align_to<T: NoUninit, U: AnyBitPattern>(
370 vals: &[T],
371) -> (&[T], &[U], &[T]) {
372 unsafe { vals.align_to::<U>() }
373}
374
375/// As [`align_to_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.align_to_mut),
376/// but safe because of the [`Pod`] bound.
377#[inline]
378pub fn pod_align_to_mut<
379 T: NoUninit + AnyBitPattern,
380 U: NoUninit + AnyBitPattern,
381>(
382 vals: &mut [T],
383) -> (&mut [T], &mut [U], &mut [T]) {
384 unsafe { vals.align_to_mut::<U>() }
385}
386
387/// Try to cast `T` into `U`.
388///
389/// Note that for this particular type of cast, alignment isn't a factor. The
390/// input value is semantically copied into the function and then returned to a
391/// new memory location which will have whatever the required alignment of the
392/// output type is.
393///
394/// ## Failure
395///
396/// * If the types don't have the same size this fails.
397#[inline]
398pub fn try_cast<A: NoUninit, B: AnyBitPattern>(
399 a: A,
400) -> Result<B, PodCastError> {
401 unsafe { internal::try_cast(a) }
402}
403
404/// Try to convert a `&T` into `&U`.
405///
406/// ## Failure
407///
408/// * If the reference isn't aligned in the new type
409/// * If the source type and target type aren't the same size.
410#[inline]
411pub fn try_cast_ref<A: NoUninit, B: AnyBitPattern>(
412 a: &A,
413) -> Result<&B, PodCastError> {
414 unsafe { internal::try_cast_ref(a) }
415}
416
417/// Try to convert a `&mut T` into `&mut U`.
418///
419/// As [`try_cast_ref`], but `mut`.
420#[inline]
421pub fn try_cast_mut<
422 A: NoUninit + AnyBitPattern,
423 B: NoUninit + AnyBitPattern,
424>(
425 a: &mut A,
426) -> Result<&mut B, PodCastError> {
427 unsafe { internal::try_cast_mut(a) }
428}
429
430/// Try to convert `&[A]` into `&[B]` (possibly with a change in length).
431///
432/// * `input.as_ptr() as usize == output.as_ptr() as usize`
433/// * `input.len() * size_of::<A>() == output.len() * size_of::<B>()`
434///
435/// ## Failure
436///
437/// * If the target type has a greater alignment requirement and the input slice
438/// isn't aligned.
439/// * If the target element type is a different size from the current element
440/// type, and the output slice wouldn't be a whole number of elements when
441/// accounting for the size change (eg: 3 `u16` values is 1.5 `u32` values, so
442/// that's a failure).
443/// * Similarly, you can't convert between a [ZST](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
444/// and a non-ZST.
445#[inline]
446pub fn try_cast_slice<A: NoUninit, B: AnyBitPattern>(
447 a: &[A],
448) -> Result<&[B], PodCastError> {
449 unsafe { internal::try_cast_slice(a) }
450}
451
452/// Try to convert `&mut [A]` into `&mut [B]` (possibly with a change in
453/// length).
454///
455/// As [`try_cast_slice`], but `&mut`.
456#[inline]
457pub fn try_cast_slice_mut<
458 A: NoUninit + AnyBitPattern,
459 B: NoUninit + AnyBitPattern,
460>(
461 a: &mut [A],
462) -> Result<&mut [B], PodCastError> {
463 unsafe { internal::try_cast_slice_mut(a) }
464}
465
466/// Fill all bytes of `target` with zeroes (see [`Zeroable`]).
467///
468/// This is similar to `*target = Zeroable::zeroed()`, but guarantees that any
469/// padding bytes in `target` are zeroed as well.
470///
471/// See also [`fill_zeroes`], if you have a slice rather than a single value.
472#[inline]
473pub fn write_zeroes<T: Zeroable>(target: &mut T) {
474 struct EnsureZeroWrite<T>(*mut T);
475 impl<T> Drop for EnsureZeroWrite<T> {
476 #[inline(always)]
477 fn drop(&mut self) {
478 unsafe {
479 core::ptr::write_bytes(self.0, val:0u8, count:1);
480 }
481 }
482 }
483 unsafe {
484 let guard: EnsureZeroWrite = EnsureZeroWrite(target);
485 core::ptr::drop_in_place(to_drop:guard.0);
486 drop(guard);
487 }
488}
489
490/// Fill all bytes of `slice` with zeroes (see [`Zeroable`]).
491///
492/// This is similar to `slice.fill(Zeroable::zeroed())`, but guarantees that any
493/// padding bytes in `slice` are zeroed as well.
494///
495/// See also [`write_zeroes`], which zeroes all bytes of a single value rather
496/// than a slice.
497#[inline]
498pub fn fill_zeroes<T: Zeroable>(slice: &mut [T]) {
499 if core::mem::needs_drop::<T>() {
500 // If `T` needs to be dropped then we have to do this one item at a time, in
501 // case one of the intermediate drops does a panic.
502 slice.iter_mut().for_each(write_zeroes);
503 } else {
504 // Otherwise we can be really fast and just fill everthing with zeros.
505 let len: usize = core::mem::size_of_val::<[T]>(slice);
506 unsafe { core::ptr::write_bytes(dst:slice.as_mut_ptr() as *mut u8, val:0u8, count:len) }
507 }
508}
509