fidl_next_codec/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, WireHandle, WireOptionalHandle};
8use crate::{
9    Constrained, Decode, DecodeError, Encode, EncodeError, EncodeOption, FromWire, FromWireOption,
10    IntoNatural, Slot, Unconstrained, Wire, munge,
11};
12
13use zx::NullableHandle;
14use zx::sys::zx_handle_t;
15
16macro_rules! define_wire_handle_types {
17    ($(
18        $wire:ident($wire_optional:ident):
19            $natural:ident $(<$($generics:ident $(: $bound:path)?),+>)?
20    ),* $(,)?) => { $(
21        #[doc = concat!("A Zircon ", stringify!($natural), ".")]
22        #[derive(Debug)]
23        #[repr(transparent)]
24        pub struct $wire {
25            handle: WireHandle,
26        }
27
28        unsafe impl Wire for $wire {
29            type Owned<'de> = Self;
30
31            #[inline]
32            fn zero_padding(out: &mut MaybeUninit<Self>) {
33                munge!(let Self { handle } = out);
34                WireHandle::zero_padding(handle);
35            }
36        }
37
38        impl $wire {
39            #[doc = concat!("Encodes a ", stringify!($natural), " as present in an output.")]
40            pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
41                munge!(let Self { handle } = out);
42                WireHandle::set_encoded_present(handle);
43            }
44
45            /// Returns whether the underlying `zx_handle_t` is invalid.
46            pub fn is_invalid(&self) -> bool {
47                self.handle.is_invalid()
48            }
49
50            /// Returns the underlying [`zx_handle_t`].
51            #[inline]
52            pub fn as_raw_handle(&self) -> zx_handle_t {
53                self.handle.as_raw_handle()
54            }
55        }
56
57        unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for $wire {
58            fn decode(
59                mut slot: Slot<'_, Self>,
60                decoder: &mut D,
61                constraint: <Self as Constrained>::Constraint,
62            ) -> Result<(), DecodeError> {
63                munge!(let Self { handle } = slot.as_mut());
64                WireHandle::decode(handle, decoder, constraint)
65            }
66        }
67
68        #[doc = concat!("An optional Zircon ", stringify!($natural), ".")]
69        #[derive(Debug)]
70        #[repr(transparent)]
71        pub struct $wire_optional {
72            handle: WireOptionalHandle,
73        }
74
75        unsafe impl Wire for $wire_optional {
76            type Owned<'de> = Self;
77
78            #[inline]
79            fn zero_padding(out: &mut MaybeUninit<Self>) {
80                munge!(let Self { handle } = out);
81                WireOptionalHandle::zero_padding(handle);
82            }
83        }
84
85        impl $wire_optional {
86            #[doc = concat!("Encodes a ", stringify!($natural), " as present in an output.")]
87            pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
88                munge!(let Self { handle } = out);
89                WireOptionalHandle::set_encoded_present(handle);
90            }
91
92            #[doc = concat!("Encodes a ", stringify!($natural), " as absent in an output.")]
93            pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
94                munge!(let Self { handle } = out);
95                WireOptionalHandle::set_encoded_absent(handle);
96            }
97
98            #[doc = concat!("Returns whether a ", stringify!($natural), " is present.")]
99            pub fn is_some(&self) -> bool {
100                !self.handle.is_some()
101            }
102
103            #[doc = concat!("Returns whether a ", stringify!($natural), " is absent.")]
104            pub fn is_none(&self) -> bool {
105                self.handle.is_none()
106            }
107
108            /// Returns the underlying [`zx_handle_t`], if any.
109            #[inline]
110            pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
111                self.handle.as_raw_handle()
112            }
113        }
114
115        unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for $wire_optional {
116            fn decode(
117                mut slot: Slot<'_, Self>,
118                decoder: &mut D, constraint: <Self as Constrained>::Constraint,
119            ) -> Result<(), DecodeError> {
120                munge!(let Self { handle } = slot.as_mut());
121                WireOptionalHandle::decode(handle, decoder, constraint)
122            }
123        }
124
125        unsafe impl<
126            E: HandleEncoder + ?Sized,
127            $($($generics $(: $bound)?,)+)?
128        > Encode<$wire, E> for zx::$natural $(<$($generics,)+>)? {
129            fn encode(
130                self,
131                encoder: &mut E,
132                out: &mut MaybeUninit<$wire>,
133                constraint:  <$wire as Constrained>::Constraint,
134            ) -> Result<(), EncodeError> {
135                munge!(let $wire { handle } = out);
136                NullableHandle::from(self).encode(encoder, handle, constraint)
137            }
138        }
139
140        impl $(<$($generics $(: $bound)?,)+>)? FromWire<$wire>
141            for zx::$natural $(<$($generics,)+>)?
142        {
143            fn from_wire(wire: $wire) -> Self {
144                NullableHandle::from_wire(wire.handle).into()
145            }
146        }
147
148        impl IntoNatural for $wire {
149            type Natural = zx::$natural;
150        }
151
152        unsafe impl<
153            E: HandleEncoder + ?Sized,
154            $($($generics $(: $bound)?,)+)?
155        > EncodeOption<$wire_optional, E> for zx::$natural $(<$($generics,)+>)? {
156            fn encode_option(
157                this: Option<Self>,
158                encoder: &mut E,
159                out: &mut MaybeUninit<$wire_optional>,
160                constraint: (),
161            ) -> Result<(), EncodeError> {
162                munge!(let $wire_optional { handle } = out);
163                Encode::encode(this.map(NullableHandle::from), encoder, handle, constraint)
164            }
165        }
166
167        impl $(<$($generics $(: $bound)?,)+>)? FromWireOption<$wire_optional>
168            for zx::$natural $(<$($generics,)+>)?
169        {
170            fn from_wire_option(wire: $wire_optional) -> Option<Self> {
171                NullableHandle::from_wire_option(wire.handle).map(zx::$natural::from)
172            }
173        }
174
175        impl IntoNatural for $wire_optional {
176            type Natural = Option<zx::$natural>;
177        }
178
179        // TODO: validate handle rights.
180        impl Unconstrained for $wire {}
181        impl Unconstrained for $wire_optional {}
182    )* };
183}
184
185define_wire_handle_types! {
186    WireProcess(WireOptionalProcess): Process,
187    WireThread(WireOptionalThread): Thread,
188    WireVmo(WireOptionalVmo): Vmo,
189    WireChannel(WireOptionalChannel): Channel,
190    WireEvent(WireOptionalEvent): Event,
191    WirePort(WireOptionalPort): Port,
192    WireInterrupt(WireOptionalInterrupt): Interrupt<K: zx::InterruptKind, T: zx::Timeline>,
193    // WirePciDevice(WireOptionalPciDevice): PciDevice,
194    WireDebugLog(WireOptionalDebugLog): DebugLog,
195    WireSocket(WireOptionalSocket): Socket,
196    WireResource(WireOptionalResource): Resource,
197    WireEventPair(WireOptionalEventPair): EventPair,
198    WireJob(WireOptionalJob): Job,
199    WireVmar(WireOptionalVmar): Vmar,
200    WireFifo(WireOptionalFifo): Fifo<R, W>,
201    WireGuest(WireOptionalGuest): Guest,
202    WireVcpu(WireOptionalVcpu): Vcpu,
203    WireTimer(WireOptionalTimer): Timer<T: zx::Timeline>,
204    WireIommu(WireOptionalIommu): Iommu,
205    WireBti(WireOptionalBti): Bti,
206    WireProfile(WireOptionalProfile): Profile,
207    WirePmt(WireOptionalPmt): Pmt,
208    // WireSuspendToken(WireOptionalSuspendToken): SuspendToken,
209    WirePager(WireOptionalPager): Pager,
210    WireException(WireOptionalException): Exception,
211    WireClock(WireOptionalClock): Clock<Reference: zx::Timeline, Output: zx::Timeline>,
212    WireStream(WireOptionalStream): Stream,
213    // WireMsi(WireOptionalMsi): Msi,
214    WireIob(WireOptionalIob): Iob,
215    WireCounter(WireOptionalCounter): Counter,
216}