1#![feature(generic_associated_types)]
2#![deny(unsafe_op_in_unsafe_fn)]
3
4mod pin;
5mod maybe_uninit;
6
7pub trait Project {
8 type Base: ?Sized;
9 type Output<'a, Field: 'a> where Self: 'a;
10
11 unsafe fn project<'a, Field>(&'a self, project_field: fn(*const Self::Base) -> *const Field) -> Self::Output<'a, Field>;
12}
13
14pub trait ProjectMut: Project {
15 type OutputMut<'a, Field: 'a> where Self: 'a;
16
17 unsafe fn project_mut<'a, Field>(&'a mut self, project_field: fn(*mut Self::Base) -> *mut Field) -> Self::OutputMut<'a, Field>;
18}
19
20impl<T> Project for &'_ T where T: Project {
21 type Base = T::Base;
22 type Output<'a, Field: 'a> where Self: 'a = T::Output<'a, Field>;
23
24 unsafe fn project<'a, Field>(&'a self, project_field: fn(*const Self::Base) -> *const Field) -> Self::Output<'a, Field> {
25 unsafe {
26 T::project(*self, project_field)
27 }
28 }
29}
30
31impl<T> Project for &'_ mut T where T: Project {
32 type Base = T::Base;
33 type Output<'a, Field: 'a> where Self: 'a = T::Output<'a, Field>;
34
35 unsafe fn project<'a, Field>(&'a self, project_field: fn(*const Self::Base) -> *const Field) -> Self::Output<'a, Field> {
36 unsafe {
37 T::project(*self, project_field)
38 }
39 }
40}
41
42impl<T> ProjectMut for &'_ mut T where T: ProjectMut {
43 type OutputMut<'a, Field: 'a> where Self: 'a = T::OutputMut<'a, Field>;
44
45 unsafe fn project_mut<'a, Field>(&'a mut self, project_field: fn(*mut Self::Base) -> *mut Field) -> Self::OutputMut<'a, Field> {
46 unsafe {
47 T::project_mut(*self, project_field)
48 }
49 }
50}
51
52impl<T> Project for Box<T> where T: Project {
53 type Base = T::Base;
54 type Output<'a, Field: 'a> where Self: 'a = T::Output<'a, Field>;
55
56 unsafe fn project<'a, Field>(&'a self, project_field: fn(*const Self::Base) -> *const Field) -> Self::Output<'a, Field> {
57 unsafe {
58 T::project(&**self, project_field)
59 }
60 }
61}
62
63#[macro_export]
79macro_rules! proj {
80 ($input:ident.$field:ident) => {{
81 unsafe {
82 <_ as $crate::Project>::project(&$input, |base| unsafe { core::ptr::addr_of!((*base).$field) })
83 }
84 }};
85 (mut $input:ident.$field:ident) => {{
86 unsafe {
87 <_ as $crate::ProjectMut>::project_mut(&mut $input, |base| unsafe { core::ptr::addr_of_mut!((*base).$field) })
88 }
89 }};
90}