• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 Amari Robinson
2 //
3 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 // http://opensource.org/licenses/MIT>, at your option. This file may not be
6 // copied, modified, or distributed except according to those terms.
7 
8 #[cfg(feature = "alloc")]
9 use crate::alloc::boxed::Box;
10 #[cfg(feature = "alloc")]
11 use crate::alloc::rc::Rc;
12 #[cfg(feature = "alloc")]
13 use crate::alloc::sync::Arc;
14 use crate::UnsafeRef;
15 use core::marker::PhantomData;
16 use core::mem::ManuallyDrop;
17 use core::ops::Deref;
18 use core::pin::Pin;
19 
20 /// Trait for pointer conversion operations.
21 ///
22 /// `Value` is the actual object type managed by the collection. This type will
23 /// typically have a link as a struct field.
24 ///
25 /// `Pointer` is a pointer type which "owns" an object of type `Value`.
26 /// Operations which insert an element into an intrusive collection will accept
27 /// such a pointer and operations which remove an element will return this type.
28 pub unsafe trait PointerOps {
29     /// Object type which is inserted into an intrusive collection.
30     type Value: ?Sized;
31     /// Pointer type which owns an instance of a value.
32     type Pointer;
33 
34     /// Constructs an owned pointer from a raw pointer.
35     ///
36     /// # Safety
37     /// The raw pointer must have been previously returned by `into_raw`.
38     ///
39     /// An implementation of `from_raw` must not panic.
from_raw(&self, value: *const Self::Value) -> Self::Pointer40     unsafe fn from_raw(&self, value: *const Self::Value) -> Self::Pointer;
41 
42     /// Consumes the owned pointer and returns a raw pointer to the owned object.
into_raw(&self, ptr: Self::Pointer) -> *const Self::Value43     fn into_raw(&self, ptr: Self::Pointer) -> *const Self::Value;
44 }
45 
46 /// The `PointerOps` type used by an `Adapter` generated by `intrusive_adapter!`.
47 pub struct DefaultPointerOps<Pointer>(PhantomData<Pointer>);
48 
49 impl<Pointer> DefaultPointerOps<Pointer> {
50     /// Constructs an instance of `DefaultPointerOps`.
51     #[inline]
new() -> DefaultPointerOps<Pointer>52     pub const fn new() -> DefaultPointerOps<Pointer> {
53         DefaultPointerOps(PhantomData)
54     }
55 }
56 
57 impl<Pointer> Clone for DefaultPointerOps<Pointer> {
58     #[inline]
clone(&self) -> Self59     fn clone(&self) -> Self {
60         *self
61     }
62 }
63 
64 impl<Pointer> Copy for DefaultPointerOps<Pointer> {}
65 
66 impl<Pointer> Default for DefaultPointerOps<Pointer> {
67     #[inline]
default() -> Self68     fn default() -> Self {
69         Self::new()
70     }
71 }
72 
73 unsafe impl<'a, T: ?Sized> PointerOps for DefaultPointerOps<&'a T> {
74     type Value = T;
75     type Pointer = &'a T;
76 
77     #[inline]
from_raw(&self, raw: *const T) -> &'a T78     unsafe fn from_raw(&self, raw: *const T) -> &'a T {
79         &*raw
80     }
81 
82     #[inline]
into_raw(&self, ptr: &'a T) -> *const T83     fn into_raw(&self, ptr: &'a T) -> *const T {
84         ptr
85     }
86 }
87 
88 unsafe impl<'a, T: ?Sized> PointerOps for DefaultPointerOps<Pin<&'a T>> {
89     type Value = T;
90     type Pointer = Pin<&'a T>;
91 
92     #[inline]
from_raw(&self, raw: *const T) -> Pin<&'a T>93     unsafe fn from_raw(&self, raw: *const T) -> Pin<&'a T> {
94         Pin::new_unchecked(&*raw)
95     }
96 
97     #[inline]
into_raw(&self, ptr: Pin<&'a T>) -> *const T98     fn into_raw(&self, ptr: Pin<&'a T>) -> *const T {
99         unsafe { Pin::into_inner_unchecked(ptr) as *const T }
100     }
101 }
102 
103 unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<UnsafeRef<T>> {
104     type Value = T;
105     type Pointer = UnsafeRef<T>;
106 
107     #[inline]
from_raw(&self, raw: *const T) -> UnsafeRef<T>108     unsafe fn from_raw(&self, raw: *const T) -> UnsafeRef<T> {
109         UnsafeRef::from_raw(raw as *mut T)
110     }
111 
112     #[inline]
into_raw(&self, ptr: UnsafeRef<T>) -> *const T113     fn into_raw(&self, ptr: UnsafeRef<T>) -> *const T {
114         UnsafeRef::into_raw(ptr) as *const T
115     }
116 }
117 
118 unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Pin<UnsafeRef<T>>> {
119     type Value = T;
120     type Pointer = Pin<UnsafeRef<T>>;
121 
122     #[inline]
from_raw(&self, raw: *const T) -> Pin<UnsafeRef<T>>123     unsafe fn from_raw(&self, raw: *const T) -> Pin<UnsafeRef<T>> {
124         Pin::new_unchecked(UnsafeRef::from_raw(raw as *mut T))
125     }
126 
127     #[inline]
into_raw(&self, ptr: Pin<UnsafeRef<T>>) -> *const T128     fn into_raw(&self, ptr: Pin<UnsafeRef<T>>) -> *const T {
129         UnsafeRef::into_raw(unsafe { Pin::into_inner_unchecked(ptr) }) as *const T
130     }
131 }
132 
133 #[cfg(feature = "alloc")]
134 unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Box<T>> {
135     type Value = T;
136     type Pointer = Box<T>;
137 
138     #[inline]
from_raw(&self, raw: *const T) -> Box<T>139     unsafe fn from_raw(&self, raw: *const T) -> Box<T> {
140         Box::from_raw(raw as *mut T)
141     }
142 
143     #[inline]
into_raw(&self, ptr: Box<T>) -> *const T144     fn into_raw(&self, ptr: Box<T>) -> *const T {
145         Box::into_raw(ptr) as *const T
146     }
147 }
148 
149 #[cfg(feature = "alloc")]
150 unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Pin<Box<T>>> {
151     type Value = T;
152     type Pointer = Pin<Box<T>>;
153 
154     #[inline]
from_raw(&self, raw: *const T) -> Pin<Box<T>>155     unsafe fn from_raw(&self, raw: *const T) -> Pin<Box<T>> {
156         Pin::new_unchecked(Box::from_raw(raw as *mut T))
157     }
158 
159     #[inline]
into_raw(&self, ptr: Pin<Box<T>>) -> *const T160     fn into_raw(&self, ptr: Pin<Box<T>>) -> *const T {
161         Box::into_raw(unsafe { Pin::into_inner_unchecked(ptr) }) as *const T
162     }
163 }
164 
165 #[cfg(feature = "alloc")]
166 unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Rc<T>> {
167     type Value = T;
168     type Pointer = Rc<T>;
169 
170     #[inline]
from_raw(&self, raw: *const T) -> Rc<T>171     unsafe fn from_raw(&self, raw: *const T) -> Rc<T> {
172         Rc::from_raw(raw)
173     }
174 
175     #[inline]
into_raw(&self, ptr: Rc<T>) -> *const T176     fn into_raw(&self, ptr: Rc<T>) -> *const T {
177         Rc::into_raw(ptr)
178     }
179 }
180 
181 #[cfg(feature = "alloc")]
182 unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Pin<Rc<T>>> {
183     type Value = T;
184     type Pointer = Pin<Rc<T>>;
185 
186     #[inline]
from_raw(&self, raw: *const T) -> Pin<Rc<T>>187     unsafe fn from_raw(&self, raw: *const T) -> Pin<Rc<T>> {
188         Pin::new_unchecked(Rc::from_raw(raw))
189     }
190 
191     #[inline]
into_raw(&self, ptr: Pin<Rc<T>>) -> *const T192     fn into_raw(&self, ptr: Pin<Rc<T>>) -> *const T {
193         Rc::into_raw(unsafe { Pin::into_inner_unchecked(ptr) })
194     }
195 }
196 
197 #[cfg(feature = "alloc")]
198 unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Arc<T>> {
199     type Value = T;
200     type Pointer = Arc<T>;
201 
202     #[inline]
from_raw(&self, raw: *const T) -> Arc<T>203     unsafe fn from_raw(&self, raw: *const T) -> Arc<T> {
204         Arc::from_raw(raw)
205     }
206 
207     #[inline]
into_raw(&self, ptr: Arc<T>) -> *const T208     fn into_raw(&self, ptr: Arc<T>) -> *const T {
209         Arc::into_raw(ptr)
210     }
211 }
212 
213 #[cfg(feature = "alloc")]
214 unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Pin<Arc<T>>> {
215     type Value = T;
216     type Pointer = Pin<Arc<T>>;
217 
218     #[inline]
from_raw(&self, raw: *const T) -> Pin<Arc<T>>219     unsafe fn from_raw(&self, raw: *const T) -> Pin<Arc<T>> {
220         Pin::new_unchecked(Arc::from_raw(raw))
221     }
222 
223     #[inline]
into_raw(&self, ptr: Pin<Arc<T>>) -> *const T224     fn into_raw(&self, ptr: Pin<Arc<T>>) -> *const T {
225         Arc::into_raw(unsafe { Pin::into_inner_unchecked(ptr) })
226     }
227 }
228 
229 /// Clones a `PointerOps::Pointer` from a `*const PointerOps::Value`
230 ///
231 /// This method is only safe to call if the raw pointer is known to be
232 /// managed by the provided `PointerOps` type.
233 #[inline]
clone_pointer_from_raw<T: PointerOps>( pointer_ops: &T, ptr: *const T::Value, ) -> T::Pointer where T::Pointer: Clone,234 pub(crate) unsafe fn clone_pointer_from_raw<T: PointerOps>(
235     pointer_ops: &T,
236     ptr: *const T::Value,
237 ) -> T::Pointer
238 where
239     T::Pointer: Clone,
240 {
241     /// Guard which converts an pointer back into its raw version
242     /// when it gets dropped. This makes sure we also perform a full
243     /// `from_raw` and `into_raw` round trip - even in the case of panics.
244     struct PointerGuard<'a, T: PointerOps> {
245         pointer: ManuallyDrop<T::Pointer>,
246         pointer_ops: &'a T,
247     }
248 
249     impl<'a, T: PointerOps> Drop for PointerGuard<'a, T> {
250         #[inline]
251         fn drop(&mut self) {
252             // Prevent shared pointers from being released by converting them
253             // back into the raw pointers
254             // SAFETY: `pointer` is never dropped. `ManuallyDrop::take` is not stable until 1.42.0.
255             let _ = self
256                 .pointer_ops
257                 .into_raw(unsafe { core::ptr::read(&*self.pointer) });
258         }
259     }
260 
261     let holder = PointerGuard {
262         pointer: ManuallyDrop::new(pointer_ops.from_raw(ptr)),
263         pointer_ops,
264     };
265     holder.pointer.deref().clone()
266 }
267 
268 #[cfg(test)]
269 mod tests {
270     use super::{DefaultPointerOps, PointerOps};
271     use std::boxed::Box;
272     use std::fmt::Debug;
273     use std::mem;
274     use std::pin::Pin;
275     use std::rc::Rc;
276     use std::sync::Arc;
277 
278     #[test]
test_box()279     fn test_box() {
280         unsafe {
281             let pointer_ops = DefaultPointerOps::<Box<_>>::new();
282             let p = Box::new(1);
283             let a: *const i32 = &*p;
284             let r = pointer_ops.into_raw(p);
285             assert_eq!(a, r);
286             let p2: Box<i32> = pointer_ops.from_raw(r);
287             let a2: *const i32 = &*p2;
288             assert_eq!(a, a2);
289         }
290     }
291 
292     #[test]
test_rc()293     fn test_rc() {
294         unsafe {
295             let pointer_ops = DefaultPointerOps::<Rc<_>>::new();
296             let p = Rc::new(1);
297             let a: *const i32 = &*p;
298             let r = pointer_ops.into_raw(p);
299             assert_eq!(a, r);
300             let p2: Rc<i32> = pointer_ops.from_raw(r);
301             let a2: *const i32 = &*p2;
302             assert_eq!(a, a2);
303         }
304     }
305 
306     #[test]
test_arc()307     fn test_arc() {
308         unsafe {
309             let pointer_ops = DefaultPointerOps::<Arc<_>>::new();
310             let p = Arc::new(1);
311             let a: *const i32 = &*p;
312             let r = pointer_ops.into_raw(p);
313             assert_eq!(a, r);
314             let p2: Arc<i32> = pointer_ops.from_raw(r);
315             let a2: *const i32 = &*p2;
316             assert_eq!(a, a2);
317         }
318     }
319 
320     #[test]
test_box_unsized()321     fn test_box_unsized() {
322         unsafe {
323             let pointer_ops = DefaultPointerOps::<Box<_>>::new();
324             let p = Box::new(1) as Box<dyn Debug>;
325             let a: *const dyn Debug = &*p;
326             let b: (usize, usize) = mem::transmute(a);
327             let r = pointer_ops.into_raw(p);
328             assert_eq!(a, r);
329             assert_eq!(b, mem::transmute(r));
330             let p2: Box<dyn Debug> = pointer_ops.from_raw(r);
331             let a2: *const dyn Debug = &*p2;
332             assert_eq!(a, a2);
333             assert_eq!(b, mem::transmute(a2));
334         }
335     }
336 
337     #[test]
test_rc_unsized()338     fn test_rc_unsized() {
339         unsafe {
340             let pointer_ops = DefaultPointerOps::<Rc<_>>::new();
341             let p = Rc::new(1) as Rc<dyn Debug>;
342             let a: *const dyn Debug = &*p;
343             let b: (usize, usize) = mem::transmute(a);
344             let r = pointer_ops.into_raw(p);
345             assert_eq!(a, r);
346             assert_eq!(b, mem::transmute(r));
347             let p2: Rc<dyn Debug> = pointer_ops.from_raw(r);
348             let a2: *const dyn Debug = &*p2;
349             assert_eq!(a, a2);
350             assert_eq!(b, mem::transmute(a2));
351         }
352     }
353 
354     #[test]
test_arc_unsized()355     fn test_arc_unsized() {
356         unsafe {
357             let pointer_ops = DefaultPointerOps::<Arc<_>>::new();
358             let p = Arc::new(1) as Arc<dyn Debug>;
359             let a: *const dyn Debug = &*p;
360             let b: (usize, usize) = mem::transmute(a);
361             let r = pointer_ops.into_raw(p);
362             assert_eq!(a, r);
363             assert_eq!(b, mem::transmute(r));
364             let p2: Arc<dyn Debug> = pointer_ops.from_raw(r);
365             let a2: *const dyn Debug = &*p2;
366             assert_eq!(a, a2);
367             assert_eq!(b, mem::transmute(a2));
368         }
369     }
370 
371     #[test]
clone_arc_from_raw()372     fn clone_arc_from_raw() {
373         use super::clone_pointer_from_raw;
374         unsafe {
375             let pointer_ops = DefaultPointerOps::<Arc<_>>::new();
376             let p = Arc::new(1);
377             let raw = &*p as *const i32;
378             let p2: Arc<i32> = clone_pointer_from_raw(&pointer_ops, raw);
379             assert_eq!(2, Arc::strong_count(&p2));
380         }
381     }
382 
383     #[test]
clone_rc_from_raw()384     fn clone_rc_from_raw() {
385         use super::clone_pointer_from_raw;
386         unsafe {
387             let pointer_ops = DefaultPointerOps::<Rc<_>>::new();
388             let p = Rc::new(1);
389             let raw = &*p as *const i32;
390             let p2: Rc<i32> = clone_pointer_from_raw(&pointer_ops, raw);
391             assert_eq!(2, Rc::strong_count(&p2));
392         }
393     }
394 
395     #[test]
test_pin_box()396     fn test_pin_box() {
397         unsafe {
398             let pointer_ops = DefaultPointerOps::<Pin<Box<_>>>::new();
399             let p = Pin::new(Box::new(1));
400             let a: *const i32 = &*p;
401             let r = pointer_ops.into_raw(p);
402             assert_eq!(a, r);
403             let p2: Pin<Box<i32>> = pointer_ops.from_raw(r);
404             let a2: *const i32 = &*p2;
405             assert_eq!(a, a2);
406         }
407     }
408 
409     #[test]
test_pin_rc()410     fn test_pin_rc() {
411         unsafe {
412             let pointer_ops = DefaultPointerOps::<Pin<Rc<_>>>::new();
413             let p = Pin::new(Rc::new(1));
414             let a: *const i32 = &*p;
415             let r = pointer_ops.into_raw(p);
416             assert_eq!(a, r);
417             let p2: Pin<Rc<i32>> = pointer_ops.from_raw(r);
418             let a2: *const i32 = &*p2;
419             assert_eq!(a, a2);
420         }
421     }
422 
423     #[test]
test_pin_arc()424     fn test_pin_arc() {
425         unsafe {
426             let pointer_ops = DefaultPointerOps::<Pin<Arc<_>>>::new();
427             let p = Pin::new(Arc::new(1));
428             let a: *const i32 = &*p;
429             let r = pointer_ops.into_raw(p);
430             assert_eq!(a, r);
431             let p2: Pin<Arc<i32>> = pointer_ops.from_raw(r);
432             let a2: *const i32 = &*p2;
433             assert_eq!(a, a2);
434         }
435     }
436 
437     #[test]
test_pin_box_unsized()438     fn test_pin_box_unsized() {
439         unsafe {
440             let pointer_ops = DefaultPointerOps::<Pin<Box<_>>>::new();
441             let p = Pin::new(Box::new(1)) as Pin<Box<dyn Debug>>;
442             let a: *const dyn Debug = &*p;
443             let b: (usize, usize) = mem::transmute(a);
444             let r = pointer_ops.into_raw(p);
445             assert_eq!(a, r);
446             assert_eq!(b, mem::transmute(r));
447             let p2: Pin<Box<dyn Debug>> = pointer_ops.from_raw(r);
448             let a2: *const dyn Debug = &*p2;
449             assert_eq!(a, a2);
450             assert_eq!(b, mem::transmute(a2));
451         }
452     }
453 
454     #[test]
test_pin_rc_unsized()455     fn test_pin_rc_unsized() {
456         unsafe {
457             let pointer_ops = DefaultPointerOps::<Pin<Rc<_>>>::new();
458             let p = Pin::new(Rc::new(1)) as Pin<Rc<dyn Debug>>;
459             let a: *const dyn Debug = &*p;
460             let b: (usize, usize) = mem::transmute(a);
461             let r = pointer_ops.into_raw(p);
462             assert_eq!(a, r);
463             assert_eq!(b, mem::transmute(r));
464             let p2: Pin<Rc<dyn Debug>> = pointer_ops.from_raw(r);
465             let a2: *const dyn Debug = &*p2;
466             assert_eq!(a, a2);
467             assert_eq!(b, mem::transmute(a2));
468         }
469     }
470 
471     #[test]
test_pin_arc_unsized()472     fn test_pin_arc_unsized() {
473         unsafe {
474             let pointer_ops = DefaultPointerOps::<Pin<Arc<_>>>::new();
475             let p = Pin::new(Arc::new(1)) as Pin<Arc<dyn Debug>>;
476             let a: *const dyn Debug = &*p;
477             let b: (usize, usize) = mem::transmute(a);
478             let r = pointer_ops.into_raw(p);
479             assert_eq!(a, r);
480             assert_eq!(b, mem::transmute(r));
481             let p2: Pin<Arc<dyn Debug>> = pointer_ops.from_raw(r);
482             let a2: *const dyn Debug = &*p2;
483             assert_eq!(a, a2);
484             assert_eq!(b, mem::transmute(a2));
485         }
486     }
487 
488     #[test]
clone_pin_arc_from_raw()489     fn clone_pin_arc_from_raw() {
490         use super::clone_pointer_from_raw;
491         unsafe {
492             let pointer_ops = DefaultPointerOps::<Pin<Arc<_>>>::new();
493             let p = Pin::new(Arc::new(1));
494             let raw = &*p as *const i32;
495             let p2: Pin<Arc<i32>> = clone_pointer_from_raw(&pointer_ops, raw);
496             assert_eq!(2, Arc::strong_count(&Pin::into_inner(p2)));
497         }
498     }
499 
500     #[test]
clone_pin_rc_from_raw()501     fn clone_pin_rc_from_raw() {
502         use super::clone_pointer_from_raw;
503         unsafe {
504             let pointer_ops = DefaultPointerOps::<Pin<Rc<_>>>::new();
505             let p = Pin::new(Rc::new(1));
506             let raw = &*p as *const i32;
507             let p2: Pin<Rc<i32>> = clone_pointer_from_raw(&pointer_ops, raw);
508             assert_eq!(2, Rc::strong_count(&Pin::into_inner(p2)));
509         }
510     }
511 }
512