1#![deny(rustdoc::missing_crate_level_docs)]
11#![deny(missing_docs)]
12#![doc(test(attr(deny(warnings))))]
14#![deny(clippy::all)]
15#![allow(clippy::collapsible_else_if)]
16#![allow(clippy::result_large_err)]
17
18use std::{any::Any, mem, ptr, rc::Rc, sync::Arc};
19
20pub trait Resource: Any {
31 type Error;
35
36 fn deep_clone(&self) -> Result<Self, Self::Error>
39 where Self: Sized;
40
41 fn deep_boxed_clone(&self) -> Result<Box<dyn Resource<Error=Self::Error>>, Self::Error>;
47
48 unsafe fn sync_drop(&mut self) -> Result<(), Self::Error>;
60}
61
62pub trait Handle: Any {
68 type R: Resource;
75
76 fn wrap(r: Self::R) -> Self
79 where Self: Sized;
80
81 fn clone_handle(&self) -> Result<Self, <Self::R as Resource>::Error>
84 where Self: Sized;
85
86 fn boxed_clone_handle(&self) -> Result<Box<dyn Handle<R=Self::R>>, <Self::R as Resource>::Error>;
89
90 fn handle_ref(&self) -> &Self::R;
92
93 fn eq_ref(&self, other: &dyn Handle<R=Self::R>) -> bool { equal_refs(self, other) }
96
97 fn get_mut(&mut self) -> Option<&mut Self::R>;
99
100 fn ensure_exclusive(&mut self) -> Result<(), <Self::R as Resource>::Error>;
103
104 fn make_mut(&mut self) -> Result<&mut Self::R, <Self::R as Resource>::Error> {
106 self.ensure_exclusive()?;
107 Ok(self.get_mut().unwrap())
108 }
109}
110
111pub fn equal_refs<R: Resource+?Sized>(
113 h1: &(impl Handle<R=R>+?Sized),
114 h2: &(impl Handle<R=R>+?Sized),
115) -> bool {
116 ptr::eq(h1.handle_ref(), h2.handle_ref())
117}
118
119impl<R: Resource> Handle for R {
121 type R = Self;
122
123 fn wrap(r: Self::R) -> Self
124 where Self: Sized {
125 r
126 }
127
128 fn clone_handle(&self) -> Result<Self, <Self::R as Resource>::Error>
129 where Self: Sized {
130 self.deep_clone()
131 }
132
133 fn boxed_clone_handle(&self) -> Result<Box<dyn Handle<R=Self::R>>, <Self::R as Resource>::Error> {
134 let r: Box<dyn Any> = unsafe { mem::transmute(self.deep_boxed_clone()?) };
136 let h: Box<Self> = r.downcast().unwrap();
137 Ok(h)
138 }
139
140 fn handle_ref(&self) -> &Self::R { self }
141
142 fn get_mut(&mut self) -> Option<&mut Self::R> { Some(self) }
143
144 fn ensure_exclusive(&mut self) -> Result<(), <Self::R as Resource>::Error> { Ok(()) }
145}
146
147impl<R: Resource> Handle for Rc<R> {
149 type R = R;
150
151 fn wrap(r: Self::R) -> Self
152 where Self: Sized {
153 Rc::new(r)
154 }
155
156 fn clone_handle(&self) -> Result<Self, <Self::R as Resource>::Error>
157 where Self: Sized {
158 Ok(Rc::clone(self))
159 }
160
161 fn boxed_clone_handle(&self) -> Result<Box<dyn Handle<R=Self::R>>, <Self::R as Resource>::Error> {
162 Ok(Box::new(Rc::clone(self)))
163 }
164
165 fn handle_ref(&self) -> &Self::R { self.as_ref() }
166
167 fn get_mut(&mut self) -> Option<&mut Self::R> { Rc::get_mut(self) }
168
169 fn ensure_exclusive(&mut self) -> Result<(), <Self::R as Resource>::Error> {
170 if Rc::strong_count(self) != 1 {
171 let new: R = self.as_ref().deep_clone()?;
172 *self = Rc::new(new);
173 return Ok(());
174 }
175 if Rc::weak_count(self) > 0 {
176 unsafe {
177 let mut tmp: mem::MaybeUninit<Rc<R>> = mem::MaybeUninit::uninit();
178 let s: *mut Self = self;
179 ptr::swap(s, tmp.as_mut_ptr());
180 let exclusive = Rc::into_inner(tmp.assume_init()).unwrap_unchecked();
183 s.write(Rc::new(exclusive));
185 }
187 }
188 Ok(())
189 }
190}
191
192impl<R: Resource> Handle for Arc<R> {
194 type R = R;
195
196 fn wrap(r: Self::R) -> Self
197 where Self: Sized {
198 Arc::new(r)
199 }
200
201 fn clone_handle(&self) -> Result<Self, <Self::R as Resource>::Error>
202 where Self: Sized {
203 Ok(Arc::clone(self))
204 }
205
206 fn boxed_clone_handle(&self) -> Result<Box<dyn Handle<R=Self::R>>, <Self::R as Resource>::Error> {
207 Ok(Box::new(Arc::clone(self)))
208 }
209
210 fn handle_ref(&self) -> &Self::R { self.as_ref() }
211
212 fn get_mut(&mut self) -> Option<&mut Self::R> { Arc::get_mut(self) }
213
214 fn ensure_exclusive(&mut self) -> Result<(), <Self::R as Resource>::Error> {
215 if Arc::strong_count(self) != 1 {
216 let new: R = self.as_ref().deep_clone()?;
217 *self = Arc::new(new);
218 return Ok(());
219 }
220 if Arc::weak_count(self) > 0 {
221 unsafe {
222 let mut tmp: mem::MaybeUninit<Arc<R>> = mem::MaybeUninit::uninit();
223 let s: *mut Self = self;
224 ptr::swap(s, tmp.as_mut_ptr());
225 let exclusive = Arc::into_inner(tmp.assume_init()).unwrap_unchecked();
228 s.write(Arc::new(exclusive));
230 }
232 }
233 Ok(())
234 }
235}
236
237#[cfg(test)]
238mod test {
239 use super::*;
240
241 #[derive(Debug, PartialEq, Eq)]
242 struct R {
243 pub state: u8,
244 }
245
246 impl Resource for R {
247 type Error = ();
248 fn deep_clone(&self) -> Result<Self, ()> { Ok(Self { state: self.state }) }
249 fn deep_boxed_clone(&self) -> Result<Box<dyn Resource<Error=()>>, Self::Error> {
250 Ok(Box::new(Self { state: self.state }))
251 }
252 unsafe fn sync_drop(&mut self) -> Result<(), ()> { Ok(()) }
253 }
254
255 #[test]
256 fn test_bare() {
257 let r = R { state: 0 };
258 let mut r1 = r.clone_handle().unwrap();
259
260 assert_eq!(r, r1);
263 assert!(!r.eq_ref(&r1));
264
265 r1.ensure_exclusive().unwrap();
266 assert_eq!(r, r1);
267 assert!(!r.eq_ref(&r1));
268
269 r1.make_mut().unwrap().state = 1;
270 assert_ne!(r, r1);
271 assert!(!r.eq_ref(&r1));
272 }
273
274 #[test]
275 fn test_rc() {
276 let r = Rc::new(R { state: 0 });
277 let mut r1 = r.clone_handle().unwrap();
278
279 assert_eq!(r, r1);
281 assert!(r.eq_ref(&r1));
282
283 r1.ensure_exclusive().unwrap();
284 assert_eq!(r, r1);
285 assert!(!r.eq_ref(&r1));
286
287 r1.make_mut().unwrap().state = 1;
288 assert_ne!(r, r1);
289 assert!(!r.eq_ref(&r1));
290 }
291
292 #[test]
293 fn test_arc() {
294 let r = Arc::new(R { state: 0 });
295 let mut r1 = r.clone_handle().unwrap();
296
297 assert_eq!(r, r1);
299 assert!(r.eq_ref(&r1));
300
301 r1.ensure_exclusive().unwrap();
302 assert_eq!(r, r1);
303 assert!(!r.eq_ref(&r1));
304
305 r1.make_mut().unwrap().state = 1;
306 assert_ne!(r, r1);
307 assert!(!r.eq_ref(&r1));
308 }
309
310 #[test]
311 fn test_interchange() {
312 let mut r = Box::new(R { state: 0 });
313 let r1: &mut dyn Handle<R=R> = r.as_mut();
314 let r2 = r1.boxed_clone_handle().unwrap();
315
316 let r2_test1: Box<dyn Any> = r2.boxed_clone_handle().unwrap();
317 let r2_test2: Box<dyn Any> = r2.boxed_clone_handle().unwrap();
318 assert!(r2_test1.downcast::<Rc<R>>().is_err());
319 assert!(r2_test2.downcast::<Arc<R>>().is_err());
320 let r2: Box<dyn Any> = r2;
321 let mut r2: Box<R> = r2.downcast().unwrap();
322
323 assert_eq!(r1.handle_ref(), r2.handle_ref());
324 assert!(!r1.eq_ref(r2.as_ref()));
325 r1.ensure_exclusive().unwrap();
327 r2.ensure_exclusive().unwrap();
328
329 let mut r3 = Rc::new(R { state: 0 });
330 let r3: &mut dyn Handle<R=R> = &mut r3;
331 let r4 = r3.boxed_clone_handle().unwrap();
332
333 let r4_test1: Box<dyn Any> = r4.boxed_clone_handle().unwrap();
334 let r4_test2: Box<dyn Any> = r4.boxed_clone_handle().unwrap();
335 assert!(r4_test1.downcast::<R>().is_err());
336 assert!(r4_test2.downcast::<Arc<R>>().is_err());
337 let r4: Box<dyn Any> = r4;
338 let r4: Box<Rc<R>> = r4.downcast().unwrap();
339
340 assert_eq!(r3.handle_ref(), r4.handle_ref());
341 assert_eq!(r3.handle_ref(), r1.handle_ref());
342 assert!(r3.eq_ref(r4.as_ref()));
343 assert!(!r3.eq_ref(r1));
345
346 r3.ensure_exclusive().unwrap();
347 assert_eq!(r3.handle_ref(), r4.handle_ref());
348 assert!(!r3.eq_ref(r4.as_ref()));
349 r3.get_mut().unwrap().state = 1;
350 assert_ne!(r3.handle_ref(), r4.handle_ref());
351
352 let mut r5 = Arc::new(R { state: 0 });
353 let r5: &mut dyn Handle<R=R> = &mut r5;
354 let r6 = r5.boxed_clone_handle().unwrap();
355
356 let r6_test1: Box<dyn Any> = r6.boxed_clone_handle().unwrap();
357 let r6_test2: Box<dyn Any> = r6.boxed_clone_handle().unwrap();
358 assert!(r6_test1.downcast::<R>().is_err());
359 assert!(r6_test2.downcast::<Rc<R>>().is_err());
360 let r6: Box<dyn Any> = r6;
361 let r6: Box<Arc<R>> = r6.downcast().unwrap();
362
363 assert_eq!(r5.handle_ref(), r6.handle_ref());
364 assert_eq!(r5.handle_ref(), r1.handle_ref());
365 assert!(r5.eq_ref(r6.as_ref()));
366 assert!(!r5.eq_ref(r1));
368 assert!(!r5.eq_ref(r3));
369
370 r5.ensure_exclusive().unwrap();
371 assert_eq!(r5.handle_ref(), r6.handle_ref());
372 assert!(!r5.eq_ref(r6.as_ref()));
373 r5.get_mut().unwrap().state = 1;
374 assert_ne!(r5.handle_ref(), r6.handle_ref());
375 }
376}