fidl_next_codec/fuchsia/
handle.rs
1use core::fmt;
6use core::mem::{forget, MaybeUninit};
7
8use zx::sys::{zx_handle_t, ZX_HANDLE_INVALID};
9use zx::Handle;
10
11use crate::fuchsia::{HandleDecoder, HandleEncoder};
12use crate::{
13 munge, Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption,
14 FromWire, FromWireOption, Slot, Wire, WireU32,
15};
16
17#[repr(C, align(4))]
19pub union WireHandle {
20 encoded: WireU32,
21 decoded: zx_handle_t,
22}
23
24impl Drop for WireHandle {
25 fn drop(&mut self) {
26 let handle = unsafe { Handle::from_raw(self.as_raw_handle()) };
28 drop(handle);
29 }
30}
31
32unsafe impl Wire for WireHandle {
33 type Decoded<'de> = Self;
34
35 #[inline]
36 fn zero_padding(_: &mut MaybeUninit<Self>) {
37 }
39}
40
41impl WireHandle {
42 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
44 munge!(let Self { encoded } = out);
45 encoded.write(WireU32(u32::MAX));
46 }
47
48 pub fn is_invalid(&self) -> bool {
50 self.as_raw_handle() == ZX_HANDLE_INVALID
51 }
52
53 #[inline]
55 pub fn as_raw_handle(&self) -> zx_handle_t {
56 unsafe { self.decoded }
57 }
58}
59
60impl fmt::Debug for WireHandle {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 self.as_raw_handle().fmt(f)
63 }
64}
65
66unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireHandle {
67 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
68 munge!(let Self { encoded } = slot.as_mut());
69
70 match **encoded {
71 0 => (),
72 u32::MAX => {
73 let handle = decoder.take_raw_handle()?;
74 munge!(let Self { mut decoded } = slot);
75 unsafe {
77 decoded.as_mut_ptr().write(handle);
78 }
79 }
80 e => return Err(DecodeError::InvalidHandlePresence(e)),
81 }
82 Ok(())
83 }
84}
85
86#[derive(Debug)]
88#[repr(transparent)]
89pub struct WireOptionalHandle {
90 handle: WireHandle,
91}
92
93unsafe impl Wire for WireOptionalHandle {
94 type Decoded<'de> = Self;
95
96 #[inline]
97 fn zero_padding(out: &mut MaybeUninit<Self>) {
98 munge!(let Self { handle } = out);
99 WireHandle::zero_padding(handle);
100 }
101}
102
103impl WireOptionalHandle {
104 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
106 munge!(let Self { handle } = out);
107 WireHandle::set_encoded_present(handle);
108 }
109
110 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
112 munge!(let Self { handle: WireHandle { encoded } } = out);
113 encoded.write(WireU32(ZX_HANDLE_INVALID));
114 }
115
116 pub fn is_some(&self) -> bool {
118 !self.handle.is_invalid()
119 }
120
121 pub fn is_none(&self) -> bool {
123 self.handle.is_invalid()
124 }
125
126 #[inline]
128 pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
129 self.is_some().then(|| self.handle.as_raw_handle())
130 }
131}
132
133unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalHandle {
134 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
135 munge!(let Self { handle } = slot.as_mut());
136 WireHandle::decode(handle, decoder)
137 }
138}
139
140impl Encodable for Handle {
141 type Encoded = WireHandle;
142}
143
144unsafe impl<E: HandleEncoder + ?Sized> Encode<E> for Handle {
145 fn encode(
146 self,
147 encoder: &mut E,
148 out: &mut MaybeUninit<Self::Encoded>,
149 ) -> Result<(), EncodeError> {
150 if self.is_invalid() {
151 Err(EncodeError::InvalidRequiredHandle)
152 } else {
153 encoder.push_handle(self)?;
154 WireHandle::set_encoded_present(out);
155 Ok(())
156 }
157 }
158}
159
160impl FromWire<WireHandle> for Handle {
161 fn from_wire(wire: WireHandle) -> Self {
162 let handle = unsafe { Handle::from_raw(wire.as_raw_handle()) };
164 forget(wire);
165 handle
166 }
167}
168
169impl EncodableOption for Handle {
170 type EncodedOption = WireOptionalHandle;
171}
172
173unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<E> for Handle {
174 fn encode_option(
175 this: Option<Self>,
176 encoder: &mut E,
177 out: &mut MaybeUninit<Self::EncodedOption>,
178 ) -> Result<(), EncodeError> {
179 if let Some(handle) = this {
180 encoder.push_handle(handle)?;
181 WireOptionalHandle::set_encoded_present(out);
182 } else {
183 WireOptionalHandle::set_encoded_absent(out);
184 }
185 Ok(())
186 }
187}
188
189impl FromWireOption<WireOptionalHandle> for Handle {
190 fn from_wire_option(wire: WireOptionalHandle) -> Option<Self> {
191 let raw_handle = wire.as_raw_handle();
192 forget(wire);
193 raw_handle.map(|raw| unsafe { Handle::from_raw(raw) })
194 }
195}
196
197macro_rules! impl_takefrom {
199 ($($name:ident),* $(,)?) => {
200 $(
201 impl FromWire<WireHandle> for zx::$name {
202 fn from_wire(wire: WireHandle) -> Self {
203 Handle::from_wire(wire).into()
204 }
205 }
206
207 impl FromWireOption<WireOptionalHandle> for zx::$name {
208 fn from_wire_option(wire: WireOptionalHandle) -> Option<Self> {
209 Handle::from_wire_option(wire).map(<zx::$name>::from)
210 }
211 }
212 )*
213 }
214}
215
216impl_takefrom! {
217 Process,
218 Thread,
219 Vmo,
220 Channel,
221 Event,
222 Port,
223 Interrupt,
224 Socket,
225 Resource,
226 EventPair,
227 Job,
228 Vmar,
229 Fifo,
230 Guest,
231 Vcpu,
232 Timer,
233 Iommu,
234 Bti,
235 Profile,
236 Pmt,
237 Pager,
238 Exception,
239 Clock,
240 Stream,
241 Iob,
242}