A better Rust ATProto crate
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<T: IntoStatic> IntoStatic for Box<T> {
105 type Output = Box<T::Output>;
106
107 fn into_static(self) -> Self::Output {
108 Box::new((*self).into_static())
109 }
110}
111
112impl IntoStatic for bytes::Bytes {
113 type Output = bytes::Bytes;
114
115 fn into_static(self) -> Self::Output {
116 self
117 }
118}
119
120impl IntoStatic for () {
121 type Output = ();
122
123 fn into_static(self) -> Self::Output {
124 self
125 }
126}
127
128impl<T: IntoStatic> IntoStatic for Option<T> {
129 type Output = Option<T::Output>;
130
131 fn into_static(self) -> Self::Output {
132 self.map(|v| v.into_static())
133 }
134}
135
136impl<T: IntoStatic> IntoStatic for Vec<T> {
137 type Output = Vec<T::Output>;
138
139 fn into_static(self) -> Self::Output {
140 self.into_iter().map(|v| v.into_static()).collect()
141 }
142}
143
144impl<T: IntoStatic + Clone> IntoStatic for Arc<T> {
145 type Output = Arc<T::Output>;
146
147 fn into_static(self) -> Self::Output {
148 let t: T = (*self).clone();
149 Arc::new(t.into_static())
150 }
151}
152
153impl<K, V, S> IntoStatic for HashMap<K, V, S>
154where
155 S: BuildHasher + Default + 'static,
156 K: IntoStatic + Eq + Hash,
157 V: IntoStatic,
158 K::Output: Eq + Hash,
159{
160 type Output = HashMap<K::Output, V::Output, S>;
161
162 fn into_static(self) -> Self::Output {
163 self.into_iter()
164 .map(|(k, v)| (k.into_static(), v.into_static()))
165 .collect()
166 }
167}
168
169impl<K, V> IntoStatic for BTreeMap<K, V>
170where
171 K: IntoStatic + Ord,
172 V: IntoStatic,
173 K::Output: Ord,
174{
175 type Output = BTreeMap<K::Output, V::Output>;
176
177 fn into_static(self) -> Self::Output {
178 self.into_iter()
179 .map(|(k, v)| (k.into_static(), v.into_static()))
180 .collect()
181 }
182}
183
184impl<T: IntoStatic> IntoStatic for HashSet<T>
185where
186 T::Output: Eq + Hash,
187{
188 type Output = HashSet<T::Output>;
189
190 fn into_static(self) -> Self::Output {
191 self.into_iter().map(|v| v.into_static()).collect()
192 }
193}
194
195impl<T: IntoStatic> IntoStatic for VecDeque<T> {
196 type Output = VecDeque<T::Output>;
197
198 fn into_static(self) -> Self::Output {
199 self.into_iter().map(|v| v.into_static()).collect()
200 }
201}
202
203impl<T1: IntoStatic> IntoStatic for (T1,) {
204 type Output = (T1::Output,);
205
206 fn into_static(self) -> Self::Output {
207 (self.0.into_static(),)
208 }
209}
210
211impl<T1: IntoStatic, T2: IntoStatic> IntoStatic for (T1, T2) {
212 type Output = (T1::Output, T2::Output);
213
214 fn into_static(self) -> Self::Output {
215 (self.0.into_static(), self.1.into_static())
216 }
217}
218
219impl<T1: IntoStatic, T2: IntoStatic, T3: IntoStatic> IntoStatic for (T1, T2, T3) {
220 type Output = (T1::Output, T2::Output, T3::Output);
221
222 fn into_static(self) -> Self::Output {
223 (
224 self.0.into_static(),
225 self.1.into_static(),
226 self.2.into_static(),
227 )
228 }
229}
230
231impl<T1: IntoStatic, T2: IntoStatic, T3: IntoStatic, T4: IntoStatic> IntoStatic
232 for (T1, T2, T3, T4)
233{
234 type Output = (T1::Output, T2::Output, T3::Output, T4::Output);
235
236 fn into_static(self) -> Self::Output {
237 (
238 self.0.into_static(),
239 self.1.into_static(),
240 self.2.into_static(),
241 self.3.into_static(),
242 )
243 }
244}
245
246impl<T1: IntoStatic, T2: IntoStatic, T3: IntoStatic, T4: IntoStatic, T5: IntoStatic> IntoStatic
247 for (T1, T2, T3, T4, T5)
248{
249 type Output = (T1::Output, T2::Output, T3::Output, T4::Output, T5::Output);
250
251 fn into_static(self) -> Self::Output {
252 (
253 self.0.into_static(),
254 self.1.into_static(),
255 self.2.into_static(),
256 self.3.into_static(),
257 self.4.into_static(),
258 )
259 }
260}
261
262impl<T1: IntoStatic, T2: IntoStatic, T3: IntoStatic, T4: IntoStatic, T5: IntoStatic, T6: IntoStatic>
263 IntoStatic for (T1, T2, T3, T4, T5, T6)
264{
265 type Output = (
266 T1::Output,
267 T2::Output,
268 T3::Output,
269 T4::Output,
270 T5::Output,
271 T6::Output,
272 );
273
274 fn into_static(self) -> Self::Output {
275 (
276 self.0.into_static(),
277 self.1.into_static(),
278 self.2.into_static(),
279 self.3.into_static(),
280 self.4.into_static(),
281 self.5.into_static(),
282 )
283 }
284}
285
286impl<
287 T1: IntoStatic,
288 T2: IntoStatic,
289 T3: IntoStatic,
290 T4: IntoStatic,
291 T5: IntoStatic,
292 T6: IntoStatic,
293 T7: IntoStatic,
294> IntoStatic for (T1, T2, T3, T4, T5, T6, T7)
295{
296 type Output = (
297 T1::Output,
298 T2::Output,
299 T3::Output,
300 T4::Output,
301 T5::Output,
302 T6::Output,
303 T7::Output,
304 );
305
306 fn into_static(self) -> Self::Output {
307 (
308 self.0.into_static(),
309 self.1.into_static(),
310 self.2.into_static(),
311 self.3.into_static(),
312 self.4.into_static(),
313 self.5.into_static(),
314 self.6.into_static(),
315 )
316 }
317}
318
319impl<
320 T1: IntoStatic,
321 T2: IntoStatic,
322 T3: IntoStatic,
323 T4: IntoStatic,
324 T5: IntoStatic,
325 T6: IntoStatic,
326 T7: IntoStatic,
327 T8: IntoStatic,
328> IntoStatic for (T1, T2, T3, T4, T5, T6, T7, T8)
329{
330 type Output = (
331 T1::Output,
332 T2::Output,
333 T3::Output,
334 T4::Output,
335 T5::Output,
336 T6::Output,
337 T7::Output,
338 T8::Output,
339 );
340
341 fn into_static(self) -> Self::Output {
342 (
343 self.0.into_static(),
344 self.1.into_static(),
345 self.2.into_static(),
346 self.3.into_static(),
347 self.4.into_static(),
348 self.5.into_static(),
349 self.6.into_static(),
350 self.7.into_static(),
351 )
352 }
353}