Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/derive/src/string_expr.rs
6599 views
1
use proc_macro2::TokenStream;
2
use quote::{quote, ToTokens};
3
use syn::{spanned::Spanned, LitStr};
4
5
/// Contains tokens representing different kinds of string.
6
#[derive(Clone)]
7
pub(crate) enum StringExpr {
8
/// A string that is valid at compile time.
9
///
10
/// This is either a string literal like `"mystring"`,
11
/// or a string created by a macro like [`module_path`]
12
/// or [`concat`].
13
Const(TokenStream),
14
/// A [string slice](str) that is borrowed for a `'static` lifetime.
15
Borrowed(TokenStream),
16
/// An [owned string](String).
17
Owned(TokenStream),
18
}
19
20
impl<T: ToString + Spanned> From<T> for StringExpr {
21
fn from(value: T) -> Self {
22
Self::from_lit(&LitStr::new(&value.to_string(), value.span()))
23
}
24
}
25
26
impl StringExpr {
27
/// Creates a [constant] [`StringExpr`] from a [`struct@LitStr`].
28
///
29
/// [constant]: StringExpr::Const
30
pub fn from_lit(lit: &LitStr) -> Self {
31
Self::Const(lit.to_token_stream())
32
}
33
34
/// Creates a [constant] [`StringExpr`] by interpreting a [string slice][str] as a [`struct@LitStr`].
35
///
36
/// [constant]: StringExpr::Const
37
pub fn from_str(string: &str) -> Self {
38
Self::Const(string.into_token_stream())
39
}
40
41
/// Returns tokens for an [owned string](String).
42
///
43
/// The returned expression will allocate unless the [`StringExpr`] is [already owned].
44
///
45
/// [already owned]: StringExpr::Owned
46
pub fn into_owned(self) -> TokenStream {
47
let bevy_reflect_path = crate::meta::get_bevy_reflect_path();
48
49
match self {
50
Self::Const(tokens) | Self::Borrowed(tokens) => quote! {
51
#bevy_reflect_path::__macro_exports::alloc_utils::ToString::to_string(#tokens)
52
},
53
Self::Owned(owned) => owned,
54
}
55
}
56
57
/// Returns tokens for a statically borrowed [string slice](str).
58
pub fn into_borrowed(self) -> TokenStream {
59
match self {
60
Self::Const(tokens) | Self::Borrowed(tokens) => tokens,
61
Self::Owned(owned) => quote! {
62
&#owned
63
},
64
}
65
}
66
67
/// Appends a [`StringExpr`] to another.
68
///
69
/// If both expressions are [`StringExpr::Const`] this will use [`concat`] to merge them.
70
pub fn appended_by(mut self, other: StringExpr) -> Self {
71
if let Self::Const(tokens) = self {
72
if let Self::Const(more) = other {
73
return Self::Const(quote! {
74
::core::concat!(#tokens, #more)
75
});
76
}
77
self = Self::Const(tokens);
78
}
79
80
let owned = self.into_owned();
81
let borrowed = other.into_borrowed();
82
Self::Owned(quote! {
83
::core::ops::Add::<&str>::add(#owned, #borrowed)
84
})
85
}
86
}
87
88
impl Default for StringExpr {
89
fn default() -> Self {
90
StringExpr::from_str("")
91
}
92
}
93
94
impl FromIterator<StringExpr> for StringExpr {
95
fn from_iter<T: IntoIterator<Item = StringExpr>>(iter: T) -> Self {
96
let mut iter = iter.into_iter();
97
match iter.next() {
98
Some(mut expr) => {
99
for next in iter {
100
expr = expr.appended_by(next);
101
}
102
103
expr
104
}
105
None => Default::default(),
106
}
107
}
108
}
109
110