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, Unconstrained, Wire, WireU16, WireU32,
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 Send for WireEnvelope {}
37unsafe impl Sync for WireEnvelope {}
38
39unsafe impl Wire for WireEnvelope {
40 type Decoded<'de> = WireEnvelope;
41
42 fn zero_padding(_: &mut MaybeUninit<Self>) {}
43}
44
45impl Unconstrained for WireEnvelope {}
46
47impl WireEnvelope {
48 const IS_INLINE_BIT: u16 = 1;
49
50 #[inline]
52 pub fn encode_zero(out: &mut MaybeUninit<Self>) {
53 out.write(WireEnvelope { zero: [0; 8] });
54 }
55
56 #[inline]
58 pub fn encode_value_static<E: InternalHandleEncoder + ?Sized, T: Encode<E>>(
59 value: T,
60 encoder: &mut E,
61 out: &mut MaybeUninit<Self>,
62 constraint: <T::Encoded as Constrained>::Constraint,
63 ) -> Result<(), EncodeError> {
64 munge! {
65 let Self {
66 encoded: Encoded {
67 maybe_num_bytes,
68 num_handles,
69 flags,
70 },
71 } = out;
72 }
73
74 let handles_before = encoder.__internal_handle_count();
75
76 let encoded_size = size_of::<T::Encoded>();
77 if encoded_size <= INLINE_SIZE {
78 unsafe {
81 maybe_num_bytes
82 .as_mut_ptr()
83 .cast::<u8>()
84 .add(encoded_size)
85 .write_bytes(0, INLINE_SIZE - encoded_size);
86 }
87 } else {
88 return Err(EncodeError::ExpectedInline(encoded_size));
89 }
90
91 let value_out = unsafe { &mut *maybe_num_bytes.as_mut_ptr().cast() };
92 T::Encoded::zero_padding(value_out);
93 value.encode(encoder, value_out, constraint)?;
94
95 flags.write(WireU16(Self::IS_INLINE_BIT));
96
97 let handle_count = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
98 num_handles.write(WireU16(handle_count));
99
100 Ok(())
101 }
102
103 #[inline]
105 pub fn encode_value<E: Encoder + ?Sized, T: Encode<E>>(
106 value: T,
107 encoder: &mut E,
108 out: &mut MaybeUninit<Self>,
109 constraint: <T::Encoded as Constrained>::Constraint,
110 ) -> Result<(), EncodeError> {
111 munge! {
112 let Self {
113 encoded: Encoded {
114 maybe_num_bytes,
115 num_handles,
116 flags,
117 },
118 } = out;
119 }
120
121 let handles_before = encoder.__internal_handle_count();
122
123 let encoded_size = size_of::<T::Encoded>();
124 if encoded_size <= INLINE_SIZE {
125 unsafe {
128 maybe_num_bytes
129 .as_mut_ptr()
130 .cast::<u8>()
131 .add(encoded_size)
132 .write_bytes(0, INLINE_SIZE - encoded_size);
133 }
134 let value_out = unsafe { &mut *maybe_num_bytes.as_mut_ptr().cast() };
135 T::Encoded::zero_padding(value_out);
136 value.encode(encoder, value_out, constraint)?;
137 flags.write(WireU16(Self::IS_INLINE_BIT));
138 } else {
139 let bytes_before = encoder.bytes_written();
140
141 encoder.encode_next(value, constraint)?;
142
143 let bytes_count = (encoder.bytes_written() - bytes_before).try_into().unwrap();
144 maybe_num_bytes.write(WireU32(bytes_count));
145 flags.write(WireU16(0));
146 }
147
148 let handle_count = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
149 num_handles.write(WireU16(handle_count));
150
151 Ok(())
152 }
153
154 #[inline]
156 pub fn zero() -> Self {
157 Self { zero: [0; 8] }
158 }
159
160 #[inline]
162 pub fn is_encoded_zero(slot: Slot<'_, Self>) -> bool {
163 munge!(let Self { zero } = slot);
164 *zero == [0; 8]
165 }
166
167 #[inline]
169 pub fn is_zero(&self) -> bool {
170 unsafe { self.zero == [0; 8] }
171 }
172
173 #[inline]
174 fn out_of_line_chunks(
175 maybe_num_bytes: Slot<'_, WireU32>,
176 flags: Slot<'_, WireU16>,
177 ) -> Result<Option<usize>, DecodeError> {
178 match **flags {
179 Self::IS_INLINE_BIT => Ok(None),
180 0 => {
181 let num_bytes = **maybe_num_bytes;
182 if !(num_bytes as usize).is_multiple_of(CHUNK_SIZE) {
183 Err(DecodeError::InvalidEnvelopeSize(num_bytes))
184 } else if num_bytes <= INLINE_SIZE as u32 {
185 Err(DecodeError::OutOfLineValueTooSmall(num_bytes))
186 } else {
187 Ok(Some(num_bytes as usize / CHUNK_SIZE))
188 }
189 }
190 _ => Err(DecodeError::InvalidEnvelopeFlags(**flags)),
191 }
192 }
193
194 #[inline]
196 pub fn decode_unknown_static<D: InternalHandleDecoder + ?Sized>(
197 slot: Slot<'_, Self>,
198 decoder: &mut D,
199 ) -> Result<(), DecodeError> {
200 munge! {
201 let Self {
202 encoded: Encoded {
203 maybe_num_bytes,
204 num_handles,
205 flags,
206 },
207 } = slot;
208 }
209
210 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
211 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
212 }
213
214 decoder.__internal_take_handles(**num_handles as usize)?;
215
216 Ok(())
217 }
218
219 #[inline]
221 pub fn decode_unknown<D: Decoder + ?Sized>(
222 slot: Slot<'_, Self>,
223 mut decoder: &mut D,
224 ) -> Result<(), DecodeError> {
225 munge! {
226 let Self {
227 encoded: Encoded {
228 maybe_num_bytes,
229 num_handles,
230 flags,
231 },
232 } = slot;
233 }
234
235 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
236 decoder.take_chunks(count)?;
237 }
238
239 decoder.__internal_take_handles(**num_handles as usize)?;
240
241 Ok(())
242 }
243
244 #[inline]
246 pub fn decode_as_static<D: InternalHandleDecoder + ?Sized, T: Decode<D>>(
247 mut slot: Slot<'_, Self>,
248 decoder: &mut D,
249 constraint: <T as Constrained>::Constraint,
250 ) -> Result<(), DecodeError> {
251 munge! {
252 let Self {
253 encoded: Encoded {
254 maybe_num_bytes,
255 num_handles,
256 flags,
257 },
258 } = slot.as_mut();
259 }
260
261 let handles_before = decoder.__internal_handles_remaining();
262 let num_handles = **num_handles as usize;
263
264 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
265 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
266 }
267
268 if size_of::<T>() > INLINE_SIZE {
270 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
271 }
272 munge!(let Self { mut decoded_inline } = slot);
273 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
274 T::decode(slot.as_mut(), decoder, constraint)?;
275
276 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
277 if handles_consumed != num_handles {
278 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
279 expected: num_handles,
280 actual: handles_consumed,
281 });
282 }
283
284 Ok(())
285 }
286
287 #[inline]
289 pub fn decode_as<D: Decoder + ?Sized, T: Decode<D>>(
290 mut slot: Slot<'_, Self>,
291 mut decoder: &mut D,
292 constraint: <T as Constrained>::Constraint,
293 ) -> Result<(), DecodeError> {
294 munge! {
295 let Self {
296 encoded: Encoded {
297 mut maybe_num_bytes,
298 num_handles,
299 flags,
300 },
301 } = slot.as_mut();
302 }
303
304 let handles_before = decoder.__internal_handles_remaining();
305 let num_handles = **num_handles as usize;
306
307 let out_of_line_chunks = Self::out_of_line_chunks(maybe_num_bytes.as_mut(), flags)?;
308 if let Some(_count) = out_of_line_chunks {
309 let mut value_slot = decoder.take_slot::<T>()?;
313 let value_ptr = value_slot.as_mut_ptr();
314 T::decode(value_slot, decoder, constraint)?;
315
316 munge!(let Self { mut decoded_out_of_line } = slot);
317 unsafe { decoded_out_of_line.as_mut_ptr().write(value_ptr.cast()) };
320 } else {
321 if size_of::<T>() > INLINE_SIZE {
323 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
324 }
325 munge!(let Self { mut decoded_inline } = slot);
326 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
327 T::decode(slot.as_mut(), decoder, constraint)?;
328 }
329
330 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
331 if handles_consumed != num_handles {
332 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
333 expected: num_handles,
334 actual: handles_consumed,
335 });
336 }
337
338 Ok(())
339 }
340
341 #[inline]
342 unsafe fn as_ptr<T>(this: *mut Self) -> *mut T {
343 if size_of::<T>() <= INLINE_SIZE {
344 let inline = unsafe { addr_of_mut!((*this).decoded_inline) };
345 inline.cast()
346 } else {
347 unsafe { (*this).decoded_out_of_line.cast() }
348 }
349 }
350
351 #[inline]
357 pub unsafe fn deref_unchecked<T>(&self) -> &T {
358 let ptr = unsafe { Self::as_ptr::<T>((self as *const Self).cast_mut()).cast_const() };
359 unsafe { &*ptr }
360 }
361
362 #[inline]
368 pub unsafe fn read_unchecked<T>(&self) -> T {
369 unsafe { Self::as_ptr::<T>((self as *const Self).cast_mut()).read() }
372 }
373
374 #[inline]
380 pub unsafe fn clone_inline_unchecked<T: Clone>(&self) -> Self {
381 debug_assert!(size_of::<T>() <= INLINE_SIZE);
382
383 union ClonedToDecodedInline<T> {
384 cloned: ManuallyDrop<T>,
385 decoded_inline: [MaybeUninit<u8>; INLINE_SIZE],
386 }
387
388 let cloned = unsafe { self.deref_unchecked::<T>().clone() };
389 unsafe {
390 Self {
391 decoded_inline: ClonedToDecodedInline { cloned: ManuallyDrop::new(cloned) }
392 .decoded_inline,
393 }
394 }
395 }
396}