1
use std::collections::VecDeque;
2
use std::mem::transmute;
3

            
4
use merc_collections::IndexedSet;
5

            
6
use crate::SymbolRef;
7
use crate::aterm::ATermRef;
8

            
9
/// A trait for transmuting the lifetime of an object to a shorter lifetime.
10
///
11
/// # Safety
12
///
13
/// The implementation of this trait must ensure that the transmuted lifetime is
14
/// always shorter than the original lifetime.
15
pub unsafe trait Transmutable {
16
    type Target<'a>: ?Sized
17
    where
18
        Self: 'a;
19

            
20
    /// Transmute the lifetime of the object to 'a.
21
    ///
22
    /// # Safety
23
    ///
24
    /// The caller must ensure that 'a does not outlive the borrow of `self`; nothing in the
25
    /// signature constrains 'a, so requesting e.g. 'static would produce a dangling reference.
26
    unsafe fn transmute_lifetime<'a>(&'_ self) -> &'a Self::Target<'a>;
27

            
28
    /// Transmute the lifetime of the object to 'a.
29
    ///
30
    /// # Safety
31
    ///
32
    /// The caller must ensure that 'a does not outlive the borrow of `self`; nothing in the
33
    /// signature constrains 'a, so requesting e.g. 'static would produce a dangling reference.
34
    unsafe fn transmute_lifetime_mut<'a>(&'_ mut self) -> &'a mut Self::Target<'a>;
35
}
36

            
37
unsafe impl Transmutable for ATermRef<'static> {
38
    type Target<'a> = ATermRef<'a>;
39

            
40
    unsafe fn transmute_lifetime<'a>(&self) -> &'a Self::Target<'a> {
41
        unsafe { transmute::<&Self, &'a ATermRef<'a>>(self) }
42
    }
43

            
44
    unsafe fn transmute_lifetime_mut<'a>(&mut self) -> &'a mut Self::Target<'a> {
45
        unsafe { transmute::<&mut Self, &'a mut ATermRef<'a>>(self) }
46
    }
47
}
48

            
49
unsafe impl Transmutable for SymbolRef<'static> {
50
    type Target<'a> = SymbolRef<'a>;
51

            
52
    unsafe fn transmute_lifetime<'a>(&self) -> &'a Self::Target<'a> {
53
        unsafe { transmute::<&Self, &'a SymbolRef<'a>>(self) }
54
    }
55

            
56
    unsafe fn transmute_lifetime_mut<'a>(&mut self) -> &'a mut Self::Target<'a> {
57
        unsafe { transmute::<&mut Self, &'a mut SymbolRef<'a>>(self) }
58
    }
59
}
60

            
61
unsafe impl<T: Transmutable> Transmutable for Option<T>
62
where
63
    for<'a> T::Target<'a>: Sized,
64
{
65
    type Target<'a>
66
        = Option<T::Target<'a>>
67
    where
68
        T: 'a;
69

            
70
    unsafe fn transmute_lifetime<'a>(&self) -> &'a Self::Target<'a> {
71
        unsafe { transmute::<&Self, &'a Option<T::Target<'a>>>(self) }
72
    }
73

            
74
    unsafe fn transmute_lifetime_mut<'a>(&mut self) -> &'a mut Self::Target<'a> {
75
        unsafe { transmute::<&mut Self, &'a mut Option<T::Target<'a>>>(self) }
76
    }
77
}
78

            
79
unsafe impl<T: Transmutable> Transmutable for Vec<T>
80
where
81
    for<'a> T::Target<'a>: Sized,
82
{
83
    type Target<'a>
84
        = Vec<T::Target<'a>>
85
    where
86
        T: 'a;
87

            
88
786195410
    unsafe fn transmute_lifetime<'a>(&self) -> &'a Self::Target<'a> {
89
786195410
        unsafe { transmute::<&Self, &'a Vec<T::Target<'a>>>(self) }
90
786195410
    }
91

            
92
181402854
    unsafe fn transmute_lifetime_mut<'a>(&mut self) -> &'a mut Self::Target<'a> {
