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 PunctuatedItems<T: Parse> {
81  pub inner: Vec<T>,
82}
83
84impl<T: Parse> Parse for PunctuatedItems<T> {
85  fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
86    let inner = Punctuated::<T, Token![,]>::parse_terminated(input)?
87      .into_iter()
88      .collect();
89
90    Ok(Self { inner })
91  }
92}
93
94pub struct StringList {
95  pub list: Vec<String>,
96}
97
98impl Parse for StringList {
99  fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
100    let items = Punctuated::<LitStr, Token![,]>::parse_terminated(input)?;
101
102    let list: Vec<String> = items
103      .into_iter()
104      .map(|lit_str| lit_str.value())
105      .collect();
106
107    Ok(Self { list })
108  }
109}
110
111pub struct NumList {
112  pub list: Vec<i32>,
113}
114
115impl Parse for NumList {
116  fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
117    let items = Punctuated::<LitInt, Token![,]>::parse_terminated(input)?;
118
119    let mut list: Vec<i32> = Vec::new();
120
121    for item in items {
122      list.push(item.base10_parse()?);
123    }
124
125    Ok(Self { list })
126  }
127}