A better Rust ATProto crate
at main 7.6 kB view raw
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}