fdomain_client/fidl_next/
wire_handle.rs1use std::cell::UnsafeCell;
6use std::fmt;
7use std::mem::MaybeUninit;
8use std::sync::RwLock;
9use std::sync::atomic::{AtomicPtr, Ordering};
10
11use super::codec::{HandleDecoder, HandleEncoder};
12use fidl_next_codec::{
13 Decode, DecodeError, Encodable, EncodableOption, Encode, EncodeError, EncodeOption, FromWire,
14 FromWireOption, Slot, Wire, WireU32, munge,
15};
16
17use crate::{Client, Handle};
18
19struct HandleAssoc {
20 hid: UnsafeCell<u32>,
21 client: AtomicPtr<Client>,
22}
23
24unsafe impl Send for HandleAssoc {}
26unsafe impl Sync for HandleAssoc {}
27
28const HANDLE_CLIENT_ASSOC_START_SIZE: usize = 32;
29static HANDLE_CLIENT_ASSOC: RwLock<&'static [HandleAssoc]> = RwLock::new(&[]);
30
31#[repr(C, align(4))]
33pub union WireHandle {
34 encoded: WireU32,
35 decoded: u32,
36}
37
38impl From<Handle> for WireHandle {
39 fn from(mut handle: Handle) -> WireHandle {
40 let id = handle.id;
41 let client = std::mem::replace(&mut handle.client, std::sync::Weak::new());
42 let ptr = client.into_raw() as *mut Client;
43
44 loop {
45 let table = HANDLE_CLIENT_ASSOC.read().unwrap();
46
47 for (got_id, entry) in table.iter().enumerate() {
48 let got_id: u32 = got_id.try_into().expect("Handle table overflowed u32");
49 if entry
50 .client
51 .compare_exchange(
52 std::ptr::null_mut(),
53 ptr,
54 Ordering::Acquire,
55 Ordering::Relaxed,
56 )
57 .is_ok()
58 {
59 unsafe {
62 *entry.hid.get() = id;
63 return WireHandle { decoded: got_id + 1 };
64 }
65 }
66 }
67
68 std::mem::drop(table);
69 let mut table = HANDLE_CLIENT_ASSOC.write().unwrap();
70 let new_len = std::cmp::max(table.len() * 2, HANDLE_CLIENT_ASSOC_START_SIZE);
71
72 let new = std::iter::repeat_with(|| HandleAssoc {
73 hid: UnsafeCell::new(0),
74 client: AtomicPtr::new(std::ptr::null_mut()),
75 })
76 .take(new_len)
77 .collect::<Box<[_]>>();
78
79 let new = Box::leak(new);
80 let old = std::mem::replace(&mut *table, new);
81
82 if old.len() > 0 {
83 unsafe { drop(Box::from_raw(old as *const [HandleAssoc] as *mut [HandleAssoc])) }
86 }
87 }
88 }
89}
90
91impl Drop for WireHandle {
92 fn drop(&mut self) {
93 drop(self.take_handle());
94 }
95}
96
97unsafe impl Wire for WireHandle {
98 type Decoded<'de> = Self;
99
100 #[inline]
101 fn zero_padding(_: &mut MaybeUninit<Self>) {
102 }
104}
105
106impl WireHandle {
107 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
109 munge!(let Self { encoded } = out);
110 encoded.write(WireU32(u32::MAX));
111 }
112
113 pub fn is_invalid(&self) -> bool {
115 self.as_raw_handle() == 0
116 }
117
118 pub fn invalidate(&mut self) {
119 self.decoded = 0;
120 }
121
122 #[inline]
124 pub fn as_raw_handle(&self) -> u32 {
125 unsafe { self.decoded }
126 }
127
128 pub(crate) fn take_handle(&mut self) -> Handle {
130 unsafe {
133 let pos = self.decoded as usize;
134 self.decoded = 0;
135 let Some(pos) = pos.checked_sub(1) else {
136 return Handle::invalid();
137 };
138 let (id, ptr) = {
139 let table = HANDLE_CLIENT_ASSOC.read().unwrap();
140 let entry = &table[pos];
141 let hid = *entry.hid.get();
144 let ptr = entry.client.swap(std::ptr::null_mut(), Ordering::Release);
145 (hid, ptr)
146 };
147
148 let client = std::sync::Weak::from_raw(ptr);
149
150 Handle { id, client }
151 }
152 }
153}
154
155impl fmt::Debug for WireHandle {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 self.as_raw_handle().fmt(f)
158 }
159}
160
161unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireHandle {
162 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
163 munge!(let Self { encoded } = slot.as_mut());
164
165 match **encoded {
166 0 => (),
167 u32::MAX => {
168 let handle = decoder.take_raw_handle()?;
169 munge!(let Self { mut decoded } = slot);
170 decoded.write(handle);
171 }
172 e => return Err(DecodeError::InvalidHandlePresence(e)),
173 }
174 Ok(())
175 }
176}
177
178#[derive(Debug)]
180#[repr(transparent)]
181pub struct WireOptionalHandle {
182 pub(crate) handle: WireHandle,
183}
184
185unsafe impl Wire for WireOptionalHandle {
186 type Decoded<'de> = Self;
187
188 #[inline]
189 fn zero_padding(out: &mut MaybeUninit<Self>) {
190 munge!(let Self { handle } = out);
191 WireHandle::zero_padding(handle);
192 }
193}
194
195impl WireOptionalHandle {
196 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
198 munge!(let Self { handle } = out);
199 WireHandle::set_encoded_present(handle);
200 }
201
202 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
204 munge!(let Self { handle: WireHandle { encoded } } = out);
205 encoded.write(WireU32(0));
206 }
207
208 pub fn is_some(&self) -> bool {
210 !self.handle.is_invalid()
211 }
212
213 pub fn is_none(&self) -> bool {
215 self.handle.is_invalid()
216 }
217
218 #[inline]
220 pub fn as_raw_handle(&self) -> Option<u32> {
221 self.is_some().then(|| self.handle.as_raw_handle())
222 }
223}
224
225unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalHandle {
226 fn decode(mut slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
227 munge!(let Self { handle } = slot.as_mut());
228 WireHandle::decode(handle, decoder)
229 }
230}
231
232impl Encodable for Handle {
233 type Encoded = WireHandle;
234}
235
236unsafe impl<E: HandleEncoder + ?Sized> Encode<E> for Handle {
237 fn encode(
238 self,
239 encoder: &mut E,
240 out: &mut MaybeUninit<Self::Encoded>,
241 ) -> Result<(), EncodeError> {
242 if self.client.upgrade().is_none() {
243 Err(EncodeError::InvalidRequiredHandle)
244 } else {
245 encoder.push_handle(self)?;
246 WireHandle::set_encoded_present(out);
247 Ok(())
248 }
249 }
250}
251
252impl FromWire<WireHandle> for Handle {
253 fn from_wire(mut wire: WireHandle) -> Self {
254 wire.take_handle()
255 }
256}
257
258impl EncodableOption for Handle {
259 type EncodedOption = WireOptionalHandle;
260}
261
262unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<E> for Handle {
263 fn encode_option(
264 this: Option<Self>,
265 encoder: &mut E,
266 out: &mut MaybeUninit<Self::EncodedOption>,
267 ) -> Result<(), EncodeError> {
268 if let Some(handle) = this {
269 encoder.push_handle(handle)?;
270 WireOptionalHandle::set_encoded_present(out);
271 } else {
272 WireOptionalHandle::set_encoded_absent(out);
273 }
274 Ok(())
275 }
276}
277
278impl FromWireOption<WireOptionalHandle> for Handle {
279 fn from_wire_option(mut wire: WireOptionalHandle) -> Option<Self> {
280 if wire.handle.is_invalid() { None } else { Some(wire.handle.take_handle()) }
281 }
282}