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 munge!(let Self { encoded } = out);
59 encoded.write(wire::Uint32(ALLOC_PRESENT_U32));
60 }
61
62 pub fn is_invalid(&self) -> bool {
64 self.as_raw_handle() == ZX_HANDLE_INVALID
65 }
66
67 #[inline]
69 pub fn as_raw_handle(&self) -> zx_handle_t {
70 unsafe { self.decoded }
74 }
75}
76
77impl fmt::Debug for Handle {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 self.as_raw_handle().fmt(f)
80 }
81}
82
83unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for Handle {
86 fn decode(
87 mut slot: Slot<'_, Self>,
88 decoder: &mut D,
89 _constraint: Self::Constraint,
90 ) -> Result<(), DecodeError> {
91 munge!(let Self { encoded } = slot.as_mut());
92
93 match **encoded {
94 ALLOC_ABSENT_U32 => return Err(DecodeError::RequiredHandleAbsent),
95 ALLOC_PRESENT_U32 => {
96 let handle = decoder.take_raw_handle()?;
97 munge!(let Self { mut decoded } = slot);
98 decoded.write(handle);
99 }
100 e => return Err(DecodeError::InvalidHandlePresence(e)),
101 }
102 Ok(())
103 }
104}
105
106pub type OptionalNullableHandle = OptionalHandle;
108
109#[derive(Debug)]
111#[repr(transparent)]
112pub struct OptionalHandle {
113 handle: Handle,
114}
115
116impl Constrained for OptionalHandle {
118 type Constraint = ();
119
120 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
121 Ok(())
122 }
123}
124
125unsafe impl Wire for OptionalHandle {
127 type Narrowed<'de> = Self;
128
129 #[inline]
130 fn zero_padding(out: &mut MaybeUninit<Self>) {
131 munge!(let Self { handle } = out);
132 Handle::zero_padding(handle);
133 }
134}
135
136impl OptionalHandle {
137 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
139 munge!(let Self { handle } = out);
140 Handle::set_encoded_present(handle);
141 }
142
143 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
145 munge!(let Self { handle: Handle { encoded } } = out);
146 encoded.write(wire::Uint32(ZX_HANDLE_INVALID));
147 }
148
149 pub fn is_some(&self) -> bool {
151 !self.handle.is_invalid()
152 }
153
154 pub fn is_none(&self) -> bool {
156 self.handle.is_invalid()
157 }
158
159 #[inline]
161 pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
162 self.is_some().then(|| self.handle.as_raw_handle())
163 }
164}
165
166unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for OptionalHandle {
170 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D, _: ()) -> Result<(), DecodeError> {
171 munge!(let Self { handle: mut wire_handle } = slot.as_mut());
172 munge!(let Handle { encoded } = wire_handle.as_mut());
173
174 match **encoded {
175 ALLOC_ABSENT_U32 => (),
176 ALLOC_PRESENT_U32 => {
177 let handle = decoder.take_raw_handle()?;
178 munge!(let Handle { mut decoded } = wire_handle);
179 decoded.write(handle);
180 }
181 e => return Err(DecodeError::InvalidHandlePresence(e)),
182 }
183 Ok(())
184 }
185}
186
187unsafe impl<E: HandleEncoder + ?Sized> Encode<Handle, E> for zx::NullableHandle {
190 fn encode(
191 self,
192 encoder: &mut E,
193 out: &mut MaybeUninit<Handle>,
194 _constraint: (),
195 ) -> Result<(), EncodeError> {
196 if self.is_invalid() {
197 Err(EncodeError::InvalidRequiredHandle)
198 } else {
199 encoder.push_handle(self)?;
200 Handle::set_encoded_present(out);
201 Ok(())
202 }
203 }
204}
205
206impl FromWire<Handle> for zx::NullableHandle {
207 fn from_wire(wire: Handle) -> Self {
208 let handle = unsafe { zx::NullableHandle::from_raw(wire.as_raw_handle()) };
210 forget(wire);
211 handle
212 }
213}
214
215impl IntoNatural for Handle {
216 type Natural = zx::NullableHandle;
217}
218
219unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<OptionalHandle, E> for zx::NullableHandle {
222 fn encode_option(
223 this: Option<Self>,
224 encoder: &mut E,
225 out: &mut MaybeUninit<OptionalHandle>,
226 _constraint: (),
227 ) -> Result<(), EncodeError> {
228 if let Some(handle) = this {
229 encoder.push_handle(handle)?;
230 OptionalHandle::set_encoded_present(out);
231 } else {
232 OptionalHandle::set_encoded_absent(out);
233 }
234 Ok(())
235 }
236}
237
238impl FromWireOption<OptionalHandle> for zx::NullableHandle {
239 fn from_wire_option(wire: OptionalHandle) -> Option<Self> {
240 let raw_handle = wire.as_raw_handle();
241 forget(wire);
242 raw_handle.map(|raw| unsafe { zx::NullableHandle::from_raw(raw) })
245 }
246}
247
248impl IntoNatural for OptionalHandle {
249 type Natural = Option<zx::NullableHandle>;
250}