Skip to main content

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