ser_raw/serialize_impls/
ptrs.rs1use std::{marker::PhantomData, mem};
2
3use crate::{pos::Addr, Serialize, Serializer};
4
5const PTR_SIZE: usize = mem::size_of::<usize>();
6
7impl<T, S> Serialize<S> for Box<T>
8where
9 S: Serializer,
10 T: Serialize<S> + Sized,
11{
12 fn serialize_data(&self, serializer: &mut S) {
13 let _ = SizeCheck::<Box<T>, PTR_SIZE>::ASSERT_SIZE_IS;
16
17 if mem::size_of::<T>() == 0 {
20 return;
21 }
22
23 let ptr_addr = S::Addr::from_ref(self);
25 serializer.push_and_process(&**self, ptr_addr, |serializer| {
26 (**self).serialize_data(serializer);
28 });
29 }
30}
31
32impl<T, S> Serialize<S> for Vec<T>
33where
34 S: Serializer,
35 T: Serialize<S>,
36{
37 fn serialize_data(&self, serializer: &mut S) {
38 if mem::size_of::<T>() == 0 {
41 return;
42 }
43
44 if self.len() == 0 {
46 serializer.write_correction(|serializer| {
48 if self.capacity() != 0 {
49 unsafe { write_capacity_and_ptr_for_empty_vec(self, serializer) };
50 }
51 });
52
53 return;
54 }
55
56 serializer.write_correction(|serializer| {
58 if self.capacity() != self.len() {
59 let cap_offset = VecOffsets::<T>::OFFSETS_VEC.capacity();
60 let cap_addr = S::Addr::from_ref_offset(self, cap_offset).addr();
61 unsafe { serializer.write(&self.len(), cap_addr) };
62 }
63 });
64
65 let ptr_addr = S::Addr::from_ref_offset(self, VecOffsets::<T>::PTR_OFFSET);
67 serializer.push_and_process_slice(self.as_slice(), ptr_addr, |serializer| {
68 for value in &**self {
70 value.serialize_data(serializer);
71 }
72 });
73 }
74}
75
76impl<S> Serialize<S> for String
77where S: Serializer
78{
79 fn serialize_data(&self, serializer: &mut S) {
80 if self.len() == 0 {
82 serializer.write_correction(|serializer| {
84 if self.capacity() != 0 {
85 unsafe { write_capacity_and_ptr_for_empty_string(self, serializer) };
86 }
87 });
88
89 return;
90 }
91
92 serializer.write_correction(|serializer| {
94 if self.capacity() != self.len() {
95 let cap_offset = OFFSETS_STRING.capacity();
96 let cap_addr = S::Addr::from_ref_offset(self, cap_offset).addr();
97 unsafe { serializer.write(&self.len(), cap_addr) };
98 }
99 });
100
101 let ptr_addr = S::Addr::from_ref_offset(self, STRING_PTR_OFFSET);
103 serializer.push_slice(self.as_bytes(), ptr_addr);
104 }
105}
106
107struct SizeCheck<T, const SIZE: usize> {
109 _marker: PhantomData<T>,
110}
111
112impl<T, const SIZE: usize> SizeCheck<T, SIZE> {
113 const ASSERT_SIZE_IS: () = assert!(mem::size_of::<T>() == SIZE);
114}
115
116struct VecOffsets<T> {
125 _marker: PhantomData<T>,
126}
127
128impl<T> VecOffsets<T> {
129 const PTR_INDEX: usize = {
130 let vec = Vec::<T>::new();
132 let bytes: [usize; 3] = unsafe { mem::transmute(vec) };
134 let dangle = mem::align_of::<T>();
135 if bytes[0] == dangle {
136 assert!(bytes[1] == 0 && bytes[2] == 0);
137 0
138 } else if bytes[1] == dangle {
139 assert!(bytes[0] == 0 && bytes[2] == 0);
140 1
141 } else if bytes[2] == dangle {
142 assert!(bytes[0] == 0 && bytes[1] == 0);
143 2
144 } else {
145 panic!("Could not determine offset of Vec's ptr field");
146 }
147 };
148
149 const PTR_OFFSET: usize = Self::PTR_INDEX * PTR_SIZE;
150
151 const OFFSETS_VEC: mem::ManuallyDrop<Vec<T>> = {
159 let dangle = mem::align_of::<T>();
160 let bytes = match Self::PTR_INDEX {
161 0 => [dangle, PTR_SIZE, PTR_SIZE * 2],
162 1 => [0, dangle, PTR_SIZE * 2],
163 2 => [0, PTR_SIZE, dangle],
164 _ => unreachable!(),
165 };
166 unsafe { mem::transmute(bytes) }
167 };
168}
169
170const STRING_PTR_INDEX: usize = {
177 let s = String::new();
179 let bytes: [usize; 3] = unsafe { mem::transmute(s) };
181 let dangle = 1;
182 if bytes[0] == dangle {
183 assert!(bytes[1] == 0 && bytes[2] == 0);
184 0
185 } else if bytes[1] == dangle {
186 assert!(bytes[0] == 0 && bytes[2] == 0);
187 1
188 } else if bytes[2] == dangle {
189 assert!(bytes[0] == 0 && bytes[1] == 0);
190 2
191 } else {
192 panic!("Could not determine offset of String's ptr field");
193 }
194};
195const STRING_PTR_OFFSET: usize = STRING_PTR_INDEX * PTR_SIZE;
196
197const OFFSETS_STRING: mem::ManuallyDrop<String> = {
198 let dangle = 1;
199 let bytes = match STRING_PTR_INDEX {
200 0 => [dangle, PTR_SIZE, PTR_SIZE * 2],
201 1 => [0, dangle, PTR_SIZE * 2],
202 2 => [0, PTR_SIZE, dangle],
203 _ => unreachable!(),
204 };
205 unsafe { mem::transmute(bytes) }
206};
207
208#[inline]
220unsafe fn write_capacity_and_ptr_for_empty_vec<T, Ser: Serializer>(
221 v: &Vec<T>,
222 serializer: &mut Ser,
223) {
224 let dangle = mem::align_of::<T>();
227 let cap_offset = VecOffsets::<T>::OFFSETS_VEC.capacity();
228 let ptr_offset = VecOffsets::<T>::PTR_OFFSET;
229
230 if cap_offset == 0 && ptr_offset == PTR_SIZE {
231 serializer.write(&[0, dangle], Ser::Addr::from_ref(v).addr());
232 } else if cap_offset == PTR_SIZE && ptr_offset == 0 {
233 serializer.write(&[dangle, 0], Ser::Addr::from_ref(v).addr());
234 } else if cap_offset == PTR_SIZE && ptr_offset == PTR_SIZE * 2 {
235 serializer.write(&[0, dangle], Ser::Addr::from_ref_offset(v, PTR_SIZE).addr());
236 } else if cap_offset == PTR_SIZE * 2 && ptr_offset == PTR_SIZE {
237 serializer.write(&[dangle, 0], Ser::Addr::from_ref_offset(v, PTR_SIZE).addr());
238 } else {
239 serializer.write(&0usize, Ser::Addr::from_ref_offset(v, cap_offset).addr());
240 serializer.write(&dangle, Ser::Addr::from_ref_offset(v, ptr_offset).addr());
241 }
242}
243
244#[inline]
255unsafe fn write_capacity_and_ptr_for_empty_string<Ser: Serializer>(
256 s: &String,
257 serializer: &mut Ser,
258) {
259 let dangle = 1usize;
262 let cap_offset = OFFSETS_STRING.capacity();
263
264 if cap_offset == 0 && STRING_PTR_OFFSET == PTR_SIZE {
265 serializer.write(&[0, dangle], Ser::Addr::from_ref(s).addr());
266 } else if cap_offset == PTR_SIZE && STRING_PTR_OFFSET == 0 {
267 serializer.write(&[dangle, 0], Ser::Addr::from_ref(s).addr());
268 } else if cap_offset == PTR_SIZE && STRING_PTR_OFFSET == PTR_SIZE * 2 {
269 serializer.write(&[0, dangle], Ser::Addr::from_ref_offset(s, PTR_SIZE).addr());
270 } else if cap_offset == PTR_SIZE * 2 && STRING_PTR_OFFSET == PTR_SIZE {
271 serializer.write(&[dangle, 0], Ser::Addr::from_ref_offset(s, PTR_SIZE).addr());
272 } else {
273 serializer.write(&0usize, Ser::Addr::from_ref_offset(s, cap_offset).addr());
274 serializer.write(
275 &dangle,
276 Ser::Addr::from_ref_offset(s, STRING_PTR_OFFSET).addr(),
277 );
278 }
279}