1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{cmp, fmt, hash}; |
4 | |
5 | use super::prelude::*; |
6 | use 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. |
17 | pub struct ObjectImplRef<T: ObjectSubclass>(T::Type); |
18 | |
19 | unsafe impl<T: ObjectSubclass + Send + Sync> Send for ObjectImplRef<T> {} |
20 | unsafe impl<T: ObjectSubclass + Send + Sync> Sync for ObjectImplRef<T> {} |
21 | |
22 | impl<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 | |
40 | impl<T: ObjectSubclass> Clone for ObjectImplRef<T> { |
41 | #[inline ] |
42 | fn clone(&self) -> Self { |
43 | Self(self.0.clone()) |
44 | } |
45 | } |
46 | |
47 | impl<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 | |
53 | impl<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 | |
62 | impl<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 | |
71 | impl<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 | |
78 | impl<T: ObjectSubclass, OT: crate::object::ObjectType> PartialOrd<OT> for ObjectImplRef<T> |
79 | where |
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 | |
88 | impl<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 | |
95 | impl<T: ObjectSubclass> PartialEq for ObjectImplRef<T> { |
96 | #[inline ] |
97 | fn eq(&self, other: &Self) -> bool { |
98 | self.0 == other.0 |
99 | } |
100 | } |
101 | |
102 | impl<T: ObjectSubclass, OT: crate::object::ObjectType> PartialEq<OT> for ObjectImplRef<T> |
103 | where |
104 | T::Type: PartialEq<OT>, |
105 | { |
106 | #[inline ] |
107 | fn eq(&self, other: &OT) -> bool { |
108 | self.0 == *other |
109 | } |
110 | } |
111 | |
112 | impl<T: ObjectSubclass> Eq for ObjectImplRef<T> {} |
113 | |
114 | impl<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. |
126 | pub struct ObjectImplWeakRef<T: ObjectSubclass>(WeakRef<T::Type>); |
127 | |
128 | unsafe impl<T: ObjectSubclass + Send + Sync> Send for ObjectImplWeakRef<T> {} |
129 | unsafe impl<T: ObjectSubclass + Send + Sync> Sync for ObjectImplWeakRef<T> {} |
130 | |
131 | impl<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 | |
143 | impl<T: ObjectSubclass> Clone for ObjectImplWeakRef<T> { |
144 | #[inline ] |
145 | fn clone(&self) -> Self { |
146 | Self(self.0.clone()) |
147 | } |
148 | } |
149 | |
150 | impl<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 | |
156 | impl<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 | |