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
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
34unsafe impl ZeroPadding for WireEnvelope {
35 fn zero_padding(_: &mut MaybeUninit<Self>) {}
36}
37
38impl WireEnvelope {
39 const IS_INLINE_BIT: u16 = 1;
40
41 #[inline]
43 pub fn encode_zero(out: &mut MaybeUninit<Self>) {
44 out.write(WireEnvelope { zero: [0; 8] });
45 }
46
47 #[inline]
49 pub fn encode_value_static<E: InternalHandleEncoder + ?Sized, T: Encode<E>>(
50 value: &mut T,
51 encoder: &mut E,
52 out: &mut MaybeUninit<Self>,
53 ) -> Result<(), EncodeError> {
54 munge! {
55 let Self {
56 encoded: Encoded {
57 maybe_num_bytes,
58 num_handles,
59 flags,
60 },
61 } = out;
62 }
63
64 let handles_before = encoder.__internal_handle_count();
65
66 if size_of::<T::Encoded>() > 4 {
67 return Err(EncodeError::ExpectedInline(size_of::<T::Encoded>()));
68 }
69
70 let value_out = unsafe { &mut *maybe_num_bytes.as_mut_ptr().cast() };
71 value.encode(encoder, value_out)?;
72
73 flags.write(WireU16(Self::IS_INLINE_BIT));
74
75 let handle_count = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
76 num_handles.write(WireU16(handle_count));
77
78 Ok(())
79 }
80
81 #[inline]
83 pub fn encode_value<E: Encoder + ?Sized, T: Encode<E>>(
84 value: &mut T,
85 encoder: &mut E,
86 out: &mut MaybeUninit<Self>,
87 ) -> Result<(), EncodeError> {
88 munge! {
89 let Self {
90 encoded: Encoded {
91 maybe_num_bytes,
92 num_handles,
93 flags,
94 },
95 } = out;
96 }
97
98 let handles_before = encoder.__internal_handle_count();
99
100 if size_of::<T::Encoded>() <= 4 {
101 let value_out = unsafe { &mut *maybe_num_bytes.as_mut_ptr().cast() };
102 value.encode(encoder, value_out)?;
103 flags.write(WireU16(Self::IS_INLINE_BIT));
104 } else {
105 let bytes_before = encoder.bytes_written();
106
107 encoder.encode_next(value)?;
108
109 let bytes_count = (encoder.bytes_written() - bytes_before).try_into().unwrap();
110 maybe_num_bytes.write(WireU32(bytes_count));
111 flags.write(WireU16(0));
112 }
113
114 let handle_count = (encoder.__internal_handle_count() - handles_before).try_into().unwrap();
115 num_handles.write(WireU16(handle_count));
116
117 Ok(())
118 }
119
120 #[inline]
122 pub fn zero() -> Self {
123 Self { zero: [0; 8] }
124 }
125
126 #[inline]
128 pub fn is_encoded_zero(slot: Slot<'_, Self>) -> bool {
129 munge!(let Self { zero } = slot);
130 *zero == [0; 8]
131 }
132
133 #[inline]
135 pub fn is_zero(&self) -> bool {
136 unsafe { self.zero == [0; 8] }
137 }
138
139 #[inline]
140 fn out_of_line_chunks(
141 maybe_num_bytes: Slot<'_, WireU32>,
142 flags: Slot<'_, WireU16>,
143 ) -> Result<Option<usize>, DecodeError> {
144 if **flags & Self::IS_INLINE_BIT == 0 {
145 let num_bytes = **maybe_num_bytes;
146 if num_bytes as usize % CHUNK_SIZE != 0 {
147 return Err(DecodeError::InvalidEnvelopeSize(num_bytes));
148 }
149 if num_bytes <= 4 {
150 return Err(DecodeError::OutOfLineValueTooSmall(num_bytes));
151 }
152 Ok(Some(num_bytes as usize / CHUNK_SIZE))
153 } else {
154 Ok(None)
155 }
156 }
157
158 #[inline]
160 pub fn decode_unknown_static<D: InternalHandleDecoder + ?Sized>(
161 slot: Slot<'_, Self>,
162 decoder: &mut D,
163 ) -> Result<(), DecodeError> {
164 munge! {
165 let Self {
166 encoded: Encoded {
167 maybe_num_bytes,
168 num_handles,
169 flags,
170 },
171 } = slot;
172 }
173
174 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
175 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
176 }
177
178 decoder.__internal_take_handles(**num_handles as usize)?;
179
180 Ok(())
181 }
182
183 #[inline]
185 pub fn decode_unknown<D: Decoder + ?Sized>(
186 slot: Slot<'_, Self>,
187 mut 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 decoder.take_chunks(count)?;
201 }
202
203 decoder.__internal_take_handles(**num_handles as usize)?;
204
205 Ok(())
206 }
207
208 #[inline]
210 pub fn decode_as_static<D: InternalHandleDecoder + ?Sized, T: Decode<D>>(
211 mut slot: Slot<'_, Self>,
212 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.as_mut();
222 }
223
224 let handles_before = decoder.__internal_handles_remaining();
225 let num_handles = **num_handles as usize;
226
227 if let Some(count) = Self::out_of_line_chunks(maybe_num_bytes, flags)? {
228 return Err(DecodeError::ExpectedInline(count * CHUNK_SIZE));
229 }
230
231 if size_of::<T>() > 4 {
233 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
234 }
235 munge!(let Self { mut decoded_inline } = slot);
236 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
237 T::decode(slot.as_mut(), decoder)?;
238
239 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
240 if handles_consumed != num_handles {
241 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
242 expected: num_handles,
243 actual: handles_consumed,
244 });
245 }
246
247 Ok(())
248 }
249
250 #[inline]
252 pub fn decode_as<D: Decoder + ?Sized, T: Decode<D>>(
253 mut slot: Slot<'_, Self>,
254 mut decoder: &mut D,
255 ) -> Result<(), DecodeError> {
256 munge! {
257 let Self {
258 encoded: Encoded {
259 mut maybe_num_bytes,
260 num_handles,
261 flags,
262 },
263 } = slot.as_mut();
264 }
265
266 let handles_before = decoder.__internal_handles_remaining();
267 let num_handles = **num_handles as usize;
268
269 let out_of_line_chunks = Self::out_of_line_chunks(maybe_num_bytes.as_mut(), flags)?;
270 if let Some(_count) = out_of_line_chunks {
271 let mut value_slot = decoder.take_slot::<T>()?;
275 let value_ptr = value_slot.as_mut_ptr();
276 T::decode(value_slot, decoder)?;
277
278 munge!(let Self { mut decoded_out_of_line } = slot);
279 unsafe { decoded_out_of_line.as_mut_ptr().write(value_ptr.cast()) };
282 } else {
283 if size_of::<T>() > 4 {
285 return Err(DecodeError::InlineValueTooBig(size_of::<T>()));
286 }
287 munge!(let Self { mut decoded_inline } = slot);
288 let mut slot = unsafe { Slot::<T>::new_unchecked(decoded_inline.as_mut_ptr().cast()) };
289 T::decode(slot.as_mut(), decoder)?;
290 }
291
292 let handles_consumed = handles_before - decoder.__internal_handles_remaining();
293 if handles_consumed != num_handles {
294 return Err(DecodeError::IncorrectNumberOfHandlesConsumed {
295 expected: num_handles,
296 actual: handles_consumed,
297 });
298 }
299
300 Ok(())
301 }
302
303 #[inline]
304 unsafe fn as_ptr<T>(this: *mut Self) -> *mut T {
305 if size_of::<T>() <= 4 {
306 let inline = unsafe { addr_of_mut!((*this).decoded_inline) };
307 inline.cast()
308 } else {
309 unsafe { (*this).decoded_out_of_line.cast() }
310 }
311 }
312
313 #[inline]
319 pub unsafe fn deref_unchecked<T>(&self) -> &T {
320 let ptr = unsafe { Self::as_ptr::<T>((self as *const Self).cast_mut()).cast_const() };
321 unsafe { &*ptr }
322 }
323
324 #[inline]
330 pub unsafe fn clone_unchecked<T: Clone>(&self) -> Self {
331 debug_assert_eq!(size_of::<T>(), 4);
332
333 union ClonedToDecodedInline<T> {
334 cloned: ManuallyDrop<T>,
335 decoded_inline: [MaybeUninit<u8>; 4],
336 }
337
338 let cloned = unsafe { self.deref_unchecked::<T>().clone() };
339 unsafe {
340 Self {
341 decoded_inline: ClonedToDecodedInline { cloned: ManuallyDrop::new(cloned) }
342 .decoded_inline,
343 }
344 }
345 }
346}