gdnative_core/export/
user_data.rs

1//! Customizable user-data wrappers.
2//!
3//! ## `NativeClass` and user-data
4//!
5//! In Godot Engine, scripted behavior is attached to base objects through "script instances":
6//! objects that store script state, and allow dynamic dispatch of overridden methods. GDNative
7//! exposes this to native languages as a `void *` pointer, known as "user-data", that may point
8//! to anything defined by the native library in question.
9//!
10//! Godot is written in C++, and unlike Rust, it doesn't have the same strict reference aliasing
11//! constraints. This user-data pointer can be aliased mutably, and called freely from different
12//! threads by the engine or other scripts. Thus, to maintain safety, wrapper types are to be used
13//! to make sure that the Rust rules for references are always held for the `self` argument, and
14//! no UB can occur because we freed `owner` or put another script on it.
15//!
16//! ## Choosing a wrapper type
17//!
18//! The default user data wrapper used by derive macro, when no `user_data` attribute is present,
19//! is defined as the type alias `DefaultUserData<T>`. Currently, it is `LocalCellData<T>`. This
20//! may change in the future, and changes to it will not be considered breaking changes.
21//!
22//! To choose another wrapper type, put the `#[user_data]` attribute on your `NativeScript` type
23//! if you are using the derive macro:
24//!
25//! ```ignore
26//! #[derive(NativeClass)]
27//! #[inherit(gdnative::api::Node)]
28//! #[user_data(gdnative::export::user_data::MutexData<HelloWorld>)]
29//! struct HelloWorld;
30//! ```
31//!
32//! ...or, if you are implementing `NativeScript` manually, set the `UserData` associated type
33//! to the type you choose.
34//!
35//! ## Which wrapper to use?
36//!
37//! ### Use a `MutexData<T>` when:
38//!
39//! - You don't want to handle locks explicitly.
40//! - Your `NativeClass` type is only `Send`, but not `Sync`.
41//!
42//! ### Use a `RwLockData<T>` when:
43//!
44//! - You don't want to handle locks explicitly.
45//! - Some of your exported methods take `&self`, and you don't need them to be exclusive.
46//! - Your `NativeClass` type is `Send + Sync`.
47//!
48//! ### Use a `ArcData<T>` when:
49//!
50//! - You want safety for your methods, but can't tolerate lock overhead on each method call.
51//! - You want fine grained lock control for parallelism.
52//! - All your exported methods take `&self`.
53//! - Your `NativeClass` type is `Send + Sync`.
54//!
55//! ### Use a `LocalCellData<T>` when:
56//!
57//! - Your `NativeClass` type is not `Send`, and you will only ever use it from the thread where
58//!   it's originally created.
59//!
60//! ### Use `Aether<T>` when:
61//!
62//! - Your `NativeClass` type is a zero-sized type (ZST) that is `Copy + Default`.
63//! - You don't need to do anything special in `Drop`.
64
65use parking_lot::{Mutex, RwLock};
66use std::fmt::{self, Debug, Display};
67use std::marker::PhantomData;
68use std::mem;
69use std::sync::Arc;
70use std::time::Duration;
71
72use crate::export::NativeClass;
73
74/// Trait for customizable user-data wrappers.
75///
76/// See module-level documentation for detailed explanation on user-data.
77pub unsafe trait UserData: Sized + Clone {
78    type Target: NativeClass;
79
80    /// Creates a new owned wrapper from a `NativeClass` instance.
81    ///
82    /// This operation must never fail.
83    fn new(val: Self::Target) -> Self;
84
85    /// Takes a native instance and returns an opaque pointer that can be used to recover it.
86    ///
87    /// This gives "ownership" to the engine.
88    ///
89    /// This operation must never fail.
90    fn into_user_data(self) -> *const libc::c_void;
91
92    /// Takes an opaque pointer produced by `into_user_data` and "consumes" it to produce the
93    /// original instance, keeping the reference count.
94    ///
95    /// This should be used when "ownership" is taken from the engine, i.e. destructors.
96    /// Use elsewhere can lead to premature drops of the instance contained inside.
97    ///
98    /// `ptr` is guaranteed to be non-null.
99    ///
100    /// This operation must never fail.
101    ///
102    /// # Safety
103    ///
104    /// `ptr` must be pointing to valid data of the correct type.
105    unsafe fn consume_user_data_unchecked(ptr: *const libc::c_void) -> Self;
106
107    /// Takes an opaque pointer produced by `into_user_data` and "clones" it to produce the
108    /// original instance, increasing the reference count.
109    ///
110    /// This should be used when user data is "borrowed" from the engine.
111    ///
112    /// `ptr` is guaranteed to be non-null.
113    ///
114    /// This operation must never fail.
115    ///
116    /// # Safety
117    ///
118    /// `ptr` must be pointing to valid data of the correct type.
119    unsafe fn clone_from_user_data_unchecked(ptr: *const libc::c_void) -> Self;
120}
121
122/// Trait for wrappers that can be mapped immutably.
123pub trait Map: UserData {
124    type Err: Debug;
125
126    /// Maps a `&T` to `U`. Called for methods that take `&self`.
127    ///
128    /// Implementations of this method must not panic. Failures should be indicated by
129    /// returning `Err`.
130    fn map<F, U>(&self, op: F) -> Result<U, Self::Err>
131    where
132        F: FnOnce(&Self::Target) -> U;
133}
134
135/// Trait for wrappers that can be mapped mutably.
136pub trait MapMut: UserData {
137    type Err: Debug;
138
139    /// Maps a `&mut T` to `U`. Called for methods that take `&mut self`.
140    ///
141    /// Implementations of this method must not panic. Failures should be indicated by
142    /// returning `Err`.
143    fn map_mut<F, U>(&self, op: F) -> Result<U, Self::Err>
144    where
145        F: FnOnce(&mut Self::Target) -> U;
146}
147
148/// Trait for wrappers that can be mapped once.
149pub trait MapOwned: UserData {
150    type Err: Debug;
151
152    /// Maps a `T` to `U`. Called for methods that take `self`. This method may fail with
153    /// an error if it is called more than once on the same object.
154    ///
155    /// Implementations of this method must not panic. Failures should be indicated by
156    /// returning `Err`.
157    fn map_owned<F, U>(&self, op: F) -> Result<U, Self::Err>
158    where
159        F: FnOnce(Self::Target) -> U;
160}
161
162/// The default user data wrapper used by derive macro, when no `user_data` attribute is present.
163/// This may change in the future.
164pub type DefaultUserData<T> = LocalCellData<T>;
165
166/// Error type indicating that an operation can't fail.
167#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
168pub enum Infallible {}
169
170impl std::fmt::Display for Infallible {
171    #[inline]
172    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
173        write!(f, "operation that can't fail just failed")
174    }
175}
176
177/// Policies to deal with potential deadlocks
178///
179/// As Godot allows mutable pointer aliasing, doing certain things in exported method bodies may
180/// lead to the engine calling another method on `owner`, leading to another locking attempt
181/// within the same thread:
182///
183/// - Variant calls on anything may dispatch to a script method.
184/// - Anything that could emit signals, that are connected to in a non-deferred manner.
185///
186/// As there is no universal way to deal with such situations, behavior of locking wrappers can
187/// be customized using this enum.
188#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
189pub enum DeadlockPolicy {
190    /// Block on all locks. Deadlocks are possible.
191    Allow,
192
193    /// Never block on any locks. Methods will return Nil immediately if the lock isn't
194    /// available. Deadlocks are prevented.
195    Pessimistic,
196
197    /// Block on locks for at most `Duration`. Methods return Nil on timeout. Deadlocks are
198    /// prevented.
199    Timeout(Duration),
200}
201
202/// Trait defining associated constants for locking wrapper options
203///
204/// This is required because constant generics ([RFC 2000][rfc-2000]) isn't available in stable
205/// rust yet.
206///
207/// See also `DeadlockPolicy`.
208///
209/// [rfc-2000]: https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md
210pub trait LockOptions {
211    const DEADLOCK_POLICY: DeadlockPolicy;
212}
213
214/// Default lock policy that may change in future versions.
215///
216/// Currently, it has a deadlock policy of `Allow`.
217#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
218pub struct DefaultLockPolicy;
219
220impl LockOptions for DefaultLockPolicy {
221    const DEADLOCK_POLICY: DeadlockPolicy = DeadlockPolicy::Allow;
222}
223
224/// Error indicating that a lock wasn't obtained.
225#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
226pub enum LockFailed {
227    Pessimistic,
228    Timeout(Duration),
229}
230
231impl std::fmt::Display for LockFailed {
232    #[inline]
233    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234        match self {
235            LockFailed::Timeout(wait) => write!(f, "failed to acquire lock within {wait:?}"),
236            LockFailed::Pessimistic => write!(f, "failed to acquire lock, it was already held"),
237        }
238    }
239}
240impl std::error::Error for LockFailed {}
241
242/// User-data wrapper encapsulating a `Arc<Mutex<T>>`.
243///
244/// The underlying `Mutex` may change in the future. The current implementation is
245/// `parking_lot`.
246#[derive(Debug)]
247pub struct MutexData<T, OPT = DefaultLockPolicy> {
248    lock: Arc<Mutex<T>>,
249    _marker: PhantomData<OPT>,
250}
251
252unsafe impl<T, OPT> UserData for MutexData<T, OPT>
253where
254    T: NativeClass + Send,
255    OPT: LockOptions,
256{
257    type Target = T;
258
259    #[inline]
260    fn new(val: Self::Target) -> Self {
261        MutexData {
262            lock: Arc::new(Mutex::new(val)),
263            _marker: PhantomData,
264        }
265    }
266
267    #[inline]
268    fn into_user_data(self) -> *const libc::c_void {
269        Arc::into_raw(self.lock) as *const libc::c_void
270    }
271
272    #[inline]
273    unsafe fn consume_user_data_unchecked(ptr: *const libc::c_void) -> Self {
274        MutexData {
275            lock: Arc::from_raw(ptr as *const Mutex<T>),
276            _marker: PhantomData,
277        }
278    }
279
280    #[inline]
281    unsafe fn clone_from_user_data_unchecked(ptr: *const libc::c_void) -> Self {
282        let borrowed = Arc::from_raw(ptr as *const Mutex<T>);
283        let lock = borrowed.clone();
284        mem::forget(borrowed);
285        MutexData {
286            lock,
287            _marker: PhantomData,
288        }
289    }
290}
291
292impl<T, OPT> Map for MutexData<T, OPT>
293where
294    T: NativeClass + Send,
295    OPT: LockOptions,
296{
297    type Err = LockFailed;
298
299    #[inline]
300    fn map<F, U>(&self, op: F) -> Result<U, LockFailed>
301    where
302        F: FnOnce(&T) -> U,
303    {
304        self.map_mut(|val| op(val))
305    }
306}
307
308impl<T, OPT> MapMut for MutexData<T, OPT>
309where
310    T: NativeClass + Send,
311    OPT: LockOptions,
312{
313    type Err = LockFailed;
314
315    #[inline]
316    fn map_mut<F, U>(&self, op: F) -> Result<U, LockFailed>
317    where
318        F: FnOnce(&mut T) -> U,
319    {
320        let mut guard = match OPT::DEADLOCK_POLICY {
321            DeadlockPolicy::Allow => self.lock.lock(),
322            DeadlockPolicy::Pessimistic => self.lock.try_lock().ok_or(LockFailed::Pessimistic)?,
323            DeadlockPolicy::Timeout(dur) => self
324                .lock
325                .try_lock_for(dur)
326                .ok_or(LockFailed::Timeout(dur))?,
327        };
328
329        Ok(op(&mut *guard))
330    }
331}
332
333impl<T, OPT> Clone for MutexData<T, OPT> {
334    #[inline]
335    fn clone(&self) -> Self {
336        MutexData {
337            lock: self.lock.clone(),
338            _marker: PhantomData,
339        }
340    }
341}
342
343/// User-data wrapper encapsulating a `Arc<RwLock<T>>`.
344///
345/// The underlying `RwLock` may change in the future. The current implementation is
346/// `parking_lot`.
347#[derive(Debug)]
348pub struct RwLockData<T, OPT = DefaultLockPolicy> {
349    lock: Arc<RwLock<T>>,
350    _marker: PhantomData<OPT>,
351}
352
353unsafe impl<T, OPT> UserData for RwLockData<T, OPT>
354where
355    T: NativeClass + Send + Sync,
356    OPT: LockOptions,
357{
358    type Target = T;
359
360    #[inline]
361    fn new(val: Self::Target) -> Self {
362        RwLockData {
363            lock: Arc::new(RwLock::new(val)),
364            _marker: PhantomData,
365        }
366    }
367
368    #[inline]
369    fn into_user_data(self) -> *const libc::c_void {
370        Arc::into_raw(self.lock) as *const libc::c_void
371    }
372
373    #[inline]
374    unsafe fn consume_user_data_unchecked(ptr: *const libc::c_void) -> Self {
375        RwLockData {
376            lock: Arc::from_raw(ptr as *const RwLock<T>),
377            _marker: PhantomData,
378        }
379    }
380
381    #[inline]
382    unsafe fn clone_from_user_data_unchecked(ptr: *const libc::c_void) -> Self {
383        let borrowed = Arc::from_raw(ptr as *const RwLock<T>);
384        let lock = borrowed.clone();
385        mem::forget(borrowed);
386        RwLockData {
387            lock,
388            _marker: PhantomData,
389        }
390    }
391}
392
393impl<T, OPT> Map for RwLockData<T, OPT>
394where
395    T: NativeClass + Send + Sync,
396    OPT: LockOptions,
397{
398    type Err = LockFailed;
399
400    #[inline]
401    fn map<F, U>(&self, op: F) -> Result<U, LockFailed>
402    where
403        F: FnOnce(&T) -> U,
404    {
405        let guard = match OPT::DEADLOCK_POLICY {
406            DeadlockPolicy::Allow => self.lock.read(),
407            DeadlockPolicy::Pessimistic => self.lock.try_read().ok_or(LockFailed::Pessimistic)?,
408            DeadlockPolicy::Timeout(dur) => self
409                .lock
410                .try_read_for(dur)
411                .ok_or(LockFailed::Timeout(dur))?,
412        };
413
414        Ok(op(&*guard))
415    }
416}
417
418impl<T, OPT> MapMut for RwLockData<T, OPT>
419where
420    T: NativeClass + Send + Sync,
421    OPT: LockOptions,
422{
423    type Err = LockFailed;
424
425    #[inline]
426    fn map_mut<F, U>(&self, op: F) -> Result<U, LockFailed>
427    where
428        F: FnOnce(&mut T) -> U,
429    {
430        let mut guard = match OPT::DEADLOCK_POLICY {
431            DeadlockPolicy::Allow => self.lock.write(),
432            DeadlockPolicy::Pessimistic => self.lock.try_write().ok_or(LockFailed::Pessimistic)?,
433            DeadlockPolicy::Timeout(dur) => self
434                .lock
435                .try_write_for(dur)
436                .ok_or(LockFailed::Timeout(dur))?,
437        };
438
439        Ok(op(&mut *guard))
440    }
441}
442
443impl<T, OPT> Clone for RwLockData<T, OPT> {
444    #[inline]
445    fn clone(&self) -> Self {
446        RwLockData {
447            lock: self.lock.clone(),
448            _marker: PhantomData,
449        }
450    }
451}
452
453/// User-data wrapper encapsulating a `Arc<T>`. Does not implement `MapMut`.
454#[derive(Debug)]
455pub struct ArcData<T>(Arc<T>);
456
457impl<T> ArcData<T> {
458    /// Returns the internal `Arc<T>`. Useful for API's that require an `Arc`
459    /// directly, or for coercing it into a trait object.
460    ///
461    /// Note that this removes
462    /// the restriction of only being able to access the `NativeClass` instance
463    /// temporarily through the `Map` trait; however, it should be exactly as safe
464    /// as permanently storing an owned `ArcData` and then calling `.map()` on
465    /// it later.
466    #[inline]
467    pub fn into_inner(self) -> Arc<T> {
468        self.0
469    }
470}
471
472unsafe impl<T> UserData for ArcData<T>
473where
474    T: NativeClass + Send + Sync,
475{
476    type Target = T;
477
478    #[inline]
479    fn new(val: Self::Target) -> Self {
480        ArcData(Arc::new(val))
481    }
482
483    #[inline]
484    fn into_user_data(self) -> *const libc::c_void {
485        Arc::into_raw(self.0) as *const libc::c_void
486    }
487
488    #[inline]
489    unsafe fn consume_user_data_unchecked(ptr: *const libc::c_void) -> Self {
490        ArcData(Arc::from_raw(ptr as *const T))
491    }
492
493    #[inline]
494    unsafe fn clone_from_user_data_unchecked(ptr: *const libc::c_void) -> Self {
495        let borrowed = Arc::from_raw(ptr as *const T);
496        let arc = borrowed.clone();
497        mem::forget(borrowed);
498        ArcData(arc)
499    }
500}
501
502impl<T> Map for ArcData<T>
503where
504    T: NativeClass + Send + Sync,
505{
506    type Err = Infallible;
507
508    #[inline]
509    fn map<F, U>(&self, op: F) -> Result<U, Infallible>
510    where
511        F: FnOnce(&T) -> U,
512    {
513        Ok(op(&*self.0))
514    }
515}
516
517impl<T> Clone for ArcData<T> {
518    #[inline]
519    fn clone(&self) -> Self {
520        ArcData(self.0.clone())
521    }
522}
523
524/// User-data wrapper analogous to a `Arc<RefCell<T>>`, that is restricted to the thread
525/// where it was originally created. The destructor of `T` is not guaranteed to be run if
526/// this is actually shared across multiple threads.
527///
528/// This works by checking `ThreadId` before touching the underlying reference. If the id
529/// doesn't match the original thread, `map` and `map_mut` will return an error.
530///
531/// Since it isn't possible to control where the last reference is dropped, the destructor
532/// isn't run if the last reference is dropped on a different thread than the one where the
533/// wrapper was originally created. To ensure that values are cleaned up properly, keep the
534/// game single-threaded, or use a real thread-safe wrapper such as [`MutexData`] instead.
535#[derive(Debug)]
536pub struct LocalCellData<T> {
537    inner: Arc<local_cell::LocalCell<T>>,
538}
539
540pub use self::local_cell::LocalCellError;
541
542mod local_cell {
543    use std::cell::{Ref, RefCell, RefMut};
544    use std::mem::ManuallyDrop;
545    use std::thread::{self, ThreadId};
546
547    #[derive(Debug)]
548    pub struct LocalCell<T> {
549        thread_id: ThreadId,
550        cell: RefCell<ManuallyDrop<T>>,
551    }
552
553    impl<T> Drop for LocalCell<T> {
554        fn drop(&mut self) {
555            if self.thread_id == thread::current().id() {
556                unsafe {
557                    ManuallyDrop::drop(self.cell.get_mut());
558                }
559            }
560        }
561    }
562
563    /// Error indicating that a borrow has failed.
564    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
565    pub enum LocalCellError {
566        DifferentThread {
567            original: ThreadId,
568            current: ThreadId,
569        },
570        BorrowFailed,
571    }
572
573    impl std::fmt::Display for LocalCellError {
574        #[inline]
575        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
576            match self {
577                LocalCellError::DifferentThread { original, current } => write!(
578                    f,
579                    "accessing from the wrong thread, expected {original:?} found {current:?}"
580                ),
581                LocalCellError::BorrowFailed => write!(
582                    f,
583                    "borrow failed; a &mut reference was requested, but one already exists. The cause is likely a re-entrant call \
584                    (e.g. a GDNative Rust method calls to GDScript, which again calls a Rust method on the same object)"
585                ),
586            }
587        }
588    }
589
590    impl std::error::Error for LocalCellError {}
591
592    impl<T> LocalCell<T> {
593        #[inline]
594        pub fn new(val: T) -> Self {
595            LocalCell {
596                thread_id: thread::current().id(),
597                cell: RefCell::new(ManuallyDrop::new(val)),
598            }
599        }
600
601        #[inline]
602        fn inner(&self) -> Result<&RefCell<ManuallyDrop<T>>, LocalCellError> {
603            let current = thread::current().id();
604
605            if self.thread_id == current {
606                Ok(&self.cell)
607            } else {
608                Err(LocalCellError::DifferentThread {
609                    original: self.thread_id,
610                    current,
611                })
612            }
613        }
614
615        #[inline]
616        pub fn try_borrow(&self) -> Result<Ref<ManuallyDrop<T>>, LocalCellError> {
617            let inner = self.inner()?;
618            inner.try_borrow().map_err(|_| LocalCellError::BorrowFailed)
619        }
620
621        #[inline]
622        pub fn try_borrow_mut(&self) -> Result<RefMut<ManuallyDrop<T>>, LocalCellError> {
623            let inner = self.inner()?;
624            inner
625                .try_borrow_mut()
626                .map_err(|_| LocalCellError::BorrowFailed)
627        }
628    }
629
630    // Implementing Send + Sync is ok because the cell is guarded from access outside the
631    // original thread.
632    unsafe impl<T> Send for LocalCell<T> {}
633    unsafe impl<T> Sync for LocalCell<T> {}
634}
635
636unsafe impl<T> UserData for LocalCellData<T>
637where
638    T: NativeClass,
639{
640    type Target = T;
641
642    #[inline]
643    fn new(val: Self::Target) -> Self {
644        LocalCellData {
645            inner: Arc::new(local_cell::LocalCell::new(val)),
646        }
647    }
648
649    #[inline]
650    fn into_user_data(self) -> *const libc::c_void {
651        Arc::into_raw(self.inner) as *const libc::c_void
652    }
653
654    #[inline]
655    unsafe fn consume_user_data_unchecked(ptr: *const libc::c_void) -> Self {
656        LocalCellData {
657            inner: Arc::from_raw(ptr as *const local_cell::LocalCell<T>),
658        }
659    }
660
661    #[inline]
662    unsafe fn clone_from_user_data_unchecked(ptr: *const libc::c_void) -> Self {
663        let borrowed = Arc::from_raw(ptr as *const local_cell::LocalCell<T>);
664        let arc = borrowed.clone();
665        mem::forget(borrowed);
666        LocalCellData { inner: arc }
667    }
668}
669
670impl<T> Map for LocalCellData<T>
671where
672    T: NativeClass,
673{
674    type Err = LocalCellError;
675
676    #[inline]
677    fn map<F, U>(&self, op: F) -> Result<U, Self::Err>
678    where
679        F: FnOnce(&Self::Target) -> U,
680    {
681        self.inner.try_borrow().map(|r| op(&r))
682    }
683}
684
685impl<T> MapMut for LocalCellData<T>
686where
687    T: NativeClass,
688{
689    type Err = LocalCellError;
690
691    #[inline]
692    fn map_mut<F, U>(&self, op: F) -> Result<U, Self::Err>
693    where
694        F: FnOnce(&mut Self::Target) -> U,
695    {
696        self.inner.try_borrow_mut().map(|mut w| op(&mut w))
697    }
698}
699
700impl<T> Clone for LocalCellData<T> {
701    #[inline]
702    fn clone(&self) -> Self {
703        LocalCellData {
704            inner: self.inner.clone(),
705        }
706    }
707}
708
709/// Special user-data wrapper intended for zero-sized types, that does not perform any
710/// allocation or synchronization at runtime. Does not implement `MapMut`.
711///
712/// `Aether` produces a value using `Default` each time it's mapped. This is most useful when
713/// used with auto-load scripts to simulate static functions, since actual static functions
714/// can't be exported in GDNative.
715#[derive(Copy, Debug)]
716pub struct Aether<T> {
717    _marker: PhantomData<T>,
718}
719
720unsafe impl<T> Send for Aether<T> {}
721unsafe impl<T> Sync for Aether<T> {}
722
723impl<T> Clone for Aether<T> {
724    #[inline]
725    fn clone(&self) -> Self {
726        Aether::default()
727    }
728}
729
730impl<T> Default for Aether<T> {
731    #[inline]
732    fn default() -> Self {
733        Aether {
734            _marker: PhantomData,
735        }
736    }
737}
738
739unsafe impl<T> UserData for Aether<T>
740where
741    T: NativeClass + Copy + Default,
742{
743    type Target = T;
744
745    #[inline]
746    fn new(_val: Self::Target) -> Self {
747        Aether::default()
748    }
749
750    #[inline]
751    fn into_user_data(self) -> *const libc::c_void {
752        1 as *const libc::c_void
753    }
754
755    #[inline]
756    unsafe fn consume_user_data_unchecked(_ptr: *const libc::c_void) -> Self {
757        Aether::default()
758    }
759
760    #[inline]
761    unsafe fn clone_from_user_data_unchecked(_ptr: *const libc::c_void) -> Self {
762        Aether::default()
763    }
764}
765
766impl<T> Map for Aether<T>
767where
768    T: NativeClass + Copy + Default,
769{
770    type Err = Infallible;
771
772    #[inline]
773    fn map<F, U>(&self, op: F) -> Result<U, Infallible>
774    where
775        F: FnOnce(&T) -> U,
776    {
777        Ok(op(&Default::default()))
778    }
779}
780
781/// Special user-data wrapper intended for objects that can only be used once. Only
782/// implements `MapOwned`.
783pub struct Once<T>(Arc<atomic_take::AtomicTake<T>>);
784
785impl<T> Clone for Once<T> {
786    #[inline]
787    fn clone(&self) -> Self {
788        Once(Arc::clone(&self.0))
789    }
790}
791
792unsafe impl<T> UserData for Once<T>
793where
794    T: NativeClass + Send,
795{
796    type Target = T;
797
798    #[inline]
799    fn new(val: Self::Target) -> Self {
800        Once(Arc::new(atomic_take::AtomicTake::new(val)))
801    }
802
803    #[inline]
804    fn into_user_data(self) -> *const libc::c_void {
805        Arc::into_raw(self.0) as *const _
806    }
807
808    #[inline]
809    unsafe fn consume_user_data_unchecked(ptr: *const libc::c_void) -> Self {
810        Once(Arc::from_raw(ptr as *const _))
811    }
812
813    #[inline]
814    unsafe fn clone_from_user_data_unchecked(ptr: *const libc::c_void) -> Self {
815        let borrowed = Arc::from_raw(ptr as *const _);
816        let arc = Arc::clone(&borrowed);
817        mem::forget(borrowed);
818        Once(arc)
819    }
820}
821
822#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
823pub struct ValueTaken;
824
825impl std::error::Error for ValueTaken {}
826impl Display for ValueTaken {
827    #[inline]
828    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
829        write!(f, "this object has already been used once")
830    }
831}
832
833impl<T> MapOwned for Once<T>
834where
835    T: NativeClass + Send,
836{
837    type Err = ValueTaken;
838
839    /// Maps a `T` to `U`. Called for methods that take `self`. This method may fail with
840    /// an error if it is called more than once on the same object.
841    ///
842    /// Implementations of this method must not panic. Failures should be indicated by
843    /// returning `Err`.
844    #[inline]
845    fn map_owned<F, U>(&self, op: F) -> Result<U, Self::Err>
846    where
847        F: FnOnce(Self::Target) -> U,
848    {
849        let v = self.0.take().ok_or(ValueTaken)?;
850        Ok(op(v))
851    }
852}