fdomain_client/fidl_next/wire/
wire_handle.rs1use fidl_next::ValidationError;
6use fuchsia_sync::RwLock;
7use std::cell::UnsafeCell;
8use std::fmt;
9use std::mem::MaybeUninit;
10use std::sync::atomic::{AtomicPtr, Ordering};
11
12use fidl_next_codec::{
13 Constrained, Decode, DecodeError, Encode, EncodeError, EncodeOption, FromWire, FromWireOption,
14 Slot, Wire, munge, wire,
15};
16
17use crate::Client;
18use crate::fidl_next::{HandleDecoder, HandleEncoder};
19
20struct HandleAssoc {
21 hid: UnsafeCell<u32>,
22 client: AtomicPtr<Client>,
23}
24
25unsafe impl Send for HandleAssoc {}
27unsafe impl Sync for HandleAssoc {}
28
29const HANDLE_CLIENT_ASSOC_START_SIZE: usize = 32;
30static HANDLE_CLIENT_ASSOC: RwLock<&'static [HandleAssoc]> = RwLock::new(&[]);
31
32#[repr(C, align(4))]
34pub union Handle {
35 encoded: wire::Uint32,
36 decoded: u32,
37}
38
39impl From<crate::Handle> for Handle {
40 fn from(mut handle: crate::Handle) -> Handle {
41 let id = handle.id;
42 let client = std::mem::replace(&mut handle.client, std::sync::Weak::new());
43 let ptr = client.into_raw() as *mut Client;
44
45 loop {
46 let table = HANDLE_CLIENT_ASSOC.read();
47
48 for (got_id, entry) in table.iter().enumerate() {
49 let got_id: u32 = got_id.try_into().expect("Handle table overflowed u32");
50 if entry
51 .client
52 .compare_exchange(
53 std::ptr::null_mut(),
54 ptr,
55 Ordering::Acquire,
56 Ordering::Relaxed,
57 )
58 .is_ok()
59 {
60 unsafe {
63 *entry.hid.get() = id;
64 return Handle { decoded: got_id + 1 };
65 }
66 }
67 }
68
69 std::mem::drop(table);
70 let mut table = HANDLE_CLIENT_ASSOC.write();
71 let new_len = std::cmp::max(table.len() * 2, HANDLE_CLIENT_ASSOC_START_SIZE);
72
73 let mut new_vec = Vec::with_capacity(new_len);
74 for entry in table.iter() {
75 let hid = unsafe { *entry.hid.get() };
81 let client_ptr = entry.client.load(Ordering::Relaxed);
82 new_vec.push(HandleAssoc {
83 hid: UnsafeCell::new(hid),
84 client: AtomicPtr::new(client_ptr),
85 });
86 }
87 new_vec.resize_with(new_len, || HandleAssoc {
88 hid: UnsafeCell::new(0),
89 client: AtomicPtr::new(std::ptr::null_mut()),
90 });
91
92 let new = new_vec.into_boxed_slice();
93 let new = Box::leak(new);
94 let old = std::mem::replace(&mut *table, new);
95
96 if old.len() > 0 {
97 unsafe { drop(Box::from_raw(old as *const [HandleAssoc] as *mut [HandleAssoc])) }
100 }
101 }
102 }
103}
104
105impl Drop for Handle {
106 fn drop(&mut self) {
107 drop(self.take_handle());
108 }
109}
110
111impl Constrained for Handle {
112 type Constraint = ();
113
114 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
115 Ok(())
116 }
117}
118
119unsafe impl Wire for Handle {
120 type Narrowed<'de> = Self;
121
122 #[inline]
123 fn zero_padding(_: &mut MaybeUninit<Self>) {
124 }
126}
127
128impl Handle {
129 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
131 let encoded = unsafe {
135 munge!(let Self { encoded } = out);
136 encoded
137 };
138 encoded.write(wire::Uint32(u32::MAX));
139 }
140
141 pub fn is_invalid(&self) -> bool {
143 self.as_raw_handle() == 0
144 }
145
146 pub fn invalidate(&mut self) {
147 self.decoded = 0;
148 }
149
150 #[inline]
152 pub fn as_raw_handle(&self) -> u32 {
153 unsafe { self.decoded }
154 }
155
156 pub(crate) fn take_handle(&mut self) -> crate::Handle {
158 unsafe {
161 let pos = self.decoded as usize;
162 self.decoded = 0;
163 let Some(pos) = pos.checked_sub(1) else {
164 return crate::Handle::invalid();
165 };
166 let (id, ptr) = {
167 let table = HANDLE_CLIENT_ASSOC.read();
168 let entry = &table[pos];
169 let hid = *entry.hid.get();
172 let ptr = entry.client.swap(std::ptr::null_mut(), Ordering::Release);
173 (hid, ptr)
174 };
175
176 assert!(!ptr.is_null(), "Attempted to take an invalid or already taken handle slot");
179 let client = std::sync::Weak::from_raw(ptr);
180
181 crate::Handle { id, client }
182 }
183 }
184}
185
186impl fmt::Debug for Handle {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 self.as_raw_handle().fmt(f)
189 }
190}
191
192unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for Handle {
193 fn decode(
194 mut slot: Slot<'_, Self>,
195 decoder: &mut D,
196 _: <Self as Constrained>::Constraint,
197 ) -> Result<(), DecodeError> {
198 let encoded = unsafe {
201 munge!(let Self { encoded } = slot.as_mut());
202 encoded
203 };
204
205 match **encoded {
206 0 => (),
207 u32::MAX => {
208 let handle = decoder.take_raw_handle()?;
209 let mut decoded = unsafe {
212 munge!(let Self { decoded } = slot);
213 decoded
214 };
215 decoded.write(handle);
216 }
217 e => return Err(DecodeError::InvalidHandlePresence(e)),
218 }
219 Ok(())
220 }
221}
222
223#[derive(Debug)]
225#[repr(transparent)]
226pub struct OptionalHandle {
227 pub(crate) handle: Handle,
228}
229
230impl Constrained for OptionalHandle {
231 type Constraint = ();
232
233 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
234 Ok(())
235 }
236}
237
238unsafe impl Wire for OptionalHandle {
239 type Narrowed<'de> = Self;
240
241 #[inline]
242 fn zero_padding(out: &mut MaybeUninit<Self>) {
243 munge!(let Self { handle } = out);
244 Handle::zero_padding(handle);
245 }
246}
247
248impl OptionalHandle {
249 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
251 munge!(let Self { handle } = out);
252 Handle::set_encoded_present(handle);
253 }
254
255 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
257 let encoded = unsafe {
261 munge!(let Self { handle: Handle { encoded } } = out);
262 encoded
263 };
264 encoded.write(wire::Uint32(0));
265 }
266
267 pub fn is_some(&self) -> bool {
269 !self.handle.is_invalid()
270 }
271
272 pub fn is_none(&self) -> bool {
274 self.handle.is_invalid()
275 }
276
277 #[inline]
279 pub fn as_raw_handle(&self) -> Option<u32> {
280 self.is_some().then(|| self.handle.as_raw_handle())
281 }
282}
283
284unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for OptionalHandle {
285 fn decode(
286 mut slot: Slot<'_, Self>,
287 decoder: &mut D,
288 constraint: <Self as Constrained>::Constraint,
289 ) -> Result<(), DecodeError> {
290 munge!(let Self { handle } = slot.as_mut());
291 Handle::decode(handle, decoder, constraint)
292 }
293}
294
295unsafe impl<E: HandleEncoder + ?Sized> Encode<Handle, E> for crate::Handle {
296 fn encode(
297 self,
298 encoder: &mut E,
299 out: &mut MaybeUninit<Handle>,
300 _: (),
301 ) -> Result<(), EncodeError> {
302 if self.client.upgrade().is_none() {
303 Err(EncodeError::InvalidRequiredHandle)
304 } else {
305 encoder.push_handle(self)?;
306 Handle::set_encoded_present(out);
307 Ok(())
308 }
309 }
310}
311
312impl FromWire<Handle> for crate::Handle {
313 fn from_wire(mut wire: Handle) -> Self {
314 wire.take_handle()
315 }
316}
317
318unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<OptionalHandle, E> for crate::Handle {
319 fn encode_option(
320 this: Option<Self>,
321 encoder: &mut E,
322 out: &mut MaybeUninit<OptionalHandle>,
323 _: (),
324 ) -> Result<(), EncodeError> {
325 if let Some(handle) = this {
326 encoder.push_handle(handle)?;
327 OptionalHandle::set_encoded_present(out);
328 } else {
329 OptionalHandle::set_encoded_absent(out);
330 }
331 Ok(())
332 }
333}
334
335impl FromWireOption<OptionalHandle> for crate::Handle {
336 fn from_wire_option(mut wire: OptionalHandle) -> Option<Self> {
337 if wire.handle.is_invalid() { None } else { Some(wire.handle.take_handle()) }
338 }
339}