1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! This module defines helpers and utilities for working with references.

// ============
// === With ===
// ============

/// Surprisingly useful function. Consider the following code:
///
/// ```compile_fail
/// fn init(self) -> Self {
///    let mut data = self.borrow_mut();
///    ...
///    self
///    }
/// ```
///
/// It may not compile telling that the last line moves self out, however,
/// borrow might be used there, when `data` is dropped and runs the destructor.
///
/// We can use this function to narrow-down the lifetimes. The following code
/// compiles just fine:
///
/// ```compile_fail
/// fn init(self) -> Self {
///    with(self.borrow_mut(), |mut data| {
///        ...
///    });
///    self
///    }
/// ```
pub fn with<T, F: FnOnce(T) -> Out, Out>(t: T, f: F) -> Out { f(t) }



// =============
// === ToRef ===
// =============

/// Similar to `AsRef` but more specific and automatically implemented for every type. Allows for
/// conversion `&T` to `&T` (identity) and `T` to `&T` for any type `T`. In contrast, `AsRef`
/// requires explicit impls, so for example you cannot do `let t:&() = ().as_ref()`
pub trait ToRef<T>        where T:?Sized { fn to_ref(&self) -> &T; }
impl<T>   ToRef<T> for  T where T:?Sized { fn to_ref(&self) -> &T { self } }
impl<T>   ToRef<T> for &T where T:?Sized { fn to_ref(&self) -> &T { self } }

// pub trait ToRef = ?Sized + HasRefValue + ToRef__<RefValue<Self>>;

pub trait HasRefValue where                {         type RefValue:?Sized; }
impl <T> HasRefValue for  T where T:?Sized { default type RefValue=T; }
impl <T> HasRefValue for &T where T:?Sized {         type RefValue=T; }

pub type RefValue<T> = <T as HasRefValue>::RefValue;



// =============
// === Owned ===
// =============

/// The owned version of a type. It would be super cool if Rust would allow us to automatically
/// implement it for every type: `Owned<&T> = T` and `Owned<T> = T` if `T` was not a reference.
/// Unfortunately, we need to implement it by hand for every type now.
pub trait AsOwned {
    type Owned;
}

/// Owned type family.
pub type Owned<T> = <T as AsOwned>::Owned;

/// Converts type to its owned version.
pub trait IntoOwned = AsOwned + Into<Owned<Self>>;


// === Default Impls ===

impl<T> AsOwned for &T {
    type Owned = T;
}