repr_offset/struct_field_offset/
impl_fieldoffset_methods.rs

1// Defined this macro to reduce the amount of instructions in debug builds
2// caused by delegating to `raw_get`
3macro_rules! get_ptr_method {
4    ($self:expr, $base:expr, $S:ty, $F:ty) => {{
5        #[cfg(feature = "testing")]
6        let _: *const $S = $base;
7
8        ($base as *const $S as *const u8).offset($self.offset as isize) as *const $F
9    }};
10}
11
12// Defined this macro to reduce the amount of instructions in debug builds
13// caused by delegating to `raw_get_mut`
14macro_rules! get_mut_ptr_method {
15    ($self:expr, $base:expr, $S:ty, $F:ty) => {{
16        #[cfg(feature = "testing")]
17        let _: *mut $S = $base;
18
19        ($base as *mut $S as *mut u8).offset($self.offset as isize) as *mut $F
20    }};
21}
22
23macro_rules! replace_unaligned {
24    ($self:expr, $base:expr, $value:expr, $S:ty, $F:ty) => {{
25        let ptr = get_mut_ptr_method!($self, $base, $S, $F);
26        let ret = ptr.read_unaligned();
27        ptr.write_unaligned($value);
28        ret
29    }};
30}
31
32macro_rules! unaligned_swap {
33    ($self:expr, $left:expr, $right:expr, $left_to_right:expr, $S:ty, $F:ty) => {{
34        // This function can definitely be optimized.
35        let mut tmp = core::mem::MaybeUninit::<$F>::uninit();
36        let tmp = tmp.as_mut_ptr() as *mut u8;
37
38        let left = get_mut_ptr_method!($self, $left, $S, $F) as *mut u8;
39        let right = get_mut_ptr_method!($self, $right, $S, $F) as *mut u8;
40        core::ptr::copy_nonoverlapping(left, tmp, crate::utils::Mem::<$F>::SIZE);
41        $left_to_right(right, left, crate::utils::Mem::<$F>::SIZE);
42        core::ptr::copy_nonoverlapping(tmp, right, crate::utils::Mem::<$F>::SIZE);
43    }};
44}
45
46macro_rules! impl_fo {
47    (fn get<$S:ty, $F:ty, Aligned>($self:expr, $base:expr)) => {
48        &*get_ptr_method!($self, $base, $S, $F)
49    };
50    (fn get_mut<$S:ty, $F:ty, Aligned>($self:expr, $base:expr)) => {
51        &mut *get_mut_ptr_method!($self, $base, $S, $F)
52    };
53    (fn get_ptr<$S:ty, $F:ty, $A:ident>($self:expr, $base:expr)) => {
54        get_ptr_method!($self, $base, $S, $F)
55    };
56    (fn get_mut_ptr<$S:ty, $F:ty, $A:ident>($self:expr, $base:expr)) => {
57        get_mut_ptr_method!($self, $base, $S, $F)
58    };
59    (fn raw_get<$S:ty, $F:ty, $A:ident>($self:expr, $base:expr)) => {
60        get_ptr_method!($self, $base, $S, $F)
61    };
62    (fn raw_get_mut<$S:ty, $F:ty, $A:ident>($self:expr, $base:expr)) => {
63        get_mut_ptr_method!($self, $base, $S, $F)
64    };
65    (fn get_copy<$S:ty, $F:ty, $A:ident>($self:expr, $base:expr)) => {
66        if_aligned! {
67            $A {
68                *get_ptr_method!($self, $base, $S, $F)
69            } else {
70                get_ptr_method!($self, $base, $S, $F).read_unaligned()
71            }
72        }
73    };
74    (fn read_copy<$S:ty, $F:ty, $A:ident>($self:expr, $base:expr)) => {
75        if_aligned! {
76            $A {
77                *get_ptr_method!($self, $base, $S, $F)
78            } else {
79                get_ptr_method!($self, $base, $S, $F).read_unaligned()
80            }
81        }
82    };
83    (fn read<$S:ty, $F:ty, $A:ident>($self:expr, $source:ident)) => {
84        if_aligned! {
85            $A {
86                get_ptr_method!($self, $source, $S, $F).read()
87            } else {
88                get_ptr_method!($self, $source, $S, $F).read_unaligned()
89            }
90        }
91    };
92    (fn write<$S:ty, $F:ty, $A:ident>($self:expr, $dst:ident, $value:ident)) => {
93        if_aligned! {
94            $A {
95                get_mut_ptr_method!($self, $dst, $S, $F).write($value)
96            } else {
97                get_mut_ptr_method!($self, $dst, $S, $F).write_unaligned($value)
98            }
99        }
100    };
101    (fn copy<$S:ty, $F:ty, $A:ident>($self:expr, $source:ident, $dst:ident)) => {
102        if_aligned! {
103            $A {
104                core::ptr::copy(
105                    get_ptr_method!($self, $source, $S, $F),
106                    get_mut_ptr_method!($self, $dst, $S, $F),
107                    1,
108                )
109            } else {
110                core::ptr::copy(
111                    get_ptr_method!($self, $source, $S, $F) as *const u8,
112                    get_mut_ptr_method!($self, $dst, $S, $F) as *mut u8,
113                    crate::utils::Mem::<F>::SIZE,
114                )
115            }
116        }
117    };
118    (fn copy_nonoverlapping<$S:ty, $F:ty, $A:ident>($self:expr, $source:ident, $dst:ident)) => {
119        if_aligned! {
120            $A {
121                core::ptr::copy_nonoverlapping(
122                    get_ptr_method!($self, $source, $S, $F),
123                    get_mut_ptr_method!($self, $dst, $S, $F),
124                    1,
125                )
126            } else {
127                core::ptr::copy_nonoverlapping(
128                    get_ptr_method!($self, $source, $S, $F) as *const u8,
129                    get_mut_ptr_method!($self, $dst, $S, $F) as *mut u8,
130                    crate::utils::Mem::<F>::SIZE,
131                )
132            }
133        }
134    };
135    (fn replace<$S:ty, $F:ty, $A:ident>($self:expr, $dst:ident, $value:ident)) => {
136        if_aligned! {
137            $A {
138                core::ptr::replace(get_mut_ptr_method!($self, $dst, $S, $F), $value)
139            } else {
140                replace_unaligned!($self, $dst, $value, $S, $F)
141            }
142        }
143    };
144    (fn replace_mut<$S:ty, $F:ty, $A:ident>($self:expr, $dst:ident, $value:ident)) => {
145        if_aligned! {
146            $A {
147                core::mem::replace(&mut *get_mut_ptr_method!($self, $dst, $S, $F), $value)
148            } else {
149                replace_unaligned!($self, $dst, $value, $S, $F)
150            }
151        }
152    };
153    (fn swap<$S:ty, $F:ty, $A:ident>($self:expr, $l:ident, $r:ident)) => {
154        if_aligned! {
155            $A {
156                core::ptr::swap::<F>(
157                    get_mut_ptr_method!($self, $l, $S, $F),
158                    get_mut_ptr_method!($self, $r, $S, $F),
159                )
160            } else {
161                unaligned_swap!($self, $l, $r, core::ptr::copy, $S, $F)
162            }
163        }
164    };
165    (fn swap_nonoverlapping<$S:ty, $F:ty, $A:ident>($self:expr, $l:ident, $r:ident)) => {
166        if_aligned! {
167            $A {
168                core::ptr::swap_nonoverlapping::<F>(
169                    get_mut_ptr_method!($self, $l, $S, $F),
170                    get_mut_ptr_method!($self, $r, $S, $F),
171                    1,
172                )
173            } else {
174                unaligned_swap!($self, $l, $r, core::ptr::copy_nonoverlapping, $S, $F)
175            }
176        }
177    };
178    (fn swap_mut<$S:ty, $F:ty, $A:ident>($self:expr, $l:ident, $r:ident)) => {
179        if_aligned! {
180            $A {
181                core::mem::swap(
182                    &mut *get_mut_ptr_method!($self, $l, $S, $F),
183                    &mut *get_mut_ptr_method!($self, $r, $S, $F),
184                )
185            } else {{
186                // This function could probably be optimized.
187                let l = get_mut_ptr_method!($self, $l, $S, $F);
188                let r = get_mut_ptr_method!($self, $r, $S, $F);
189                let tmp = l.read_unaligned();
190                l.write_unaligned(r.read_unaligned());
191                r.write_unaligned(tmp);
192            }}
193        }
194    };
195}
196
197macro_rules! if_aligned {
198    (Aligned {$($then:tt)*} else {$($else:tt)*}) => {
199        $($then)*
200    };
201    (Unaligned {$($then:tt)*} else {$($else:tt)*}) => {
202        $($else)*
203    };
204}