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 munge!(let Self { encoded } = out);
64 encoded.write(wire::Uint32(u32::MAX));
65 }
66
67 #[inline]
69 pub fn as_raw_handle(&self) -> fdf_handle_t {
70 unsafe { self.decoded }
73 }
74}
75
76impl fmt::Debug for DriverChannel {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 self.as_raw_handle().fmt(f)
79 }
80}
81
82unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for DriverChannel {
85 fn decode(
86 mut slot: Slot<'_, Self>,
87 decoder: &mut D,
88 _: <Self as Constrained>::Constraint,
89 ) -> Result<(), DecodeError> {
90 munge!(let Self { encoded } = slot.as_mut());
91
92 match **encoded {
93 u32::MAX => {
94 let handle = decoder.take_raw_driver_handle()?;
95 munge!(let Self { mut decoded } = slot);
96 decoded.write(handle);
97 }
98 e => return Err(DecodeError::InvalidHandlePresence(e)),
99 }
100 Ok(())
101 }
102}
103
104#[repr(C, align(4))]
110pub union OptionalDriverChannel {
111 encoded: wire::Uint32,
112 decoded: fdf_handle_t,
113}
114
115impl Drop for OptionalDriverChannel {
116 fn drop(&mut self) {
117 if let Some(handle) = self.as_raw_handle() {
118 let handle = unsafe { NonZero::new_unchecked(handle) };
121 let handle = unsafe { DriverHandle::new_unchecked(handle) };
123 drop(handle);
124 }
125 }
126}
127
128impl Constrained for OptionalDriverChannel {
129 type Constraint = ();
130
131 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
132 Ok(())
133 }
134}
135
136unsafe impl Wire for OptionalDriverChannel {
140 type Narrowed<'de> = Self;
141
142 #[inline]
143 fn zero_padding(_: &mut MaybeUninit<Self>) {
144 }
146}
147
148impl OptionalDriverChannel {
149 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
151 munge!(let Self { encoded } = out);
152 encoded.write(wire::Uint32(u32::MAX));
153 }
154
155 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
157 munge!(let Self { encoded } = out);
158 encoded.write(wire::Uint32(0));
159 }
160
161 pub fn is_some(&self) -> bool {
163 self.as_raw_handle().is_some()
164 }
165
166 pub fn is_none(&self) -> bool {
168 self.as_raw_handle().is_none()
169 }
170
171 #[inline]
173 pub fn as_raw_handle(&self) -> Option<fdf_handle_t> {
174 let decoded = unsafe { self.decoded };
177 if decoded == 0 { None } else { Some(decoded) }
178 }
179}
180
181unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for OptionalDriverChannel {
185 fn decode(
186 mut slot: Slot<'_, Self>,
187 decoder: &mut D,
188 _: <Self as Constrained>::Constraint,
189 ) -> Result<(), DecodeError> {
190 munge!(let Self { encoded } = slot.as_mut());
191
192 match **encoded {
193 0 => (),
194 u32::MAX => {
195 let handle = decoder.take_raw_driver_handle()?;
196 munge!(let Self { mut decoded } = slot);
197 decoded.write(handle);
198 }
199 e => return Err(DecodeError::InvalidHandlePresence(e)),
200 }
201 Ok(())
202 }
203}
204
205unsafe impl<E: HandleEncoder + ?Sized> Encode<DriverChannel, E> for crate::DriverChannel {
208 fn encode(
209 self,
210 encoder: &mut E,
211 out: &mut MaybeUninit<DriverChannel>,
212 _: (),
213 ) -> Result<(), EncodeError> {
214 let handle = self.channel.into_driver_handle();
215 unsafe {
217 encoder.push_raw_driver_handle(handle.into_raw().get())?;
218 }
219 DriverChannel::set_encoded_present(out);
220 Ok(())
221 }
222}
223
224impl FromWire<DriverChannel> for crate::DriverChannel {
225 fn from_wire(wire: DriverChannel) -> Self {
226 let raw_handle = unsafe { NonZero::new_unchecked(wire.as_raw_handle()) };
228 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
230 let channel = unsafe { Channel::from_driver_handle(handle) };
232 forget(wire);
233 crate::DriverChannel::new(channel)
234 }
235}
236
237impl IntoNatural for DriverChannel {
238 type Natural = crate::DriverChannel;
239}
240
241unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<OptionalDriverChannel, E>
244 for crate::DriverChannel
245{
246 fn encode_option(
247 this: Option<Self>,
248 encoder: &mut E,
249 out: &mut MaybeUninit<OptionalDriverChannel>,
250 _: (),
251 ) -> Result<(), EncodeError> {
252 if let Some(driver_channel) = this {
253 let handle = driver_channel.channel.into_driver_handle();
254 unsafe {
256 encoder.push_raw_driver_handle(handle.into_raw().get())?;
257 }
258 OptionalDriverChannel::set_encoded_present(out);
259 } else {
260 OptionalDriverChannel::set_encoded_absent(out);
261 }
262 Ok(())
263 }
264}
265
266impl FromWireOption<OptionalDriverChannel> for crate::DriverChannel {
267 fn from_wire_option(wire: OptionalDriverChannel) -> Option<Self> {
268 let raw_handle = wire.as_raw_handle();
269 forget(wire);
270 raw_handle.map(|raw| {
271 let raw_handle = unsafe { NonZero::new_unchecked(raw) };
274 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
277 let channel = unsafe { Channel::from_driver_handle(handle) };
279 crate::DriverChannel::new(channel)
280 })
281 }
282}
283
284impl IntoNatural for OptionalDriverChannel {
285 type Natural = Option<crate::DriverChannel>;
286}
287
288#[cfg(test)]
289mod tests {
290 use fdf_channel::arena::Arena;
291 use fdf_channel::message::Message;
292 use fdf_core::handle::MixedHandleType;
293 use fidl_next::{AsDecoderExt as _, Chunk, EncoderExt as _, chunks};
294
295 use crate::{RecvBuffer, SendBuffer};
296
297 use super::*;
298
299 #[test]
300 fn roundtrip() {
301 let (channel, _) = Channel::<[Chunk]>::create();
302 let handle_raw = unsafe { channel.driver_handle().get_raw() };
304 let driver_channel = crate::DriverChannel::new(channel);
305
306 let encoder = SendBuffer::encode(driver_channel).unwrap();
307
308 assert_eq!(encoder.handles.len(), 1);
309 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
310 let MixedHandleType::Driver(handle) = &driver_ref else {
311 panic!("expected a driver handle");
312 };
313 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
314 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
315
316 let arena = Arena::new();
317 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
318 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
319 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
320 let decoder = RecvBuffer { message: buffer };
321
322 let decoded = decoder.into_decoded::<DriverChannel>().unwrap();
323 assert_eq!(decoded.as_raw_handle(), handle_raw.get());
324
325 let handle = decoded.take();
326 let roundtripped_raw = unsafe { handle.channel.driver_handle().get_raw() };
327 assert_eq!(roundtripped_raw, handle_raw);
328 }
329
330 #[test]
331 fn roundtrip_some() {
332 let (channel, _) = Channel::<[Chunk]>::create();
333 let handle_raw = unsafe { channel.driver_handle().get_raw() };
335 let driver_channel = crate::DriverChannel::new(channel);
336
337 let encoder = SendBuffer::encode(Some(driver_channel)).unwrap();
338
339 assert_eq!(encoder.handles.len(), 1);
340 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
341 let MixedHandleType::Driver(handle) = &driver_ref else {
342 panic!("expected a driver handle");
343 };
344 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
345 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
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 { message: buffer };
352
353 let decoded = decoder.into_decoded::<OptionalDriverChannel>().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 encoder = SendBuffer::encode(None::<crate::DriverChannel>).unwrap();
364
365 assert_eq!(encoder.handles.len(), 0);
366 assert_eq!(encoder.data, chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],);
367
368 let arena = Arena::new();
369 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
370 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
371 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
372 let decoder = RecvBuffer { message: buffer };
373
374 let decoded = decoder.into_decoded::<OptionalDriverChannel>().unwrap();
375 assert_eq!(decoded.as_raw_handle(), None);
376
377 let handle = decoded.take();
378 assert!(handle.is_none());
379 }
380}