anchor_experiment/mem.rs
1use std::ffi::{CString, OsString};
2use std::marker::PhantomData;
3use std::ops::{Deref, DerefMut};
4use std::path::PathBuf;
5use std::rc::Rc;
6use std::sync::Arc;
7
8/// A pointer type which guarantees a stable address.
9///
10/// This type must guarantee:
11/// - It owns the data which is the target of its Deref impl.
12/// - The memory address of that data will never be moved between immutable
13/// dereferences.
14pub unsafe trait StableDeref: Deref { }
15
16unsafe impl<T> StableDeref for Box<T> { }
17unsafe impl<T> StableDeref for Vec<T> { }
18
19unsafe impl<T> StableDeref for Rc<T> { }
20unsafe impl<T> StableDeref for Arc<T> { }
21unsafe impl StableDeref for String { }
22unsafe impl StableDeref for PathBuf { }
23unsafe impl StableDeref for OsString { }
24unsafe impl StableDeref for CString { }
25
26/// A pointer type which guarantees a stable address under mutable conditions.
27///
28/// This type must guarantee:
29/// - It owns the data which is the target of its Deref impl.
30/// - The memory address of that data will never be moved between immutable
31/// dereferences.
32pub unsafe trait StableDerefMut: DerefMut { }
33
34unsafe impl<T> StableDerefMut for Box<T> { }
35unsafe impl<T> StableDerefMut for Vec<T> { }
36
37pub struct Pin<'a, T: ?Sized> {
38 _marker: PhantomData<&'a mut &'a ()>,
39 data: T,
40}
41
42/// Pin an object in place.
43///
44/// This is intended to be combined with an Anchor to keep data from moving out
45/// of its location on the stack.
46pub fn pin<'a, T>(data: T) -> Pin<'a, T> {
47 Pin {
48 _marker: PhantomData,
49 data
50 }
51}
52
53/// Anchor a pointer in place.
54///
55/// This type makes it unsafe to move out of or mutably access the pointer
56/// that it is wrapped around. This way, the value the pointer refers to is
57/// guaranteed never to move again.
58///
59/// This can be applied to any pointer type that implements `StableDeref`, but
60/// it can also be applied to a reference using pinning.
61pub struct Anchor<Ptr: ?Sized> {
62 ptr: Ptr,
63}
64
65impl<Ptr: StableDeref> Anchor<Ptr> {
66 /// Construct a new Anchor from any StableDeref pointer.
67 pub fn new(ptr: Ptr) -> Anchor<Ptr> {
68 Anchor { ptr }
69 }
70
71 /// Convert this anchor to an anchored reference.
72 pub fn as_ref<'a>(&'a self) -> Anchor<&'a Ptr::Target> {
73 Anchor {
74 ptr: &*self.ptr
75 }
76 }
77}
78
79impl<Ptr: StableDerefMut> Anchor<Ptr> {
80 /// Convert this anchor to an anchored mutable reference.
81 pub fn as_mut<'a>(&'a mut self) -> Anchor<&'a mut Ptr::Target> {
82 Anchor {
83 ptr: &mut *self.ptr
84 }
85 }
86}
87
88impl<'a, T> Anchor<&'a mut T> {
89 /// Construct an anchor from pinned data.
90 ///
91 /// ```
92 /// Anchor::pinned(&mut pin(0));
93 /// ```
94 pub fn pinned(data: &'a mut Pin<'a, T>) -> Anchor<&'a mut T> {
95 Anchor {
96 ptr: &mut data.data
97 }
98 }
99}
100
101impl<'a, T> Anchor<&'a T> {
102 /// Construct an anchor from pinned data.
103 ///
104 /// ```
105 /// Anchor::pinned(&pin(0));
106 /// ```
107 pub fn pinned(data: &'a Pin<'a, T>) -> Anchor<&'a T> {
108 Anchor {
109 ptr: &data.data
110 }
111 }
112}
113
114impl<Ptr> Anchor<Ptr> {
115 /// Access a mutable reference to the underlying pointer. This method is
116 /// unsafe.
117 ///
118 /// You must guarantee that you never move out of the reference you get
119 /// when you call this.
120 pub unsafe fn get_mut(&mut self) -> &mut Ptr {
121 &mut self.ptr
122 }
123}
124
125impl<Ptr> Deref for Anchor<Ptr> {
126 type Target = Ptr;
127 fn deref(&self) -> &Ptr {
128 &self.ptr
129 }
130}