aboutsummaryrefslogtreecommitdiff
path: root/mingling_macros/src/entry.rs
diff options
context:
space:
mode:
authorWeicao-CatilGrass <1992414357@qq.com>2026-05-23 23:41:04 +0800
committerWeicao-CatilGrass <1992414357@qq.com>2026-05-23 23:49:34 +0800
commit0a2ef958c0dca21d19e4ffc38ba5a7c4078e182a (patch)
treec82fc4242ed393b132ba514eb434d722e7d9c387 /mingling_macros/src/entry.rs
parentccab1940c019dfbfb7dfcbbe4cb927258933755f (diff)
Rework examples and add entry macro for testing
Diffstat (limited to 'mingling_macros/src/entry.rs')
-rw-r--r--mingling_macros/src/entry.rs75
1 files changed, 75 insertions, 0 deletions
diff --git a/mingling_macros/src/entry.rs b/mingling_macros/src/entry.rs
new file mode 100644
index 0000000..6237e41
--- /dev/null
+++ b/mingling_macros/src/entry.rs
@@ -0,0 +1,75 @@
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{Ident, LitStr, parse_macro_input};
+
+enum EntryInput {
+ Typed { ident: Ident, strings: Vec<String> },
+ Untyped { strings: Vec<String> },
+}
+
+impl syn::parse::Parse for EntryInput {
+ fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
+ // entry!(EntryType, ["a", "b", "c"])
+ // entry!["a", "b", "c"] — comes in as just ["a", "b", "c"]
+ if input.peek(Ident) && input.peek2(syn::Token![,]) {
+ // entry!(EntryType, ["a", "b", "c"])
+ let ident: Ident = input.parse()?;
+ let _comma: syn::Token![,] = input.parse()?;
+ let content;
+ syn::bracketed!(content in input);
+ let strings = parse_strings(&content)?;
+ Ok(EntryInput::Typed { ident, strings })
+ } else {
+ // entry!["a", "b", "c"] — bare bracket content
+ let strings = parse_strings(input)?;
+ Ok(EntryInput::Untyped { strings })
+ }
+ }
+}
+
+fn parse_strings(input: &syn::parse::ParseBuffer) -> syn::Result<Vec<String>> {
+ let mut strings = Vec::new();
+ while !input.is_empty() {
+ let s: LitStr = input.parse()?;
+ strings.push(s.value());
+ if input.peek(syn::Token![,]) {
+ let _comma: syn::Token![,] = input.parse()?;
+ }
+ }
+ Ok(strings)
+}
+
+pub fn entry(input: TokenStream) -> TokenStream {
+ let parsed = parse_macro_input!(input as EntryInput);
+
+ let string_exprs = match &parsed {
+ EntryInput::Typed { .. } | EntryInput::Untyped { .. } => {
+ let strings = match &parsed {
+ EntryInput::Typed { strings, .. } => strings,
+ EntryInput::Untyped { strings } => strings,
+ };
+ strings
+ .iter()
+ .map(|s| {
+ let lit = syn::LitStr::new(s, proc_macro2::Span::call_site());
+ quote! { #lit.to_string() }
+ })
+ .collect::<Vec<_>>()
+ }
+ };
+
+ let expanded = match parsed {
+ EntryInput::Typed { ident, .. } => {
+ quote! {
+ #ident::new(vec![#(#string_exprs),*])
+ }
+ }
+ EntryInput::Untyped { .. } => {
+ quote! {
+ vec![#(#string_exprs),*].into()
+ }
+ }
+ };
+
+ expanded.into()
+}