17 releases (10 breaking)
Uses old Rust 2015
| 0.11.3 | May 21, 2024 |
|---|---|
| 0.11.2 | May 31, 2021 |
| 0.11.1 | Feb 3, 2021 |
| 0.11.0 | Jun 20, 2020 |
| 0.3.0 | Nov 11, 2016 |
#285 in Rust patterns
67,960 downloads per month
Used in 134 crates
(24 directly)
95KB
690 lines
safe-transmute-rs
A safeguarded transmute() for Rust.
Documentation
lib.rs:
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
basemodule 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
guardmodule contains the Guard API, which imposes slice boundary restrictions in a conversion. - The
trivialmodule introduces theTriviallyTransmutabletrait, which statically ensures that any bit combination makes a valid value for a given type. The functions in this module are safer thanbase, but still do not prevent unaligned memory access. to_bytesenables the opposite operation of reintepreting values as bytes.- The
boolmodule 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 to help get you going quickly.
Examples
View bytes as a series of u16s, with a single-many boundary
guard (at least one value, extraneous bytes are allowed):
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),
}
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.
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)]);
View all bytes as a series of u16s:
// Assuming little-endian
let bytes = &[0x00, 0x01, 0x12, 0x34];
let words = try_copy!(transmute_many_pedantic::<u16>(bytes));
assert_eq!(*words, [0x0100, 0x3412]);
View a byte slice as a single f64:
assert_eq!(transmute_one::<f64>(
&[0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40])?,
2.0);
View a series of u16s as bytes:
assert_eq!(transmute_to_bytes(&[0x0001u16,
0x1234u16]),
&[0x01, 0x00, 0x34, 0x12]);