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