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