Skip to main content

jacquard_common/
into_static.rs

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