fidl_next_codec/fuchsia/
mod.rs

1// Copyright 2024 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//! Fuchsia-specific extensions to the FIDL codec.
6
7mod handle;
8mod handle_types;
9
10use zx::Handle;
11use zx::sys::zx_handle_t;
12
13use crate::decoder::InternalHandleDecoder;
14use crate::encoder::InternalHandleEncoder;
15use crate::{DecodeError, EncodeError};
16
17pub use self::handle::*;
18pub use self::handle_types::*;
19pub use zx;
20
21/// A decoder which support Zircon handles.
22pub trait HandleDecoder: InternalHandleDecoder {
23    /// Takes the next raw handle from the decoder.
24    ///
25    /// The returned raw handle must not be considered owned until the decoder is committed.
26    fn take_raw_handle(&mut self) -> Result<zx_handle_t, DecodeError>;
27
28    /// Returns the number of handles remaining in the decoder.
29    fn handles_remaining(&mut self) -> usize;
30
31    /// Takes the next raw driver handle from the decoder.
32    #[doc(hidden)]
33    fn take_raw_driver_handle(&mut self) -> Result<u32, DecodeError> {
34        Err(DecodeError::DriverHandlesUnsupported)
35    }
36}
37
38/// An encoder which supports Zircon handles.
39pub trait HandleEncoder: InternalHandleEncoder {
40    /// Pushes a handle into the encoder.
41    fn push_handle(&mut self, handle: Handle) -> Result<(), EncodeError>;
42
43    /// Returns the number of handles added to the encoder.
44    fn handles_pushed(&self) -> usize;
45
46    /// Pushes a raw driver handle into the encoder.
47    ///
48    /// # Safety
49    ///
50    /// `raw_driver_handle` must be a valid `DriverHandle`. Calling
51    /// `push_raw_driver_Handle` moves ownership of the handle into the encoder.
52    #[doc(hidden)]
53    unsafe fn push_raw_driver_handle(
54        &mut self,
55        #[allow(unused)] raw_driver_handle: u32,
56    ) -> Result<(), EncodeError> {
57        Err(EncodeError::DriverHandlesUnsupported)
58    }
59}
60
61// TODO: `HandleDecoder` and `HandleEncoder` have terrible little methods:
62// `take_raw_driver_handle` and `push_raw_driver_handle`. These exist because of
63// two intersecting problems:
64//
65// 1. When writing `Encode` and `Decode` impls for a type, it can't just add
66//    `where` clauses bounding `<field_ty>: Encode<___E>`. This is because some
67//    FIDL type definitions are recursive, and Rust impls can't be coinductive.
68//    So instead, we have to check whether the type is a `resource` and emit
69//    `E: HandleEncoder` if it is.
70//
71// 2. The FIDL IR only tracks whether or not a type is a resource. It doesn't
72//    track which resource types it contains. That means that if a type is a
73//    resource, we don't know whether that's because it contains a handle, or
74//    because it contains a driver handle.
75//
76// So the unfortunate result is that we have to combine all of the resource type
77// encoding and decoding traits into a single one. If we fix this someday, then
78// we can get rid of those methods and make separate `DriverHandleDecoder` and
79// `DriverHandleEncoder` types.
80//
81// /// A decoder which support driver handles.
82// pub trait DriverHandleDecoder: InternalHandleDecoder {
83//     /// Takes the next raw driver handle from the decoder.
84//     ///
85//     /// The returned raw driver handle must not be considered owned until the decoder is committed.
86//     fn take_raw_driver_handle(&mut self) -> Result<fdf_handle_t, DecodeError>;
87//
88//     /// Returns the number of driver handles remaining in the decoder.
89//     fn driver_handles_remaining(&mut self) -> usize;
90// }
91//
92// /// An encoder which supports Zircon handles.
93// pub trait DriverHandleEncoder: InternalHandleEncoder {
94//     /// Pushes a driver handle into the encoder.
95//     fn push_driver_handle(&mut self, handle: DriverHandle) -> Result<(), EncodeError>;
96//
97//     /// Returns the number of driver handles added to the encoder.
98//     fn driver_handles_pushed(&self) -> usize;
99// }