fidl_next_codec/wire/fuchsia/
handle.rs1use core::fmt;
6use core::mem::{MaybeUninit, forget};
7
8use fidl_constants::{ALLOC_ABSENT_U32, ALLOC_PRESENT_U32};
9use zx::sys::{ZX_HANDLE_INVALID, zx_handle_t};
10
11use crate::fuchsia::{HandleDecoder, HandleEncoder};
12use crate::{
13 Constrained, Decode, DecodeError, Encode, EncodeError, EncodeOption, FromWire, FromWireOption,
14 IntoNatural, Slot, ValidationError, Wire, munge, wire,
15};
16
17pub type NullableHandle = Handle;
19
20#[repr(C, align(4))]
22pub union Handle {
23 encoded: wire::Uint32,
24 decoded: zx_handle_t,
25}
26
27impl Drop for Handle {
28 fn drop(&mut self) {
29 let handle = unsafe { zx::NullableHandle::from_raw(self.as_raw_handle()) };
31 drop(handle);
32 }
33}
34
35impl Constrained for Handle {
37 type Constraint = ();
38
39 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
40 Ok(())
41 }
42}
43
44unsafe impl Wire for Handle {
47 type Narrowed<'de> = Self;
48
49 #[inline]
50 fn zero_padding(_: &mut MaybeUninit<Self>) {
51 }
53}
54
55impl Handle {
56 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
58 let encoded = unsafe {
62 munge!(let Self { encoded } = out);
63 encoded
64 };
65 encoded.write(wire::Uint32(ALLOC_PRESENT_U32));
66 }
67
68 pub fn is_invalid(&self) -> bool {
70 self.as_raw_handle() == ZX_HANDLE_INVALID
71 }
72
73 #[inline]
75 pub fn as_raw_handle(&self) -> zx_handle_t {
76 unsafe { self.decoded }
80 }
81}
82
83impl fmt::Debug for Handle {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 self.as_raw_handle().fmt(f)
86 }
87}
88
89unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for Handle {
92 fn decode(
93 mut slot: Slot<'_, Self>,
94 decoder: &mut D,
95 _constraint: Self::Constraint,
96 ) -> Result<(), DecodeError> {
97 let encoded = unsafe {
100 munge!(let Self { encoded } = slot.as_mut());
101 encoded
102 };
103
104 match **encoded {
105 ALLOC_ABSENT_U32 => return Err(DecodeError::RequiredHandleAbsent),
106 ALLOC_PRESENT_U32 => {
107 let handle = decoder.take_raw_handle()?;
108 let mut decoded = unsafe {
111 munge!(let Self { decoded } = slot);
112 decoded
113 };
114 decoded.write(handle);
115 }
116 e => return Err(DecodeError::InvalidHandlePresence(e)),
117 }
118 Ok(())
119 }
120}
121
122pub type OptionalNullableHandle = OptionalHandle;
124
125#[derive(Debug)]
127#[repr(transparent)]
128pub struct OptionalHandle {
129 handle: Handle,
130}
131
132impl Constrained for OptionalHandle {
134 type Constraint = ();
135
136 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
137 Ok(())
138 }
139}
140
141unsafe impl Wire for OptionalHandle {
143 type Narrowed<'de> = Self;
144
145 #[inline]
146 fn zero_padding(out: &mut MaybeUninit<Self>) {
147 munge!(let Self { handle } = out);
148 Handle::zero_padding(handle);
149 }
150}
151
152impl OptionalHandle {
153 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
155 munge!(let Self { handle } = out);
156 Handle::set_encoded_present(handle);
157 }
158
159 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
161 let encoded = unsafe {
165 munge!(let Self { handle: Handle { encoded } } = out);
166 encoded
167 };
168 encoded.write(wire::Uint32(ZX_HANDLE_INVALID));
169 }
170
171 pub fn is_some(&self) -> bool {
173 !self.handle.is_invalid()
174 }
175
176 pub fn is_none(&self) -> bool {
178 self.handle.is_invalid()
179 }
180
181 #[inline]
183 pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
184 self.is_some().then(|| self.handle.as_raw_handle())
185 }
186}
187
188unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for OptionalHandle {
192 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D, _: ()) -> Result<(), DecodeError> {
193 munge!(let Self { handle: mut wire_handle } = slot.as_mut());
194 let encoded = unsafe {
197 munge!(let Handle { encoded } = wire_handle.as_mut());
198 encoded
199 };
200
201 match **encoded {
202 ALLOC_ABSENT_U32 => (),
203 ALLOC_PRESENT_U32 => {
204 let handle = decoder.take_raw_handle()?;
205 let mut decoded = unsafe {
208 munge!(let Handle { decoded } = wire_handle);
209 decoded
210 };
211 decoded.write(handle);
212 }
213 e => return Err(DecodeError::InvalidHandlePresence(e)),
214 }
215 Ok(())
216 }
217}
218
219unsafe impl<E: HandleEncoder + ?Sized> Encode<Handle, E> for zx::NullableHandle {
222 fn encode(
223 self,
224 encoder: &mut E,
225 out: &mut MaybeUninit<Handle>,
226 _constraint: (),
227 ) -> Result<(), EncodeError> {
228 if self.is_invalid() {
229 Err(EncodeError::InvalidRequiredHandle)
230 } else {
231 encoder.push_handle(self)?;
232 Handle::set_encoded_present(out);
233 Ok(())
234 }
235 }
236}
237
238impl FromWire<Handle> for zx::NullableHandle {
239 fn from_wire(wire: Handle) -> Self {
240 let handle = unsafe { zx::NullableHandle::from_raw(wire.as_raw_handle()) };
242 forget(wire);
243 handle
244 }
245}
246
247impl IntoNatural for Handle {
248 type Natural = zx::NullableHandle;
249}
250
251unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<OptionalHandle, E> for zx::NullableHandle {
254 fn encode_option(
255 this: Option<Self>,
256 encoder: &mut E,
257 out: &mut MaybeUninit<OptionalHandle>,
258 _constraint: (),
259 ) -> Result<(), EncodeError> {
260 if let Some(handle) = this {
261 encoder.push_handle(handle)?;
262 OptionalHandle::set_encoded_present(out);
263 } else {
264 OptionalHandle::set_encoded_absent(out);
265 }
266 Ok(())
267 }
268}
269
270impl FromWireOption<OptionalHandle> for zx::NullableHandle {
271 fn from_wire_option(wire: OptionalHandle) -> Option<Self> {
272 let raw_handle = wire.as_raw_handle();
273 forget(wire);
274 raw_handle.map(|raw| unsafe { zx::NullableHandle::from_raw(raw) })
277 }
278}
279
280impl IntoNatural for OptionalHandle {
281 type Natural = Option<zx::NullableHandle>;
282}