fusen_macro/
lib.rs

1use fusen_common::fusen_attr;
2use proc_macro::TokenStream;
3use quote::{quote, ToTokens};
4use syn::{parse::Parser, parse_macro_input, Attribute, DeriveInput, Meta};
5
6mod data;
7mod handler_macro;
8mod server_macro;
9mod trait_macro;
10
11#[proc_macro_attribute]
12pub fn handler(attr: TokenStream, item: TokenStream) -> TokenStream {
13    let attr = HandlerAttr::from_attr(attr);
14    match attr {
15        Ok(attr) => handler_macro::fusen_handler(attr, item),
16        Err(err) => err.into_compile_error().into(),
17    }
18}
19
20#[proc_macro_attribute]
21pub fn fusen_trait(attr: TokenStream, item: TokenStream) -> TokenStream {
22    let attr = FusenAttr::from_attr(attr);
23    match attr {
24        Ok(attr) => trait_macro::fusen_trait(attr, item),
25        Err(err) => err.into_compile_error().into(),
26    }
27}
28
29#[proc_macro_derive(Data)]
30pub fn data(item: TokenStream) -> TokenStream {
31    data::data(item)
32}
33
34#[proc_macro_attribute]
35pub fn fusen_server(attr: TokenStream, item: TokenStream) -> TokenStream {
36    let attr = FusenAttr::from_attr(attr);
37    match attr {
38        Ok(attr) => server_macro::fusen_server(attr, item),
39        Err(err) => err.into_compile_error().into(),
40    }
41}
42
43#[proc_macro_attribute]
44pub fn asset(_attr: TokenStream, item: TokenStream) -> TokenStream {
45    item
46}
47
48#[proc_macro_attribute]
49pub fn url_config(attr: TokenStream, item: TokenStream) -> TokenStream {
50    let attr = UrlConfigAttr::from_attr(attr);
51    if let Err(err) = attr {
52        return err.into_compile_error().into();
53    }
54    let attr = attr.unwrap();
55    let attr = attr.attr;
56    let org_item = parse_macro_input!(item as DeriveInput);
57    let Some(attr) = attr else {
58        return syn::Error::new_spanned(
59            org_item.to_token_stream(),
60            "url_config must label to attr",
61        )
62        .into_compile_error()
63        .into();
64    };
65    let id = &org_item.ident;
66    let token = quote! {
67
68        #[derive(serde::Serialize, serde::Deserialize, Default, fusen_macro::Data)]
69        #org_item
70
71        impl #id {
72            pub fn from_url(url : &str) -> Result<Self,fusen_common::Error> {
73                let info : Vec<&str> = url.split("://").collect();
74                if info[0] != #attr {
75                   return Err(format!("err1 url {}",url).into());
76                }
77                let info : Vec<&str> = info[1].split("?").collect();
78                if info[0] != stringify!(#id) {
79                    return Err(format!("err2 url {}",url).into());
80                }
81                fusen_common::url::from_url(info[1])
82            }
83            pub fn to_url(&self) -> Result<String, fusen_common::Error> {
84                let mut res = String::new();
85                res.push_str(&(#attr.to_owned() + "://" + stringify!(#id) + "?" ));
86                res.push_str(&(fusen_common::url::to_url(self)?));
87                Ok(res)
88            }
89        }
90    };
91    token.into()
92}
93
94fn get_asset_by_attrs(attrs: &Vec<Attribute>) -> Result<ResourceAttr, syn::Error> {
95    for attr in attrs {
96        if let Meta::List(list) = &attr.meta {
97            if let Some(segment) = list.path.segments.first() {
98                if segment.ident == "asset" {
99                    return ResourceAttr::from_attr(list.tokens.clone().into());
100                }
101            }
102        }
103    }
104    Ok(ResourceAttr::default())
105}
106
107fusen_attr! {
108    ResourceAttr,
109    path,
110    method
111}
112
113fusen_attr! {
114    UrlConfigAttr,
115    attr
116}
117
118fusen_attr! {
119    FusenAttr,
120    id,
121    version,
122    group
123}
124
125fusen_attr! {
126    HandlerAttr,
127    id
128}