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 Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption, FromWire,
14 FromWireOption, Slot, 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(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
68 munge!(let Self { encoded } = slot.as_mut());
69
70 match **encoded {
71 0 => (),
72 u32::MAX => {
73 let handle = decoder.take_raw_handle()?;
74 munge!(let Self { mut decoded } = slot);
75 decoded.write(handle);
76 }
77 e => return Err(DecodeError::InvalidHandlePresence(e)),
78 }
79 Ok(())
80 }
81}
82
83#[derive(Debug)]
85#[repr(transparent)]
86pub struct WireOptionalHandle {
87 handle: WireHandle,
88}
89
90unsafe impl Wire for WireOptionalHandle {
91 type Decoded<'de> = Self;
92
93 #[inline]
94 fn zero_padding(out: &mut MaybeUninit<Self>) {
95 munge!(let Self { handle } = out);
96 WireHandle::zero_padding(handle);
97 }
98}
99
100impl WireOptionalHandle {
101 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
103 munge!(let Self { handle } = out);
104 WireHandle::set_encoded_present(handle);
105 }
106
107 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
109 munge!(let Self { handle: WireHandle { encoded } } = out);
110 encoded.write(WireU32(ZX_HANDLE_INVALID));
111 }
112
113 pub fn is_some(&self) -> bool {
115 !self.handle.is_invalid()
116 }
117
118 pub fn is_none(&self) -> bool {
120 self.handle.is_invalid()
121 }
122
123 #[inline]
125 pub fn as_raw_handle(&self) -> Option<zx_handle_t> {
126 self.is_some().then(|| self.handle.as_raw_handle())
127 }
128}
129
130unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalHandle {
131 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
132 munge!(let Self { handle } = slot.as_mut());
133 WireHandle::decode(handle, decoder)
134 }
135}
136
137impl Encodable for Handle {
138 type Encoded = WireHandle;
139}
140
141unsafe impl<E: HandleEncoder + ?Sized> Encode<E> for Handle {
142 fn encode(
143 self,
144 encoder: &mut E,
145 out: &mut MaybeUninit<Self::Encoded>,
146 ) -> Result<(), EncodeError> {
147 if self.is_invalid() {
148 Err(EncodeError::InvalidRequiredHandle)
149 } else {
150 encoder.push_handle(self)?;
151 WireHandle::set_encoded_present(out);
152 Ok(())
153 }
154 }
155}
156
157impl FromWire<WireHandle> for Handle {
158 fn from_wire(wire: WireHandle) -> Self {
159 let handle = unsafe { Handle::from_raw(wire.as_raw_handle()) };
161 forget(wire);
162 handle
163 }
164}
165
166impl EncodableOption for Handle {
167 type EncodedOption = WireOptionalHandle;
168}
169
170unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<E> for Handle {
171 fn encode_option(
172 this: Option<Self>,
173 encoder: &mut E,
174 out: &mut MaybeUninit<Self::EncodedOption>,
175 ) -> Result<(), EncodeError> {
176 if let Some(handle) = this {
177 encoder.push_handle(handle)?;
178 WireOptionalHandle::set_encoded_present(out);
179 } else {
180 WireOptionalHandle::set_encoded_absent(out);
181 }
182 Ok(())
183 }
184}
185
186impl FromWireOption<WireOptionalHandle> for Handle {
187 fn from_wire_option(wire: WireOptionalHandle) -> Option<Self> {
188 let raw_handle = wire.as_raw_handle();
189 forget(wire);
190 raw_handle.map(|raw| unsafe { Handle::from_raw(raw) })
191 }
192}