fidl_next_codec/fuchsia/
handle.rs1use core::fmt;
6use core::mem::{MaybeUninit, forget};
7
8use fidl_constants::{ALLOC_ABSENT_U32, ALLOC_PRESENT_U32};
9use zx::NullableHandle;
10use zx::sys::{ZX_HANDLE_INVALID, zx_handle_t};
11
12use crate::fuchsia::{HandleDecoder, HandleEncoder};
13use crate::{
14 Constrained, Decode, DecodeError, Encode, EncodeError, EncodeOption, FromWire, FromWireOption,
15 IntoNatural, Slot, Unconstrained, Wire, WireU32, munge,
16};
17
18pub type WireNullableHandle = WireHandle;
20
21#[repr(C, align(4))]
23pub union WireHandle {
24 encoded: WireU32,
25 decoded: zx_handle_t,
26}
27
28impl Drop for WireHandle {
29 fn drop(&mut self) {
30 let handle = unsafe { NullableHandle::from_raw(self.as_raw_handle()) };
32 drop(handle);
33 }
34}
35
36unsafe impl Wire for WireHandle {
37 type Owned<'de> = Self;
38
39 #[inline]
40 fn zero_padding(_: &mut MaybeUninit<Self>) {
41 }
43}
44
45impl WireHandle {
46 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
48 munge!(let Self { encoded } = out);
49 encoded.write(WireU32(ALLOC_PRESENT_U32));
50 }
51
52 pub fn is_invalid(&self) -> bool {
54 self.as_raw_handle() == ZX_HANDLE_INVALID
55 }
56
57 #[inline]
59 pub fn as_raw_handle(&self) -> zx_handle_t {
60 unsafe { self.decoded }
61 }
62}
63
64impl fmt::Debug for WireHandle {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 self.as_raw_handle().fmt(f)
67 }
68}
69
70unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireHandle {
71 fn decode(
72 mut slot: Slot<'_, Self>,
73 decoder: &mut D,
74 _constraint: <Self as Constrained>::Constraint,
75 ) -> Result<(), DecodeError> {
76 munge!(let Self { encoded } = slot.as_mut());
77
78 match **encoded {
79 ALLOC_ABSENT_U32 => return Err(DecodeError::RequiredHandleAbsent),
80 ALLOC_PRESENT_U32 => {
81 let handle = decoder.take_raw_handle()?;
82 munge!(let Self { mut decoded } = slot);
83 decoded.write(handle);
84 }
85 e => return Err(DecodeError::InvalidHandlePresence(e)),
86 }
87 Ok(())
88 }
89}
90
91impl Constrained for WireHandle {
92 type Constraint = ();
93
94 fn validate(
95 _slot: Slot<'_, Self>,
96 _constraint: Self::Constraint,
97 ) -> Result<(), crate::ValidationError> {
98 Ok(())
100 }
101}
102
103pub type WireOptionalNullableHandle = WireOptionalHandle;
105
106#[derive(Debug)]
108#[repr(transparent)]
109pub struct WireOptionalHandle {
110 handle: WireHandle,
111}
112
113unsafe impl Wire for WireOptionalHandle {
114 type Owned<'de> = Self;
115
116 #[inline]
117 fn zero_padding(out: &mut MaybeUninit<Self>) {
118 munge!(let Self { handle } = out);
119 WireHandle::zero_padding(handle);
120 }
121}
122
123impl WireOptionalHandle {
124 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
126 munge!(let Self { handle } = out);
127 WireHandle::set_encoded_present(handle);
128 }
129
130 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
132 munge!(let Self { handle: WireHandle { encoded } } = out);
133 encoded.write(WireU32(ZX_HANDLE_INVALID));
134 }
135
136 pub fn is_some(&self) -> bool {
138 !self.handle.is_invalid()
139 }
140
141 pub fn is_none(&self) -> bool {
143 self.handle.is_invalid()
144 }
145
146 #[inline]
148 pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
149 self.is_some().then(|| self.handle.as_raw_handle())
150 }
151}
152
153unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalHandle {
154 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D, _: ()) -> Result<(), DecodeError> {
155 munge!(let Self { handle: mut wire_handle } = slot.as_mut());
156 munge!(let WireHandle { encoded } = wire_handle.as_mut());
157
158 match **encoded {
159 ALLOC_ABSENT_U32 => (),
160 ALLOC_PRESENT_U32 => {
161 let handle = decoder.take_raw_handle()?;
162 munge!(let WireHandle { mut decoded } = wire_handle);
163 decoded.write(handle);
164 }
165 e => return Err(DecodeError::InvalidHandlePresence(e)),
166 }
167 Ok(())
168 }
169}
170
171unsafe impl<E: HandleEncoder + ?Sized> Encode<WireHandle, E> for NullableHandle {
172 fn encode(
173 self,
174 encoder: &mut E,
175 out: &mut MaybeUninit<WireHandle>,
176 _constraint: (),
177 ) -> Result<(), EncodeError> {
178 if self.is_invalid() {
179 Err(EncodeError::InvalidRequiredHandle)
180 } else {
181 encoder.push_handle(self)?;
182 WireHandle::set_encoded_present(out);
183 Ok(())
184 }
185 }
186}
187
188impl FromWire<WireHandle> for NullableHandle {
189 fn from_wire(wire: WireHandle) -> Self {
190 let handle = unsafe { NullableHandle::from_raw(wire.as_raw_handle()) };
192 forget(wire);
193 handle
194 }
195}
196
197impl IntoNatural for WireHandle {
198 type Natural = NullableHandle;
199}
200
201unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<WireOptionalHandle, E> for NullableHandle {
202 fn encode_option(
203 this: Option<Self>,
204 encoder: &mut E,
205 out: &mut MaybeUninit<WireOptionalHandle>,
206 _constraint: (),
207 ) -> Result<(), EncodeError> {
208 if let Some(handle) = this {
209 encoder.push_handle(handle)?;
210 WireOptionalHandle::set_encoded_present(out);
211 } else {
212 WireOptionalHandle::set_encoded_absent(out);
213 }
214 Ok(())
215 }
216}
217
218impl FromWireOption<WireOptionalHandle> for NullableHandle {
219 fn from_wire_option(wire: WireOptionalHandle) -> Option<Self> {
220 let raw_handle = wire.as_raw_handle();
221 forget(wire);
222 raw_handle.map(|raw| unsafe { NullableHandle::from_raw(raw) })
223 }
224}
225
226impl IntoNatural for WireOptionalHandle {
227 type Natural = Option<NullableHandle>;
228}
229
230impl Unconstrained for WireOptionalHandle {}