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, ValidationError, Wire, munge, wire,
17};
18
19#[repr(C, align(4))]
25pub union DriverChannel {
26 encoded: wire::Uint32,
27 decoded: fdf_handle_t,
28}
29
30impl Drop for DriverChannel {
31 fn drop(&mut self) {
32 let raw_handle = unsafe { NonZero::new_unchecked(self.as_raw_handle()) };
34 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
36 drop(handle);
37 }
38}
39
40impl Constrained for DriverChannel {
41 type Constraint = ();
42
43 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
44 Ok(())
45 }
46}
47
48unsafe impl Wire for DriverChannel {
52 type Narrowed<'de> = Self;
53
54 #[inline]
55 fn zero_padding(_: &mut MaybeUninit<Self>) {
56 }
58}
59
60impl DriverChannel {
61 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
63 let encoded = unsafe {
67 munge!(let Self { encoded } = out);
68 encoded
69 };
70 encoded.write(wire::Uint32(u32::MAX));
71 }
72
73 #[inline]
75 pub fn as_raw_handle(&self) -> fdf_handle_t {
76 unsafe { self.decoded }
79 }
80}
81
82impl fmt::Debug for DriverChannel {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 self.as_raw_handle().fmt(f)
85 }
86}
87
88unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for DriverChannel {
91 fn decode(
92 mut slot: Slot<'_, Self>,
93 decoder: &mut D,
94 _: <Self as Constrained>::Constraint,
95 ) -> Result<(), DecodeError> {
96 let encoded = unsafe {
99 munge!(let Self { encoded } = slot.as_mut());
100 encoded
101 };
102
103 match **encoded {
104 u32::MAX => {
105 let handle = decoder.take_raw_driver_handle()?;
106 let mut decoded = unsafe {
109 munge!(let Self { decoded } = slot);
110 decoded
111 };
112 decoded.write(handle);
113 }
114 e => return Err(DecodeError::InvalidHandlePresence(e)),
115 }
116 Ok(())
117 }
118}
119
120#[repr(C, align(4))]
126pub union OptionalDriverChannel {
127 encoded: wire::Uint32,
128 decoded: fdf_handle_t,
129}
130
131impl Drop for OptionalDriverChannel {
132 fn drop(&mut self) {
133 if let Some(handle) = self.as_raw_handle() {
134 let handle = unsafe { NonZero::new_unchecked(handle) };
137 let handle = unsafe { DriverHandle::new_unchecked(handle) };
139 drop(handle);
140 }
141 }
142}
143
144impl Constrained for OptionalDriverChannel {
145 type Constraint = ();
146
147 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
148 Ok(())
149 }
150}
151
152unsafe impl Wire for OptionalDriverChannel {
156 type Narrowed<'de> = Self;
157
158 #[inline]
159 fn zero_padding(_: &mut MaybeUninit<Self>) {
160 }
162}
163
164impl OptionalDriverChannel {
165 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
167 let encoded = unsafe {
171 munge!(let Self { encoded } = out);
172 encoded
173 };
174 encoded.write(wire::Uint32(u32::MAX));
175 }
176
177 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
179 let encoded = unsafe {
183 munge!(let Self { encoded } = out);
184 encoded
185 };
186 encoded.write(wire::Uint32(0));
187 }
188
189 pub fn is_some(&self) -> bool {
191 self.as_raw_handle().is_some()
192 }
193
194 pub fn is_none(&self) -> bool {
196 self.as_raw_handle().is_none()
197 }
198
199 #[inline]
201 pub fn as_raw_handle(&self) -> Option<fdf_handle_t> {
202 let decoded = unsafe { self.decoded };
205 if decoded == 0 { None } else { Some(decoded) }
206 }
207}
208
209impl fmt::Debug for OptionalDriverChannel {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 self.as_raw_handle().fmt(f)
212 }
213}
214
215unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for OptionalDriverChannel {
219 fn decode(
220 mut slot: Slot<'_, Self>,
221 decoder: &mut D,
222 _: <Self as Constrained>::Constraint,
223 ) -> Result<(), DecodeError> {
224 let encoded = unsafe {
227 munge!(let Self { encoded } = slot.as_mut());
228 encoded
229 };
230
231 match **encoded {
232 0 => (),
233 u32::MAX => {
234 let handle = decoder.take_raw_driver_handle()?;
235 let mut decoded = unsafe {
238 munge!(let Self { decoded } = slot);
239 decoded
240 };
241 decoded.write(handle);
242 }
243 e => return Err(DecodeError::InvalidHandlePresence(e)),
244 }
245 Ok(())
246 }
247}
248
249unsafe impl<E: HandleEncoder + ?Sized> Encode<DriverChannel, E> for crate::DriverChannel {
252 fn encode(
253 self,
254 encoder: &mut E,
255 out: &mut MaybeUninit<DriverChannel>,
256 _: (),
257 ) -> Result<(), EncodeError> {
258 let handle = self.channel.into_driver_handle();
259 unsafe {
261 encoder.push_raw_driver_handle(handle.into_raw().get())?;
262 }
263 DriverChannel::set_encoded_present(out);
264 Ok(())
265 }
266}
267
268impl FromWire<DriverChannel> for crate::DriverChannel {
269 fn from_wire(wire: DriverChannel) -> Self {
270 let raw_handle = unsafe { NonZero::new_unchecked(wire.as_raw_handle()) };
272 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
274 let channel = unsafe { Channel::from_driver_handle(handle) };
276 forget(wire);
277 crate::DriverChannel::new(channel)
278 }
279}
280
281impl IntoNatural for DriverChannel {
282 type Natural = crate::DriverChannel;
283}
284
285unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<OptionalDriverChannel, E>
288 for crate::DriverChannel
289{
290 fn encode_option(
291 this: Option<Self>,
292 encoder: &mut E,
293 out: &mut MaybeUninit<OptionalDriverChannel>,
294 _: (),
295 ) -> Result<(), EncodeError> {
296 if let Some(driver_channel) = this {
297 let handle = driver_channel.channel.into_driver_handle();
298 unsafe {
300 encoder.push_raw_driver_handle(handle.into_raw().get())?;
301 }
302 OptionalDriverChannel::set_encoded_present(out);
303 } else {
304 OptionalDriverChannel::set_encoded_absent(out);
305 }
306 Ok(())
307 }
308}
309
310impl FromWireOption<OptionalDriverChannel> for crate::DriverChannel {
311 fn from_wire_option(wire: OptionalDriverChannel) -> Option<Self> {
312 let raw_handle = wire.as_raw_handle();
313 forget(wire);
314 raw_handle.map(|raw| {
315 let raw_handle = unsafe { NonZero::new_unchecked(raw) };
318 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
321 let channel = unsafe { Channel::from_driver_handle(handle) };
323 crate::DriverChannel::new(channel)
324 })
325 }
326}
327
328impl IntoNatural for OptionalDriverChannel {
329 type Natural = Option<crate::DriverChannel>;
330}
331
332#[cfg(test)]
333mod tests {
334 use fdf_channel::arena::Arena;
335 use fdf_channel::message::Message;
336 use fdf_core::handle::MixedHandleType;
337 use fidl_next::{AsDecoderExt as _, Chunk, EncoderExt as _, chunks};
338
339 use crate::{RecvBuffer, SendBuffer};
340
341 use super::*;
342
343 #[test]
344 fn roundtrip() {
345 let (channel, _) = Channel::<[Chunk]>::create();
346 let handle_raw = unsafe { channel.driver_handle().get_raw() };
348 let driver_channel = crate::DriverChannel::new(channel);
349
350 let encoder = SendBuffer::encode(driver_channel).unwrap();
351
352 assert_eq!(encoder.handles.len(), 1);
353 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
354 let MixedHandleType::Driver(handle) = &driver_ref else {
355 panic!("expected a driver handle");
356 };
357 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
358 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
359
360 let arena = Arena::new();
361 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
362 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
363 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
364 let decoder = RecvBuffer { message: buffer };
365
366 let decoded = decoder.into_decoded::<DriverChannel>().unwrap();
367 assert_eq!(decoded.as_raw_handle(), handle_raw.get());
368
369 let handle = decoded.take();
370 let roundtripped_raw = unsafe { handle.channel.driver_handle().get_raw() };
371 assert_eq!(roundtripped_raw, handle_raw);
372 }
373
374 #[test]
375 fn roundtrip_some() {
376 let (channel, _) = Channel::<[Chunk]>::create();
377 let handle_raw = unsafe { channel.driver_handle().get_raw() };
379 let driver_channel = crate::DriverChannel::new(channel);
380
381 let encoder = SendBuffer::encode(Some(driver_channel)).unwrap();
382
383 assert_eq!(encoder.handles.len(), 1);
384 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
385 let MixedHandleType::Driver(handle) = &driver_ref else {
386 panic!("expected a driver handle");
387 };
388 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
389 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
390
391 let arena = Arena::new();
392 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
393 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
394 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
395 let decoder = RecvBuffer { message: buffer };
396
397 let decoded = decoder.into_decoded::<OptionalDriverChannel>().unwrap();
398 assert_eq!(decoded.as_raw_handle(), Some(handle_raw.get()));
399
400 let handle = decoded.take();
401 let roundtripped_raw = unsafe { handle.unwrap().channel.driver_handle().get_raw() };
402 assert_eq!(roundtripped_raw, handle_raw);
403 }
404
405 #[test]
406 fn roundtrip_none() {
407 let encoder = SendBuffer::encode(None::<crate::DriverChannel>).unwrap();
408
409 assert_eq!(encoder.handles.len(), 0);
410 assert_eq!(encoder.data, chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],);
411
412 let arena = Arena::new();
413 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
414 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
415 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
416 let decoder = RecvBuffer { message: buffer };
417
418 let decoded = decoder.into_decoded::<OptionalDriverChannel>().unwrap();
419 assert_eq!(decoded.as_raw_handle(), None);
420
421 let handle = decoded.take();
422 assert!(handle.is_none());
423 }
424}