into_static/
lib.rs

1//! Upgrading to static lifetimes.
2//!
3//! This crate provides the [`IntoStatic`] trait, which allows upgrading all lifetimes to `'static`.
4
5#![forbid(unsafe_code)]
6#![deny(missing_docs)]
7#![cfg_attr(not(feature = "std"), no_std)]
8#![cfg_attr(docsrs, feature(doc_auto_cfg))]
9
10use cfg_if::cfg_if;
11
12cfg_if! {
13    if #[cfg(feature = "std")] {
14        use std::borrow::Cow;
15    } else if #[cfg(feature = "alloc")] {
16        extern crate alloc;
17
18        use alloc::{borrow::Cow, vec::Vec};
19    }
20}
21
22/// Upgrading to `'static` lifetimes.
23pub trait IntoStatic {
24    /// The type with `'static` lifetimes.
25    type Static: IntoStatic<Static = Self::Static> + 'static;
26
27    /// Upgrades [`Self`] to [`Self::Static`].
28    fn into_static(self) -> Self::Static;
29}
30
31cfg_if! {
32    if #[cfg(any(feature = "std", feature = "alloc"))] {
33        impl IntoStatic for Cow<'_, str> {
34            type Static = Cow<'static, str>;
35
36            fn into_static(self) -> Self::Static {
37                Self::Static::Owned(self.into_owned())
38            }
39        }
40
41        impl IntoStatic for Cow<'_, [u8]> {
42            type Static = Cow<'static, [u8]>;
43
44            fn into_static(self) -> Self::Static {
45                Self::Static::Owned(self.into_owned())
46            }
47        }
48
49        impl<T: Clone + IntoStatic<Static: Clone>> IntoStatic for Cow<'_, [T]> {
50            type Static = Cow<'static, [T::Static]>;
51
52            fn into_static(self) -> Self::Static {
53                Self::Static::Owned(self.into_owned().into_static())
54            }
55        }
56
57        impl<T: IntoStatic> IntoStatic for Vec<T> {
58            type Static = Vec<T::Static>;
59
60            fn into_static(self) -> Self::Static {
61                self.into_iter().map(IntoStatic::into_static).collect()
62            }
63        }
64    }
65}
66
67impl<T: IntoStatic> IntoStatic for Option<T> {
68    type Static = Option<T::Static>;
69
70    fn into_static(self) -> Self::Static {
71        self.map(IntoStatic::into_static)
72    }
73}
74
75impl<T: IntoStatic, E: IntoStatic> IntoStatic for Result<T, E> {
76    type Static = Result<T::Static, E::Static>;
77
78    fn into_static(self) -> Self::Static {
79        self.map(IntoStatic::into_static)
80            .map_err(IntoStatic::into_static)
81    }
82}
83
84impl<T: IntoStatic, const N: usize> IntoStatic for [T; N] {
85    type Static = [T::Static; N];
86
87    fn into_static(self) -> Self::Static {
88        self.map(IntoStatic::into_static)
89    }
90}
91
92macro_rules! impl_tuple {
93    ($($name: ident: $type: ident),+) => {
94        impl<$($type: $crate::IntoStatic),+> $crate::IntoStatic for ($($type,)+) {
95            type Static = ($($type::Static,)+);
96
97            fn into_static(self) -> Self::Static {
98                let ($($name,)+) = self;
99
100                ($($name.into_static(),)+)
101            }
102        }
103    }
104}
105
106impl_tuple!(a: A);
107impl_tuple!(a: A, b: B);
108impl_tuple!(a: A, b: B, c: C);
109impl_tuple!(a: A, b: B, c: C, d: D);
110impl_tuple!(a: A, b: B, c: C, d: D, e: E);
111impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F);
112impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
113impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
114impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
115impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
116impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
117impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);