syn_utils/
lib.rs

1#[macro_use]
2mod macros;
3
4mod expr_trait;
5use std::{fmt::Display, str::FromStr};
6
7pub use expr_trait::*;
8use proc_macro2::{Span, TokenStream as TokenStream2};
9use quote::{quote, ToTokens};
10use syn::{
11  parse::Parse, punctuated::Punctuated, Expr, ExprCall, ExprClosure, Ident, Lit, LitInt, LitStr,
12  Path, Token,
13};
14
15pub fn new_ident(name: &str) -> Ident {
16  Ident::new(name, Span::call_site())
17}
18
19#[derive(Default, Clone, Debug)]
20pub struct ControlFlow {
21  pub dummy: Option<TokenStream2>,
22}
23
24impl ControlFlow {
25  pub fn new() -> Self {
26    Self { dummy: None }
27  }
28
29  pub fn with_custom_dummy(dummy: &TokenStream2) -> Self {
30    Self {
31      dummy: Some(dummy.to_token_stream()),
32    }
33  }
34}
35
36pub trait MacroResult: Sized {
37  type Output;
38
39  fn unwrap_or_dummy(self, dummy: TokenStream2) -> Result<Self::Output, TokenStream2>;
40
41  fn unwrap_or_unimplemented(self) -> Result<Self::Output, TokenStream2> {
42    self.unwrap_or_dummy(quote! { unimplemented!() })
43  }
44}
45
46impl<T> MacroResult for syn::Result<T> {
47  type Output = T;
48
49  fn unwrap_or_dummy(self, dummy: TokenStream2) -> Result<Self::Output, TokenStream2> {
50    match self {
51      Ok(o) => Ok(o),
52      Err(e) => {
53        let error = e.into_compile_error();
54
55        Err(quote! {
56          #error #dummy
57        })
58      }
59    }
60  }
61}
62
63#[derive(Debug, Clone)]
64pub enum CallOrClosure {
65  Call(ExprCall),
66  Closure(ExprClosure),
67}
68
69impl ToTokens for CallOrClosure {
70  fn to_tokens(&self, tokens: &mut TokenStream2) {
71    let output = match self {
72      CallOrClosure::Call(call) => call.to_token_stream(),
73      CallOrClosure::Closure(expr_closure) => expr_closure.to_token_stream(),
74    };
75
76    tokens.extend(output);
77  }
78}
79
80pub struct PunctuatedParser<T: Parse> {
81  pub inner: Punctuated<T, Token![,]>,
82}
83
84impl<T: Parse> Parse for PunctuatedParser<T> {
85  fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
86    let inner = Punctuated::parse_terminated(input)?;
87
88    Ok(Self { inner })
89  }
90}
91
92pub struct StringList {
93  pub list: Vec<String>,
94}
95
96impl Parse for StringList {
97  fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
98    let items = Punctuated::<LitStr, Token![,]>::parse_terminated(input)?;
99
100    let list: Vec<String> = items
101      .into_iter()
102      .map(|lit_str| lit_str.value())
103      .collect();
104
105    Ok(Self { list })
106  }
107}
108
109pub struct NumList {
110  pub list: Vec<i32>,
111}
112
113impl Parse for NumList {
114  fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
115    let items = Punctuated::<LitInt, Token![,]>::parse_terminated(input)?;
116
117    let mut list: Vec<i32> = Vec::new();
118
119    for item in items {
120      list.push(item.base10_parse()?);
121    }
122
123    Ok(Self { list })
124  }
125}