1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
//! # Dioptre //! //! Dioptre is a library for working with struct fields. //! //! The [`Fields`] trait records a struct's layout, and deriving it provides matching [`Field`] //! consts. //! //! Downstream code, like [`CellExt::project`](`ext::CellExt::project`), can build on this data to //! provide new ways to safely manipulate structs. #![no_std] use core::marker::PhantomData; pub use dioptre_derive::Fields; pub mod ext; /// Layout metadata for a struct. /// /// This trait should not normally be implemented by hand. Instead, use `#[derive(Fields)]`- this /// will safely generate the appropriate trait impl as well as associated const [`Field`]s. /// /// # Safety /// /// * `OFFSETS`, `SIZES` and `ALIGNS` must accurately describe `Self`'s fields. pub unsafe trait Fields { /// The offsets of individual struct elements. // // These are encoded as functions because Rust has no sound way to compute field offsets ahead // of time, without a valid object. // Further, the parameter is a `*mut u8` instead of a `&Self`, despite requiring a valid // object, because Rust has no way to express the type `for<'a> fn(&'a Self) where Self: 'a`. const OFFSETS: &'static [fn(*mut u8) -> usize]; /// The sizes of individual struct elements. const SIZES: &'static [usize]; /// The alignments of individual struct elements. const ALIGNS: &'static [usize]; } /// A handle to a field in struct `S` of type `F`. /// /// These should be generated by `#[derive(Fields)]`. pub struct Field<S, F> { index: usize, _marker: PhantomData<(*mut S, *mut F)> } impl<S, F> Field<S, F> { pub const unsafe fn new(index: usize) -> Field<S, F> { Field { index, _marker: PhantomData } } pub const fn index(self) -> usize { self.index } }