An attempt to make a procedural macro to support safe casting in Rust.
This library is designed to allow for copying raw underlying data between different types in Rust. This is helpful for handling things like binary files or network protocols. Using this library you are able to safely create structures and cast/copy between them.
In Cargo.toml
:
[dependencies]
safecast = { path = "../path/to/safecast" }
Example program:
use safecast::Safecast;
#[derive(Safecast, Debug)]
#[repr(C)]
struct PacketData {
data: u64,
sequence: u64,
flags: u32,
_padding: u32,
}
fn main() {
let packet = [0x41u8; 0x18];
let val: PacketData = packet.cast_copy();
print!("Packet data is {:#x?}\n", val);
}
Output:
Packet data is PacketData {
data: 0x4141414141414141,
sequence: 0x4141414141414141,
flags: 0x41414141,
_padding: 0x41414141
}
This casting/copying is safe given the following:
u8
, u16
, u32
, u64
, u128
, usize
, i8
, i16
, i32
, i64
, i128
, isize
are considered
to have these properties.Safecast::cast_copy_into<T: Safecast + ?Sized>(&self, dest: &mut T)
This routine allows the casting from an existing structure to another type given the other
type also implemented Safecast. This method is the one used when T
is ?Sized
, allowing for
us to cast into things like slices/Vecs. This is the core implementation and is used by
cast()
.
This method will panic unless both self and T are equal in size (in bytes).
Safecast::cast_copy<T: Safecast>(&self) -> T
Creates an uninitialized value of type T, and calls cast_into
on self
to cast it into T. Returns the new value.
This method will panic unless both self and T are equal in size (in bytes).
Safecast::cast<T: Safecast>(&self) -> &[T]
Casts Self
to a slice of T
s, where Self
is evenly divisible by T
.
Safecast::cast_mut<T: Safecast>(&mut self) -> &mut [T]
Casts Self
to a mutable slice of T
s, where Self
is evenly divisible by T
.
I'm not sure if it matches Rust's definition, however I think it is fine for the endianness to be up to the user to handle. There is no safety violation by having an unexpected endian swap, thus I'm okay with this not handling endian swaps for you. It is up to the user to manually swap fields as they use them.