fidl_next_codec/fuchsia/
handle.rs
1use core::cell::Cell;
6use core::fmt;
7use core::mem::{replace, ManuallyDrop};
8
9use zx::sys::{zx_handle_t, ZX_HANDLE_INVALID};
10use zx::{Handle, HandleBased as _};
11
12use crate::fuchsia::{HandleDecoder, HandleEncoder};
13use crate::{
14 munge, Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption,
15 Slot, TakeFrom, WireU32, ZeroPadding,
16};
17
18#[repr(C, align(4))]
20pub union WireHandle {
21 encoded: WireU32,
22 decoded: ManuallyDrop<Cell<zx_handle_t>>,
23}
24
25impl Drop for WireHandle {
26 fn drop(&mut self) {
27 drop(self.take());
28 }
29}
30
31unsafe impl ZeroPadding for WireHandle {
32 #[inline]
33 unsafe fn zero_padding(_: *mut Self) {
34 }
36}
37
38impl WireHandle {
39 pub fn set_encoded_present(slot: Slot<'_, Self>) {
41 munge!(let Self { mut encoded } = slot);
42 *encoded = WireU32(u32::MAX);
43 }
44
45 pub fn is_invalid(&self) -> bool {
47 self.as_raw_handle() == ZX_HANDLE_INVALID
48 }
49
50 pub fn take(&self) -> Handle {
52 let raw = unsafe { self.decoded.replace(ZX_HANDLE_INVALID) };
53 unsafe { Handle::from_raw(raw) }
54 }
55
56 #[inline]
58 pub fn as_raw_handle(&self) -> zx_handle_t {
59 unsafe { self.decoded.get() }
60 }
61}
62
63impl fmt::Debug for WireHandle {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 self.as_raw_handle().fmt(f)
66 }
67}
68
69unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireHandle {
70 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
71 munge!(let Self { encoded } = slot.as_mut());
72
73 match **encoded {
74 0 => (),
75 u32::MAX => {
76 let handle = decoder.take_handle()?;
77 munge!(let Self { mut decoded } = slot);
78 unsafe {
80 decoded.as_mut_ptr().write(ManuallyDrop::new(Cell::new(handle.into_raw())));
81 }
82 }
83 e => return Err(DecodeError::InvalidHandlePresence(e)),
84 }
85 Ok(())
86 }
87}
88
89impl TakeFrom<WireHandle> for Handle {
90 fn take_from(from: &WireHandle) -> Self {
91 from.take()
92 }
93}
94
95#[derive(Debug)]
97#[repr(transparent)]
98pub struct WireOptionalHandle {
99 handle: WireHandle,
100}
101
102unsafe impl ZeroPadding for WireOptionalHandle {
103 #[inline]
104 unsafe fn zero_padding(ptr: *mut Self) {
105 unsafe {
106 WireHandle::zero_padding(ptr.cast());
107 }
108 }
109}
110
111impl WireOptionalHandle {
112 pub fn set_encoded_present(slot: Slot<'_, Self>) {
114 munge!(let Self { handle } = slot);
115 WireHandle::set_encoded_present(handle);
116 }
117
118 pub fn set_encoded_absent(slot: Slot<'_, Self>) {
120 munge!(let Self { handle: WireHandle { mut encoded } } = slot);
121 *encoded = WireU32(ZX_HANDLE_INVALID);
122 }
123
124 pub fn is_some(&self) -> bool {
126 !self.handle.is_invalid()
127 }
128
129 pub fn is_none(&self) -> bool {
131 self.handle.is_invalid()
132 }
133
134 pub fn take(&self) -> Option<Handle> {
136 self.is_some().then(|| self.handle.take())
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
146impl Encodable for Handle {
147 type Encoded = WireHandle;
148}
149
150impl<E: HandleEncoder + ?Sized> Encode<E> for Handle {
151 fn encode(
152 &mut self,
153 encoder: &mut E,
154 slot: Slot<'_, Self::Encoded>,
155 ) -> Result<(), EncodeError> {
156 if self.is_invalid() {
157 Err(EncodeError::InvalidRequiredHandle)
158 } else {
159 let handle = replace(self, Handle::invalid());
160 encoder.push_handle(handle)?;
161 WireHandle::set_encoded_present(slot);
162 Ok(())
163 }
164 }
165}
166
167impl EncodableOption for Handle {
168 type EncodedOption = WireOptionalHandle;
169}
170
171impl<E: HandleEncoder + ?Sized> EncodeOption<E> for Handle {
172 fn encode_option(
173 this: Option<&mut Self>,
174 encoder: &mut E,
175 slot: Slot<'_, Self::EncodedOption>,
176 ) -> Result<(), EncodeError> {
177 if let Some(handle) = this {
178 let handle = replace(handle, Handle::invalid());
179 encoder.push_handle(handle)?;
180 WireOptionalHandle::set_encoded_present(slot);
181 } else {
182 WireOptionalHandle::set_encoded_absent(slot);
183 }
184 Ok(())
185 }
186}
187
188unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalHandle {
189 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
190 munge!(let Self { handle } = slot.as_mut());
191 WireHandle::decode(handle, decoder)
192 }
193}
194
195impl TakeFrom<WireOptionalHandle> for Option<Handle> {
196 fn take_from(from: &WireOptionalHandle) -> Self {
197 from.take()
198 }
199}