Skip to main content

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}