mpst_seq_proc/macros_simple/roles/
create_normal_role_short.rs

1use proc_macro2::{Span, TokenStream};
2use quote::quote;
3use syn::parse::{Parse, ParseStream};
4use syn::{Ident, Result};
5
6#[derive(Debug)]
7pub(crate) struct CreateNormalRoleShort {
8    role: Ident,
9}
10
11impl Parse for CreateNormalRoleShort {
12    fn parse(input: ParseStream) -> Result<Self> {
13        let role = Ident::parse(input)?;
14
15        Ok(CreateNormalRoleShort { role })
16    }
17}
18
19impl From<CreateNormalRoleShort> for TokenStream {
20    fn from(input: CreateNormalRoleShort) -> TokenStream {
21        input.expand()
22    }
23}
24
25impl CreateNormalRoleShort {
26    fn expand(&self) -> TokenStream {
27        let role = &self.role;
28
29        // Build the new names
30        // role
31        let concatenated_role = format!("Role{role}");
32        let role_name = Ident::new(&concatenated_role, Span::call_site());
33        // dual
34        let concatenated_dual = format!("Role{role}Dual");
35        let dual_name = Ident::new(&concatenated_dual, Span::call_site());
36
37        quote! {
38            ////////////////////////////////////////////
39            /// The Role
40
41            #[derive(Debug)]
42            struct #role_name<R>
43            where
44                R: mpstthree::role::Role,
45                R::Dual: mpstthree::role::Role,
46            {
47                sender: crossbeam_channel::Sender<R::Dual>,
48            }
49
50            ////////////////////////////////////////////
51            /// The Dual
52
53            #[derive(Debug)]
54            struct #dual_name<R>
55            where
56                R: mpstthree::role::Role,
57                R::Dual: mpstthree::role::Role,
58            {
59                sender: crossbeam_channel::Sender<R::Dual>,
60            }
61
62            ////////////////////////////////////////////
63            /// The Role methods
64
65            impl<R: mpstthree::role::Role> mpstthree::role::Role for #role_name<R> {
66                type Dual = #dual_name::<<R as mpstthree::role::Role>::Dual>;
67
68                #[doc(hidden)]
69                fn new() -> (Self, Self::Dual) {
70                    let (sender_normal, _) = crossbeam_channel::bounded::<R>(1);
71                    let (sender_dual, _) = crossbeam_channel::bounded::<R::Dual>(1);
72
73                    (
74                        #role_name {
75                            sender: sender_dual,
76                        },
77                        #dual_name {
78                            sender: sender_normal,
79                        },
80                    )
81                }
82
83                #[doc(hidden)]
84                fn head_str() -> String {
85                    String::from(stringify!(#role_name))
86                }
87
88                #[doc(hidden)]
89                fn tail_str() -> String {
90                    format!(
91                        "{}<{}>",
92                        <R as mpstthree::role::Role>::head_str(),
93                        <R as mpstthree::role::Role>::tail_str()
94                    )
95                }
96
97                #[doc(hidden)]
98                fn self_head_str(&self) -> String {
99                    String::from(stringify!(#role_name))
100                }
101
102                #[doc(hidden)]
103                fn self_tail_str(&self) -> String {
104                    format!(
105                        "{}<{}>",
106                        <R as mpstthree::role::Role>::head_str(),
107                        <R as mpstthree::role::Role>::tail_str()
108                    )
109                }
110            }
111
112            ////////////////////////////////////////////
113            /// The Dual methods
114
115            impl<R: mpstthree::role::Role> mpstthree::role::Role for #dual_name<R> {
116                type Dual = #role_name::<<R as mpstthree::role::Role>::Dual>;
117
118                #[doc(hidden)]
119                fn new() -> (Self, Self::Dual) {
120                    let (sender_normal, _) = crossbeam_channel::bounded::<R>(1);
121                    let (sender_dual, _) = crossbeam_channel::bounded::<R::Dual>(1);
122
123                    (
124                        #dual_name {
125                            sender: sender_dual,
126                        },
127                        #role_name {
128                            sender: sender_normal,
129                        },
130                    )
131                }
132
133                #[doc(hidden)]
134                fn head_str() -> String {
135                    String::from(stringify!(#dual_name))
136                }
137
138                #[doc(hidden)]
139                fn tail_str() -> String {
140                    format!(
141                        "{}<{}>",
142                        <R as mpstthree::role::Role>::head_str(),
143                        <R as mpstthree::role::Role>::tail_str()
144                    )
145                }
146
147                #[doc(hidden)]
148                fn self_head_str(&self) -> String {
149                    String::from(stringify!(#dual_name))
150                }
151
152                #[doc(hidden)]
153                fn self_tail_str(&self) -> String {
154                    format!(
155                        "{}<{}>",
156                        <R as mpstthree::role::Role>::head_str(),
157                        <R as mpstthree::role::Role>::tail_str()
158                    )
159                }
160            }
161
162            ////////////////////////////////////////////
163            /// The associated functions for Role
164
165            impl<R: mpstthree::role::Role> #role_name<R> {
166                pub fn continuation(&self) -> R {
167                    let (here, there) = R::new();
168                    self.sender.send(there).unwrap_or(());
169                    here
170                }
171            }
172
173            ////////////////////////////////////////////
174            /// The associated functions for Dual
175
176            impl<R: mpstthree::role::Role> #dual_name<R> {
177                pub fn continuation(&self) -> R {
178                    let (here, there) = R::new();
179                    self.sender.send(there).unwrap_or(());
180                    here
181                }
182            }
183        }
184    }
185}