93
181402854
        unsafe { transmute::<&mut Self, &'a mut Vec<T::Target<'a>>>(self) }
94
181402854
    }
95
}
96

            
97
unsafe impl<T: Transmutable> Transmutable for VecDeque<T>
98
where
99
    for<'a> T::Target<'a>: Sized,
100
{
101
    type Target<'a>
102
        = VecDeque<T::Target<'a>>
103
    where
104
        T: 'a;
105

            
106
    unsafe fn transmute_lifetime<'a>(&self) -> &'a Self::Target<'a> {
107
        unsafe { transmute::<&Self, &'a VecDeque<T::Target<'a>>>(self) }
108
    }
109

            
110
    unsafe fn transmute_lifetime_mut<'a>(&mut self) -> &'a mut Self::Target<'a> {
111
        unsafe { transmute::<&mut Self, &'a mut VecDeque<T::Target<'a>>>(self) }
112
    }
113
}
114

            
115
unsafe impl<T: Transmutable> Transmutable for IndexedSet<T>
116
where
117
    for<'a> T::Target<'a>: Sized,
118
{
119
    type Target<'a>
120
        = IndexedSet<T::Target<'a>>
121
    where
122
        T: 'a;
123

            
124
1648829
    unsafe fn transmute_lifetime<'a>(&self) -> &'a Self::Target<'a> {
125
1648829
        unsafe { transmute::<&Self, &'a IndexedSet<T::Target<'a>>>(self) }
126
1648829
    }
127

            
128
208956
    unsafe fn transmute_lifetime_mut<'a>(&mut self) -> &'a mut Self::Target<'a> {
129
208956
        unsafe { transmute::<&mut Self, &'a mut IndexedSet<T::Target<'a>>>(self) }
130
208956
    }
131
}
132

            
133
// In Rust Its not yet possible to implement it for any tuples, so we implement it for some common sizes.
134
unsafe impl<T1: Transmutable, T2: Transmutable> Transmutable for (T1, T2)
135
where
136
    for<'a> T1::Target<'a>: Sized,
137
    for<'a> T2::Target<'a>: Sized,
138
{
139
    type Target<'a>
140
        = (T1::Target<'a>, T2::Target<'a>)
141
    where
142
        T1: 'a,
143
        T2: 'a;
144

            
145
    unsafe fn transmute_lifetime<'a>(&self) -> &'a Self::Target<'a> {
146
        unsafe { transmute::<&Self, &'a (T1::Target<'a>, T2::Target<'a>)>(self) }
147
    }
148

            
149
    unsafe fn transmute_lifetime_mut<'a>(&mut self) -> &'a mut Self::Target<'a> {
150
        unsafe { transmute::<&mut Self, &'a mut (T1::Target<'a>, T2::Target<'a>)>(self) }
151
    }
152
}
153

            
154
unsafe impl<T: Transmutable> Transmutable for [T]
155
where
156
    for<'a> T::Target<'a>: Sized,
157
{
158
    type Target<'a>
159
        = [T::Target<'a>]
160
    where
161
        T: 'a;
162

            
163
930354417
    unsafe fn transmute_lifetime<'a>(&self) -> &'a Self::Target<'a> {
164
930354417
        unsafe { transmute::<&Self, &'a [T::Target<'a>]>(self) }
165
930354417
    }
166

            
167
    unsafe fn transmute_lifetime_mut<'a>(&mut self) -> &'a mut Self::Target<'a> {
168
        unsafe { transmute::<&mut Self, &'a mut [T::Target<'a>]>(self) }
169
    }
170
}
171

            
172
unsafe impl Transmutable for bool {
173
    type Target<'a> = bool;
174

            
175
    unsafe fn transmute_lifetime<'a>(&self) -> &'a Self::Target<'a> {
176
        unsafe { transmute::<&Self, &'a bool>(self) }
177
    }
178

            
179
    unsafe fn transmute_lifetime_mut<'a>(&mut self) -> &'a mut Self::Target<'a> {
180
        unsafe { transmute::<&mut Self, &'a mut bool>(self) }
181
    }
182
}