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// }