fire_stream_api_codegen/
message.rs1use crate::util::fire_api_crate;
2
3use proc_macro2::{Span, TokenStream};
4use syn::{
5 DeriveInput, Error, Ident, Generics, Attribute, TypeGenerics, WhereClause
6};
7use quote::{quote, ToTokens};
8
9
10pub(crate) fn into_expand(input: DeriveInput) -> Result<TokenStream, Error> {
11 let DeriveInput { attrs, ident, generics, .. } = input;
12
13 let attr = MsgAttribute::from_attrs(&attrs)?;
14 let encdec_module = attr.module;
15
16 let fire = fire_api_crate()?;
17 let message = quote!(#fire::message);
18
19 let (impl_generics, ty_generics, where_clause) = split_generics(
20 &generics,
21 &fire
22 );
23
24 Ok(quote!(
25 impl #impl_generics #message::IntoMessage<A, B> for #ident #ty_generics
26 #where_clause {
27 fn into_message(
28 self
29 ) -> std::result::Result<
30 #message::Message<A, B>,
31 #fire::error::MessageError
32 > {
33 #fire::encdec::#encdec_module::encode(self)
34 }
35 }
36 ))
37}
38
39pub(crate) fn from_expand(input: DeriveInput) -> Result<TokenStream, Error> {
40 let DeriveInput { attrs, ident, generics, .. } = input;
41
42 let attr = MsgAttribute::from_attrs(&attrs)?;
43 let encdec_module = attr.module;
44
45 let fire = fire_api_crate()?;
46 let message = quote!(#fire::message);
47
48 let (impl_generics, ty_generics, where_clause) = split_generics(
49 &generics,
50 &fire
51 );
52
53 Ok(quote!(
54 impl #impl_generics #message::FromMessage<A, B> for #ident #ty_generics
55 #where_clause {
56 fn from_message(
57 msg: #message::Message<A, B>
58 ) -> std::result::Result<Self, #fire::error::MessageError> {
59 #fire::encdec::#encdec_module::decode(msg)
60 }
61 }
62 ))
63}
64
65
66struct MsgAttribute {
67 pub module: Ident
69}
70
71impl MsgAttribute {
72 pub fn from_attrs(attrs: &[Attribute]) -> Result<Self, Error> {
73 let mut module = None;
74
75 for attr in attrs {
76 if !attr.path().is_ident("message") {
77 continue
78 }
79
80 module = Some(attr.parse_args()?);
81 }
82
83 Ok(Self {
84 module: module.ok_or_else(|| Error::new(
85 Span::call_site(),
86 "need an attribute #[message(..)]"
87 ))?
88 })
89 }
90}
91
92fn split_generics<'a>(
93 generics: &'a Generics,
94 fire: &TokenStream
95) -> (ImplGenerics, TypeGenerics<'a>, Option<&'a WhereClause>) {
96 let mut impl_generics = generics.clone();
97 impl_generics.params.push(
98 syn::parse2(quote!(A: #fire::message::Action)).unwrap()
99 );
100 impl_generics.params.push(
101 syn::parse2(quote!(B: #fire::message::PacketBytes)).unwrap()
102 );
103
104 let (_, ty_generics, where_clause) = generics.split_for_impl();
105 (ImplGenerics(impl_generics), ty_generics, where_clause)
106}
107
108struct ImplGenerics(Generics);
109
110impl ToTokens for ImplGenerics {
111 fn to_tokens(&self, tokens: &mut TokenStream) {
112 let (impl_generics, _, _) = self.0.split_for_impl();
113 impl_generics.to_tokens(tokens);
114 }
115}