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 }
}