rust2go_convert/
convert.rs

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    /// # Safety
41    /// The pointer must be valid, and it must has enough capacity.
42    #[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
123// Owned to Ref
124// Vec<T> -> ListRef
125impl<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            // Complex since we need buffer
354            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);