gmt_dos_clients_scopehub/
lib.rs1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3use syn::{Ident, ItemEnum, Type, parse_macro_input};
4
5#[proc_macro_attribute]
6pub fn scopehub(_args: TokenStream, input: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(input as ItemEnum);
8
9 let hub = input.ident;
10 let hub_error = format_ident!("{hub}Error");
11
12 let (scope_ty, signal_ty): (Vec<_>, Vec<_>) = input
13 .variants
14 .iter()
15 .flat_map(|v| {
16 v.fields
17 .iter()
18 .map(|field| (v.ident.clone(), field.ty.clone()))
19 .collect::<Vec<(Ident, Type)>>()
20 })
21 .unzip();
22
23 let idents: Vec<_> = scope_ty
24 .iter()
25 .enumerate()
26 .map(|(i, _)| format_ident!("scope_{i}"))
28 .collect();
29
30 let scope_hub_server = quote! {
32 #[derive(Debug)]
33 pub enum #hub_error{
34 Server(::gmt_dos_clients_scope::server::ServerError)
35 }
36 impl ::std::fmt::Display for #hub_error{
37 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
38 write!(f, "failed to initiate scopes hub")
39 }
40 }
41 impl ::std::error::Error for #hub_error{
42 fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
43 match self {
44 Self::Server(source) => Some(source),
45 _ => None
46 }
47 }
48 }
49 impl From<::gmt_dos_clients_scope::server::ServerError> for #hub_error{
50 fn from(e: ::gmt_dos_clients_scope::server::ServerError) -> Self {
51 Self::Server(e)
52 }
53 }
54 pub struct #hub {
56 monitor: Option<::gmt_dos_clients_scope::server::Monitor>,
57 #(#idents: ::gmt_dos_clients_scope::server::#scope_ty<#signal_ty>),*
58 }
59 impl #hub {
60 pub fn new() -> Result<Self,#hub_error> {
62 let mut monitor = ::gmt_dos_clients_scope::server::Monitor::new();
63 #(let #idents = ::gmt_dos_clients_scope::server::#scope_ty::<#signal_ty>::builder(&mut monitor).build()?;)*
64 Ok(Self {
65 monitor: Some(monitor),
66 #(#idents),*
67 })
68 }
69 pub async fn close(&mut self) -> Result<(),#hub_error> {
71 #(self.#idents.end_transmission();)*
72 if let Some(monitor) = self.monitor.take() {
73 monitor.join().await.map_err(|e| ::gmt_dos_clients_scope::server::ServerError::Transmitter(e))?;
74 }
75 Ok(())
76 }
77 }
78 impl ::interface::Update for #hub {}
79 #(
80 impl ::interface::Read<#signal_ty> for #hub {
81 fn read(&mut self, data: ::interface::Data<#signal_ty>) {
82 <_ as ::interface::Read<#signal_ty>>::read(&mut self.#idents, data);
83 }
84 }
85 )*
86 impl ::std::future::IntoFuture for &mut #hub {
87 type Output = <::gmt_dos_clients_scope::server::Monitor as ::std::future::IntoFuture>::Output;
88 type IntoFuture = <::gmt_dos_clients_scope::server::Monitor as ::std::future::IntoFuture>::IntoFuture;
89 fn into_future(self) -> Self::IntoFuture {
90 #(self.#idents.end_transmission();)*
91 self.monitor.take().unwrap().into_future()
92 }
93 }
94 };
95
96 TokenStream::from(scope_hub_server)
98}