Skip to content

gcoakes/transmute-tools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages