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