auto_delegate_macros/lib.rs
1use proc_macro::TokenStream;
2
3use ::syn::__private::TokenStream2;
4
5use crate::delegate_trait::expand_delegate_trait;
6use crate::derive_delegate::expand_derive_delegate;
7
8mod derive_delegate;
9mod delegate_trait;
10mod ident;
11mod macro_marker;
12mod span;
13mod syn;
14mod trait_item;
15mod attribute;
16
17
18/// The trait given this attribute are eligible for delegation.
19///
20/// ```rust
21/// use auto_delegate::delegate;
22///
23/// #[delegate]
24/// pub trait Readable{
25/// fn read(&self) -> String;
26/// }
27/// ```
28#[proc_macro_attribute]
29pub fn delegate(attr: TokenStream, input: TokenStream) -> TokenStream {
30 let output: proc_macro2::TokenStream = expand_delegate_trait(attr, input.clone());
31 expand_join(input, output)
32}
33
34
35/// Implement the specified trait and delegate its processing to the children.
36///
37///
38/// ## Note
39///
40/// The trait to be delegated must be given a 'delegate'.
41///
42///
43/// ## Example1:
44///
45/// ```rust
46/// use auto_delegate::*;
47///
48/// #[delegate]
49/// trait Calc {
50/// fn calc(&self, x1: usize, x2: usize) -> usize;
51/// }
52///
53/// #[derive(Default)]
54/// struct CalcAdd;
55///
56/// impl Calc for CalcAdd {
57/// fn calc(&self, x1: usize, x2: usize) -> usize {
58/// x1 + x2
59/// }
60/// }
61///
62/// #[derive(Delegate, Default)]
63/// struct Parent {
64/// #[to(Calc)]
65/// child: CalcAdd
66/// }
67///
68/// let parent = Parent::default();
69///
70/// assert_eq!(parent.calc(3, 2), 5);
71/// ```
72///
73///
74/// ## Example2: Generics-type Child
75///
76/// It is possible to use generic type for member types
77///
78/// ```rust
79/// use auto_delegate::*;
80///
81/// #[delegate]
82/// trait Calc {
83/// fn calc(&self, x1: usize, x2: usize) -> usize;
84/// }
85///
86/// #[derive(Default)]
87/// struct CalcAdd;
88///
89///
90/// impl Calc for CalcAdd {
91/// fn calc(&self, x1: usize, x2: usize) -> usize {
92/// x1 + x2
93/// }
94/// }
95///
96///
97/// #[derive(Default, Delegate)]
98/// struct Parent<T: Default + Calc>{
99/// #[to(Calc)]
100/// child: T
101/// }
102///
103///
104/// let parent = Parent::<CalcAdd>::default();
105///
106/// assert_eq!(parent.calc(3, 2), 5);
107/// ```
108///
109/// ## Example3: Multiple traits and fields
110///
111/// It is possible to use generic param for member types
112///
113/// ```rust
114/// use auto_delegate::*;
115///
116/// #[delegate]
117/// trait Calc {
118/// fn calc(&self, x1: usize, x2: usize) -> usize;
119/// }
120///
121///
122/// #[derive(Default)]
123/// struct CalcAdd;
124///
125///
126/// impl Calc for CalcAdd {
127/// fn calc(&self, x1: usize, x2: usize) -> usize {
128/// x1 + x2
129/// }
130/// }
131///
132///
133/// #[delegate]
134/// trait Movable{
135/// fn move_to(&mut self, pos: (usize, usize));
136///
137/// fn pos(&self) -> (usize, usize);
138/// }
139///
140///
141/// #[delegate]
142/// trait Resizable{
143/// fn resize(&mut self, width: usize, height: usize);
144///
145/// fn size(&self) -> (usize, usize);
146/// }
147///
148///
149/// #[derive(Default)]
150/// struct Transform2D{
151/// pos: (usize, usize),
152/// width: usize,
153/// height: usize
154/// }
155///
156///
157/// impl Movable for Transform2D {
158/// fn move_to(&mut self, pos: (usize, usize)) {
159/// self.pos = pos;
160/// }
161///
162/// fn pos(&self) -> (usize, usize) {
163/// self.pos
164/// }
165/// }
166///
167///
168/// impl Resizable for Transform2D{
169/// fn resize(&mut self, width: usize, height: usize) {
170/// self.width = width;
171/// self.height = height;
172/// }
173///
174/// fn size(&self) -> (usize, usize){
175/// (self.width, self.height)
176/// }
177/// }
178///
179/// #[derive(Default, Delegate)]
180/// struct Parent<T: Default + Calc>{
181/// #[to(Movable, Resizable)]
182/// transform: Transform2D,
183///
184/// #[to(Calc)]
185/// calculator: T
186/// }
187///
188///
189/// let mut parent = Parent::<CalcAdd>::default();
190///
191/// assert_eq!(parent.calc(3, 2), 5);
192///
193/// parent.move_to((10, 11));
194/// assert_eq!(parent.pos(), (10, 11));
195///
196/// parent.resize(100, 120);
197/// assert_eq!(parent.size(), (100, 120));
198/// ```
199///
200/// ## Example4: Enum
201///
202///
203/// ```rust
204/// use auto_delegate::{delegate, Delegate};
205///
206/// #[delegate]
207/// trait Calc {
208/// fn calc(&self, x1: usize, x2: usize) -> usize;
209/// }
210///
211///
212/// #[derive(Default)]
213/// struct CalcAdd;
214///
215///
216/// impl Calc for CalcAdd {
217/// fn calc(&self, x1: usize, x2: usize) -> usize {
218/// x1 + x2
219/// }
220/// }
221///
222///
223/// #[derive(Default)]
224/// struct CalcSub;
225///
226///
227/// impl Calc for CalcSub {
228/// fn calc(&self, x1: usize, x2: usize) -> usize {
229/// x1 - x2
230/// }
231/// }
232///
233///
234/// #[derive(Delegate)]
235/// #[to(Calc)]
236/// enum EnumCalc {
237/// Add(CalcAdd),
238/// Sub(CalcSub),
239/// }
240///
241///
242/// let c = EnumCalc::Add(CalcAdd::default());
243/// assert_eq!(c.calc(3, 5), 8);
244///
245/// let c = EnumCalc::Sub(CalcSub::default());
246/// assert_eq!(c.calc(3, 2), 1);
247/// ```
248///
249#[proc_macro_derive(Delegate, attributes(to))]
250pub fn derive_delegate(input: TokenStream) -> TokenStream {
251 expand_derive_delegate(input).into()
252}
253
254
255fn expand_join(input: TokenStream, output: proc_macro2::TokenStream) -> TokenStream {
256 let input = proc_macro2::TokenStream::from(input);
257
258 let expand = quote::quote! {
259 #input
260 #output
261 };
262
263 expand.into()
264}
265
266
267pub(crate) fn intersperse(
268 separator: TokenStream2,
269 iter: impl Iterator<Item=TokenStream2>) -> Vec<TokenStream2> {
270 let mut tokens = Vec::<TokenStream2>::new();
271 for token in iter{
272 tokens.push(token);
273 tokens.push(separator.clone());
274 }
275
276 if !tokens.is_empty() {
277 tokens.remove(tokens.len() - 1);
278 }
279
280 tokens
281}