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