1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{cmp, fmt, hash};
4
5use super::prelude::*;
6use crate::{
7 clone::{Downgrade, Upgrade},
8 prelude::*,
9 WeakRef,
10};
11
12// rustdoc-stripper-ignore-next
13/// Reference-counted wrapper around an [`ObjectSubclass`] reference.
14///
15/// This can be used for passing into closures as strong or weak reference without manually going
16/// from the implementation type to the instance type and back.
17pub struct ObjectImplRef<T: ObjectSubclass>(T::Type);
18
19unsafe impl<T: ObjectSubclass + Send + Sync> Send for ObjectImplRef<T> {}
20unsafe impl<T: ObjectSubclass + Send + Sync> Sync for ObjectImplRef<T> {}
21
22impl<T: ObjectSubclass> ObjectImplRef<T> {
23 // rustdoc-stripper-ignore-next
24 /// Create a new reference-counting wrapper around `imp`.
25 #[inline]
26 pub fn new(imp: &T) -> Self {
27 Self(imp.obj().clone())
28 }
29
30 // rustdoc-stripper-ignore-next
31 /// Downgrade to a weak reference.
32 ///
33 /// This can be upgraded to a strong reference again via [`ObjectImplWeakRef::upgrade`].
34 #[inline]
35 pub fn downgrade(&self) -> ObjectImplWeakRef<T> {
36 ObjectImplWeakRef(self.0.downgrade())
37 }
38}
39
40impl<T: ObjectSubclass> Clone for ObjectImplRef<T> {
41 #[inline]
42 fn clone(&self) -> Self {
43 Self(self.0.clone())
44 }
45}
46
47impl<T: ObjectSubclass> fmt::Debug for ObjectImplRef<T> {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 <T::Type as fmt::Debug>::fmt(&self.0, f)
50 }
51}
52
53impl<T: ObjectSubclass> std::ops::Deref for ObjectImplRef<T> {
54 type Target = T;
55
56 #[inline]
57 fn deref(&self) -> &Self::Target {
58 T::from_obj(&self.0)
59 }
60}
61
62impl<T: ObjectSubclass> Downgrade for ObjectImplRef<T> {
63 type Weak = ObjectImplWeakRef<T>;
64
65 #[inline]
66 fn downgrade(&self) -> Self::Weak {
67 self.downgrade()
68 }
69}
70
71impl<T: ObjectSubclass> PartialOrd for ObjectImplRef<T> {
72 #[inline]
73 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
74 Some(self.cmp(other))
75 }
76}
77
78impl<T: ObjectSubclass, OT: crate::object::ObjectType> PartialOrd<OT> for ObjectImplRef<T>
79where
80 T::Type: PartialOrd<OT>,
81{
82 #[inline]
83 fn partial_cmp(&self, other: &OT) -> Option<cmp::Ordering> {
84 self.0.partial_cmp(other)
85 }
86}
87
88impl<T: ObjectSubclass> Ord for ObjectImplRef<T> {
89 #[inline]
90 fn cmp(&self, other: &Self) -> cmp::Ordering {
91 self.0.cmp(&other.0)
92 }
93}
94
95impl<T: ObjectSubclass> PartialEq for ObjectImplRef<T> {
96 #[inline]
97 fn eq(&self, other: &Self) -> bool {
98 self.0 == other.0
99 }
100}
101
102impl<T: ObjectSubclass, OT: crate::object::ObjectType> PartialEq<OT> for ObjectImplRef<T>
103where
104 T::Type: PartialEq<OT>,
105{
106 #[inline]
107 fn eq(&self, other: &OT) -> bool {
108 self.0 == *other
109 }
110}
111
112impl<T: ObjectSubclass> Eq for ObjectImplRef<T> {}
113
114impl<T: ObjectSubclass> hash::Hash for ObjectImplRef<T> {
115 #[inline]
116 fn hash<H>(&self, state: &mut H)
117 where
118 H: hash::Hasher,
119 {
120 self.0.hash(state)
121 }
122}
123
124// rustdoc-stripper-ignore-next
125/// Weak reference to an [`ObjectSubclass`] reference.
126pub struct ObjectImplWeakRef<T: ObjectSubclass>(WeakRef<T::Type>);
127
128unsafe impl<T: ObjectSubclass + Send + Sync> Send for ObjectImplWeakRef<T> {}
129unsafe impl<T: ObjectSubclass + Send + Sync> Sync for ObjectImplWeakRef<T> {}
130
131impl<T: ObjectSubclass> ObjectImplWeakRef<T> {
132 // rustdoc-stripper-ignore-next
133 /// Upgrade to a strong reference, if possible.
134 ///
135 /// This will return `None` if the underlying object was freed in the meantime.
136 #[inline]
137 pub fn upgrade(&self) -> Option<ObjectImplRef<T>> {
138 let obj: ::Type = self.0.upgrade()?;
139 Some(ObjectImplRef(obj))
140 }
141}
142
143impl<T: ObjectSubclass> Clone for ObjectImplWeakRef<T> {
144 #[inline]
145 fn clone(&self) -> Self {
146 Self(self.0.clone())
147 }
148}
149
150impl<T: ObjectSubclass> fmt::Debug for ObjectImplWeakRef<T> {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 <crate::WeakRef<T::Type> as fmt::Debug>::fmt(&self.0, f)
153 }
154}
155
156impl<T: ObjectSubclass> Upgrade for ObjectImplWeakRef<T> {
157 type Strong = ObjectImplRef<T>;
158
159 #[inline]
160 fn upgrade(&self) -> Option<Self::Strong> {
161 self.upgrade()
162 }
163}
164