]> git.proxmox.com Git - proxmox-backup.git/blob - src/tools/borrow.rs
d/control: add ',' after qrencode dependency
[proxmox-backup.git] / src / tools / borrow.rs
1 /// This ties two values T and U together, such that T does not move and cannot be used as long as
2 /// there's an U. This essentially replaces the borrow checker's job for dependent values which
3 /// need to be stored together in a struct {}, and is similar to what the 'rental' crate produces.
4 pub struct Tied<T, U: ?Sized>(Option<Box<T>>, Option<Box<U>>);
5
6 impl<T, U: ?Sized> Drop for Tied<T, U> {
7 fn drop(&mut self) {
8 // let's be explicit about order here!
9 std::mem::drop(self.1.take());
10 }
11 }
12
13 impl<T, U: ?Sized> Tied<T, U> {
14 /// Takes an owner and a function producing the depending value. The owner will be inaccessible
15 /// until the tied value is resolved. The dependent value is only accessible by reference.
16 pub fn new<F>(owner: T, producer: F) -> Self
17 where
18 F: FnOnce(*mut T) -> Box<U>,
19 {
20 let mut owner = Box::new(owner);
21 let dep = producer(&mut *owner);
22 Tied(Some(owner), Some(dep))
23 }
24
25 pub fn into_boxed_inner(mut self) -> Box<T> {
26 self.1 = None;
27 self.0.take().unwrap()
28 }
29
30 pub fn into_inner(self) -> T {
31 *self.into_boxed_inner()
32 }
33 }
34
35 impl<T, U: ?Sized> AsRef<U> for Tied<T, U> {
36 fn as_ref(&self) -> &U {
37 self.1.as_ref().unwrap()
38 }
39 }
40
41 impl<T, U: ?Sized> AsMut<U> for Tied<T, U> {
42 fn as_mut(&mut self) -> &mut U {
43 self.1.as_mut().unwrap()
44 }
45 }
46
47 impl<T, U: ?Sized> std::ops::Deref for Tied<T, U> {
48 type Target = U;
49
50 fn deref(&self) -> &U {
51 self.as_ref()
52 }
53 }
54
55 impl<T, U: ?Sized> std::ops::DerefMut for Tied<T, U> {
56 fn deref_mut(&mut self) -> &mut U {
57 self.as_mut()
58 }
59 }