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