bevy_reflect_derive/
string_expr.rs1use proc_macro2::TokenStream;
2use quote::{quote, ToTokens};
3use syn::{spanned::Spanned, LitStr};
4
5#[derive(Clone)]
7pub(crate) enum StringExpr {
8 Const(TokenStream),
14 Borrowed(TokenStream),
16 Owned(TokenStream),
18}
19
20impl<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
26impl StringExpr {
27 pub fn from_lit(lit: &LitStr) -> Self {
31 Self::Const(lit.to_token_stream())
32 }
33
34 pub fn from_str(string: &str) -> Self {
38 Self::Const(string.into_token_stream())
39 }
40
41 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 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 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
88impl Default for StringExpr {
89 fn default() -> Self {
90 StringExpr::from_str("")
91 }
92}
93
94impl 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}