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 new = std::iter::repeat_with(|| HandleAssoc {
74 hid: UnsafeCell::new(0),
75 client: AtomicPtr::new(std::ptr::null_mut()),
76 })
77 .take(new_len)
78 .collect::<Box<[_]>>();
79
80 let new = Box::leak(new);
81 let old = std::mem::replace(&mut *table, new);
82
83 if old.len() > 0 {
84 unsafe { drop(Box::from_raw(old as *const [HandleAssoc] as *mut [HandleAssoc])) }
87 }
88 }
89 }
90}
91
92impl Drop for Handle {
93 fn drop(&mut self) {
94 drop(self.take_handle());
95 }
96}
97
98impl Constrained for Handle {
99 type Constraint = ();
100
101 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
102 Ok(())
103 }
104}
105
106unsafe impl Wire for Handle {
107 type Narrowed<'de> = Self;
108
109 #[inline]
110 fn zero_padding(_: &mut MaybeUninit<Self>) {
111 }
113}
114
115impl Handle {
116 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
118 munge!(let Self { encoded } = out);
119 encoded.write(wire::Uint32(u32::MAX));
120 }
121
122 pub fn is_invalid(&self) -> bool {
124 self.as_raw_handle() == 0
125 }
126
127 pub fn invalidate(&mut self) {
128 self.decoded = 0;
129 }
130
131 #[inline]
133 pub fn as_raw_handle(&self) -> u32 {
134 unsafe { self.decoded }
135 }
136
137 pub(crate) fn take_handle(&mut self) -> crate::Handle {
139 unsafe {
142 let pos = self.decoded as usize;
143 self.decoded = 0;
144 let Some(pos) = pos.checked_sub(1) else {
145 return crate::Handle::invalid();
146 };
147 let (id, ptr) = {
148 let table = HANDLE_CLIENT_ASSOC.read();
149 let entry = &table[pos];
150 let hid = *entry.hid.get();
153 let ptr = entry.client.swap(std::ptr::null_mut(), Ordering::Release);
154 (hid, ptr)
155 };
156
157 let client = std::sync::Weak::from_raw(ptr);
158
159 crate::Handle { id, client }
160 }
161 }
162}
163
164impl fmt::Debug for Handle {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 self.as_raw_handle().fmt(f)
167 }
168}
169
170unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for Handle {
171 fn decode(
172 mut slot: Slot<'_, Self>,
173 decoder: &mut D,
174 _: <Self as Constrained>::Constraint,
175 ) -> Result<(), DecodeError> {
176 munge!(let Self { encoded } = slot.as_mut());
177
178 match **encoded {
179 0 => (),
180 u32::MAX => {
181 let handle = decoder.take_raw_handle()?;
182 munge!(let Self { mut decoded } = slot);
183 decoded.write(handle);
184 }
185 e => return Err(DecodeError::InvalidHandlePresence(e)),
186 }
187 Ok(())
188 }
189}
190
191#[derive(Debug)]
193#[repr(transparent)]
194pub struct OptionalHandle {
195 pub(crate) handle: Handle,
196}
197
198impl Constrained for OptionalHandle {
199 type Constraint = ();
200
201 fn validate(_: Slot<'_, Self>, _: Self::Constraint) -> Result<(), ValidationError> {
202 Ok(())
203 }
204}
205
206unsafe impl Wire for OptionalHandle {
207 type Narrowed<'de> = Self;
208
209 #[inline]
210 fn zero_padding(out: &mut MaybeUninit<Self>) {
211 munge!(let Self { handle } = out);
212 Handle::zero_padding(handle);
213 }
214}
215
216impl OptionalHandle {
217 pub fn set_encoded_present(out: &mut MaybeUninit<Self>) {
219 munge!(let Self { handle } = out);
220 Handle::set_encoded_present(handle);
221 }
222
223 pub fn set_encoded_absent(out: &mut MaybeUninit<Self>) {
225 munge!(let Self { handle: Handle { encoded } } = out);
226 encoded.write(wire::Uint32(0));
227 }
228
229 pub fn is_some(&self) -> bool {
231 !self.handle.is_invalid()
232 }
233
234 pub fn is_none(&self) -> bool {
236 self.handle.is_invalid()
237 }
238
239 #[inline]
241 pub fn as_raw_handle(&self) -> Option<u32> {
242 self.is_some().then(|| self.handle.as_raw_handle())
243 }
244}
245
246unsafe impl<D: HandleDecoder + ?Sized> Decode<D> for OptionalHandle {
247 fn decode(
248 mut slot: Slot<'_, Self>,
249 decoder: &mut D,
250 constraint: <Self as Constrained>::Constraint,
251 ) -> Result<(), DecodeError> {
252 munge!(let Self { handle } = slot.as_mut());
253 Handle::decode(handle, decoder, constraint)
254 }
255}
256
257unsafe impl<E: HandleEncoder + ?Sized> Encode<Handle, E> for crate::Handle {
258 fn encode(
259 self,
260 encoder: &mut E,
261 out: &mut MaybeUninit<Handle>,
262 _: (),
263 ) -> Result<(), EncodeError> {
264 if self.client.upgrade().is_none() {
265 Err(EncodeError::InvalidRequiredHandle)
266 } else {
267 encoder.push_handle(self)?;
268 Handle::set_encoded_present(out);
269 Ok(())
270 }
271 }
272}
273
274impl FromWire<Handle> for crate::Handle {
275 fn from_wire(mut wire: Handle) -> Self {
276 wire.take_handle()
277 }
278}
279
280unsafe impl<E: HandleEncoder + ?Sized> EncodeOption<OptionalHandle, E> for crate::Handle {
281 fn encode_option(
282 this: Option<Self>,
283 encoder: &mut E,
284 out: &mut MaybeUninit<OptionalHandle>,
285 _: (),
286 ) -> Result<(), EncodeError> {
287 if let Some(handle) = this {
288 encoder.push_handle(handle)?;
289 OptionalHandle::set_encoded_present(out);
290 } else {
291 OptionalHandle::set_encoded_absent(out);
292 }
293 Ok(())
294 }
295}
296
297impl FromWireOption<OptionalHandle> for crate::Handle {
298 fn from_wire_option(mut wire: OptionalHandle) -> Option<Self> {
299 if wire.handle.is_invalid() { None } else { Some(wire.handle.take_handle()) }
300 }
301}