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