qtbridge_interfaces/object_access/
rust_object_access.rs1use std::mem::MaybeUninit;
5use std::ptr::{self, NonNull, addr_of_mut};
6use std::rc::{Rc, Weak};
7use std::cell::{BorrowError, BorrowMutError, Cell, Ref, RefCell, RefMut};
8
9#[macro_export]
10macro_rules! call_rust_trait_impl {
11 (mut $self:expr, $method:ident ( $($arg:expr),* )) => {
13 $self.rust_obj
14 .try_with_borrow_mut(|vtable| {
15 vtable.$method($($arg),*)
16 })
17 .expect(concat!(
18 "Failed to borrow mutably for ",
19 stringify!($method),
20 "()"
21 ))
22 };
23
24 ($self:expr, $method:ident ( $($arg:expr),* )) => {
26 $self.rust_obj
27 .try_with_borrow(|vtable| {
28 vtable.$method($($arg),*)
29 })
30 .expect(concat!(
31 "Failed to borrow for ",
32 stringify!($method),
33 "()"
34 ))
35 };
36}
37
38#[macro_export]
39macro_rules! call_cpp_impl {
40 (mut $self:expr, $method:ident ( $($arg:expr),* )) => {{
41 let proxy = unsafe {
42 $self.cpp_proxy
43 .as_mut()
44 .expect("cpp_proxy was null")
45 };
46 let proxy_pinned = unsafe { std::pin::Pin::new_unchecked(proxy) };
47 $self.rust_obj
48 .try_store_handle_and_call_qml_mut(|_| proxy_pinned.$method($($arg),*))
49 .expect(concat!(
50 "Failed to borrow mutably for ",
51 stringify!($method),
52 "()"
53 ))
54 }};
55
56 ($self:expr, $method:ident ( $($arg:expr),* )) => {{
57 let proxy = unsafe {
58 $self.cpp_proxy
59 .as_ref()
60 .expect("cpp_proxy was null")
61 };
62 $self.rust_obj
63 .try_store_handle_and_call_qml(|_| proxy.$method($($arg),*))
64 .expect(concat!(
65 "Failed to borrow for ",
66 stringify!($method),
67 "()"
68 ))
69 }};
70}
71
72
73pub struct RustObjAccess<T: ?Sized + 'static>
98{
99 shared_reference: SharedReferenceWithQml<T>,
100 borrow_handle: Cell<*mut RustObjBorrowHandle<'static, T>>,
101}
102
103impl<T: ?Sized> RustObjAccess<T> {
104 pub fn new_strong(ptr: Rc<RefCell<T>>) -> Self {
105 Self {
106 shared_reference: SharedReferenceWithQml::OwnedByRust(ptr),
107 borrow_handle: Cell::new(ptr::null_mut()),
108 }
109 }
110
111 pub fn new_weak(ptr: Weak<RefCell<T>>) -> Self {
112 Self {
113 shared_reference: SharedReferenceWithQml::OwnedByQml(ptr),
114 borrow_handle: Cell::new(ptr::null_mut()),
115 }
116 }
117
118 pub fn try_with_borrow<F, R>(&self, f: F) -> Result<R, RustObjAccessError>
119 where F:FnOnce(&T) -> R
120 {
121 let ptr_to_borrowed = self.borrow_handle.get();
123 if let Some(borrowed) = unsafe { ptr_to_borrowed.as_ref() } {
124 return Ok(f(borrowed.obj_ref.deref()))
125 };
126
127 let rc = self.shared_reference.get_rc()
129 .ok_or(RustObjAccessError::ExpiredWeakPtr)?;
130 let mut borrowed = RustObjBorrowHandle::new(rc, false)?;
131
132 self.borrow_handle.set(&mut borrowed);
134 let result = f(borrowed.obj_ref.deref());
135 self.borrow_handle.set(ptr::null_mut());
136
137 Ok(result)
138 }
139
140 pub fn try_with_borrow_mut<F, R>(&self, f: F) -> Result<R, RustObjAccessError>
141 where F:FnOnce(&mut T) -> R
142 {
143 let ptr_to_borrowed = self.borrow_handle.get();
144 if let Some(borrowed) = unsafe { ptr_to_borrowed.as_mut() } {
145 match &mut borrowed.obj_ref {
146 RustHandle::Immutable(_) |
147 RustHandle::ImmutableUnguardedBorrow(_) => {
148 let _ref = borrowed.obj_rc.try_borrow_mut()
150 .map_err(|err| RustObjAccessError::BorrowMutError(err))?;
151 unreachable!()
152 },
153 RustHandle::Mutable(_) |
154 RustHandle::MutableUnguardedBorrow(_) => {
155 return Ok(f(borrowed.obj_ref.deref_mut().unwrap()))
156 }
157 }
158 }
159
160 let rc = self.shared_reference.get_rc()
161 .ok_or(RustObjAccessError::ExpiredWeakPtr)?;
162 let mut borrowed = RustObjBorrowHandle::new(rc, true)?;
163
164 self.borrow_handle.set(&mut borrowed);
165 let result = f(borrowed.obj_ref.deref_mut().unwrap());
166 self.borrow_handle.set(ptr::null_mut());
167
168 Ok(result)
169 }
170
171 pub fn try_store_handle_and_call_qml<F, R>(&self, f: F) -> Result<R, RustObjAccessError>
192 where F:FnOnce(&T) -> R
193 {
194 let ptr_to_borrowed = self.borrow_handle.get();
195 if let Some(borrowed) = unsafe { ptr_to_borrowed.as_ref() } {
196 return Ok(f(borrowed.obj_ref.deref()))
197 }
198
199 let rc = self.shared_reference.get_rc()
200 .ok_or(RustObjAccessError::ExpiredWeakPtr)?;
201
202 {
205 match rc.try_borrow_mut() {
207 Ok(_) => return Err(RustObjAccessError::ExpectedBorrowed),
208 Err(_) => {},
209 }
210
211 rc.try_borrow()
213 .map_err(|_err| RustObjAccessError::ExpectedBorrowed)?;
214 }
215
216 let mut borrowed = RustObjBorrowHandle::new_unguarded(rc, false);
217
218 self.borrow_handle.set(&mut borrowed);
219 let result = f(borrowed.obj_ref.deref());
220 self.borrow_handle.set(ptr::null_mut());
221
222 Ok(result)
223 }
224
225 pub fn try_store_handle_and_call_qml_mut<F, R>(&self, f: F) -> Result<R, RustObjAccessError>
227 where F:FnOnce(&mut T) -> R
228 {
229 let ptr_to_borrowed = self.borrow_handle.get();
230 if let Some(borrowed) = unsafe { ptr_to_borrowed.as_mut() } {
231 match &mut borrowed.obj_ref {
232 RustHandle::Immutable(_) |
233 RustHandle::ImmutableUnguardedBorrow(_) => {
234 let _ref = borrowed.obj_rc.try_borrow_mut()
236 .map_err(|err| RustObjAccessError::BorrowMutError(err))?;
237 panic!("Object assumed to be borrowed but it is not")
238 },
239 RustHandle::Mutable(_) |
240 RustHandle::MutableUnguardedBorrow(_) => {
241 return Ok(f(borrowed.obj_ref.deref_mut().unwrap()))
242 }
243 }
244 }
245
246 let rc = self.shared_reference.get_rc()
247 .ok_or(RustObjAccessError::ExpiredWeakPtr)?;
248
249 {
252 match rc.try_borrow_mut() {
254 Ok(_) => return Err(RustObjAccessError::ExpectedBorrowedMut),
255 Err(_) => {},
256 }
257
258 match rc.try_borrow() {
260 Ok(_) => return Err(RustObjAccessError::ExpectedBorrowedMut),
261 Err(_) => {},
262 }
263 }
264
265 let mut borrowed = RustObjBorrowHandle::new_unguarded(rc, true);
266
267 self.borrow_handle.set(&mut borrowed);
268 let result = f(borrowed.obj_ref.deref_mut().unwrap());
269 self.borrow_handle.set(ptr::null_mut());
270
271 Ok(result)
272 }
273
274}
275
276#[derive(Debug)]
278pub enum RustObjAccessError {
279 BorrowError(BorrowError),
281 BorrowMutError(BorrowMutError),
282 ExpiredWeakPtr,
283 ExpectedBorrowed,
284 ExpectedBorrowedMut,
285}
286
287impl From<BorrowError> for RustObjAccessError {
288 fn from(value: BorrowError) -> Self {
289 Self::BorrowError(value)
290 }
291}
292
293impl From<BorrowMutError> for RustObjAccessError {
294 fn from(value: BorrowMutError) -> Self {
295 Self::BorrowMutError(value)
296 }
297}
298
299pub enum SharedReferenceWithQml<T: ?Sized> {
300 OwnedByRust(Rc<RefCell<T>>),
301 OwnedByQml(Weak<RefCell<T>>),
302}
303
304impl<T: ?Sized> SharedReferenceWithQml<T> {
305 fn get_rc(&self) -> Option<Rc<RefCell<T>>> {
306 match self {
307 SharedReferenceWithQml::OwnedByRust(rc) => Some(rc.clone()),
308 SharedReferenceWithQml::OwnedByQml(weak) => weak.upgrade()
309 }
310 }
311}
312
313struct RustObjBorrowHandle<'a, T: ?Sized> {
315 obj_rc: Rc<RefCell<T>>,
317
318 obj_ref: RustHandle<'a, T>,
320}
321
322impl<'a, T: ?Sized> RustObjBorrowHandle<'a, T> {
323 fn new(rc: Rc<RefCell<T>>, is_mutable: bool) -> Result<Self, RustObjAccessError> {
324 let mut uninit: MaybeUninit<Self> = MaybeUninit::uninit();
325 let ptr = uninit.as_mut_ptr();
326 unsafe {
327 addr_of_mut!((*ptr).obj_rc).write(rc.clone());
328 addr_of_mut!((*ptr).obj_ref).write(RustHandle::new(&(*ptr).obj_rc, is_mutable)?);
329 Ok(uninit.assume_init())
330 }
331 }
332
333 fn new_unguarded(rc: Rc<RefCell<T>>, is_mutable: bool) -> Self {
334 let mut uninit: MaybeUninit<Self> = MaybeUninit::uninit();
335 let ptr = uninit.as_mut_ptr();
336 unsafe {
337 addr_of_mut!((*ptr).obj_rc).write(rc.clone());
338 addr_of_mut!((*ptr).obj_ref).write(RustHandle::new_unguarded(&(*ptr).obj_rc, is_mutable));
339 uninit.assume_init()
340 }
341 }
342}
343
344enum RustHandle<'a, T: ?Sized> {
348 Immutable(Ref<'a, T>),
349 Mutable(RefMut<'a, T>),
350 ImmutableUnguardedBorrow(NonNull<T>),
351 MutableUnguardedBorrow(NonNull<T>),
352}
353
354impl<'a, T: ?Sized> RustHandle<'a, T> {
355 fn new(rc: &'a Rc<RefCell<T>>, is_mutable: bool) -> Result<Self, RustObjAccessError> {
356 match is_mutable {
357 true => Ok(Self::Mutable(
358 rc.try_borrow_mut()
359 .map_err(RustObjAccessError::from)?
360 )),
361 false => Ok(Self::Immutable(
362 rc.try_borrow()
363 .map_err(RustObjAccessError::from)?
364 ))
365 }
366 }
367
368 fn new_unguarded(rc: &'a Rc<RefCell<T>>, is_mutable: bool) -> Self {
369 let nn = NonNull::new(rc.as_ptr()).unwrap();
372 match is_mutable {
373 true => Self::MutableUnguardedBorrow(nn),
374 false => Self::ImmutableUnguardedBorrow(nn),
375 }
376 }
377
378 fn deref(&self) -> &T {
379 match self {
380 Self::Immutable(ref_) => ref_,
381 Self::Mutable(ref_mut) => ref_mut,
382 Self::ImmutableUnguardedBorrow(ptr) => unsafe { ptr.as_ref() },
383 Self::MutableUnguardedBorrow(ptr) => unsafe {ptr.as_ref() },
384 }
385 }
386
387 fn deref_mut(&mut self) -> Option<&mut T> {
388 match self {
389 Self::Immutable(_) => None,
390 Self::ImmutableUnguardedBorrow(_) => None,
391 Self::Mutable(ref_mut) => Some(ref_mut),
392 Self::MutableUnguardedBorrow(ptr) => Some(unsafe {ptr.as_mut() }),
393 }
394 }
395}