crossmist/
unsized_builtins.rs1use crate::{relocation::RelocatablePtr, Deserializer, NonTrivialObject, Object, Serializer};
2use std::io::Result;
3
4#[repr(C)]
5struct DynFatPtr {
6 data: *const (),
7 vtable: *const (),
8}
9
10#[derive(PartialEq)]
11enum TypeClass {
12 Sized,
13 Dyn,
14}
15impl TypeClass {
16 const fn of<T: ?Sized>() -> Self {
17 if std::mem::size_of::<&T>() == std::mem::size_of::<usize>() {
18 Self::Sized
19 } else if std::mem::size_of::<&T>() == std::mem::size_of::<DynFatPtr>() {
20 Self::Dyn
21 } else {
22 panic!(
23 "Unexpected pointer size. You are probably trying to serialize Box<&dyn TraitA + \
24 TraitB>, which crossmist does not support, because this feature was not present \
25 in rustc when this crate was published.",
26 );
27 }
28 }
29}
30
31unsafe impl<T: Object + ?Sized> NonTrivialObject for Box<T> {
32 fn serialize_self_non_trivial(&self, s: &mut Serializer) {
33 if TypeClass::of::<T>() == TypeClass::Dyn {
39 let fat_ptr = unsafe { std::mem::transmute_copy::<&T, DynFatPtr>(&self.as_ref()) };
40 s.serialize(&RelocatablePtr(fat_ptr.vtable));
41 }
42
43 #[cfg(not(feature = "nightly"))]
44 s.serialize(&RelocatablePtr(
45 self.as_ref().deserialize_on_heap_get() as *const ()
46 ));
47
48 self.as_ref().serialize_self(s);
49 }
50
51 unsafe fn deserialize_self_non_trivial(d: &mut Deserializer) -> Result<Self> {
52 let mut pointer: *mut T = match TypeClass::of::<T>() {
53 TypeClass::Sized => std::mem::transmute_copy::<usize, *mut T>(&0usize),
54 TypeClass::Dyn => std::mem::transmute_copy::<DynFatPtr, *mut T>(&DynFatPtr {
55 data: std::ptr::null(),
56 vtable: d.deserialize::<RelocatablePtr<()>>()?.0,
57 }),
58 };
59
60 #[cfg(feature = "nightly")]
61 let pointer_thin_part = pointer.deserialize_on_heap_ptr(d)?;
62 #[cfg(not(feature = "nightly"))]
63 let pointer_thin_part = std::mem::transmute::<
64 RelocatablePtr<()>,
65 unsafe fn(&mut Deserializer) -> Result<*mut ()>,
66 >(d.deserialize::<RelocatablePtr<()>>()?)(d)?;
67
68 (&mut pointer as *mut *mut T as *mut *mut ()).write(pointer_thin_part);
69
70 Ok(Box::from_raw(pointer))
71 }
72}
73
74unsafe impl<T: Object> NonTrivialObject for Box<[T]> {
75 fn serialize_self_non_trivial(&self, s: &mut Serializer) {
76 s.serialize(&self.len());
77 s.serialize_slice(self.as_ref());
78 }
79 unsafe fn deserialize_self_non_trivial(d: &mut Deserializer) -> Result<Self> {
80 Ok(d.deserialize::<Vec<T>>()?.into_boxed_slice())
81 }
82}