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