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