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