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
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

/// `Lift` lets you construct a type `T<B>` from a type `T<A>`.
///
/// If you have a type `T<A>` which implements `Lift<A, B>`, you can derive the
/// type `T<B>` using `<T<A> as Lift<A, B>>::Target1`.
///
/// The type `T<A>` is also available as the `Source` associated type, if you
/// should need it.
pub trait Lift<A, B> {
    type Source;
    type Target1;
}

/// `Lift3` extends `Lift` to let you construct two types `T<B>` and `T<C>` from
/// a type `T<A>`.
///
/// `T<B>` can be found at `<T<A> as Lift3<A, B, C>>::Target2`, and `T<C>` at
/// `<T<A> as Lift<A, B>>::Target1`.
///
/// The naming convention is that the `Target`s are numbered from right to left.
pub trait Lift3<A, B, C>: Lift<A, C> {
    type Target2;
    fn cast(
        from: <<Self as Lift3<A, B, C>>::Target2 as Lift<B, C>>::Target1,
    ) -> <Self as Lift<A, C>>::Target1
    where
        <Self as Lift3<A, B, C>>::Target2: Lift<B, C>,
    {
        crate::unsafe_coerce(from)
    }
}

impl<F, A, B, C> Lift<A, B> for F
where
    F: Fn(A) -> C,
{
    type Source = Self;
    type Target1 = Box<dyn Fn(B) -> C>;
}

impl<A, B> Lift<A, B> for Option<A> {
    type Source = Self;
    type Target1 = Option<B>;
}

impl<A, B, E> Lift<A, B> for Result<A, E> {
    type Source = Self;
    type Target1 = Result<B, E>;
}

impl<A, B> Lift<A, B> for Vec<A> {
    type Source = Self;
    type Target1 = Vec<B>;
}

impl<A, B, S> Lift<A, B> for HashSet<A, S> {
    type Source = Self;
    type Target1 = HashSet<B, S>;
}

impl<A, B> Lift<A, B> for BTreeSet<A> {
    type Source = Self;
    type Target1 = BTreeSet<B>;
}

impl<A, B, C, D, S> Lift<(A, B), (C, D)> for HashMap<A, B, S> {
    type Source = Self;
    type Target1 = HashMap<C, D, S>;
}

impl<A, B, C, D> Lift<(A, B), (C, D)> for BTreeMap<A, B> {
    type Source = Self;
    type Target1 = BTreeMap<C, D>;
}

impl<A, B> Lift<A, B> for VecDeque<A> {
    type Source = Self;
    type Target1 = VecDeque<B>;
}

impl<A, B> Lift<A, B> for LinkedList<A> {
    type Source = Self;
    type Target1 = LinkedList<B>;
}

impl<A, B> Lift<A, B> for BinaryHeap<A> {
    type Source = Self;
    type Target1 = BinaryHeap<B>;
}

impl<A, B, C> Lift3<A, B, C> for Option<A> {
    type Target2 = Option<B>;
}

impl<A, B, C, E> Lift3<A, B, C> for Result<A, E> {
    type Target2 = Result<B, E>;
}

impl<A, B, C> Lift3<A, B, C> for Vec<A> {
    type Target2 = Vec<B>;
}

impl<A, B, C, S> Lift3<A, B, C> for HashSet<A, S> {
    type Target2 = HashSet<B, S>;
}

impl<A, B, C> Lift3<A, B, C> for BTreeSet<A> {
    type Target2 = BTreeSet<B>;
}

impl<A, B, C> Lift3<A, B, C> for VecDeque<A> {
    type Target2 = VecDeque<B>;
}

impl<A, B, C> Lift3<A, B, C> for LinkedList<A> {
    type Target2 = LinkedList<B>;
}

impl<A, B, C> Lift3<A, B, C> for BinaryHeap<A> {
    type Target2 = BinaryHeap<B>;
}