1#[repr(u8)]
2#[derive(Debug, Clone, Copy)]
3pub enum MemType {
4 Primitive,
5 SimpleWrapper,
6 Complex,
7}
8
9impl MemType {
10 pub const fn next(self) -> Self {
11 match self {
12 MemType::Primitive => MemType::SimpleWrapper,
13 MemType::SimpleWrapper => MemType::Complex,
14 MemType::Complex => MemType::Complex,
15 }
16 }
17
18 pub const fn max(self, other: Self) -> Self {
19 match (self, other) {
20 (MemType::Complex, _) => MemType::Complex,
21 (MemType::SimpleWrapper, MemType::Complex) => MemType::Complex,
22 (MemType::SimpleWrapper, _) => MemType::SimpleWrapper,
23 (MemType::Primitive, r) => r,
24 }
25 }
26}
27
28#[macro_export]
29macro_rules! max_mem_type {
30 ($($ty:ty),*) => {
31 $crate::MemType::Primitive$(.max(<$ty as $crate::ToRef>::MEM_TYPE))*
32 };
33}
34
35pub struct Writer {
36 ptr: *mut u8,
37}
38
39impl Writer {
40 #[inline]
43 pub unsafe fn new(ptr: *mut u8) -> Self {
44 Writer { ptr }
45 }
46
47 unsafe fn put<T>(&mut self, data: T) {
48 self.ptr.cast::<T>().write_unaligned(data);
49 self.ptr = self.ptr.add(std::mem::size_of::<T>());
50 }
51
52 unsafe fn reserve(&mut self, len: usize) -> Writer {
53 let fork = Writer { ptr: self.ptr };
54 self.ptr = self.ptr.add(len);
55 fork
56 }
57
58 fn as_ptr(&self) -> *const u8 {
59 self.ptr.cast()
60 }
61}
62
63pub trait ToRef {
64 const MEM_TYPE: MemType;
65
66 type Ref;
67 fn to_size(&self, acc: &mut usize);
68 fn to_ref(&self, buffer: &mut Writer) -> Self::Ref;
69
70 #[inline]
71 fn calc_size(&self) -> usize {
72 let mut size = 0;
73 self.to_size(&mut size);
74 size
75 }
76 #[inline]
77 fn calc_ref(&self) -> (Vec<u8>, Self::Ref) {
78 if matches!(Self::MEM_TYPE, MemType::Complex) {
79 let size = self.calc_size();
80 let mut buffer = Vec::with_capacity(size);
81 let ref_ = self.to_ref(&mut unsafe { Writer::new(buffer.as_ptr() as _) });
82 unsafe { buffer.set_len(size) };
83 (buffer, ref_)
84 } else {
85 let buffer = Vec::new();
86 let ref_ = self.to_ref(&mut unsafe { Writer::new(buffer.as_ptr() as _) });
87 (buffer, ref_)
88 }
89 }
90}
91
92impl<T: ToRef> ToRef for &T {
93 const MEM_TYPE: MemType = T::MEM_TYPE;
94 type Ref = T::Ref;
95
96 #[inline]
97 fn to_size(&self, acc: &mut usize) {
98 (**self).to_size(acc)
99 }
100
101 #[inline]
102 fn to_ref(&self, buffer: &mut Writer) -> Self::Ref {
103 (**self).to_ref(buffer)
104 }
105}
106
107pub trait FromRef {
108 type Ref;
109 fn from_ref(ref_: &Self::Ref) -> Self;
110}
111
112#[derive(Copy, Clone, Debug)]
113#[repr(C)]
114pub struct DataView {
115 ptr: *const (),
116 len: usize,
117}
118
119#[derive(Copy, Clone, Debug)]
120#[repr(transparent)]
121pub struct ListRef(DataView);
122
123impl<T: ToRef> ToRef for Vec<T> {
126 const MEM_TYPE: MemType = T::MEM_TYPE.next();
127 type Ref = ListRef;
128
129 fn to_size(&self, acc: &mut usize) {
130 if matches!(Self::MEM_TYPE, MemType::Complex) {
131 *acc += self.len() * std::mem::size_of::<T::Ref>();
132 self.iter().for_each(|elem| elem.to_size(acc));
133 }
134 }
135
136 fn to_ref(&self, writer: &mut Writer) -> Self::Ref {
137 let mut data = ListRef(DataView {
138 ptr: self.as_ptr().cast(),
139 len: self.len(),
140 });
141
142 if matches!(Self::MEM_TYPE, MemType::Complex) {
143 data.0.ptr = writer.as_ptr().cast();
144 unsafe {
145 let mut children = writer.reserve(self.len() * std::mem::size_of::<T::Ref>());
146 self.iter()
147 .for_each(|elem| children.put(ToRef::to_ref(elem, writer)));
148 }
149 }
150 data
151 }
152}
153
154impl<T: FromRef> FromRef for Vec<T> {
155 type Ref = ListRef;
156
157 fn from_ref(ref_: &Self::Ref) -> Self {
158 if ref_.0.len == 0 {
159 return Vec::new();
160 }
161 let slice = unsafe { std::slice::from_raw_parts(ref_.0.ptr.cast(), ref_.0.len) };
162 slice.iter().map(FromRef::from_ref).collect()
163 }
164}
165
166#[derive(Copy, Clone, Debug)]
167#[repr(transparent)]
168pub struct StringRef(DataView);
169
170impl ToRef for String {
171 const MEM_TYPE: MemType = MemType::SimpleWrapper;
172 type Ref = StringRef;
173
174 #[inline]
175 fn to_size(&self, _: &mut usize) {}
176
177 #[inline]
178 fn to_ref(&self, _: &mut Writer) -> Self::Ref {
179 StringRef(DataView {
180 ptr: self.as_ptr().cast(),
181 len: self.len(),
182 })
183 }
184}
185
186impl FromRef for String {
187 type Ref = StringRef;
188
189 fn from_ref(ref_: &Self::Ref) -> Self {
190 if ref_.0.len == 0 {
191 return String::new();
192 }
193 let slice = unsafe { std::slice::from_raw_parts(ref_.0.ptr.cast(), ref_.0.len) };
194 String::from_utf8_lossy(slice).into_owned()
195 }
196}
197
198macro_rules! primitive_impl {
199 ($($ty:ty),*) => {
200 $(
201 impl ToRef for $ty {
202 const MEM_TYPE: MemType = MemType::Primitive;
203 type Ref = $ty;
204
205 #[inline]
206 fn to_size(&self, _: &mut usize) {}
207
208 #[inline]
209 fn to_ref(&self, _: &mut Writer) -> Self::Ref {
210 *self
211 }
212 }
213
214 impl FromRef for $ty {
215 type Ref = $ty;
216
217 fn from_ref(ref_: &Self::Ref) -> Self {
218 *ref_
219 }
220 }
221 )*
222 };
223}
224
225primitive_impl!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64, bool, char);
226
227macro_rules! tuple_impl {
228 (($ty:ident, $name:tt)) => {
229 tuple_impl!(@# ($ty, $name));
230 };
231 ($(($ty:ident, $name:tt)),+) => {
232 tuple_impl!(@# $(($ty, $name)),*);
233 tuple_impl!(@! [$(($ty, $name))*]);
234 };
235 (@# $(($ty:ident, $name:tt)),*) => {
236 impl<$($ty,)*> ToRef for ($($ty,)*) where $($ty:ToRef,)* {
237 const MEM_TYPE: MemType = MemType::Primitive$(.max($ty::MEM_TYPE))*;
238 type Ref = ($($ty::Ref,)*);
239
240 fn to_size(&self, acc: &mut usize) {
241 $(self.$name.to_size(acc);)*
242 }
243
244 fn to_ref(&self, buffer: &mut Writer) -> Self::Ref {
245 (
246 $(self.$name.to_ref(buffer),)*
247 )
248 }
249 }
250 };
251 (@! [] ($ty_l:ident, $name_l:tt) $(($ty:ident, $name:tt))*) => {
252 tuple_impl!(@~ [$(($ty, $name))*]);
253 };
254 (@! [($ty_f:ident, $name_f:tt) $(($ty:ident, $name:tt))*] $(($ty_r:ident, $name_r:tt))*) => {
255 tuple_impl!(@! [$(($ty, $name))*] ($ty_f, $name_f) $(($ty_r, $name_r))*);
256 };
257 (@~ [] $(($ty:ident, $name:tt))*) => {
258 tuple_impl!($(($ty, $name)),*);
259 };
260 (@~ [($ty_f:ident, $name_f:tt) $(($ty:ident, $name:tt))*] $(($ty_r:ident, $name_r:tt))*) => {
261 tuple_impl!(@~ [$(($ty, $name))*] ($ty_f, $name_f) $(($ty_r, $name_r))*);
262 };
263}
264
265tuple_impl!(
266 (T1, 0),
267 (T2, 1),
268 (T3, 2),
269 (T4, 3),
270 (T5, 4),
271 (T6, 5),
272 (T7, 6),
273 (T8, 7),
274 (T9, 8),
275 (T10, 9),
276 (T11, 10),
277 (T12, 11),
278 (T13, 12),
279 (T14, 13),
280 (T15, 14),
281 (T16, 15)
282);
283
284#[inline]
285fn copy_item<T>(buf: &mut Writer, item: T) {
286 unsafe { buf.put(item) };
287}
288
289trait CopyTuple {
290 fn tuple_copy_to(self, buf: &mut Writer);
291}
292
293macro_rules! copy_tuple {
294 (($ty:ident, $name:tt)) => {
295 copy_tuple!(@# ($ty, $name));
296 };
297 ($(($ty:ident, $name:tt)),+) => {
298 copy_tuple!(@# $(($ty, $name)),*);
299 copy_tuple!(@! [$(($ty, $name))*]);
300 };
301 (@# $(($ty:ident, $name:tt)),*) => {
302 impl<$($ty,)*> CopyTuple for ($($ty,)*) {
303 fn tuple_copy_to(self, buf: &mut Writer) {
304 $(copy_item(buf, self.$name);)*
305 }
306 }
307 };
308 (@! [] ($ty_l:ident, $name_l:tt) $(($ty:ident, $name:tt))*) => {
309 copy_tuple!(@~ [$(($ty, $name))*]);
310 };
311 (@! [($ty_f:ident, $name_f:tt) $(($ty:ident, $name:tt))*] $(($ty_r:ident, $name_r:tt))*) => {
312 copy_tuple!(@! [$(($ty, $name))*] ($ty_f, $name_f) $(($ty_r, $name_r))*);
313 };
314 (@~ [] $(($ty:ident, $name:tt))*) => {
315 copy_tuple!($(($ty, $name)),*);
316 };
317 (@~ [($ty_f:ident, $name_f:tt) $(($ty:ident, $name:tt))*] $(($ty_r:ident, $name_r:tt))*) => {
318 copy_tuple!(@~ [$(($ty, $name))*] ($ty_f, $name_f) $(($ty_r, $name_r))*);
319 };
320}
321
322copy_tuple!(
323 (T1, 0),
324 (T2, 1),
325 (T3, 2),
326 (T4, 3),
327 (T5, 4),
328 (T6, 5),
329 (T7, 6),
330 (T8, 7),
331 (T9, 8),
332 (T10, 9),
333 (T11, 10),
334 (T12, 11),
335 (T13, 12),
336 (T14, 13),
337 (T15, 14),
338 (T16, 15)
339);
340
341pub struct CopyStruct<T>(pub T);
342
343macro_rules! copy_struct_for_tuple {
344 (($ty:ident, $name:tt)) => {
345 copy_struct_for_tuple!(@# ($ty, $name));
346 };
347 ($(($ty:ident, $name:tt)),+) => {
348 copy_struct_for_tuple!(@# $(($ty, $name)),*);
349 copy_struct_for_tuple!(@! [$(($ty, $name))*]);
350 };
351 (@# $(($ty:ident, $name:tt)),*) => {
352 impl<$($ty,)*> ToRef for CopyStruct<($($ty,)*)> where $($ty:ToRef,)* {
353 const MEM_TYPE: MemType = MemType::Complex;
355 type Ref = *const u8;
356
357 fn to_size(&self, acc: &mut usize) {
358 if matches!(MemType::Primitive$(.max($ty::MEM_TYPE))*, MemType::Complex) {
359 $(self.0.$name.to_size(acc);)*
360 }
361 *acc += (0 $(+::std::mem::size_of::<$ty::Ref>())*);
362 }
363
364 fn to_ref(&self, buffer: &mut Writer) -> Self::Ref {
365 let r = ($(self.0.$name.to_ref(buffer),)*);
366 let ptr = buffer.ptr as *const u8;
367 r.tuple_copy_to(buffer);
368 ptr
369 }
370 }
371 };
372 (@! [] ($ty_l:ident, $name_l:tt) $(($ty:ident, $name:tt))*) => {
373 copy_struct_for_tuple!(@~ [$(($ty, $name))*]);
374 };
375 (@! [($ty_f:ident, $name_f:tt) $(($ty:ident, $name:tt))*] $(($ty_r:ident, $name_r:tt))*) => {
376 copy_struct_for_tuple!(@! [$(($ty, $name))*] ($ty_f, $name_f) $(($ty_r, $name_r))*);
377 };
378 (@~ [] $(($ty:ident, $name:tt))*) => {
379 copy_struct_for_tuple!($(($ty, $name)),*);
380 };
381 (@~ [($ty_f:ident, $name_f:tt) $(($ty:ident, $name:tt))*] $(($ty_r:ident, $name_r:tt))*) => {
382 copy_struct_for_tuple!(@~ [$(($ty, $name))*] ($ty_f, $name_f) $(($ty_r, $name_r))*);
383 };
384}
385
386copy_struct_for_tuple!(
387 (T1, 0),
388 (T2, 1),
389 (T3, 2),
390 (T4, 3),
391 (T5, 4),
392 (T6, 5),
393 (T7, 6),
394 (T8, 7),
395 (T9, 8),
396 (T10, 9),
397 (T11, 10),
398 (T12, 11),
399 (T13, 12),
400 (T14, 13),
401 (T15, 14),
402 (T16, 15)
403);