1use core::mem::{ManuallyDrop, MaybeUninit};
6use core::ptr::addr_of_mut;
7
8use munge::munge;
9
10use crate::decoder::InternalHandleDecoder;
11use crate::encoder::InternalHandleEncoder;
12use crate::{
13 Decode, DecodeError, Decoder, DecoderExt as _, Encode, EncodeError, Encoder, EncoderExt as _,
14 Slot, WireU16, WireU32, ZeroPadding, CHUNK_SIZE,
15};
16
17#[derive(Clone, Copy)]
18#[repr(C)]
19struct Encoded {
20 maybe_num_bytes: WireU32,
21 num_handles: WireU16,
22 flags: WireU16,
23}
24
25const INLINE_SIZE: usize = 4;
26
27#[repr(C, align(8))]
29pub union WireEnvelope {
30 zero: [u8; 8],
31 encoded: Encoded,
32 decoded_inline: [MaybeUninit<u8>; INLINE_SIZE],
33 decoded_out_of_line: *mut (),
34}
35
36unsafe impl ZeroPadding for WireEnvelope {
37 fn zero_padding(_: &mut MaybeUninit<Self>) {}
38}
39
40impl WireEnvelope {
41 const IS_INLINE_BIT: u16 = 1;
42
43 #[inline]
45 pub fn encode_zero(out: &mut MaybeUninit<Self>) {
46 out.write(WireEnvelope { zero: [0; 8] });
47 }
48
49 #[inline]
51 pub fn encode_value_static<E: InternalHandleEncoder + ?Sized, T: Encode<E>>(
52 value: &mut T,
53 encoder: &mut E,
54 out: &mut MaybeUninit<Self>,
55 ) -> Result<(), EncodeError> {
56 munge! {
57 let Self {
58 encoded: Encoded {
59 maybe_num_bytes,
60 num_handles,
61 flags,
62 },
63 } = out;
64 }
65
66 let handles_before = encoder.__internal_handle_count();
67
68 let encoded_size = size_of::<T::Encoded>();
69 if encoded_size <= INLINE_SIZE {
70 unsafe {
73 maybe_num_bytes
74 .as_mut_ptr()
75 .cast::<u8>()
76 .add(encoded_size)
77 .write_bytes(0, INLINE_SIZE - encoded_size);
78 }
79 } else {
80 return Err(EncodeError::ExpectedInline(encoded_size));
81 }
82
83 let value_out = unsafe { &mut *maybe_num_bytes.as_mut_ptr().cast() };
84 T::Encoded::zero_padding(value_out);
85 value.encode(encoder, value_out)?;
86
87 flags.write(WireU16(Self::IS_INLINE_BIT));
88
89 let handle_count = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
90 num_handles.write(WireU16(handle_count));
91
92 Ok(())
93 }
94
95 #[inline]
97 pub fn encode_value<E: Encoder + ?Sized, T: Encode<E>>(
98 value: &mut T,
99 encoder: &mut E,
100 out: &mut MaybeUninit<Self>,
101 ) -> Result<(), EncodeError> {
102 munge! {
103 let Self {
104 encoded: Encoded {
105 maybe_num_bytes,
106 num_handles,
107 flags,
108 },
109 } = out;
110 }
111
112 let handles_before = encoder.__internal_handle_count();
113
114 let encoded_size = size_of::<T::Encoded>();
115 if encoded_size <= INLINE_SIZE {
116 unsafe {
119 maybe_num_bytes
120 .as_mut_ptr()
121 .cast::<u8>()
122 .add(encoded_size)
123 .write_bytes(0, INLINE_SIZE - encoded_size);
124 }
125 let value_out = unsafe { &mut *maybe_num_bytes.as_mut_ptr().cast() };
126 T::Encoded::zero_padding(value_out);
127 value.encode(encoder, value_out)?;
128 flags.write(WireU16(Self::IS_INLINE_BIT));
129 } else {
130 let bytes_before = encoder.bytes_written();
131
132 encoder.encode_next(value)?;
133
134 let bytes_count = (encoder.bytes_written() - bytes_before).try_into().unwrap();
135 maybe_num_bytes.write(WireU32(bytes_count));
136 flags.write(WireU16(0));
137 }
138
139 let handle_count = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
140 num_handles.write(WireU16(handle_count));
141
142 Ok(())
143 }
144
145 #[inline]
147 pub fn zero() -> Self {
148 Self { zero: [0; 8] }
149 }
150
151 #[inline]
153 pub fn is_encoded_zero(slot: Slot<'_, Self>) -> bool {
154 munge!(let Self { zero } = slot);
155 *zero == [0; 8]
156 }
157
158 #[inline]
160 pub fn is_zero(&self) -> bool {
161 unsafe { self.zero == [0; 8] }
162 }
163
164 #[inline]
165 fn out_of_line_chunks(
166 maybe_num_bytes: Slot<'_, WireU32>,
167 flags: Slot<'_, WireU16>,
168 ) -> Result<Option<usize>, DecodeError> {
169 if **flags & Self::IS_INLINE_BIT == 0 {
170 let num_bytes = **maybe_num_bytes;
171 if num_bytes as usize % CHUNK_SIZE != 0 {
172 return Err(DecodeError::InvalidEnvelopeSize(num_bytes));
173 }
174 if num_bytes <= INLINE_SIZE as u32 {
175 return Err(DecodeError::OutOfLineValueTooSmall(num_bytes));
176 }
177 Ok(Some(num_bytes as usize / CHUNK_SIZE))
178 } else {
179 Ok(None)
180 }
181 }
182
183 #[inline]
185 pub fn decode_unknown_static<D: InternalHandleDecoder + ?Sized>(
186 slot: Slot<'_, Self>,
187 decoder: &mut D,
188 ) -> Result<(), DecodeError> {
189 munge! {
190 let Self {
191 encoded: Encoded {
192 maybe_num_bytes,
193 num_handles,
194 flags,
195 },
196 } = slot;
197 }
198
199 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
200 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
201 }
202
203 decoder.__internal_take_handles(**num_handles as usize)?;
204
205 Ok(())
206 }
207
208 #[inline]
210 pub fn decode_unknown<D: Decoder + ?Sized>(
211 slot: Slot<'_, Self>,
212 mut decoder: &mut D,
213 ) -> Result<(), DecodeError> {
214 munge! {
215 let Self {
216 encoded: Encoded {
217 maybe_num_bytes,
218 num_handles,
219 flags,
220 },
221 } = slot;
222 }
223
224 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
225 decoder.take_chunks(count)?;
226 }
227
228 decoder.__internal_take_handles(**num_handles as usize)?;
229
230 Ok(())
231 }
232
233 #[inline]
235 pub fn decode_as_static<D: InternalHandleDecoder + ?Sized, T: Decode<D>>(
236 mut slot: Slot<'_, Self>,
237 decoder: &mut D,
238 ) -> Result<(), DecodeError> {
239 munge! {
240 let Self {
241 encoded: Encoded {
242 maybe_num_bytes,
243 num_handles,
244 flags,
245 },
246 } = slot.as_mut();
247 }
248
249 let handles_before = decoder.__internal_handles_remaining();
250 let num_handles = **num_handles as usize;
251
252 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
253 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
254 }
255
256 if size_of::<T>() > INLINE_SIZE {
258 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
259 }
260 munge!(let Self { mut decoded_inline } = slot);
261 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
262 T::decode(slot.as_mut(), decoder)?;
263
264 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
265 if handles_consumed != num_handles {
266 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
267 expected: num_handles,
268 actual: handles_consumed,
269 });
270 }
271
272 Ok(())
273 }
274
275 #[inline]
277 pub fn decode_as<D: Decoder + ?Sized, T: Decode<D>>(
278 mut slot: Slot<'_, Self>,
279 mut decoder: &mut D,
280 ) -> Result<(), DecodeError> {
281 munge! {
282 let Self {
283 encoded: Encoded {
284 mut maybe_num_bytes,
285 num_handles,
286 flags,
287 },
288 } = slot.as_mut();
289 }
290
291 let handles_before = decoder.__internal_handles_remaining();
292 let num_handles = **num_handles as usize;
293
294 let out_of_line_chunks = Self::out_of_line_chunks(maybe_num_bytes.as_mut(), flags)?;
295 if let Some(_count) = out_of_line_chunks {
296 let mut value_slot = decoder.take_slot::<T>()?;
300 let value_ptr = value_slot.as_mut_ptr();
301 T::decode(value_slot, decoder)?;
302
303 munge!(let Self { mut decoded_out_of_line } = slot);
304 unsafe { decoded_out_of_line.as_mut_ptr().write(value_ptr.cast()) };
307 } else {
308 if size_of::<T>() > INLINE_SIZE {
310 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
311 }
312 munge!(let Self { mut decoded_inline } = slot);
313 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
314 T::decode(slot.as_mut(), decoder)?;
315 }
316
317 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
318 if handles_consumed != num_handles {
319 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
320 expected: num_handles,
321 actual: handles_consumed,
322 });
323 }
324
325 Ok(())
326 }
327
328 #[inline]
329 unsafe fn as_ptr<T>(this: *mut Self) -> *mut T {
330 if size_of::<T>() <= INLINE_SIZE {
331 let inline = unsafe { addr_of_mut!((*this).decoded_inline) };
332 inline.cast()
333 } else {
334 unsafe { (*this).decoded_out_of_line.cast() }
335 }
336 }
337
338 #[inline]
344 pub unsafe fn deref_unchecked<T>(&self) -> &T {
345 let ptr = unsafe { Self::as_ptr::<T>((self as *const Self).cast_mut()).cast_const() };
346 unsafe { &*ptr }
347 }
348
349 #[inline]
355 pub unsafe fn clone_unchecked<T: Clone>(&self) -> Self {
356 debug_assert_eq!(size_of::<T>(), INLINE_SIZE);
357
358 union ClonedToDecodedInline<T> {
359 cloned: ManuallyDrop<T>,
360 decoded_inline: [MaybeUninit<u8>; INLINE_SIZE],
361 }
362
363 let cloned = unsafe { self.deref_unchecked::<T>().clone() };
364 unsafe {
365 Self {
366 decoded_inline: ClonedToDecodedInline { cloned: ManuallyDrop::new(cloned) }
367 .decoded_inline,
368 }
369 }
370 }
371}