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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
//! This crate contains checked implementations of transmutation procedures, some of which //! ensure memory safety. //! //! ## Crate outline //! //! The following modules are available: //! //! - The functions in the [`base`](base/index.html) module are not inherently //! safe, but just protected against out of boundary access (like trying to //! create an 8-byte type from 7 bytes). These functions are as safe as //! the data passed to them: 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 [`guard`](guard/index.html) module contains the **Guard API**, which //! imposes slice boundary restrictions in a conversion. //! - The [`trivial`](trivial/index.html) module introduces the //! [`TriviallyTransmutable`](trivial/trait.TriviallyTransmutable.html) //! trait, which statically ensures that any bit combination makes a valid //! value for a given type. The functions in this module are safer than //! [`base`](base/index.html), but still do not prevent unaligned memory access. //! - [`to_bytes`](to_bytes/index.html) enables the opposite operation of //! reintepreting values as bytes. //! - The [`bool`](bool/index.html) module ensures safe transmutation of bytes //! to boolean values. //! - At the root of this crate, there 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 programmer in //! making some use cases work. //! //! This crate can be used in a no-`std` environment by disabling the `std` //! feature through specifying `default-features = false` on import. //! However, `std` is only used for integration with `std::error::Error`. //! //! Note, though, that functions operating on items from `alloc` will also be disabled by this. //! If your no-`std` environment has an `alloc` implementation, you will have to reenable them by using `features = ["alloc"]`. //! //! # Migrating //! //! If you've used `safe-transmute` before v0.11, //! we recommend [the v0.11 migration guide](migration/v0_11/index.html) to help get you going quickly. //! //! # Examples //! //! View bytes as a series of `u16`s, with a single-many boundary //! guard (at least one value, extraneous bytes are allowed): //! //! ``` //! # use safe_transmute::{SingleManyGuard, Error, transmute_many}; //! # #[cfg(feature = "std")] //! # fn main() -> Result<(), Box<std::error::Error>> { //! let bytes = &[0x00, 0x01, 0x12, 0x24, //! 0x00]; // 1 spare byte //! match transmute_many::<u16, SingleManyGuard>(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), //! } //! # Ok(()) //! # } //! # #[cfg(not(feature = "std"))] //! # fn main() {} //! ``` //! //! Since one may not always be able to ensure that a slice of bytes is well //! aligned for reading data of different constraints, such as from `u8` to //! `u16`, the operation may fail without a trivial way of preventing it. //! //! As a remedy, the data can instead be copied byte-for-byte to a new vector, //! with the help of the [`try_copy!()`](macro.try_copy.html) macro. //! //! ``` //! # #[macro_use] //! # extern crate safe_transmute; //! # use safe_transmute::{SingleManyGuard, Error, transmute_many}; //! # #[cfg(feature = "std")] //! # fn main() -> Result<(), Box<std::error::Error>> { //! let bytes = &[0x00, 0x01, 0x12, 0x24, 0x00]; //! let words = try_copy!(transmute_many::<u16, SingleManyGuard>(bytes)); //! //! assert_eq!(*words, //! [u16::from_be(0x0001), u16::from_be(0x1224)]); //! # Ok(()) //! # } //! # #[cfg(not(feature = "std"))] //! # fn main() {} //! ``` //! //! View all bytes as a series of `u16`s: //! //! ``` //! # #[macro_use] //! # extern crate safe_transmute; //! # use safe_transmute::{Error, transmute_many_pedantic}; //! # include!("../tests/test_util/le_to_native.rs"); //! # #[cfg(feature = "std")] //! # fn main() -> Result<(), Box<std::error::Error>> { //! # let bytes = &[0x00, 0x01, 0x12, 0x34].le_to_native::<u16>(); //! # let words = try_copy!(transmute_many_pedantic::<u16>(bytes).map_err(Error::without_src)); //! # /* //! // Assuming little-endian //! let bytes = &[0x00, 0x01, 0x12, 0x34]; //! let words = try_copy!(transmute_many_pedantic::<u16>(bytes)); //! # */ //! //! assert_eq!(*words, [0x0100, 0x3412]); //! # Ok(()) //! # } //! # #[cfg(not(feature = "std"))] //! # fn main() {} //! ``` //! //! View a byte slice as a single `f64`: //! //! ``` //! # use safe_transmute::transmute_one; //! # include!("../tests/test_util/le_to_native.rs"); //! # fn main() { //! assert_eq!(transmute_one::<f64>( //! # /* //! &[0x00, 0x00, 0x00, 0x00, //! 0x00, 0x00, 0x00, 0x40])?, //! # */ //! # &Le2NAl8([0x00, 0x00, 0x00, 0x00, //! # 0x00, 0x00, 0x00, 0x40]).0.le_to_native::<f64>()).unwrap(), //! 2.0); //! # } //! ``` //! //! View a series of `u16`s as bytes: //! //! ``` //! # use safe_transmute::transmute_to_bytes; //! # include!("../tests/test_util/le_to_native.rs"); //! # fn main() { //! assert_eq!(transmute_to_bytes(&[0x0001u16, //! 0x1234u16]), //! # /* //! &[0x01, 0x00, 0x34, 0x12]); //! # */ //! # &[0x01, 0x00, 0x34, 0x12].le_to_native::<u16>()); //! # } //! ``` #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "std")] extern crate core; #[cfg(feature = "alloc")] #[doc(hidden)] pub extern crate alloc; mod full; pub mod base; pub mod bool; pub mod util; pub mod align; pub mod error; pub mod guard; pub mod trivial; pub mod to_bytes; pub mod migration; pub use self::full::{transmute_many_permissive_mut, transmute_many_pedantic_mut, transmute_many_permissive, transmute_many_pedantic, transmute_one_pedantic, transmute_many, transmute_many_mut, transmute_one}; #[cfg(feature = "alloc")] pub use self::full::transmute_vec; pub use self::guard::{SingleValueGuard, PermissiveGuard, SingleManyGuard, PedanticGuard, Guard}; pub use self::error::{UnalignedError, ErrorReason, GuardError, Error}; #[cfg(feature = "alloc")] pub use self::error::IncompatibleVecTargetError; pub use self::trivial::{TriviallyTransmutable, align_to_mut, align_to}; pub use self::to_bytes::{transmute_one_to_bytes_mut, transmute_one_to_bytes, transmute_to_bytes_mut, transmute_to_bytes}; #[cfg(feature = "alloc")] pub use self::to_bytes::transmute_to_bytes_vec; #[cfg(feature = "alloc")] pub use self::bool::{transmute_bool_vec_permissive, transmute_bool_vec_pedantic}; pub use self::bool::{transmute_bool_permissive, transmute_bool_pedantic};