endian-writer-derive

Crates.ioendian-writer-derive
lib.rsendian-writer-derive
version0.1.0
sourcesrc
created_at2024-10-27 22:04:03.83779
updated_at2024-10-27 22:04:03.83779
descriptionProcedural Macros for endian-writer crate.
homepage
repositoryhttps://github.com/Sewer56/endian-writer-derive
max_upload_size
id1425067
size12,295
Sewer. (Sewer56)

documentation

README

endian-writer-derive

Crates.io Docs.rs CI

About

Procedural Macros for endian-writer crate (version 2.X.X).

This is a procedural macro for automatically deriving EndianWritableAt, EndianReadableAt, and HasSize traits for structs whose members already implement the above traits.

Example

The following piece of Rust code.

use endian_writer_derive::EndianWritable;
#[derive(EndianWritable)]
#[repr(C)]
struct MyStruct {
    a: u32,
    b: u16,
    c: u8,
}

Expands to:

use endian_writer::*;
#[repr(C)]
struct Simple {
    a: u32,
    b: u16,
    c: u8,
}
impl HasSize for Simple {
    const SIZE: usize = <u32 as HasSize>::SIZE + <u16 as HasSize>::SIZE + <u8 as HasSize>::SIZE;
}
impl EndianWritableAt for Simple {
    unsafe fn write_at<W: EndianWriter>(&self, writer: &mut W, offset: isize) {
        let a = self.a;
        writer.write_at(&a, offset);
        let b = self.b;
        writer.write_at(&b, offset + <u32 as HasSize>::SIZE as isize);
        let c = self.c;
        writer.write_at(
            &c,
            offset + <u32 as HasSize>::SIZE as isize + <u16 as HasSize>::SIZE as isize,
        );
    }
}
impl EndianReadableAt for Simple {
    unsafe fn read_at<R: EndianReader>(reader: &mut R, offset: isize) -> Self {
        let a = <u32 as EndianReadableAt>::read_at(reader, offset);
        let b =
            <u16 as EndianReadableAt>::read_at(reader, offset + <u32 as HasSize>::SIZE as isize);
        let c = <u8 as EndianReadableAt>::read_at(
            reader,
            offset + <u32 as HasSize>::SIZE as isize + <u16 as HasSize>::SIZE as isize,
        );
        Self { a, b, c }
    }
}

This code is equivalent to what a human would write, in terms of functionality, at no overhead.

Code Generation Behaviour

Fields are written to the output in the order they are declared in the source code.

Consider the following struct

#[derive(EndianWritable)]
struct WeirdOrder {
    c: u8,
    b: u16,
    a: u32,
}

The struct will be written in the order of u8, u16 and lastly u32. On the other hand, Rust may rearrange the fields as u32, u16 and lastly u8.

In other words, the derive macro treats the code as if the struct is #[repr(C, packed(1))]. If padding is desired, the user must manually create it in the struct.

Development

For information on how to work with this codebase, see README-DEV.MD.

License

Licensed under MIT.

Learn more about Reloaded's general choice of licensing for projects..

Commit count: 5

cargo fmt