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 Constrained, Decode, DecodeError, Encode, EncodeError, EncodeOption, FromWire, FromWireOption,
14 Slot, Unconstrained, 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 Owned<'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(
163 mut slot: Slot<'_, Self>,
164 decoder: &mut D,
165 _: <Self as Constrained>::Constraint,
166 ) -> Result<(), DecodeError> {
167 munge!(let Self { encoded } = slot.as_mut());
168
169 match **encoded {
170 0 => (),
171 u32::MAX => {
172 let handle = decoder.take_raw_handle()?;
173 munge!(let Self { mut decoded } = slot);
174 decoded.write(handle);
175 }
176 e => return Err(DecodeError::InvalidHandlePresence(e)),
177 }
178 Ok(())
179 }
180}
181
182impl Unconstrained for WireHandle {}
183
184#[derive(Debug)]
186#[repr(transparent)]
187pub struct WireOptionalHandle {
188 pub(crate) handle: WireHandle,
189}
190
191unsafe impl Wire for WireOptionalHandle {
192 type Owned<'de> = Self;
193
194 #[inline]
195 fn zero_padding(out: &mut MaybeUninit<Self>) {
196 munge!(let Self { handle } = out);
197 WireHandle::zero_padding(handle);
198 }
199}
200
201impl WireOptionalHandle {
202 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
204 munge!(let Self { handle } = out);
205 WireHandle::set_encoded_present(handle);
206 }
207
208 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
210 munge!(let Self { handle: WireHandle { encoded } } = out);
211 encoded.write(WireU32(0));
212 }
213
214 pub fn is_some(&self) -> bool {
216 !self.handle.is_invalid()
217 }
218
219 pub fn is_none(&self) -> bool {
221 self.handle.is_invalid()
222 }
223
224 #[inline]
226 pub fn as_raw_handle(&self) -> Option<u32> {
227 self.is_some().then(|| self.handle.as_raw_handle())
228 }
229}
230
231unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for WireOptionalHandle {
232 fn decode(
233 mut slot: Slot<'_, Self>,
234 decoder: &mut D,
235 constraint: <Self as Constrained>::Constraint,
236 ) -> Result<(), DecodeError> {
237 munge!(let Self { handle } = slot.as_mut());
238 WireHandle::decode(handle, decoder, constraint)
239 }
240}
241
242impl Unconstrained for WireOptionalHandle {}
243
244unsafe impl<E: HandleEncoder + ?Sized> Encode<WireHandle, E> for Handle {
245 fn encode(
246 self,
247 encoder: &mut E,
248 out: &mut MaybeUninit<WireHandle>,
249 _: (),
250 ) -> Result<(), EncodeError> {
251 if self.client.upgrade().is_none() {
252 Err(EncodeError::InvalidRequiredHandle)
253 } else {
254 encoder.push_handle(self)?;
255 WireHandle::set_encoded_present(out);
256 Ok(())
257 }
258 }
259}
260
261impl FromWire<WireHandle> for Handle {
262 fn from_wire(mut wire: WireHandle) -> Self {
263 wire.take_handle()
264 }
265}
266
267unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<WireOptionalHandle, E> for Handle {
268 fn encode_option(
269 this: Option<Self>,
270 encoder: &mut E,
271 out: &mut MaybeUninit<WireOptionalHandle>,
272 _: (),
273 ) -> Result<(), EncodeError> {
274 if let Some(handle) = this {
275 encoder.push_handle(handle)?;
276 WireOptionalHandle::set_encoded_present(out);
277 } else {
278 WireOptionalHandle::set_encoded_absent(out);
279 }
280 Ok(())
281 }
282}
283
284impl FromWireOption<WireOptionalHandle> for Handle {
285 fn from_wire_option(mut wire: WireOptionalHandle) -> Option<Self> {
286 if wire.handle.is_invalid() { None } else { Some(wire.handle.take_handle()) }
287 }
288}