1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Migrating to `safe-transmute` v0.11
//!
//! This guide starts with a forewarning: `safe-transmute` had many safety issues before this version,
//! which means that there is a chance of your dependent project facing undefined behavior. Migrating
//! to version 0.11 is recommended as soon as possible, even if it might lead to a sub-optimal solution.
//!
//! ## Organization
//!
//! The crate is now organized with the following major categories:
//!   - `base` contains all baseline conversion functions. They are only protected against out of boundary
//!     access, like trying to create an 8-byte type from 7 bytes. However, they are still unsafe: any
//!     attempt of transmuting data to an invalid memory representation is still undefined behavior.
//!     Moreover, unaligned memory access is not prevented, and must be previously ensured by the caller.
//!   - The `trivial` module introduces the concept of being *trivially transmutable*, which
//!     statically ensures that any bit combination makes a valid value for a given type. Basically,
//!     if a type `T` can be filled with any arbitrary bits in its memory representation and still be
//!     valid, then `T` is trivially transmutable. Most primitive types implement the `TriviallyTransmutable`
//!     trait, as well as arrays of trivially transmutable types, but new types (such as repr-C structs)
//!     need to `unsafe impl` it manually. Functions in this module are therefore safer than the baseline,
//!     but are still unsafe because they do not check for memory alignment.
//!   - `to_bytes` enables the opposite operation of reintepreting values as bytes. They are usually safe
//!     unless when working with mutable slices, since they can break invariants of the source type.
//!   - The `bool` module ensures safe transmutation of bytes to boolean values.
//!   - That leaves the `full` functions at the crate root. These are transmutation functions with enough
//!     checks to be considered safe to use in any circumstance. The operation may still arbitrarily
//!     return (recoverable) errors due to unaligned data or incompatible vector transmutation targets,
//!     but it will not eat your laundry, and helper functions are available to assist the user in
//!     making some use cases work.
//!
//! Moreover, three utility modules have also been provided:
//!   - The `guard` module contains the **Guard API**, which imposes slice boundary restrictions in a conversion.
//!   - The `align` module is where alignment checks are implemented.
//!   - The `util` module provides some independent helper functions.
//!
//! Generally, you are strongly advised to *stick to the functions provided at the crate root*.
//! These are re-exports from the `full`, `bool`, and `to_bytes` categories depending on their safety.
//!
//! ## Transmuting slices
//!
//! One of the major use cases of the crate is to grab a slice of bytes and reinterpret it as a slice of
//! another type. This process is accompanied with a check for the source slice length, so that it
//! makes some sense as the target type. If you expect any number of elements of the target type, use
//! `transmute_many_permissive()`.
//!
//! ```rust
//! # #[cfg(feature = "alloc")]
//! # {
//! use safe_transmute::{Error, transmute_many_permissive};
//!
//! let bytes = &[0x00, 0x01, 0x12, 0x24,
//!               0x00]; // 1 spare byte
//!
//! match transmute_many_permissive::<u16>(bytes) {
//!     Ok(words) => {
//!         assert_eq!(words,
//!                    [u16::from_be(0x0001), u16::from_be(0x1224)]);
//!     },
//!     Err(Error::Unaligned(e)) => {
//!         // Copy needed, would otherwise trap on some archs
//!         let words = e.copy();
//!         assert_eq!(*words,
//!                    [u16::from_be(0x0001), u16::from_be(0x1224)]);
//!     },
//!     Err(e) => panic!("Unexpected error: {}", e),
//! }
//! # }
//! ```
//!
//! `transmute_many_permissive()` is an alias for `transmute_many()` with `PermissiveGuard`
//! as the guard type parameter. If you expect at least 1 element, use `transmute_many()` with the
//! `SingleManyGuard` as the guard type. If you expect at least one element and no extraneous bytes, use
//! `transmute_many_pedantic()`, or `transmute_many()` with `PedanticGuard`.
//!
//! As you can see, we had to manually handle the case where the slice of bytes is not well aligned for
//! reading target data, such as from `u8` to `u16`. If the slice's first element is not aligned for
//! reading `u16`s, the operation will just fail with `Error::Unaligned`. The only way to move on from
//! here is to copy the data (provided by the `Error::copy()` method).
//!
//! The good news is that this boilerplate can be off-loaded to the `try_copy!` macro. Here's how you'll
//! often be doing transmutations:
//!
//! ```rust
//! # use safe_transmute::Error;
//! # #[cfg(feature = "alloc")]
//! # {
//! use safe_transmute::{transmute_many_permissive, try_copy};
//!
//! let bytes = &[0x00, 0x01, 0x12, 0x24, 0x00];
//! let words = try_copy!(transmute_many_permissive::<u16>(bytes));
//!
//! assert_eq!(&*words, &[u16::from_be(0x0001), u16::from_be(0x1224)]);
//! # }
//! # Ok::<(), Error<u8, u16>>(())
//! ```
//!
//! You will also find `to_bytes`, `mut`, and `bool` variants of these functions. `transmute_to_bytes()` turns any slice into
//! a slice of bytes. Functions from the `*_mut()` family work with mutable slices. `transmute_bool()` checks whether all bytes
//! make valid boolean values beforehand.
//!
//! ## Transmuting vectors
//!
//! You might have used `safe-transmute`'s vector transmutation functions. Well, it turns out that they are
//! **incredibly unsafe**, and hard to get right. This will be more complicated to migrate efficiently.
//! The new `transmute_vec()` only works under very restricted conditions: the `mem::align_of()` and `mem::size_of()` between
//! the source and target element types must match. Otherwise, a full copy of the vector must be made.
//!
//! ```rust
//! # use safe_transmute::Error;
//! # #[cfg(feature = "alloc")]
//! # {
//! use safe_transmute::{transmute_vec, try_copy};
//!
//! let bytes = vec![0x00, 0x01, 0x12, 0x24, 0x00];
//! let words = try_copy!(transmute_vec::<_, u16>(bytes)); // !!! works, but will always copy
//!
//! assert_eq!(&*words, &[u16::from_be(0x0001), u16::from_be(0x1224)]);
//! # }
//! # Ok::<(), Error<u8, u16>>(())
//! ```
//!
//! Oftentimes, you'll just be avoiding vector transmutation entirely.
//!
//! In order to avoid copies, you can allocate a vector of the target type `T`, transmute a mutable slice of the vector
//! into the source data type `S`, and write the data in there directly. This still requires both `S` and `T` to be
//! trivially transmutable in order to be within the compiler's safety guarantees, though.