Skip to content

Assert struct layouts, including field sizes and offsets.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

andogq/assert_layout

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

assert_layout

Assert struct layouts, including field sizes and offsets.

assert_layout provides a single proc-macro which will perform compile-time assertions for certain qualities of a struct. In addition to field size and offset, it's also possible to provide concrete types for generics and assert that the layout still holds.

Overview

Struct containers can use the size assertion to assert the size of the struct.

use assert_layout::assert_layout;

#[assert_layout(size = 1)]
#[repr(packed)]
struct MyStruct {
    field: u8,
}

Similarly, each field can use the size and offset assertions.

use assert_layout::assert_layout;

#[assert_layout(size = 5)]
#[repr(packed)]
struct MyStruct {
    #[assert_layout(offset = 0, size = 1)]
    field: u8,

    #[assert_layout(offset = 2, size = 4)]
    another_field: f32,
}

Generics

If the struct contains generics, concrete types can be provided for assertions using generics. For instance, the following assertion would expand with T = u32.

use assert_layout::assert_layout;

#[assert_layout(size = 4, generics = "u32")]
#[repr(packed)]
struct MyStruct<T> {
    #[assert_layout(offset = 0, size = 4)]
    field: T,
}

Multiple generic parameters can by provided with commas between them, in addition to consts (in the same manner as MyStruct<...>).

use assert_layout::assert_layout;

#[assert_layout(size = 64, generics = "8, f64")]
#[repr(packed)]
struct MyStruct<const N: usize, T> {
    #[assert_layout(offset = 0, size = 64)]
    field: [T; N],
}

The generics attribute can be provided multiple times in order to assert different combinations of generics.

use assert_layout::assert_layout;

#[assert_layout(size = 12, generics = "u32, u64", generics = "i32, i64")]
#[repr(packed)]
struct MyStruct<T, U> {
    #[assert_layout(offset = 0, size = 4)]
    field: T,

    #[assert_layout(offset = 4, size = 8)]
    another_field: U,
}

Namespaces

Sometimes generic combinations will not be compatible with each other, so namespaces can be used to isolate the assertions. A namespace is created using namespace(...), where namespace is a unique identifier for the namepsace, and the previously described assertions (generics, offset, size) are within the brackets. Everything within the namespace will be asserted in isolation.

use assert_layout::assert_layout;

#[assert_layout(little(size = 4, generics = "u32"), big(size = 8, generics = "u64"))]
#[repr(packed)]
struct MyStruct<T> {
    #[assert_layout(little(offset = 0, size = 4), big(offset = 0, size = 8))]
    field: T,
}

If there are common assertions between the namespaces (such as offset = 0 above), they can be omitted from the namespace and asserted at the top level.

use assert_layout::assert_layout;

#[assert_layout(
    generics = "u32",
    generics = "u64",
    little(size = 4, generics = "u32"),
    big(size = 8, generics = "u64")
)]
#[repr(packed)]
struct MyStruct<T> {
    #[assert_layout(offset = 0, little(size = 4), big(size = 8))]
    field: T,
}

Releases

No releases published

Packages

No packages published

Languages