Skip to main content

fidl_next_codec/wire/fuchsia/
handle_types.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
5use core::mem::MaybeUninit;
6
7use crate::fuchsia::{HandleDecoder, HandleEncoder};
8use crate::{
9    Constrained, Decode, DecodeError, Encode, EncodeError, EncodeOption, FromWire, FromWireOption,
10    IntoNatural, Slot, ValidationError, Wire, munge, wire,
11};
12
13use zx::sys::zx_handle_t;
14
15macro_rules! define_wire_handle_types {
16    ($(
17        $wire:ident($wire_optional:ident):
18            $natural:ident $(<$($generics:ident $(: $bound:path)?),+>)?
19    ),* $(,)?) => { $(
20        #[doc = concat!("A Zircon ", stringify!($natural), ".")]
21        #[derive(Debug)]
22        #[repr(transparent)]
23        pub struct $wire {
24            handle: wire::fuchsia::Handle,
25        }
26
27        // TODO: validate handle rights.
28        impl Constrained for $wire {
29            type Constraint = ();
30
31            fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
32                Ok(())
33            }
34        }
35
36        // SAFETY: `$wire` is a `#[repr(transparent)]` wrapper around `wire::fuchsia::Handle`,
37        // which is `Wire`.
38        unsafe impl Wire for $wire {
39            type Narrowed<'de> = Self;
40
41            #[inline]
42            fn zero_padding(out: &mut MaybeUninit<Self>) {
43                munge!(let Self { handle } = out);
44                wire::fuchsia::Handle::zero_padding(handle);
45            }
46        }
47
48        impl $wire {
49            #[doc = concat!("Encodes a ", stringify!($natural), " as present in an output.")]
50            pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
51                munge!(let Self { handle } = out);
52                wire::fuchsia::Handle::set_encoded_present(handle);
53            }
54
55            /// Returns whether the underlying `zx_handle_t` is invalid.
56            pub fn is_invalid(&self) -> bool {
57                self.handle.is_invalid()
58            }
59
60            /// Returns the underlying [`zx_handle_t`].
61            #[inline]
62            pub fn as_raw_handle(&self) -> zx_handle_t {
63                self.handle.as_raw_handle()
64            }
65        }
66
67        // SAFETY: If `decode` returns `Ok`, `slot` is guaranteed to contain a valid decoded
68        // `$wire` because it delegates to `Handle::decode` which guarantees the slot is valid.
69        unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for $wire {
70            fn decode(
71                mut slot: Slot<'_, Self>,
72                decoder: &mut D,
73                constraint: Self::Constraint,
74            ) -> Result<(), DecodeError> {
75                munge!(let Self { handle } = slot.as_mut());
76                wire::fuchsia::Handle::decode(handle, decoder, constraint)
77            }
78        }
79
80        #[doc = concat!("An optional Zircon ", stringify!($natural), ".")]
81        #[derive(Debug)]
82        #[repr(transparent)]
83        pub struct $wire_optional {
84            handle: wire::fuchsia::OptionalHandle,
85        }
86
87        // TODO: validate handle rights.
88        impl Constrained for $wire_optional {
89            type Constraint = ();
90
91            fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
92                Ok(())
93            }
94        }
95
96        // SAFETY: `$wire_optional` is a `#[repr(transparent)]` wrapper around
97        // `wire::fuchsia::OptionalHandle`, which is `Wire`.
98        unsafe impl Wire for $wire_optional {
99            type Narrowed<'de> = Self;
100
101            #[inline]
102            fn zero_padding(out: &mut MaybeUninit<Self>) {
103                munge!(let Self { handle } = out);
104                wire::fuchsia::OptionalHandle::zero_padding(handle);
105            }
106        }
107
108        impl $wire_optional {
109            #[doc = concat!("Encodes a ", stringify!($natural), " as present in an output.")]
110            pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
111                munge!(let Self { handle } = out);
112                wire::fuchsia::OptionalHandle::set_encoded_present(handle);
113            }
114
115            #[doc = concat!("Encodes a ", stringify!($natural), " as absent in an output.")]
116            pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
117                munge!(let Self { handle } = out);
118                wire::fuchsia::OptionalHandle::set_encoded_absent(handle);
119            }
120
121            #[doc = concat!("Returns whether a ", stringify!($natural), " is present.")]
122            pub fn is_some(&self) -> bool {
123                !self.handle.is_some()
124            }
125
126            #[doc = concat!("Returns whether a ", stringify!($natural), " is absent.")]
127            pub fn is_none(&self) -> bool {
128                self.handle.is_none()
129            }
130
131            /// Returns the underlying [`zx_handle_t`], if any.
132            #[inline]
133            pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
134                self.handle.as_raw_handle()
135            }
136        }
137
138        // SAFETY: If `decode` returns `Ok`, `slot` is guaranteed to contain a valid decoded
139        // `$wire_optional` because it delegates to `OptionalHandle::decode` which guarantees the
140        // slot is valid.
141        unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for $wire_optional {
142            fn decode(
143                mut slot: Slot<'_, Self>,
144                decoder: &mut D, constraint: Self::Constraint,
145            ) -> Result<(), DecodeError> {
146                munge!(let Self { handle } = slot.as_mut());
147                wire::fuchsia::OptionalHandle::decode(handle, decoder, constraint)
148            }
149        }
150
151        // SAFETY: `$wire` is `#[repr(transparent)]` over `Handle`. `encode` delegates to
152        // `zx::NullableHandle`'s `Encode` implementation, which fully initializes the underlying
153        // `Handle`, thus initializing `$wire`.
154        unsafe impl<
155            E: HandleEncoder + ?Sized,
156            $($($generics $(: $bound)?,)+)?
157        > Encode<$wire, E> for zx::$natural $(<$($generics,)+>)? {
158            fn encode(
159                self,
160                encoder: &mut E,
161                out: &mut MaybeUninit<$wire>,
162                constraint:  <$wire as Constrained>::Constraint,
163            ) -> Result<(), EncodeError> {
164                munge!(let $wire { handle } = out);
165                zx::NullableHandle::from(self).encode(encoder, handle, constraint)
166            }
167        }
168
169        impl $(<$($generics $(: $bound)?,)+>)? FromWire<$wire>
170            for zx::$natural $(<$($generics,)+>)?
171        {
172            fn from_wire(wire: $wire) -> Self {
173                zx::NullableHandle::from_wire(wire.handle).into()
174            }
175        }
176
177        impl IntoNatural for $wire {
178            type Natural = zx::$natural;
179        }
180
181        // SAFETY: `$wire_optional` is `#[repr(transparent)]` over `OptionalHandle`.
182        // `encode_option` delegates to `zx::NullableHandle`'s `EncodeOption` implementation (via
183        // `Option`'s `Encode`), which fully initializes the underlying `OptionalHandle`, thus
184        // initializing `$wire_optional`.
185        unsafe impl<
186            E: HandleEncoder + ?Sized,
187            $($($generics $(: $bound)?,)+)?
188        > EncodeOption<$wire_optional, E> for zx::$natural $(<$($generics,)+>)? {
189            fn encode_option(
190                this: Option<Self>,
191                encoder: &mut E,
192                out: &mut MaybeUninit<$wire_optional>,
193                constraint: (),
194            ) -> Result<(), EncodeError> {
195                munge!(let $wire_optional { handle } = out);
196                Encode::encode(this.map(zx::NullableHandle::from), encoder, handle, constraint)
197            }
198        }
199
200        impl $(<$($generics $(: $bound)?,)+>)? FromWireOption<$wire_optional>
201            for zx::$natural $(<$($generics,)+>)?
202        {
203            fn from_wire_option(wire: $wire_optional) -> Option<Self> {
204                zx::NullableHandle::from_wire_option(wire.handle).map(zx::$natural::from)
205            }
206        }
207
208        impl IntoNatural for $wire_optional {
209            type Natural = Option<zx::$natural>;
210        }
211    )* };
212}
213
214define_wire_handle_types! {
215    Process(OptionalProcess): Process,
216    Thread(OptionalThread): Thread,
217    Vmo(OptionalVmo): Vmo,
218    Channel(OptionalChannel): Channel,
219    Event(OptionalEvent): Event,
220    Port(OptionalPort): Port,
221    Interrupt(OptionalInterrupt): Interrupt<K: zx::InterruptKind, T: zx::Timeline>,
222    // PciDevice(OptionalPciDevice): PciDevice,
223    DebugLog(OptionalDebugLog): DebugLog,
224    Socket(OptionalSocket): Socket,
225    Resource(OptionalResource): Resource,
226    EventPair(OptionalEventPair): EventPair,
227    Job(OptionalJob): Job,
228    Vmar(OptionalVmar): Vmar,
229    Fifo(OptionalFifo): Fifo<R, W>,
230    Guest(OptionalGuest): Guest,
231    Vcpu(OptionalVcpu): Vcpu,
232    Timer(OptionalTimer): Timer<T: zx::Timeline>,
233    Iommu(OptionalIommu): Iommu,
234    Bti(OptionalBti): Bti,
235    Profile(OptionalProfile): Profile,
236    Pmt(OptionalPmt): Pmt,
237    // SuspendToken(OptionalSuspendToken): SuspendToken,
238    Pager(OptionalPager): Pager,
239    Exception(OptionalException): Exception,
240    Clock(OptionalClock): Clock<Reference: zx::Timeline, Output: zx::Timeline>,
241    Stream(OptionalStream): Stream,
242    // Msi(OptionalMsi): Msi,
243    Iob(OptionalIob): Iob,
244    Counter(OptionalCounter): Counter,
245}