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 munge!(let Self { encoded } = out);
132 encoded.write(wire::Uint32(u32::MAX));
133 }
134
135 pub fn is_invalid(&self) -> bool {
137 self.as_raw_handle() == 0
138 }
139
140 pub fn invalidate(&mut self) {
141 self.decoded = 0;
142 }
143
144 #[inline]
146 pub fn as_raw_handle(&self) -> u32 {
147 unsafe { self.decoded }
148 }
149
150 pub(crate) fn take_handle(&mut self) -> crate::Handle {
152 unsafe {
155 let pos = self.decoded as usize;
156 self.decoded = 0;
157 let Some(pos) = pos.checked_sub(1) else {
158 return crate::Handle::invalid();
159 };
160 let (id, ptr) = {
161 let table = HANDLE_CLIENT_ASSOC.read();
162 let entry = &table[pos];
163 let hid = *entry.hid.get();
166 let ptr = entry.client.swap(std::ptr::null_mut(), Ordering::Release);
167 (hid, ptr)
168 };
169
170 assert!(!ptr.is_null(), "Attempted to take an invalid or already taken handle slot");
173 let client = std::sync::Weak::from_raw(ptr);
174
175 crate::Handle { id, client }
176 }
177 }
178}
179
180impl fmt::Debug for Handle {
181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 self.as_raw_handle().fmt(f)
183 }
184}
185
186unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for Handle {
187 fn decode(
188 mut slot: Slot<'_, Self>,
189 decoder: &mut D,
190 _: <Self as Constrained>::Constraint,
191 ) -> Result<(), DecodeError> {
192 munge!(let Self { encoded } = slot.as_mut());
193
194 match **encoded {
195 0 => (),
196 u32::MAX => {
197 let handle = decoder.take_raw_handle()?;
198 munge!(let Self { mut decoded } = slot);
199 decoded.write(handle);
200 }
201 e => return Err(DecodeError::InvalidHandlePresence(e)),
202 }
203 Ok(())
204 }
205}
206
207#[derive(Debug)]
209#[repr(transparent)]
210pub struct OptionalHandle {
211 pub(crate) handle: Handle,
212}
213
214impl Constrained for OptionalHandle {
215 type Constraint = ();
216
217 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
218 Ok(())
219 }
220}
221
222unsafe impl Wire for OptionalHandle {
223 type Narrowed<'de> = Self;
224
225 #[inline]
226 fn zero_padding(out: &mut MaybeUninit<Self>) {
227 munge!(let Self { handle } = out);
228 Handle::zero_padding(handle);
229 }
230}
231
232impl OptionalHandle {
233 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
235 munge!(let Self { handle } = out);
236 Handle::set_encoded_present(handle);
237 }
238
239 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
241 munge!(let Self { handle: Handle { encoded } } = out);
242 encoded.write(wire::Uint32(0));
243 }
244
245 pub fn is_some(&self) -> bool {
247 !self.handle.is_invalid()
248 }
249
250 pub fn is_none(&self) -> bool {
252 self.handle.is_invalid()
253 }
254
255 #[inline]
257 pub fn as_raw_handle(&self) -> Option<u32> {
258 self.is_some().then(|| self.handle.as_raw_handle())
259 }
260}
261
262unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for OptionalHandle {
263 fn decode(
264 mut slot: Slot<'_, Self>,
265 decoder: &mut D,
266 constraint: <Self as Constrained>::Constraint,
267 ) -> Result<(), DecodeError> {
268 munge!(let Self { handle } = slot.as_mut());
269 Handle::decode(handle, decoder, constraint)
270 }
271}
272
273unsafe impl<E: HandleEncoder + ?Sized> Encode<Handle, E> for crate::Handle {
274 fn encode(
275 self,
276 encoder: &mut E,
277 out: &mut MaybeUninit<Handle>,
278 _: (),
279 ) -> Result<(), EncodeError> {
280 if self.client.upgrade().is_none() {
281 Err(EncodeError::InvalidRequiredHandle)
282 } else {
283 encoder.push_handle(self)?;
284 Handle::set_encoded_present(out);
285 Ok(())
286 }
287 }
288}
289
290impl FromWire<Handle> for crate::Handle {
291 fn from_wire(mut wire: Handle) -> Self {
292 wire.take_handle()
293 }
294}
295
296unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<OptionalHandle, E> for crate::Handle {
297 fn encode_option(
298 this: Option<Self>,
299 encoder: &mut E,
300 out: &mut MaybeUninit<OptionalHandle>,
301 _: (),
302 ) -> Result<(), EncodeError> {
303 if let Some(handle) = this {
304 encoder.push_handle(handle)?;
305 OptionalHandle::set_encoded_present(out);
306 } else {
307 OptionalHandle::set_encoded_absent(out);
308 }
309 Ok(())
310 }
311}
312
313impl FromWireOption<OptionalHandle> for crate::Handle {
314 fn from_wire_option(mut wire: OptionalHandle) -> Option<Self> {
315 if wire.handle.is_invalid() { None } else { Some(wire.handle.take_handle()) }
316 }
317}