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
209// SAFETY: `decode` only returns `Ok` if either:
210// - It wrote to the `decoded` field of the handle, initializing it.
211// - The handle's encoded (and decoded) value was zero, indicating `None`.
212unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for OptionalDriverChannel {
213    fn decode(
214        mut slot: Slot<'_, Self>,
215        decoder: &mut D,
216        _: <Self as Constrained>::Constraint,
217    ) -> Result<(), DecodeError> {
218        // SAFETY: `slot` is a valid `Slot` of `OptionalDriverChannel`. Both `encoded` and `decoded`
219        // are 4-byte integer types with no invalid bit patterns.
220        let encoded = unsafe {
221            munge!(let Self { encoded } = slot.as_mut());
222            encoded
223        };
224
225        match **encoded {
226            0 => (),
227            u32::MAX => {
228                let handle = decoder.take_raw_driver_handle()?;
229                // SAFETY: `slot` is a valid `Slot` of `OptionalDriverChannel`. Destructuring it via
230                // `munge!` to write `decoded` is safe.
231                let mut decoded = unsafe {
232                    munge!(let Self { decoded } = slot);
233                    decoded
234                };
235                decoded.write(handle);
236            }
237            e => return Err(DecodeError::InvalidHandlePresence(e)),
238        }
239        Ok(())
240    }
241}
242
243// SAFETY: `encode` calls `set_encoded_present`, which initializes all of the
244// bytes of `out`.
245unsafe impl<E: HandleEncoder + ?Sized> Encode<DriverChannel, E> for crate::DriverChannel {
246    fn encode(
247        self,
248        encoder: &mut E,
249        out: &mut MaybeUninit<DriverChannel>,
250        _: (),
251    ) -> Result<(), EncodeError> {
252        let handle = self.channel.into_driver_handle();
253        // SAFETY: `self.into_raw()` returns a valid driver handle.
254        unsafe {
255            encoder.push_raw_driver_handle(handle.into_raw().get())?;
256        }
257        DriverChannel::set_encoded_present(out);
258        Ok(())
259    }
260}
261
262impl FromWire<DriverChannel> for crate::DriverChannel {
263    fn from_wire(wire: DriverChannel) -> Self {
264        // SAFETY: `WireDriverHandle` is always non-zero.
265        let raw_handle = unsafe { NonZero::new_unchecked(wire.as_raw_handle()) };
266        // SAFETY: `WireDriverHandle` is always a valid `Handle`.
267        let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
268        // SAFETY: `WireDriverHandle` is always a valid `Channel`.
269        let channel = unsafe { Channel::from_driver_handle(handle) };
270        forget(wire);
271        crate::DriverChannel::new(channel)
272    }
273}
274
275impl IntoNatural for DriverChannel {
276    type Natural = crate::DriverChannel;
277}
278
279// SAFETY: `encode_option` calls either `set_encoded_present` or
280// `set_encoded_absent`, both of which initializes all of the bytes of `out`.
281unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<OptionalDriverChannel, E>
282    for crate::DriverChannel
283{
284    fn encode_option(
285        this: Option<Self>,
286        encoder: &mut E,
287        out: &mut MaybeUninit<OptionalDriverChannel>,
288        _: (),
289    ) -> Result<(), EncodeError> {
290        if let Some(driver_channel) = this {
291            let handle = driver_channel.channel.into_driver_handle();
292            // SAFETY: `self.into_raw()` returns a valid driver handle.
293            unsafe {
294                encoder.push_raw_driver_handle(handle.into_raw().get())?;
295            }
296            OptionalDriverChannel::set_encoded_present(out);
297        } else {
298            OptionalDriverChannel::set_encoded_absent(out);
299        }
300        Ok(())
301    }
302}
303
304impl FromWireOption<OptionalDriverChannel> for crate::DriverChannel {
305    fn from_wire_option(wire: OptionalDriverChannel) -> Option<Self> {
306        let raw_handle = wire.as_raw_handle();
307        forget(wire);
308        raw_handle.map(|raw| {
309            // SAFETY: `WireDriverHandle::as_raw_handle()` only returns `Some`
310            // with a non-zero raw handle.
311            let raw_handle = unsafe { NonZero::new_unchecked(raw) };
312            // SAFETY: `wire` previously owned the valid driver handle. It has
313            // been forgotten, passing ownership to the returned `DriverHandle`.
314            let handle = unsafe { DriverHandle::new_unchecked(raw_handle) };
315            // SAFETY: `WireOptionalDriverChannel` is always a valid `Channel`.
316            let channel = unsafe { Channel::from_driver_handle(handle) };
317            crate::DriverChannel::new(channel)
318        })
319    }
320}
321
322impl IntoNatural for OptionalDriverChannel {
323    type Natural = Option<crate::DriverChannel>;
324}
325
326#[cfg(test)]
327mod tests {
328    use fdf_channel::arena::Arena;
329    use fdf_channel::message::Message;
330    use fdf_core::handle::MixedHandleType;
331    use fidl_next::{AsDecoderExt as _, Chunk, EncoderExt as _, chunks};
332
333    use crate::{RecvBuffer, SendBuffer};
334
335    use super::*;
336
337    #[test]
338    fn roundtrip() {
339        let (channel, _) = Channel::<[Chunk]>::create();
340        // SAFETY: this handle won't be used as a driver handle.
341        let handle_raw = unsafe { channel.driver_handle().get_raw() };
342        let driver_channel = crate::DriverChannel::new(channel);
343
344        let encoder = SendBuffer::encode(driver_channel).unwrap();
345
346        assert_eq!(encoder.handles.len(), 1);
347        let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
348        let MixedHandleType::Driver(handle) = &driver_ref else {
349            panic!("expected a driver handle");
350        };
351        assert_eq!(unsafe { handle.get_raw() }, handle_raw);
352        assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
353
354        let arena = Arena::new();
355        let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
356        let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
357        let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
358        let decoder = RecvBuffer { message: buffer };
359
360        let decoded = decoder.into_decoded::<DriverChannel>().unwrap();
361        assert_eq!(decoded.as_raw_handle(), handle_raw.get());
362
363        let handle = decoded.take();
364        let roundtripped_raw = unsafe { handle.channel.driver_handle().get_raw() };
365        assert_eq!(roundtripped_raw, handle_raw);
366    }
367
368    #[test]
369    fn roundtrip_some() {
370        let (channel, _) = Channel::<[Chunk]>::create();
371        // SAFETY: this handle won't be used as a driver handle.
372        let handle_raw = unsafe { channel.driver_handle().get_raw() };
373        let driver_channel = crate::DriverChannel::new(channel);
374
375        let encoder = SendBuffer::encode(Some(driver_channel)).unwrap();
376
377        assert_eq!(encoder.handles.len(), 1);
378        let driver_ref = encoder.handles[0].as_ref().unwrap().resolve_ref();
379        let MixedHandleType::Driver(handle) = &driver_ref else {
380            panic!("expected a driver handle");
381        };
382        assert_eq!(unsafe { handle.get_raw() }, handle_raw);
383        assert_eq!(encoder.data, chunks![0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00],);
384
385        let arena = Arena::new();
386        let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
387        let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
388        let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
389        let decoder = RecvBuffer { message: buffer };
390
391        let decoded = decoder.into_decoded::<OptionalDriverChannel>().unwrap();
392        assert_eq!(decoded.as_raw_handle(), Some(handle_raw.get()));
393
394        let handle = decoded.take();
395        let roundtripped_raw = unsafe { handle.unwrap().channel.driver_handle().get_raw() };
396        assert_eq!(roundtripped_raw, handle_raw);
397    }
398
399    #[test]
400    fn roundtrip_none() {
401        let encoder = SendBuffer::encode(None::<crate::DriverChannel>).unwrap();
402
403        assert_eq!(encoder.handles.len(), 0);
404        assert_eq!(encoder.data, chunks![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],);
405
406        let arena = Arena::new();
407        let data = arena.insert_boxed_slice(encoder.data.into_boxed_slice());
408        let handles = arena.insert_boxed_slice(encoder.handles.into_boxed_slice());
409        let buffer = Some(Message::new(&arena, Some(data), Some(handles)));
410        let decoder = RecvBuffer { message: buffer };
411
412        let decoded = decoder.into_decoded::<OptionalDriverChannel>().unwrap();
413        assert_eq!(decoded.as_raw_handle(), None);
414
415        let handle = decoded.take();
416        assert!(handle.is_none());
417    }
418}