1use std::borrow::Cow;
2use std::collections::HashMap;
3use std::collections::HashSet;
4use std::collections::VecDeque;
5use std::hash::BuildHasher;
6use std::hash::Hash;
7use std::sync::Arc;
8
9/// Shamelessly copied from https://github.com/bearcove/merde
10/// Allow turning a value into an "owned" variant, which can then be
11/// returned, moved, etc.
12///
13/// This usually involves allocating buffers for `Cow<'a, str>`, etc.
14pub trait IntoStatic: Sized {
15 /// The "owned" variant of the type. For `Cow<'a, str>`, this is `Cow<'static, str>`, for example.
16 type Output: 'static;
17
18 /// Turns the value into an "owned" variant, which can then be returned, moved, etc.
19 ///
20 /// This allocates, for all but the most trivial types.
21 fn into_static(self) -> Self::Output;
22}
23
24impl<T, E> IntoStatic for Result<T, E>
25where
26 T: IntoStatic,
27 E: IntoStatic,
28{
29 type Output = Result<T::Output, E::Output>;
30
31 fn into_static(self) -> Self::Output {
32 match self {
33 Ok(v) => Ok(v.into_static()),
34 Err(e) => Err(e.into_static()),
35 }
36 }
37}
38
39impl<T> IntoStatic for Cow<'_, T>
40where
41 T: ToOwned + ?Sized + 'static,
42{
43 type Output = Cow<'static, T>;
44
45 #[inline(always)]
46 fn into_static(self) -> Self::Output {
47 match self {
48 Cow::Borrowed(b) => Cow::Owned(b.to_owned()),
49 Cow::Owned(o) => Cow::Owned(o),
50 }
51 }
52}
53
54macro_rules! impl_into_static_passthru {
55 ($($ty:ty),+) => {
56 $(
57 impl IntoStatic for $ty {
58 type Output = $ty;
59
60 #[inline(always)]
61 fn into_static(self) -> Self::Output {
62 self
63 }
64 }
65 )+
66 };
67}
68
69impl_into_static_passthru!(
70 String, u128, u64, u32, u16, u8, i128, i64, i32, i16, i8, bool, char, usize, isize, f32, f64
71);
72
73impl<T: IntoStatic> IntoStatic for Box<T> {
74 type Output = Box<T::Output>;
75
76 fn into_static(self) -> Self::Output {
77 Box::new((*self).into_static())
78 }
79}
80
81impl<T: IntoStatic> IntoStatic for Option<T> {
82 type Output = Option<T::Output>;
83
84 fn into_static(self) -> Self::Output {
85 self.map(|v| v.into_static())
86 }
87}
88
89impl<T: IntoStatic> IntoStatic for Vec<T> {
90 type Output = Vec<T::Output>;
91
92 fn into_static(self) -> Self::Output {
93 self.into_iter().map(|v| v.into_static()).collect()
94 }
95}
96
97impl<T: IntoStatic + Clone> IntoStatic for Arc<T> {
98 type Output = Arc<T::Output>;
99
100 fn into_static(self) -> Self::Output {
101 let t: T = (*self).clone();
102 Arc::new(t.into_static())
103 }
104}
105
106impl<K, V, S> IntoStatic for HashMap<K, V, S>
107where
108 S: BuildHasher + Default + 'static,
109 K: IntoStatic + Eq + Hash,
110 V: IntoStatic,
111 K::Output: Eq + Hash,
112{
113 type Output = HashMap<K::Output, V::Output, S>;
114
115 fn into_static(self) -> Self::Output {
116 self.into_iter()
117 .map(|(k, v)| (k.into_static(), v.into_static()))
118 .collect()
119 }
120}
121
122impl<T: IntoStatic> IntoStatic for HashSet<T>
123where
124 T::Output: Eq + Hash,
125{
126 type Output = HashSet<T::Output>;
127
128 fn into_static(self) -> Self::Output {
129 self.into_iter().map(|v| v.into_static()).collect()
130 }
131}
132
133impl<T: IntoStatic> IntoStatic for VecDeque<T> {
134 type Output = VecDeque<T::Output>;
135
136 fn into_static(self) -> Self::Output {
137 self.into_iter().map(|v| v.into_static()).collect()
138 }
139}
140
141impl<T1: IntoStatic> IntoStatic for (T1,) {
142 type Output = (T1::Output,);
143
144 fn into_static(self) -> Self::Output {
145 (self.0.into_static(),)
146 }
147}
148
149impl<T1: IntoStatic, T2: IntoStatic> IntoStatic for (T1, T2) {
150 type Output = (T1::Output, T2::Output);
151
152 fn into_static(self) -> Self::Output {
153 (self.0.into_static(), self.1.into_static())
154 }
155}
156
157impl<T1: IntoStatic, T2: IntoStatic, T3: IntoStatic> IntoStatic for (T1, T2, T3) {
158 type Output = (T1::Output, T2::Output, T3::Output);
159
160 fn into_static(self) -> Self::Output {
161 (
162 self.0.into_static(),
163 self.1.into_static(),
164 self.2.into_static(),
165 )
166 }
167}
168
169impl<T1: IntoStatic, T2: IntoStatic, T3: IntoStatic, T4: IntoStatic> IntoStatic
170 for (T1, T2, T3, T4)
171{
172 type Output = (T1::Output, T2::Output, T3::Output, T4::Output);
173
174 fn into_static(self) -> Self::Output {
175 (
176 self.0.into_static(),
177 self.1.into_static(),
178 self.2.into_static(),
179 self.3.into_static(),
180 )
181 }
182}
183
184impl<T1: IntoStatic, T2: IntoStatic, T3: IntoStatic, T4: IntoStatic, T5: IntoStatic> IntoStatic
185 for (T1, T2, T3, T4, T5)
186{
187 type Output = (T1::Output, T2::Output, T3::Output, T4::Output, T5::Output);
188
189 fn into_static(self) -> Self::Output {
190 (
191 self.0.into_static(),
192 self.1.into_static(),
193 self.2.into_static(),
194 self.3.into_static(),
195 self.4.into_static(),
196 )
197 }
198}
199
200impl<T1: IntoStatic, T2: IntoStatic, T3: IntoStatic, T4: IntoStatic, T5: IntoStatic, T6: IntoStatic>
201 IntoStatic for (T1, T2, T3, T4, T5, T6)
202{
203 type Output = (
204 T1::Output,
205 T2::Output,
206 T3::Output,
207 T4::Output,
208 T5::Output,
209 T6::Output,
210 );
211
212 fn into_static(self) -> Self::Output {
213 (
214 self.0.into_static(),
215 self.1.into_static(),
216 self.2.into_static(),
217 self.3.into_static(),
218 self.4.into_static(),
219 self.5.into_static(),
220 )
221 }
222}
223
224impl<
225 T1: IntoStatic,
226 T2: IntoStatic,
227 T3: IntoStatic,
228 T4: IntoStatic,
229 T5: IntoStatic,
230 T6: IntoStatic,
231 T7: IntoStatic,
232> IntoStatic for (T1, T2, T3, T4, T5, T6, T7)
233{
234 type Output = (
235 T1::Output,
236 T2::Output,
237 T3::Output,
238 T4::Output,
239 T5::Output,
240 T6::Output,
241 T7::Output,
242 );
243
244 fn into_static(self) -> Self::Output {
245 (
246 self.0.into_static(),
247 self.1.into_static(),
248 self.2.into_static(),
249 self.3.into_static(),
250 self.4.into_static(),
251 self.5.into_static(),
252 self.6.into_static(),
253 )
254 }
255}
256
257impl<
258 T1: IntoStatic,
259 T2: IntoStatic,
260 T3: IntoStatic,
261 T4: IntoStatic,
262 T5: IntoStatic,
263 T6: IntoStatic,
264 T7: IntoStatic,
265 T8: IntoStatic,
266> IntoStatic for (T1, T2, T3, T4, T5, T6, T7, T8)
267{
268 type Output = (
269 T1::Output,
270 T2::Output,
271 T3::Output,
272 T4::Output,
273 T5::Output,
274 T6::Output,
275 T7::Output,
276 T8::Output,
277 );
278
279 fn into_static(self) -> Self::Output {
280 (
281 self.0.into_static(),
282 self.1.into_static(),
283 self.2.into_static(),
284 self.3.into_static(),
285 self.4.into_static(),
286 self.5.into_static(),
287 self.6.into_static(),
288 self.7.into_static(),
289 )
290 }
291}