1 unstable release
0.1.0 | Apr 22, 2021 |
---|
#1569 in Procedural macros
18KB
319 lines
transmute-tools
Proc macros to assist with safely creating transmutable data structures. To be clear, this does not make it safe to use transmute. This is just a collection of tools that might help you do that. The specific, initial use case was to help faithfully reproduce structures from the NVMe spec.
Usage
Location Assertions
transmute_tools::test_structure
provides an attribute which allows
specifying the location within a struct that a field must be placed:
use structural_assert::test_structure;
#[test_structure(size = 20)]
#[repr(C, packed)]
pub struct Foo {
#[loc(0:0)]
pub a: u8,
#[loc(1:1)]
pub b: u8,
#[loc(2:3)]
pub c: u16,
#[loc(4:19)]
pub d: u128,
}
Endianness
transmute_tools::endianness
provides an attribute which allows specifying
specific endianness for a struct's fields. A struct like this:
#[macro_use]
extern crate transmute_tools;
#[endianness(be)]
#[repr(C, packed)]
pub struct Foo {
pub a: u8,
pub b: u8,
pub c: u16,
#[le]
pub d: u128,
pub e: Box<()>,
}
Will generate this:
#[repr(C, packed)]
pub struct Convert {
// Note the missing visbilities.
a: u8,
b: u8,
c: u16,
d: u128,
pub e: Box<()>,
}
impl Convert {
#[inline]
pub fn a(&self) -> u8 {
u8::from_be(self.a)
}
#[inline]
pub fn set_a(&mut self, value: u8) {
self.a = value.to_be();
}
#[inline]
pub fn b(&self) -> u8 {
u8::from_be(self.b)
}
#[inline]
pub fn set_b(&mut self, value: u8) {
self.b = value.to_be();
}
#[inline]
pub fn c(&self) -> u16 {
u16::from_be(self.c)
}
#[inline]
pub fn set_c(&mut self, value: u16) {
self.c = value.to_be();
}
#[inline]
pub fn d(&self) -> u128 {
u128::from_le(self.d)
}
#[inline]
pub fn set_d(&mut self, value: u128) {
self.d = value.to_le();
}
}
NOTE: This must generate functions rather than use something like simple_endianness because access to fields of packed structs when done by value rather than reference.
Dependencies
~1.5MB
~38K SLoC