1use core::fmt;
8use core::mem::{MaybeUninit, forget};
9use core::num::NonZero;
10
11use fdf_channel::channel::Channel;
12use fdf_core::handle::{DriverHandle, fdf_handle_t};
13use fidl_next::fuchsia::{HandleDecoder, HandleEncoder};
14use fidl_next::{
15 Constrained, Decode, DecodeError, Encode, EncodeError, EncodeOption, FromWire, FromWireOption,
16 IntoNatural, Slot, Unconstrained, Wire, WireU32, munge,
17};
18
19use crate::DriverChannel;
20
21#[repr(C, align(4))]
27pub union WireDriverChannel {
28 encoded: WireU32,
29 decoded: fdf_handle_t,
30}
31
32impl Drop for WireDriverChannel {
33 fn drop(&mut self) {
34 let raw_handle = unsafe { NonZero::new_unchecked(self.as_raw_handle()) };
36 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
38 drop(handle);
39 }
40}
41
42unsafe impl Wire for WireDriverChannel {
46 type Decoded<'de> = Self;
47
48 #[inline]
49 fn zero_padding(_: &mut MaybeUninit<Self>) {
50 }
52}
53
54impl WireDriverChannel {
55 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
57 munge!(let Self { encoded } = out);
58 encoded.write(WireU32(u32::MAX));
59 }
60
61 #[inline]
63 pub fn as_raw_handle(&self) -> fdf_handle_t {
64 unsafe { self.decoded }
67 }
68}
69
70impl fmt::Debug for WireDriverChannel {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 self.as_raw_handle().fmt(f)
73 }
74}
75
76unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireDriverChannel {
79 fn decode(
80 mut slot: Slot<'_, Self>,
81 decoder: &mut D,
82 _: <Self as Constrained>::Constraint,
83 ) -> Result<(), DecodeError> {
84 munge!(let Self { encoded } = slot.as_mut());
85
86 match **encoded {
87 u32::MAX => {
88 let handle = decoder.take_raw_driver_handle()?;
89 munge!(let Self { mut decoded } = slot);
90 decoded.write(handle);
91 }
92 e => return Err(DecodeError::InvalidHandlePresence(e)),
93 }
94 Ok(())
95 }
96}
97
98impl Unconstrained for WireDriverChannel {}
99
100#[repr(C, align(4))]
106pub union WireOptionalDriverChannel {
107 encoded: WireU32,
108 decoded: fdf_handle_t,
109}
110
111impl Drop for WireOptionalDriverChannel {
112 fn drop(&mut self) {
113 if let Some(handle) = self.as_raw_handle() {
114 let handle = unsafe { NonZero::new_unchecked(handle) };
117 let handle = unsafe { DriverHandle::new_unchecked(handle) };
119 drop(handle);
120 }
121 }
122}
123
124unsafe impl Wire for WireOptionalDriverChannel {
128 type Decoded<'de> = Self;
129
130 #[inline]
131 fn zero_padding(_: &mut MaybeUninit<Self>) {
132 }
134}
135
136impl WireOptionalDriverChannel {
137 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
139 munge!(let Self { encoded } = out);
140 encoded.write(WireU32(u32::MAX));
141 }
142
143 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
145 munge!(let Self { encoded } = out);
146 encoded.write(WireU32(0));
147 }
148
149 pub fn is_some(&self) -> bool {
151 self.as_raw_handle().is_some()
152 }
153
154 pub fn is_none(&self) -> bool {
156 self.as_raw_handle().is_none()
157 }
158
159 #[inline]
161 pub fn as_raw_handle(&self) -> Option<fdf_handle_t> {
162 let decoded = unsafe { self.decoded };
165 if decoded == 0 { None } else { Some(decoded) }
166 }
167}
168
169unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalDriverChannel {
173 fn decode(
174 mut slot: Slot<'_, Self>,
175 decoder: &mut D,
176 _: <Self as Constrained>::Constraint,
177 ) -> Result<(), DecodeError> {
178 munge!(let Self { encoded } = slot.as_mut());
179
180 match **encoded {
181 0 => (),
182 u32::MAX => {
183 let handle = decoder.take_raw_driver_handle()?;
184 munge!(let Self { mut decoded } = slot);
185 decoded.write(handle);
186 }
187 e => return Err(DecodeError::InvalidHandlePresence(e)),
188 }
189 Ok(())
190 }
191}
192
193impl Unconstrained for WireOptionalDriverChannel {}
194
195unsafe impl<E: HandleEncoder + ?Sized> Encode<WireDriverChannel, E> for DriverChannel {
198 fn encode(
199 self,
200 encoder: &mut E,
201 out: &mut MaybeUninit<WireDriverChannel>,
202 _: (),
203 ) -> Result<(), EncodeError> {
204 let handle = self.channel.into_driver_handle();
205 unsafe {
207 encoder.push_raw_driver_handle(handle.into_raw().get())?;
208 }
209 WireDriverChannel::set_encoded_present(out);
210 Ok(())
211 }
212}
213
214impl FromWire<WireDriverChannel> for DriverChannel {
215 fn from_wire(wire: WireDriverChannel) -> Self {
216 let raw_handle = unsafe { NonZero::new_unchecked(wire.as_raw_handle()) };
218 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
220 let channel = unsafe { Channel::from_driver_handle(handle) };
222 forget(wire);
223 DriverChannel::new(channel)
224 }
225}
226
227impl IntoNatural for WireDriverChannel {
228 type Natural = DriverChannel;
229}
230
231unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<WireOptionalDriverChannel, E>
234 for DriverChannel
235{
236 fn encode_option(
237 this: Option<Self>,
238 encoder: &mut E,
239 out: &mut MaybeUninit<WireOptionalDriverChannel>,
240 _: (),
241 ) -> Result<(), EncodeError> {
242 if let Some(driver_channel) = this {
243 let handle = driver_channel.channel.into_driver_handle();
244 unsafe {
246 encoder.push_raw_driver_handle(handle.into_raw().get())?;
247 }
248 WireOptionalDriverChannel::set_encoded_present(out);
249 } else {
250 WireOptionalDriverChannel::set_encoded_absent(out);
251 }
252 Ok(())
253 }
254}
255
256impl FromWireOption<WireOptionalDriverChannel> for DriverChannel {
257 fn from_wire_option(wire: WireOptionalDriverChannel) -> Option<Self> {
258 let raw_handle = wire.as_raw_handle();
259 forget(wire);
260 raw_handle.map(|raw| {
261 let raw_handle = unsafe { NonZero::new_unchecked(raw) };
264 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
267 let channel = unsafe { Channel::from_driver_handle(handle) };
269 DriverChannel::new(channel)
270 })
271 }
272}
273
274impl IntoNatural for WireOptionalDriverChannel {
275 type Natural = Option<DriverChannel>;
276}
277
278#[cfg(test)]
279mod tests {
280 use fdf_channel::arena::Arena;
281 use fdf_channel::message::Message;
282 use fdf_core::handle::MixedHandleType;
283 use fidl_next::{Chunk, DecoderExt as _, EncoderExt as _, chunks};
284
285 use crate::{RecvBuffer, SendBuffer};
286
287 use super::*;
288
289 #[test]
290 fn roundtrip() {
291 let (channel, _) = Channel::<[Chunk]>::create();
292 let handle_raw = unsafe { channel.driver_handle().get_raw() };
294 let driver_channel = DriverChannel::new(channel);
295
296 let mut encoder = SendBuffer::new();
297 encoder.encode_next(driver_channel, ()).unwrap();
298
299 assert_eq!(encoder.handles.len(), 1);
300 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
301 let MixedHandleType::Driver(handle) = &driver_ref else {
302 panic!("expected a driver handle");
303 };
304 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
305 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
306 drop(driver_ref);
307
308 let arena = Arena::new();
309 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
310 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
311 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
312 let decoder = RecvBuffer { buffer, data_offset: 0, handle_offset: 0 };
313
314 let decoded = decoder.decode::<WireDriverChannel>().unwrap();
315 assert_eq!(decoded.as_raw_handle(), handle_raw.get());
316
317 let handle = decoded.take();
318 let roundtripped_raw = unsafe { handle.channel.driver_handle().get_raw() };
319 assert_eq!(roundtripped_raw, handle_raw);
320 }
321
322 #[test]
323 fn roundtrip_some() {
324 let (channel, _) = Channel::<[Chunk]>::create();
325 let handle_raw = unsafe { channel.driver_handle().get_raw() };
327 let driver_channel = DriverChannel::new(channel);
328
329 let mut encoder = SendBuffer::new();
330 encoder.encode_next(Some(driver_channel), ()).unwrap();
331
332 assert_eq!(encoder.handles.len(), 1);
333 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
334 let MixedHandleType::Driver(handle) = &driver_ref else {
335 panic!("expected a driver handle");
336 };
337 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
338 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
339 drop(driver_ref);
340
341 let arena = Arena::new();
342 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
343 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
344 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
345 let decoder = RecvBuffer { buffer, data_offset: 0, handle_offset: 0 };
346
347 let decoded = decoder.decode::<WireOptionalDriverChannel>().unwrap();
348 assert_eq!(decoded.as_raw_handle(), Some(handle_raw.get()));
349
350 let handle = decoded.take();
351 let roundtripped_raw = unsafe { handle.unwrap().channel.driver_handle().get_raw() };
352 assert_eq!(roundtripped_raw, handle_raw);
353 }
354
355 #[test]
356 fn roundtrip_none() {
357 let mut encoder = SendBuffer::new();
358 encoder.encode_next(Option::<DriverChannel>::None, ()).unwrap();
359
360 assert_eq!(encoder.handles.len(), 0);
361 assert_eq!(encoder.data, chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],);
362
363 let arena = Arena::new();
364 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
365 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
366 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
367 let decoder = RecvBuffer { buffer, data_offset: 0, handle_offset: 0 };
368
369 let decoded = decoder.decode::<WireOptionalDriverChannel>().unwrap();
370 assert_eq!(decoded.as_raw_handle(), None);
371
372 let handle = decoded.take();
373 assert!(handle.is_none());
374 }
375}