static_self/
lib.rs

1pub use static_self_derive::IntoOwned;
2
3/// A trait for things that can be cloned with a new lifetime.
4///
5/// `'any` lifeitme means the output should have `'static` lifetime.
6pub trait IntoOwned<'any> {
7  /// A variant of `Self` with a new lifetime.
8  type Owned: 'any;
9
10  /// Make lifetime of `self` `'static`.
11  fn into_owned(self) -> Self::Owned;
12}
13
14macro_rules! impl_into_owned {
15  ($t: ty) => {
16    impl<'a> IntoOwned<'a> for $t {
17      type Owned = Self;
18
19      #[inline]
20      fn into_owned(self) -> Self {
21        self
22      }
23    }
24  };
25  ($($t:ty),*) => {
26    $(impl_into_owned!($t);)*
27  };
28}
29
30impl_into_owned!(bool, f32, f64, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize, char, String);
31
32macro_rules! impl_tuple {
33  (
34    $($name:ident),*
35  ) =>{
36    #[allow(non_snake_case)]
37    impl<'any, $($name,)*> IntoOwned<'any> for ($($name,)*)
38    where
39        $($name: IntoOwned<'any>),*
40    {
41      type Owned = ($(<$name as IntoOwned<'any>>::Owned,)*);
42
43      #[inline]
44      fn into_owned(self) -> Self::Owned {
45        let ($($name,)*) = self;
46        ($($name.into_owned(),)*)
47      }
48    }
49  };
50}
51
52macro_rules! call_impl_tuple {
53  () => {};
54  ($first:ident) => {
55    impl_tuple!($first);
56  };
57  (
58    $first:ident,
59    $($name:ident),*
60  ) => {
61    call_impl_tuple!($($name),*);
62    impl_tuple!($first, $($name),*);
63  };
64}
65
66call_impl_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
67
68impl<'any, T> IntoOwned<'any> for Vec<T>
69where
70  T: IntoOwned<'any>,
71{
72  type Owned = Vec<<T as IntoOwned<'any>>::Owned>;
73
74  fn into_owned(self) -> Self::Owned {
75    self.into_iter().map(|v| v.into_owned()).collect()
76  }
77}
78impl<'any, T> IntoOwned<'any> for Option<T>
79where
80  T: IntoOwned<'any>,
81{
82  type Owned = Option<<T as IntoOwned<'any>>::Owned>;
83
84  fn into_owned(self) -> Self::Owned {
85    self.map(|v| v.into_owned())
86  }
87}
88
89impl<'any, T> IntoOwned<'any> for Box<T>
90where
91  T: IntoOwned<'any>,
92{
93  type Owned = Box<<T as IntoOwned<'any>>::Owned>;
94
95  fn into_owned(self) -> Self::Owned {
96    Box::new((*self).into_owned())
97  }
98}
99
100impl<'any, T> IntoOwned<'any> for Box<[T]>
101where
102  T: IntoOwned<'any>,
103{
104  type Owned = Box<[<T as IntoOwned<'any>>::Owned]>;
105
106  fn into_owned(self) -> Self::Owned {
107    self.into_vec().into_owned().into_boxed_slice()
108  }
109}
110
111#[cfg(feature = "smallvec")]
112impl<'any, T, const N: usize> IntoOwned<'any> for smallvec::SmallVec<[T; N]>
113where
114  T: IntoOwned<'any>,
115  [T; N]: smallvec::Array<Item = T>,
116  [<T as IntoOwned<'any>>::Owned; N]: smallvec::Array<Item = <T as IntoOwned<'any>>::Owned>,
117{
118  type Owned = smallvec::SmallVec<[<T as IntoOwned<'any>>::Owned; N]>;
119
120  fn into_owned(self) -> Self::Owned {
121    self.into_iter().map(|v| v.into_owned()).collect()
122  }
123}
124
125#[cfg(feature = "indexmap")]
126impl<'any, K, V> IntoOwned<'any> for indexmap::IndexMap<K, V>
127where
128  K: IntoOwned<'any>,
129  V: IntoOwned<'any>,
130  <K as IntoOwned<'any>>::Owned: Eq + std::hash::Hash,
131{
132  type Owned = indexmap::IndexMap<<K as IntoOwned<'any>>::Owned, <V as IntoOwned<'any>>::Owned>;
133
134  fn into_owned(self) -> Self::Owned {
135    self.into_iter().map(|(k, v)| (k.into_owned(), v.into_owned())).collect()
136  }
137}
138
139impl<'any, T, const N: usize> IntoOwned<'any> for [T; N]
140where
141  T: IntoOwned<'any>,
142{
143  type Owned = [<T as IntoOwned<'any>>::Owned; N];
144
145  fn into_owned(self) -> Self::Owned {
146    self
147      .into_iter()
148      .map(|v| v.into_owned())
149      .collect::<Vec<_>>()
150      .try_into()
151      .unwrap_or_else(|_| unreachable!("Vec<T> with N elements should be able to be converted to [T; N]"))
152  }
153}