raw_struct 0.1.3

raw_struct is a Rust procedural macro for easily declaring C-style structs that reference local or external memory, based on your memory implementation. It generates appropiate getter methods for easy access.
Documentation
use alloc::{
    borrow::Cow,
    boxed::Box,
    format,
};
#[cfg(feature = "no_std")]
pub use core::error::Error as ErrorType;
use core::fmt;
#[cfg(not(feature = "no_std"))]
pub use std::error::Error as ErrorType;

pub type Error = Box<dyn ErrorType + Send + Sync + 'static>;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum AccessMode {
    Read,
    Write,
}

impl AccessMode {
    fn name(&self) -> &'static str {
        match self {
            Self::Read => "read",
            Self::Write => "write",
        }
    }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct AccessViolation;

impl fmt::Display for AccessViolation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "memory outside of the struct has been accessed")
    }
}

impl ErrorType for AccessViolation {}

#[derive(Debug)]
pub struct AccessError {
    pub source: Error,

    pub offset: u64,
    pub size: usize,
    pub mode: AccessMode,

    pub object: Cow<'static, str>,
    pub member: Option<Cow<'static, str>>,
}

impl fmt::Display for AccessError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "failed to {} 0x{:X} bytes at 0x{:X} ({}): {}",
            self.mode.name(),
            self.size,
            self.offset,
            if let Some(member) = &self.member {
                Cow::from(format!("{}::{}", self.object, member))
            } else {
                self.object.clone()
            },
            self.source
        )
    }
}

impl ErrorType for AccessError {
    fn source(&self) -> Option<&(dyn ErrorType + 'static)> {
        Some(&*self.source)
    }
}