Skip to content

Commit beefbd4

Browse files
committed
Documentation
1 parent 492a8fe commit beefbd4

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/lib.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,33 @@ use std::{
33
ptr::NonNull,
44
};
55

6+
/// The stack of mutable references and their holders.
7+
///
8+
/// It allows to simulate recursion where each level holds a mutable reference to the one held by
9+
/// the caller with an iteration.
10+
///
11+
/// It is made in such a way that the rules enforced by the borrow checker during the theoretical
12+
/// recursion are still enforced during iterations. On that purpose, each object holding a mutable
13+
/// reference becomes unreachable when the recursion is similated: it is stacked until it becomes
14+
/// usable again.
15+
///
16+
/// In order to use it:
17+
///
18+
/// * create a new stack with the root mutable reference using [`RefMutStack::new`]
19+
/// * call [`RefMutStack::borrow_mut`] to create the root holder of type `T`
20+
/// * enable recursion in `T` itself by calling [`ParkableRefMut::parker`] and park the holder with
21+
/// [`Parker::park`]
22+
/// * finish recursion by calling [`ParkableRefMut::unpark`]
23+
///
24+
/// See builder examples in `tests` for more details.
625
pub struct RefMutStack<'a, R, T> {
726
root_ref: NonNull<R>,
827
stack: SafeDropVec<(T, NonNull<R>)>,
928
_a: std::marker::PhantomData<&'a ()>,
1029
}
1130

1231
impl<'a, R, T> RefMutStack<'a, R, T> {
32+
/// Creates a new stack with the root mutable reference.
1333
pub fn new(r: &'a mut R) -> Self {
1434
Self {
1535
root_ref: NonNull::from_mut(r),
@@ -18,6 +38,7 @@ impl<'a, R, T> RefMutStack<'a, R, T> {
1838
}
1939
}
2040

41+
/// Borrows the current mutable reference at the top of the stack in order to use it.
2142
pub fn borrow_mut(&'a mut self) -> ParkableRefMut<'a, R, T> {
2243
let r = self.stack.last_mut().map_or(self.root_ref, |(_, r)| *r);
2344
ParkableRefMut {
@@ -67,19 +88,28 @@ impl<T> DerefMut for SafeDropVec<T> {
6788
}
6889
}
6990

91+
/// Holder of one mutable reference.
92+
///
93+
/// It can park itself and its holder of type `T` via [`ParkableRefMut::parker`] and [`Parker::park`].
94+
///
95+
/// It can unpark itself via [`ParkableRefMut::unpark`] which returns the previously parked holder of type `T` if
96+
/// any, `None` if everything has been unparked.
7097
pub struct ParkableRefMut<'a, R, T> {
7198
r: NonNull<R>,
7299
stack: NonNull<RefMutStack<'a, R, T>>,
73100
}
74101

75102
impl<'a, R, T> ParkableRefMut<'a, R, T> {
103+
/// Creates a new parker to park the mutable reference holder and derive a new one.
76104
pub fn parker(&mut self) -> Parker<'a, R, T> {
77105
Parker {
78106
r: self.r,
79107
stack: self.stack,
80108
}
81109
}
82110

111+
/// Unparks the reference and returns the previously parked holder of type `T` if any, `None`
112+
/// if everything has been unparked.
83113
pub fn unpark(mut self) -> Option<T> {
84114
let stack = unsafe { self.stack.as_mut() };
85115
stack.stack.pop().map(|(v, _)| v)
@@ -99,13 +129,20 @@ impl<'a, R, T> DerefMut for ParkableRefMut<'a, R, T> {
99129
}
100130
}
101131

132+
/// The parker helper.
133+
///
134+
/// It must be used by calling [`Parker::park`], passing the reference holder of type `T` which
135+
/// becomes unreachable until it is unparked.
102136
#[must_use]
103137
pub struct Parker<'a, R, T> {
104138
r: NonNull<R>,
105139
stack: NonNull<RefMutStack<'a, R, T>>,
106140
}
107141

108142
impl<'a, R, T> Parker<'a, R, T> {
143+
/// Parks the reference holder which becomes unreachable until it is unparked.
144+
///
145+
/// The callback is used to derive a new mutable reference from the current one in the stack.
109146
pub fn park<F>(mut self, holder: T, f: F) -> ParkableRefMut<'a, R, T>
110147
where
111148
R: 'a,

0 commit comments

Comments
 (0)