thruster_socketio_proc/
lib.rs

1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use proc_macro2::{Ident, Span as Span2};
5use quote::quote;
6
7#[proc_macro_attribute]
8pub fn socketio_handler(attr: TokenStream, item: TokenStream) -> TokenStream {
9    if let syn::Item::Fn(mut function_item) = syn::parse(item.clone()).unwrap() {
10        let name = function_item.ident.clone();
11        let new_name = Ident::new(&format!("__async_{}", name.clone()), Span2::call_site());
12        function_item.ident = new_name.clone();
13
14        let visibility = function_item.vis.clone();
15        let arguments = function_item.decl.inputs.clone();
16        let generics = function_item.decl.generics.clone();
17
18        let context_type = match &arguments[0] {
19            syn::FnArg::Captured(cap) => &cap.ty,
20            _ => panic!("Expected the first argument to be a context type"),
21        };
22        let socket_io_type = Ident::new(&format!("__SocketIO_{}", name.clone()), Span2::call_site());
23        let crate_path = match attr.to_string().as_str() {
24            "_internal" => quote! {
25                crate::core::{ IOSocketWrapper as #socket_io_type }
26            },
27            _ => quote! {
28                thruster_socketio::{ SocketIO as #socket_io_type }
29            },
30        };
31
32        let gen = quote! {
33            #function_item
34
35            use #crate_path;
36            #visibility fn #name#generics(socket: #context_type) -> Pin<Box<dyn Future<Output = Result<#context_type, ()>> + Send>> {
37                Box::pin(#new_name(socket))
38            }
39        };
40
41        // proc_macro::Span::call_site()
42        //     .note("Thruster code output")
43        //     .note(gen.to_string())
44        //     .emit();
45
46        gen.into()
47    } else {
48        item
49    }
50}
51
52#[proc_macro_attribute]
53pub fn socketio_listener(attr: TokenStream, item: TokenStream) -> TokenStream {
54    if let syn::Item::Fn(mut function_item) = syn::parse(item.clone()).unwrap() {
55        let name = function_item.ident.clone();
56        let new_name = Ident::new(&format!("__async_{}", name.clone()), Span2::call_site());
57        function_item.ident = new_name.clone();
58
59        let visibility = function_item.vis.clone();
60        let arguments = function_item.decl.inputs.clone();
61        let generics = function_item.decl.generics.clone();
62
63        let socket_type = match &arguments[0] {
64            syn::FnArg::Captured(cap) => &cap.ty,
65            _ => panic!("Expected the first argument to be a socket type"),
66        };
67
68        let socket_io_type = Ident::new(&format!("__SocketIOListener_{}", name.clone()), Span2::call_site());
69        let crate_path = match attr.to_string().as_str() {
70            "_internal" => quote! {
71                crate::core::{ IOSocketWrapper as #socket_io_type }
72            },
73            _ => quote! {
74                thruster_socketio::{ SocketIO as #socket_io_type }
75            },
76        };
77
78        let gen = quote! {
79            #function_item
80
81            use #crate_path;
82            #visibility fn #name#generics(socket: #socket_type, value: String) -> Pin<Box<dyn Future<Output = Result<(), ()>> + Send>> {
83                Box::pin(#new_name(socket, value))
84            }
85        };
86
87        // proc_macro::Span::call_site()
88        //     .note("Thruster code output")
89        //     .note(gen.to_string())
90        //     .emit();
91
92        gen.into()
93    } else {
94        item
95    }
96}