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 Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption, FromWire,
16 FromWireOption, Slot, 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(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
80 munge!(let Self { encoded } = slot.as_mut());
81
82 match **encoded {
83 u32::MAX => {
84 let handle = decoder.take_raw_driver_handle()?;
85 munge!(let Self { mut decoded } = slot);
86 decoded.write(handle);
87 }
88 e => return Err(DecodeError::InvalidHandlePresence(e)),
89 }
90 Ok(())
91 }
92}
93
94#[repr(C, align(4))]
100pub union WireOptionalDriverChannel {
101 encoded: WireU32,
102 decoded: fdf_handle_t,
103}
104
105impl Drop for WireOptionalDriverChannel {
106 fn drop(&mut self) {
107 if let Some(handle) = self.as_raw_handle() {
108 let handle = unsafe { NonZero::new_unchecked(handle) };
111 let handle = unsafe { DriverHandle::new_unchecked(handle) };
113 drop(handle);
114 }
115 }
116}
117
118unsafe impl Wire for WireOptionalDriverChannel {
122 type Decoded<'de> = Self;
123
124 #[inline]
125 fn zero_padding(_: &mut MaybeUninit<Self>) {
126 }
128}
129
130impl WireOptionalDriverChannel {
131 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
133 munge!(let Self { encoded } = out);
134 encoded.write(WireU32(u32::MAX));
135 }
136
137 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
139 munge!(let Self { encoded } = out);
140 encoded.write(WireU32(0));
141 }
142
143 pub fn is_some(&self) -> bool {
145 self.as_raw_handle().is_some()
146 }
147
148 pub fn is_none(&self) -> bool {
150 self.as_raw_handle().is_none()
151 }
152
153 #[inline]
155 pub fn as_raw_handle(&self) -> Option<fdf_handle_t> {
156 let decoded = unsafe { self.decoded };
159 if decoded == 0 { None } else { Some(decoded) }
160 }
161}
162
163unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalDriverChannel {
167 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
168 munge!(let Self { encoded } = slot.as_mut());
169
170 match **encoded {
171 0 => (),
172 u32::MAX => {
173 let handle = decoder.take_raw_driver_handle()?;
174 munge!(let Self { mut decoded } = slot);
175 decoded.write(handle);
176 }
177 e => return Err(DecodeError::InvalidHandlePresence(e)),
178 }
179 Ok(())
180 }
181}
182
183impl Encodable for DriverChannel {
184 type Encoded = WireDriverChannel;
185}
186
187unsafe impl<E: HandleEncoder + ?Sized> Encode<E> for DriverChannel {
190 fn encode(
191 self,
192 encoder: &mut E,
193 out: &mut MaybeUninit<Self::Encoded>,
194 ) -> Result<(), EncodeError> {
195 let handle = self.channel.into_driver_handle();
196 unsafe {
198 encoder.push_raw_driver_handle(handle.into_raw().get())?;
199 }
200 WireDriverChannel::set_encoded_present(out);
201 Ok(())
202 }
203}
204
205impl FromWire<WireDriverChannel> for DriverChannel {
206 fn from_wire(wire: WireDriverChannel) -> Self {
207 let raw_handle = unsafe { NonZero::new_unchecked(wire.as_raw_handle()) };
209 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
211 let channel = unsafe { Channel::from_driver_handle(handle) };
213 forget(wire);
214 DriverChannel::new(channel)
215 }
216}
217
218impl EncodableOption for DriverChannel {
219 type EncodedOption = WireOptionalDriverChannel;
220}
221
222unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<E> for DriverChannel {
225 fn encode_option(
226 this: Option<Self>,
227 encoder: &mut E,
228 out: &mut MaybeUninit<Self::EncodedOption>,
229 ) -> Result<(), EncodeError> {
230 if let Some(driver_channel) = this {
231 let handle = driver_channel.channel.into_driver_handle();
232 unsafe {
234 encoder.push_raw_driver_handle(handle.into_raw().get())?;
235 }
236 WireOptionalDriverChannel::set_encoded_present(out);
237 } else {
238 WireOptionalDriverChannel::set_encoded_absent(out);
239 }
240 Ok(())
241 }
242}
243
244impl FromWireOption<WireOptionalDriverChannel> for DriverChannel {
245 fn from_wire_option(wire: WireOptionalDriverChannel) -> Option<Self> {
246 let raw_handle = wire.as_raw_handle();
247 forget(wire);
248 raw_handle.map(|raw| {
249 let raw_handle = unsafe { NonZero::new_unchecked(raw) };
252 let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
255 let channel = unsafe { Channel::from_driver_handle(handle) };
257 DriverChannel::new(channel)
258 })
259 }
260}
261
262#[cfg(test)]
263mod tests {
264 use fdf_channel::arena::Arena;
265 use fdf_channel::message::Message;
266 use fdf_core::handle::MixedHandleType;
267 use fidl_next::{Chunk, DecoderExt as _, EncoderExt as _, chunks};
268
269 use crate::{RecvBuffer, SendBuffer};
270
271 use super::*;
272
273 #[test]
274 fn roundtrip() {
275 let (channel, _) = Channel::<[Chunk]>::create();
276 let handle_raw = unsafe { channel.driver_handle().get_raw() };
278 let driver_channel = DriverChannel::new(channel);
279
280 let mut encoder = SendBuffer::new();
281 encoder.encode_next(driver_channel).unwrap();
282
283 assert_eq!(encoder.handles.len(), 1);
284 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
285 let MixedHandleType::Driver(handle) = &driver_ref else {
286 panic!("expected a driver handle");
287 };
288 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
289 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
290 drop(driver_ref);
291
292 let arena = Arena::new();
293 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
294 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
295 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
296 let decoder = RecvBuffer { buffer, data_offset: 0, handle_offset: 0 };
297
298 let decoded = decoder.decode::<WireDriverChannel>().unwrap();
299 assert_eq!(decoded.as_raw_handle(), handle_raw.get());
300
301 let handle: DriverChannel = decoded.take();
302 let roundtripped_raw = unsafe { handle.channel.driver_handle().get_raw() };
303 assert_eq!(roundtripped_raw, handle_raw);
304 }
305
306 #[test]
307 fn roundtrip_some() {
308 let (channel, _) = Channel::<[Chunk]>::create();
309 let handle_raw = unsafe { channel.driver_handle().get_raw() };
311 let driver_channel = DriverChannel::new(channel);
312
313 let mut encoder = SendBuffer::new();
314 encoder.encode_next(Some(driver_channel)).unwrap();
315
316 assert_eq!(encoder.handles.len(), 1);
317 let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
318 let MixedHandleType::Driver(handle) = &driver_ref else {
319 panic!("expected a driver handle");
320 };
321 assert_eq!(unsafe { handle.get_raw() }, handle_raw);
322 assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
323 drop(driver_ref);
324
325 let arena = Arena::new();
326 let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
327 let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
328 let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
329 let decoder = RecvBuffer { buffer, data_offset: 0, handle_offset: 0 };
330
331 let decoded = decoder.decode::<WireOptionalDriverChannel>().unwrap();
332 assert_eq!(decoded.as_raw_handle(), Some(handle_raw.get()));
333
334 let handle: Option<DriverChannel> = decoded.take();
335 let roundtripped_raw = unsafe { handle.unwrap().channel.driver_handle().get_raw() };
336 assert_eq!(roundtripped_raw, handle_raw);
337 }
338
339 #[test]
340 fn roundtrip_none() {
341 let mut encoder = SendBuffer::new();
342 encoder.encode_next(Option::<DriverChannel>::None).unwrap();
343
344 assert_eq!(encoder.handles.len(), 0);
345 assert_eq!(encoder.data, chunks![0x00, 0x00, 0x00, 0x00, 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 { buffer, data_offset: 0, handle_offset: 0 };
352
353 let decoded = decoder.decode::<WireOptionalDriverChannel>().unwrap();
354 assert_eq!(decoded.as_raw_handle(), None);
355
356 let handle: Option<DriverChannel> = decoded.take();
357 assert!(handle.is_none());
358 }
359}