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 CHUNK_SIZE, Constrained, Decode, DecodeError, Decoder, DecoderExt as _, Encode, EncodeError,
14 Encoder, EncoderExt as _, Slot, ValidationError, Wire, wire,
15};
16
17#[derive(Clone, Copy)]
18#[repr(C)]
19struct Encoded {
20 maybe_num_bytes: wire::Uint32,
21 num_handles: wire::Uint16,
22 flags: wire::Uint16,
23}
24
25const INLINE_SIZE: usize = 4;
26
27#[repr(C, align(8))]
29pub union Envelope {
30 zero: [u8; 8],
31 encoded: Encoded,
32 decoded_inline: [MaybeUninit<u8>; INLINE_SIZE],
33 decoded_out_of_line: *mut (),
34}
35
36unsafe impl Send for Envelope {}
39unsafe impl Sync for Envelope {}
41
42impl Constrained for Envelope {
43 type Constraint = ();
44
45 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
46 Ok(())
47 }
48}
49
50unsafe impl Wire for Envelope {
52 type Narrowed<'de> = Self;
53
54 fn zero_padding(_: &mut MaybeUninit<Self>) {}
55}
56
57impl Envelope {
58 const IS_INLINE_BIT: u16 = 1;
59
60 #[inline]
62 pub fn encode_zero(out: &mut MaybeUninit<Self>) {
63 out.write(Envelope { zero: [0; 8] });
64 }
65
66 #[inline]
68 pub fn encode_value_static<W: Wire, E: InternalHandleEncoder + ?Sized>(
69 value: impl Encode<W, E>,
70 encoder: &mut E,
71 out: &mut MaybeUninit<Self>,
72 constraint: W::Constraint,
73 ) -> Result<(), EncodeError> {
74 #[allow(unused_unsafe)]
76 let encoded = unsafe {
79 munge!(let Self { encoded } = out);
80 encoded
81 };
82 munge! {
83 let Encoded {
84 maybe_num_bytes,
85 num_handles,
86 flags,
87 } = encoded;
88 }
89
90 let handles_before = encoder.__internal_handle_count();
91
92 let encoded_size = size_of::<W>();
93 if encoded_size <= INLINE_SIZE {
94 unsafe {
99 maybe_num_bytes
100 .as_mut_ptr()
101 .cast::<u8>()
102 .add(encoded_size)
103 .write_bytes(0, INLINE_SIZE - encoded_size);
104 }
105 } else {
106 return Err(EncodeError::ExpectedInline(encoded_size));
107 }
108
109 let value_out = unsafe { &mut *maybe_num_bytes.as_mut_ptr().cast() };
114 W::zero_padding(value_out);
115 value.encode(encoder, value_out, constraint)?;
116
117 flags.write(wire::Uint16(Self::IS_INLINE_BIT));
118
119 let handle_count = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
120 num_handles.write(wire::Uint16(handle_count));
121
122 Ok(())
123 }
124
125 #[inline]
127 pub fn encode_value<W: Wire, E: Encoder + ?Sized>(
128 value: impl Encode<W, E>,
129 encoder: &mut E,
130 out: &mut MaybeUninit<Self>,
131 constraint: W::Constraint,
132 ) -> Result<(), EncodeError> {
133 #[allow(unused_unsafe)]
135 let encoded = unsafe {
138 munge!(let Self { encoded } = out);
139 encoded
140 };
141 munge! {
142 let Encoded {
143 maybe_num_bytes,
144 num_handles,
145 flags,
146 } = encoded;
147 }
148
149 let handles_before = encoder.__internal_handle_count();
150
151 let encoded_size = size_of::<W>();
152 if encoded_size <= INLINE_SIZE {
153 unsafe {
158 maybe_num_bytes
159 .as_mut_ptr()
160 .cast::<u8>()
161 .add(encoded_size)
162 .write_bytes(0, INLINE_SIZE - encoded_size);
163 }
164 let value_out = unsafe { &mut *maybe_num_bytes.as_mut_ptr().cast() };
169 W::zero_padding(value_out);
170 value.encode(encoder, value_out, constraint)?;
171 flags.write(wire::Uint16(Self::IS_INLINE_BIT));
172 } else {
173 let bytes_before = encoder.bytes_written();
174
175 encoder.encode_next_with_constraint(value, constraint)?;
176
177 let bytes_count = (encoder.bytes_written() - bytes_before).try_into().unwrap();
178 maybe_num_bytes.write(wire::Uint32(bytes_count));
179 flags.write(wire::Uint16(0));
180 }
181
182 let handle_count = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
183 num_handles.write(wire::Uint16(handle_count));
184
185 Ok(())
186 }
187
188 #[inline]
190 pub fn zero() -> Self {
191 Self { zero: [0; 8] }
192 }
193
194 #[inline]
196 pub fn is_encoded_zero(slot: Slot<'_, Self>) -> bool {
197 #[allow(unused_unsafe)]
199 let zero = unsafe {
201 munge!(let Self { zero } = slot);
202 zero
203 };
204 *zero == [0; 8]
205 }
206
207 #[inline]
209 pub fn is_zero(&self) -> bool {
210 unsafe { self.zero == [0; 8] }
213 }
214
215 #[inline]
216 fn out_of_line_chunks(
217 maybe_num_bytes: Slot<'_, wire::Uint32>,
218 flags: Slot<'_, wire::Uint16>,
219 ) -> Result<Option<usize>, DecodeError> {
220 match **flags {
221 Self::IS_INLINE_BIT => Ok(None),
222 0 => {
223 let num_bytes = **maybe_num_bytes;
224 if !(num_bytes as usize).is_multiple_of(CHUNK_SIZE) {
225 Err(DecodeError::InvalidEnvelopeSize(num_bytes))
226 } else if num_bytes <= INLINE_SIZE as u32 {
227 Err(DecodeError::OutOfLineValueTooSmall(num_bytes))
228 } else {
229 Ok(Some(num_bytes as usize / CHUNK_SIZE))
230 }
231 }
232 _ => Err(DecodeError::InvalidEnvelopeFlags(**flags)),
233 }
234 }
235
236 #[inline]
238 pub fn decode_unknown_static<D: InternalHandleDecoder + ?Sized>(
239 slot: Slot<'_, Self>,
240 decoder: &mut D,
241 ) -> Result<(), DecodeError> {
242 #[allow(unused_unsafe)]
244 let encoded = unsafe {
246 munge!(let Self { encoded } = slot);
247 encoded
248 };
249 munge! {
250 let Encoded {
251 maybe_num_bytes,
252 num_handles,
253 flags,
254 } = encoded;
255 }
256
257 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
258 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
259 }
260
261 decoder.__internal_take_handles(**num_handles as usize)?;
262
263 Ok(())
264 }
265
266 #[inline]
268 pub fn decode_unknown<'de, D: Decoder<'de> + ?Sized>(
269 slot: Slot<'_, Self>,
270 decoder: &mut D,
271 ) -> Result<(), DecodeError> {
272 #[allow(unused_unsafe)]
274 let encoded = unsafe {
276 munge!(let Self { encoded } = slot);
277 encoded
278 };
279 munge! {
280 let Encoded {
281 maybe_num_bytes,
282 num_handles,
283 flags,
284 } = encoded;
285 }
286
287 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
288 decoder.take_chunks(count)?;
289 }
290
291 decoder.__internal_take_handles(**num_handles as usize)?;
292
293 Ok(())
294 }
295
296 #[inline]
298 pub fn decode_as_static<D: InternalHandleDecoder + ?Sized, T: Decode<D>>(
299 mut slot: Slot<'_, Self>,
300 decoder: &mut D,
301 constraint: T::Constraint,
302 ) -> Result<(), DecodeError> {
303 #[allow(unused_unsafe)]
305 let encoded = unsafe {
307 munge!(let Self { encoded } = slot.as_mut());
308 encoded
309 };
310 munge! {
311 let Encoded {
312 maybe_num_bytes,
313 num_handles,
314 flags,
315 } = encoded;
316 }
317
318 let handles_before = decoder.__internal_handles_remaining();
319 let num_handles = **num_handles as usize;
320
321 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
322 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
323 }
324
325 if size_of::<T>() > INLINE_SIZE {
327 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
328 }
329 #[allow(unused_unsafe)]
331 let mut decoded_inline = unsafe {
333 munge!(let Self { decoded_inline } = slot);
334 decoded_inline
335 };
336 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
340 T::decode(slot.as_mut(), decoder, constraint)?;
341
342 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
343 if handles_consumed != num_handles {
344 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
345 expected: num_handles,
346 actual: handles_consumed,
347 });
348 }
349
350 Ok(())
351 }
352
353 #[inline]
355 pub fn decode_as<'de, D: Decoder<'de> + ?Sized, T: Decode<D>>(
356 mut slot: Slot<'_, Self>,
357 decoder: &mut D,
358 constraint: T::Constraint,
359 ) -> Result<(), DecodeError> {
360 #[allow(unused_unsafe)]
362 let encoded = unsafe {
364 munge!(let Self { encoded } = slot.as_mut());
365 encoded
366 };
367 munge! {
368 let Encoded {
369 mut maybe_num_bytes,
370 num_handles,
371 flags,
372 } = encoded;
373 }
374
375 let handles_before = decoder.__internal_handles_remaining();
376 let num_handles = **num_handles as usize;
377
378 let out_of_line_chunks = Self::out_of_line_chunks(maybe_num_bytes.as_mut(), flags)?;
379 if let Some(_count) = out_of_line_chunks {
380 let mut value_slot = decoder.take_slot::<T>()?;
384 let value_ptr = value_slot.as_mut_ptr();
385 T::decode(value_slot, decoder, constraint)?;
386
387 #[allow(unused_unsafe)]
389 let mut decoded_out_of_line = unsafe {
391 munge!(let Self { decoded_out_of_line } = slot);
392 decoded_out_of_line
393 };
394 unsafe { decoded_out_of_line.as_mut_ptr().write(value_ptr.cast()) };
397 } else {
398 if size_of::<T>() > INLINE_SIZE {
400 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
401 }
402 #[allow(unused_unsafe)]
404 let mut decoded_inline = unsafe {
406 munge!(let Self { decoded_inline } = slot);
407 decoded_inline
408 };
409 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
413 T::decode(slot.as_mut(), decoder, constraint)?;
414 }
415
416 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
417 if handles_consumed != num_handles {
418 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
419 expected: num_handles,
420 actual: handles_consumed,
421 });
422 }
423
424 Ok(())
425 }
426
427 #[inline]
433 pub unsafe fn as_ptr<T>(this: *mut Self) -> *mut T {
434 if size_of::<T>() <= INLINE_SIZE {
435 let inline = unsafe { addr_of_mut!((*this).decoded_inline) };
437 inline.cast()
438 } else {
439 unsafe { (*this).decoded_out_of_line.cast() }
442 }
443 }
444
445 #[inline]
451 pub unsafe fn deref_unchecked<T>(&self) -> &T {
452 let ptr = unsafe { Self::as_ptr::<T>((self as *const Self).cast_mut()).cast_const() };
456 unsafe { &*ptr }
458 }
459
460 #[inline]
469 pub unsafe fn read_unchecked<T>(&self) -> T {
470 unsafe { Self::as_ptr::<T>((self as *const Self).cast_mut()).read() }
473 }
474
475 #[inline]
481 pub unsafe fn take_unchecked<T>(&mut self) -> T {
482 let result = unsafe { self.read_unchecked() };
486 *self = Self::zero();
487 result
488 }
489
490 #[inline]
496 pub unsafe fn clone_inline_unchecked<T: Clone>(&self) -> Self {
497 debug_assert!(size_of::<T>() <= INLINE_SIZE);
498
499 union ClonedToDecodedInline<T> {
500 cloned: ManuallyDrop<T>,
501 decoded_inline: [MaybeUninit<u8>; INLINE_SIZE],
502 }
503
504 let cloned = unsafe { self.deref_unchecked::<T>().clone() };
506 unsafe {
509 Self {
510 decoded_inline: ClonedToDecodedInline { cloned: ManuallyDrop::new(cloned) }
511 .decoded_inline,
512 }
513 }
514 }
515}