Skip to main content

fdf_fidl/
wire.rs

1// Copyright 2025 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Driver-specific extensions to FIDL.
6
7use 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/// The FIDL wire type for [`DriverChannel`].
20///
21/// This type follows the FIDL wire format for handles, and is separate from the
22/// Zircon handle wire type. This ensures that we never confuse the two types
23/// when using FIDL.
24#[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        // SAFETY: `WireDriverHandle` is always non-zero.
33        let raw_handle = unsafe { NonZero::new_unchecked(self.as_raw_handle()) };
34        // SAFETY: `WireDriverHandle` is always a valid `DriverHandle`.
35        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
48// SAFETY:
49// - `WireDriverHandle` doesn't reference any other decoded data.
50// - `WireDriverHandle` does not have any padding bytes.
51unsafe impl Wire for DriverChannel {
52    type Narrowed<'de> = Self;
53
54    #[inline]
55    fn zero_padding(_: &mut MaybeUninit<Self>) {
56        // Wire driver handles have no padding
57    }
58}
59
60impl DriverChannel {
61    /// Encodes a driver handle as present in an output.
62    pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
63        // SAFETY: `out` is a valid mutable reference to a `MaybeUninit<DriverChannel>`.
64        // Destructuring it via `munge!` only projects a pointer to `MaybeUninit<Uint32>`
65        // and does not read uninitialized memory.
66        let encoded = unsafe {
67            munge!(let Self { encoded } = out);
68            encoded
69        };
70        encoded.write(wire::Uint32(u32::MAX));
71    }
72
73    /// Returns the underlying [`fdf_handle_t`].
74    #[inline]
75    pub fn as_raw_handle(&self) -> fdf_handle_t {
76        // SAFETY: If we have a reference to `WireDriverHandle`, then it has
77        // been successfully decoded and the `decoded` field is safe to read.
78        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
88// SAFETY: `decode` only returns `Ok` if it wrote to the `decoded` field of the
89// handle, initializing it.
90unsafe 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        // SAFETY: `slot` is a valid `Slot` of `DriverChannel`. Both `encoded` and `decoded` are
97        // 4-byte integer types with no invalid bit patterns.
98        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                // SAFETY: `slot` is a valid `Slot` of `DriverChannel`. Destructuring it via
107                // `munge!` to write `decoded` is safe.
108                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/// The FIDL wire type for optional [`DriverChannel`]s.
121///
122/// This type follows the FIDL wire format for handles, and is separate from the
123/// Zircon handle optional wire type. This ensures that we never confuse the two
124/// types when using FIDL.
125#[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            // SAFETY: If the return value from `as_raw_handle` is `Some`, then
135            // it is always non-zero.
136            let handle = unsafe { NonZero::new_unchecked(handle) };
137            // SAFETY: `WireDriverHandle` is always a valid `DriverHandle`.
138            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
152// SAFETY:
153// - `WireOptionalDriverHandle` doesn't reference any other decoded data.
154// - `WireOptionalDriverHandle` does not have any padding bytes.
155unsafe impl Wire for OptionalDriverChannel {
156    type Narrowed<'de> = Self;
157
158    #[inline]
159    fn zero_padding(_: &mut MaybeUninit<Self>) {
160        // Wire optional driver handles have no padding
161    }
162}
163
164impl OptionalDriverChannel {
165    /// Encodes a driver handle as present in a slot.
166    pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
167        // SAFETY: `out` is a valid mutable reference to a `MaybeUninit<OptionalDriverChannel>`.
168        // Destructuring it via `munge!` only projects a pointer to `MaybeUninit<Uint32>`
169        // and does not read uninitialized memory.
170        let encoded = unsafe {
171            munge!(let Self { encoded } = out);
172            encoded
173        };
174        encoded.write(wire::Uint32(u32::MAX));
175    }
176
177    /// Encodes a driver handle as absent in an output.
178    pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
179        // SAFETY: `out` is a valid mutable reference to a `MaybeUninit<OptionalDriverChannel>`.
180        // Destructuring it via `munge!` only projects a pointer to `MaybeUninit<Uint32>`
181        // and does not read uninitialized memory.
182        let encoded = unsafe {
183            munge!(let Self { encoded } = out);
184            encoded
185        };
186        encoded.write(wire::Uint32(0));
187    }
188
189    /// Returns whether a handle is present.
190    pub fn is_some(&self) -> bool {
191        self.as_raw_handle().is_some()
192    }
193
194    /// Returns whether a handle is absent.
195    pub fn is_none(&self) -> bool {
196        self.as_raw_handle().is_none()
197    }
198
199    /// Returns the underlying [`fdf_handle_t`], if any.
200    #[inline]
201    pub fn as_raw_handle(&self) -> Option<fdf_handle_t> {
202        // SAFETY: If we have a reference to `WireDriverHandle`, then it has
203        // been successfully decoded and the `decoded` field is safe to read.
204        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
215// SAFETY: `decode` only returns `Ok` if either:
216// - It wrote to the `decoded` field of the handle, initializing it.
217// - The handle's encoded (and decoded) value was zero, indicating `None`.
218unsafe 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        // SAFETY: `slot` is a valid `Slot` of `OptionalDriverChannel`. Both `encoded` and `decoded`
225        // are 4-byte integer types with no invalid bit patterns.
226        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                // SAFETY: `slot` is a valid `Slot` of `OptionalDriverChannel`. Destructuring it via
236                // `munge!` to write `decoded` is safe.
237                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
249// SAFETY: `encode` calls `set_encoded_present`, which initializes all of the
250// bytes of `out`.
251unsafe 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        // SAFETY: `self.into_raw()` returns a valid driver handle.
260        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        // SAFETY: `WireDriverHandle` is always non-zero.
271        let raw_handle = unsafe { NonZero::new_unchecked(wire.as_raw_handle()) };
272        // SAFETY: `WireDriverHandle` is always a valid `Handle`.
273        let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
274        // SAFETY: `WireDriverHandle` is always a valid `Channel`.
275        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
285// SAFETY: `encode_option` calls either `set_encoded_present` or
286// `set_encoded_absent`, both of which initializes all of the bytes of `out`.
287unsafe 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            // SAFETY: `self.into_raw()` returns a valid driver handle.
299            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            // SAFETY: `WireDriverHandle::as_raw_handle()` only returns `Some`
316            // with a non-zero raw handle.
317            let raw_handle = unsafe { NonZero::new_unchecked(raw) };
318            // SAFETY: `wire` previously owned the valid driver handle. It has
319            // been forgotten, passing ownership to the returned `DriverHandle`.
320            let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
321            // SAFETY: `WireOptionalDriverChannel` is always a valid `Channel`.
322            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        // SAFETY: this handle won't be used as a driver handle.
347        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        // SAFETY: this handle won't be used as a driver handle.
378        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}