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, 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
25#[repr(C, align(8))]
27pub union WireEnvelope {
28 zero: [u8; 8],
29 encoded: Encoded,
30 decoded_inline: [MaybeUninit<u8>; 4],
31 decoded_out_of_line: *mut (),
32}
33
34impl WireEnvelope {
35 const IS_INLINE_BIT: u16 = 1;
36
37 #[inline]
39 pub fn encode_zero(slot: Slot<'_, Self>) {
40 munge!(let Self { mut zero } = slot);
41 *zero = [0; 8];
42 }
43
44 #[inline]
46 pub fn encode_value_static<E: InternalHandleEncoder + ?Sized, T: Encode<E>>(
47 value: &mut T,
48 encoder: &mut E,
49 slot: Slot<'_, Self>,
50 ) -> Result<(), EncodeError> {
51 munge! {
52 let Self {
53 encoded: Encoded {
54 mut maybe_num_bytes,
55 mut num_handles,
56 mut flags,
57 },
58 } = slot;
59 }
60
61 let handles_before = encoder.__internal_handle_count();
62
63 if size_of::<T::Encoded>() > 4 {
64 return Err(EncodeError::ExpectedInline(size_of::<T::Encoded>()));
65 }
66
67 let slot = unsafe { Slot::new_unchecked(maybe_num_bytes.as_mut_ptr().cast()) };
68 value.encode(encoder, slot)?;
69
70 **flags = Self::IS_INLINE_BIT;
71
72 **num_handles = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
73
74 Ok(())
75 }
76
77 #[inline]
79 pub fn encode_value<E: Encoder + ?Sized, T: Encode<E>>(
80 value: &mut T,
81 encoder: &mut E,
82 slot: Slot<'_, Self>,
83 ) -> Result<(), EncodeError> {
84 munge! {
85 let Self {
86 encoded: Encoded {
87 mut maybe_num_bytes,
88 mut num_handles,
89 mut flags,
90 },
91 } = slot;
92 }
93
94 let handles_before = encoder.__internal_handle_count();
95
96 if size_of::<T::Encoded>() <= 4 {
97 let slot = unsafe { Slot::new_unchecked(maybe_num_bytes.as_mut_ptr().cast()) };
98 value.encode(encoder, slot)?;
99
100 **flags = Self::IS_INLINE_BIT;
101 } else {
102 let bytes_before = encoder.bytes_written();
103
104 encoder.encode_next(value)?;
105
106 **maybe_num_bytes = (encoder.bytes_written() - bytes_before).try_into().unwrap();
107 **flags = 0;
108 }
109
110 **num_handles = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
111
112 Ok(())
113 }
114
115 #[inline]
117 pub fn zero() -> Self {
118 Self { zero: [0; 8] }
119 }
120
121 #[inline]
123 pub fn is_encoded_zero(slot: Slot<'_, Self>) -> bool {
124 munge!(let Self { zero } = slot);
125 *zero == [0; 8]
126 }
127
128 #[inline]
130 pub fn is_zero(&self) -> bool {
131 unsafe { self.zero == [0; 8] }
132 }
133
134 #[inline]
135 fn out_of_line_chunks(
136 maybe_num_bytes: Slot<'_, WireU32>,
137 flags: Slot<'_, WireU16>,
138 ) -> Result<Option<usize>, DecodeError> {
139 if **flags & Self::IS_INLINE_BIT == 0 {
140 let num_bytes = **maybe_num_bytes;
141 if num_bytes as usize % CHUNK_SIZE != 0 {
142 return Err(DecodeError::InvalidEnvelopeSize(num_bytes));
143 }
144 if num_bytes <= 4 {
145 return Err(DecodeError::OutOfLineValueTooSmall(num_bytes));
146 }
147 Ok(Some(num_bytes as usize / CHUNK_SIZE))
148 } else {
149 Ok(None)
150 }
151 }
152
153 #[inline]
155 pub fn decode_unknown_static<D: InternalHandleDecoder + ?Sized>(
156 slot: Slot<'_, Self>,
157 decoder: &mut D,
158 ) -> Result<(), DecodeError> {
159 munge! {
160 let Self {
161 encoded: Encoded {
162 maybe_num_bytes,
163 num_handles,
164 flags,
165 },
166 } = slot;
167 }
168
169 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
170 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
171 }
172
173 decoder.__internal_take_handles(**num_handles as usize)?;
174
175 Ok(())
176 }
177
178 #[inline]
180 pub fn decode_unknown<D: Decoder + ?Sized>(
181 slot: Slot<'_, Self>,
182 mut decoder: &mut D,
183 ) -> Result<(), DecodeError> {
184 munge! {
185 let Self {
186 encoded: Encoded {
187 maybe_num_bytes,
188 num_handles,
189 flags,
190 },
191 } = slot;
192 }
193
194 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
195 decoder.take_chunks(count)?;
196 }
197
198 decoder.__internal_take_handles(**num_handles as usize)?;
199
200 Ok(())
201 }
202
203 #[inline]
205 pub fn decode_as_static<D: InternalHandleDecoder + ?Sized, T: Decode<D>>(
206 mut slot: Slot<'_, Self>,
207 decoder: &mut D,
208 ) -> Result<(), DecodeError> {
209 munge! {
210 let Self {
211 encoded: Encoded {
212 maybe_num_bytes,
213 num_handles,
214 flags,
215 },
216 } = slot.as_mut();
217 }
218
219 let handles_before = decoder.__internal_handles_remaining();
220 let num_handles = **num_handles as usize;
221
222 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
223 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
224 }
225
226 if size_of::<T>() > 4 {
228 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
229 }
230 munge!(let Self { mut decoded_inline } = slot);
231 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
232 T::decode(slot.as_mut(), decoder)?;
233
234 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
235 if handles_consumed != num_handles {
236 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
237 expected: num_handles,
238 actual: handles_consumed,
239 });
240 }
241
242 Ok(())
243 }
244
245 #[inline]
247 pub fn decode_as<D: Decoder + ?Sized, T: Decode<D>>(
248 mut slot: Slot<'_, Self>,
249 mut decoder: &mut D,
250 ) -> Result<(), DecodeError> {
251 munge! {
252 let Self {
253 encoded: Encoded {
254 mut 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 let out_of_line_chunks = Self::out_of_line_chunks(maybe_num_bytes.as_mut(), flags)?;
265 if let Some(_count) = out_of_line_chunks {
266 let mut value_slot = decoder.take_slot::<T>()?;
270 let value_ptr = value_slot.as_mut_ptr();
271 T::decode(value_slot, decoder)?;
272
273 munge!(let Self { mut decoded_out_of_line } = slot);
274 unsafe { decoded_out_of_line.as_mut_ptr().write(value_ptr.cast()) };
277 } else {
278 if size_of::<T>() > 4 {
280 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
281 }
282 munge!(let Self { mut decoded_inline } = slot);
283 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
284 T::decode(slot.as_mut(), decoder)?;
285 }
286
287 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
288 if handles_consumed != num_handles {
289 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
290 expected: num_handles,
291 actual: handles_consumed,
292 });
293 }
294
295 Ok(())
296 }
297
298 #[inline]
299 unsafe fn as_ptr<T>(this: *mut Self) -> *mut T {
300 if size_of::<T>() <= 4 {
301 let inline = unsafe { addr_of_mut!((*this).decoded_inline) };
302 inline.cast()
303 } else {
304 unsafe { (*this).decoded_out_of_line.cast() }
305 }
306 }
307
308 #[inline]
314 pub unsafe fn deref_unchecked<T>(&self) -> &T {
315 let ptr = unsafe { Self::as_ptr::<T>((self as *const Self).cast_mut()).cast_const() };
316 unsafe { &*ptr }
317 }
318
319 #[inline]
325 pub unsafe fn clone_unchecked<T: Clone>(&self) -> Self {
326 debug_assert_eq!(size_of::<T>(), 4);
327
328 union ClonedToDecodedInline<T> {
329 cloned: ManuallyDrop<T>,
330 decoded_inline: [MaybeUninit<u8>; 4],
331 }
332
333 let cloned = unsafe { self.deref_unchecked::<T>().clone() };
334 unsafe {
335 Self {
336 decoded_inline: ClonedToDecodedInline { cloned: ManuallyDrop::new(cloned) }
337 .decoded_inline,
338 }
339 }
340 }
341}