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