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, Encodable, EncodableOption, Encode, EncodeError,
16 EncodeOption, FromWire, FromWireOption, 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
195impl Encodable for DriverChannel {
196 type Encoded = WireDriverChannel;
197}
198
199unsafe impl<E: HandleEncoder + ?Sized> Encode<E> for DriverChannel {
202 fn encode(
203 self,
204 encoder: &mut E,
205 out: &mut MaybeUninit<Self::Encoded>,
206 _: <WireDriverChannel as Constrained>::Constraint,
207 ) -> Result<(), EncodeError> {
208 let handle = self.channel.into_driver_handle();
209 unsafe {
211 encoder.push_raw_driver_handle(handle.into_raw().get())?;
212 }
213 WireDriverChannel::set_encoded_present(out);
214 Ok(())
215 }
216}
217
218impl FromWire<WireDriverChannel> for DriverChannel {
219 fn from_wire(wire: WireDriverChannel) -> Self {
220 let raw_handle = unsafe { NonZero::new_unchecked(wire.as_raw_handle()) };
222 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
224 let channel = unsafe { Channel::from_driver_handle(handle) };
226 forget(wire);
227 DriverChannel::new(channel)
228 }
229}
230
231impl IntoNatural for WireDriverChannel {
232 type Natural = DriverChannel;
233}
234
235impl EncodableOption for DriverChannel {
236 type EncodedOption = WireOptionalDriverChannel;
237}
238
239unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<E> for DriverChannel {
242 fn encode_option(
243 this: Option<Self>,
244 encoder: &mut E,
245 out: &mut MaybeUninit<Self::EncodedOption>,
246 _: <Self::EncodedOption as Constrained>::Constraint,
247 ) -> Result<(), EncodeError> {
248 if let Some(driver_channel) = this {
249 let handle = driver_channel.channel.into_driver_handle();
250 unsafe {
252 encoder.push_raw_driver_handle(handle.into_raw().get())?;
253 }
254 WireOptionalDriverChannel::set_encoded_present(out);
255 } else {
256 WireOptionalDriverChannel::set_encoded_absent(out);
257 }
258 Ok(())
259 }
260}
261
262impl FromWireOption<WireOptionalDriverChannel> for DriverChannel {
263 fn from_wire_option(wire: WireOptionalDriverChannel) -> Option<Self> {
264 let raw_handle = wire.as_raw_handle();
265 forget(wire);
266 raw_handle.map(|raw| {
267 let raw_handle = unsafe { NonZero::new_unchecked(raw) };
270 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
273 let channel = unsafe { Channel::from_driver_handle(handle) };
275 DriverChannel::new(channel)
276 })
277 }
278}
279
280impl IntoNatural for WireOptionalDriverChannel {
281 type Natural = Option<DriverChannel>;
282}
283
284#[cfg(test)]
285mod tests {
286 use fdf_channel::arena::Arena;
287 use fdf_channel::message::Message;
288 use fdf_core::handle::MixedHandleType;
289 use fidl_next::{Chunk, DecoderExt as _, EncoderExt as _, chunks};
290
291 use crate::{RecvBuffer, SendBuffer};
292
293 use super::*;
294
295 #[test]
296 fn roundtrip() {
297 let (channel, _) = Channel::<[Chunk]>::create();
298 let handle_raw = unsafe { channel.driver_handle().get_raw() };
300 let driver_channel = DriverChannel::new(channel);
301
302 let mut encoder = SendBuffer::new();
303 encoder.encode_next(driver_channel, ()).unwrap();
304
305 assert_eq!(encoder.handles.len(), 1);
306 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
307 let MixedHandleType::Driver(handle) = &driver_ref else {
308 panic!("expected a driver handle");
309 };
310 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
311 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
312 drop(driver_ref);
313
314 let arena = Arena::new();
315 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
316 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
317 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
318 let decoder = RecvBuffer { buffer, data_offset: 0, handle_offset: 0 };
319
320 let decoded = decoder.decode::<WireDriverChannel>().unwrap();
321 assert_eq!(decoded.as_raw_handle(), handle_raw.get());
322
323 let handle = decoded.take();
324 let roundtripped_raw = unsafe { handle.channel.driver_handle().get_raw() };
325 assert_eq!(roundtripped_raw, handle_raw);
326 }
327
328 #[test]
329 fn roundtrip_some() {
330 let (channel, _) = Channel::<[Chunk]>::create();
331 let handle_raw = unsafe { channel.driver_handle().get_raw() };
333 let driver_channel = DriverChannel::new(channel);
334
335 let mut encoder = SendBuffer::new();
336 encoder.encode_next(Some(driver_channel), ()).unwrap();
337
338 assert_eq!(encoder.handles.len(), 1);
339 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
340 let MixedHandleType::Driver(handle) = &driver_ref else {
341 panic!("expected a driver handle");
342 };
343 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
344 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
345 drop(driver_ref);
346
347 let arena = Arena::new();
348 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
349 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
350 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
351 let decoder = RecvBuffer { buffer, data_offset: 0, handle_offset: 0 };
352
353 let decoded = decoder.decode::<WireOptionalDriverChannel>().unwrap();
354 assert_eq!(decoded.as_raw_handle(), Some(handle_raw.get()));
355
356 let handle = decoded.take();
357 let roundtripped_raw = unsafe { handle.unwrap().channel.driver_handle().get_raw() };
358 assert_eq!(roundtripped_raw, handle_raw);
359 }
360
361 #[test]
362 fn roundtrip_none() {
363 let mut encoder = SendBuffer::new();
364 encoder.encode_next(Option::<DriverChannel>::None, ()).unwrap();
365
366 assert_eq!(encoder.handles.len(), 0);
367 assert_eq!(encoder.data, chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],);
368
369 let arena = Arena::new();
370 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
371 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
372 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
373 let decoder = RecvBuffer { buffer, data_offset: 0, handle_offset: 0 };
374
375 let decoded = decoder.decode::<WireOptionalDriverChannel>().unwrap();
376 assert_eq!(decoded.as_raw_handle(), None);
377
378 let handle = decoded.take();
379 assert!(handle.is_none());
380 }
381}