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