meshx_derive/
lib.rs

1#![recursion_limit = "256"]
2extern crate proc_macro;
3
4mod attrib;
5mod intrinsic;
6
7use proc_macro2::{Span, TokenStream};
8use quote::{quote, TokenStreamExt};
9use syn::{
10    Data, DataStruct, DeriveInput, Expr, Fields, GenericArgument, Generics, Ident, Index, Path,
11    PathArguments, Type, TypeArray, TypePath,
12};
13
14/// Intrinsic derive macro. Intrinsic is not a real trait, but an indicator that intrinsic
15/// intrinsic traits need to be implemented for this type. The name of the trait itself is
16/// specified by the intrinsic attribute, which is to be specified in front of a field containing
17/// the `IntrinsicAttribute` type.
18#[proc_macro_derive(Intrinsic, attributes(intrinsics, intrinsic))]
19pub fn intrinsic(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
20    let input: DeriveInput = syn::parse(input).unwrap();
21
22    let gen = intrinsic::impl_intrinsic(&input);
23
24    gen.into()
25}
26
27/// Derive macro for implementing the `Attrib` trait for given struct.
28#[proc_macro_derive(Attrib, attributes(attributes))]
29pub fn attrib(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
30    let input: DeriveInput = syn::parse(input).unwrap();
31
32    let gen = attrib::impl_attrib(&input);
33
34    gen.into()
35}
36
37#[proc_macro_derive(NewCollectionType)]
38pub fn new_collection_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
39    let input: DeriveInput = syn::parse(input).unwrap();
40
41    let gen = impl_new_collection_type(&input);
42
43    gen.into()
44}
45
46fn impl_new_array_collection(
47    generics: &Generics,
48    name: &Ident,
49    parm: &Type,
50    len: &Expr,
51    field_idx: Index,
52) -> TokenStream {
53    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
54    quote! {
55        //impl #impl_generics ::std::ops::Deref for #name #ty_generics #where_clause {
56        //    type Target = [#parm;#len];
57        //    #[inline]
58        //    fn deref(&self) -> &[#parm;#len] {
59        //        &self.#field_idx
60        //    }
61        //}
62        //impl #impl_generics ::std::ops::DerefMut for #name #ty_generics #where_clause {
63        //    #[inline]
64        //    fn deref_mut(&mut self) -> &mut [#parm;#len] {
65        //        &mut self.#field_idx
66        //    }
67        //}
68        impl #impl_generics #name #ty_generics #where_clause {
69            /// Get the underlying container.
70            #[inline]
71            pub fn get(&self) -> &[#parm;#len] {
72                &self.#field_idx
73            }
74            #[inline]
75            pub fn get_mut(&mut self) -> &mut [#parm;#len] {
76                &mut self.#field_idx
77            }
78            #[inline]
79            pub fn into_inner(self) -> [#parm;#len] {
80                self.0
81            }
82        }
83
84        impl #impl_generics Into<[#parm;#len]>for #name #ty_generics #where_clause {
85            #[inline]
86            fn into(self) -> [#parm;#len] {
87                self.0
88            }
89        }
90
91        impl #impl_generics ::std::ops::Index<usize>for #name #ty_generics #where_clause {
92            type Output = #parm;
93            #[inline]
94            fn index(&self, index: usize) -> &#parm {
95                &self.#field_idx[index]
96            }
97        }
98        impl #impl_generics ::std::ops::IndexMut<usize>for #name #ty_generics #where_clause {
99            #[inline]
100            fn index_mut(&mut self, index: usize) -> &mut #parm {
101                &mut self.#field_idx[index]
102            }
103        }
104    }
105}
106
107fn impl_new_vec_collection(
108    generics: &Generics,
109    name: &Ident,
110    vec_type: &Type,
111    parm: &GenericArgument,
112    field_idx: Index,
113) -> TokenStream {
114    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
115    quote! {
116        //impl #impl_generics ::std::ops::Deref for #name #ty_generics #where_clause {
117        //    type Target = #vec_type;
118        //    #[inline]
119        //    fn deref(&self) -> &#vec_type {
120        //        &self.#field_idx
121        //    }
122        //}
123        //impl #impl_generics ::std::ops::DerefMut for #name #ty_generics #where_clause {
124        //    #[inline]
125        //    fn deref_mut(&mut self) -> &mut #vec_type {
126        //        &mut self.#field_idx
127        //    }
128        //}
129        impl #impl_generics #name #ty_generics #where_clause {
130            /// Get the underlying container.
131            #[inline]
132            pub fn get(&self) -> &#vec_type {
133                &self.#field_idx
134            }
135            #[inline]
136            pub fn get_mut(&mut self) -> &mut #vec_type {
137                &mut self.#field_idx
138            }
139            #[inline]
140            pub fn capacity(&self) -> usize {
141                self.#field_idx.capacity()
142            }
143            #[inline]
144            pub fn reserve(&mut self, additional: usize) {
145                self.#field_idx.reserve(additional)
146            }
147            #[inline]
148            pub fn reserve_exact(&mut self, additional: usize) {
149                self.#field_idx.reserve_exact(additional)
150            }
151            #[inline]
152            pub fn shrink_to_fit(&mut self) {
153                self.#field_idx.shrink_to_fit()
154            }
155            #[inline]
156            pub fn into_boxed_slice(self) -> Box<[#parm]>{
157                self.#field_idx.into_boxed_slice()
158            }
159            #[inline]
160            pub fn truncate(&mut self, len: usize) {
161                self.#field_idx.truncate(len)
162            }
163            #[inline]
164            pub fn as_slice(&self) -> &[#parm] {
165                self.#field_idx.as_slice()
166            }
167            #[inline]
168            pub fn as_mut_slice(&mut self) -> &mut [#parm] {
169                self.#field_idx.as_mut_slice()
170            }
171            // unsafe function set_len skipped
172            #[inline]
173            pub fn swap_remove(&mut self, index: usize) -> #parm {
174                self.#field_idx.swap_remove(index)
175            }
176            #[inline]
177            pub fn insert(&mut self, index: usize, element: #parm) {
178                self.#field_idx.insert(index, element)
179            }
180            #[inline]
181            pub fn remove(&mut self, index: usize) -> #parm {
182                self.#field_idx.remove(index)
183            }
184            #[inline]
185            pub fn retain<F>(&mut self, f: F) where F: FnMut(&#parm) -> bool {
186                self.#field_idx.retain(f)
187            }
188            #[inline]
189            pub fn push(&mut self, value: #parm) {
190                self.#field_idx.push(value)
191            }
192            #[inline]
193            pub fn pop(&mut self) -> Option<#parm> {
194                self.#field_idx.pop()
195            }
196            #[inline]
197            pub fn append(&mut self, other: &mut Vec<#parm>) {
198                self.#field_idx.append(other)
199            }
200            // Skipped drain due to unstable API
201            #[inline]
202            pub fn clear(&mut self) {
203                self.#field_idx.clear()
204            }
205            #[inline]
206            pub fn len(&self) -> usize {
207                self.#field_idx.len()
208            }
209            #[inline]
210            pub fn is_empty(&self) -> bool {
211                self.#field_idx.is_empty()
212            }
213            #[inline]
214            pub fn split_off(&mut self, at: usize) -> Vec<#parm> {
215                self.#field_idx.split_off(at)
216            }
217        }
218
219        impl #impl_generics Into<#vec_type>for #name #ty_generics #where_clause {
220            #[inline]
221            fn into(self) -> #vec_type {
222                self.0
223            }
224        }
225
226        impl #impl_generics ::std::ops::Index<usize>for #name #ty_generics #where_clause {
227            type Output = #parm;
228            #[inline]
229            fn index(&self, index: usize) -> &#parm {
230                &self.#field_idx[index]
231            }
232        }
233        impl #impl_generics ::std::ops::IndexMut<usize>for #name #ty_generics #where_clause {
234            #[inline]
235            fn index_mut(&mut self, index: usize) -> &mut #parm {
236                &mut self.#field_idx[index]
237            }
238        }
239    }
240}
241
242fn impl_new_collection_type(ast: &DeriveInput) -> TokenStream {
243    let mut tokens = TokenStream::new();
244    let name = &ast.ident;
245
246    let supported_collection_types = vec!["Vec"];
247
248    if let Data::Struct(DataStruct {
249        fields: Fields::Unnamed(ref fields),
250        ..
251    }) = ast.data
252    {
253        for (i, field) in fields.unnamed.iter().enumerate() {
254            if let Type::Path(TypePath {
255                path: Path { ref segments, .. },
256                ..
257            }) = field.ty
258            {
259                if segments.last().is_none() {
260                    continue;
261                }
262
263                let ty = segments.last().unwrap();
264
265                if supported_collection_types
266                    .iter()
267                    .find(|&&x| Ident::new(x, Span::call_site()) == ty.ident)
268                    .is_none()
269                {
270                    continue;
271                }
272
273                if let PathArguments::AngleBracketed(ref angled_args) = ty.arguments {
274                    if angled_args.args.len() != 1 {
275                        panic!(
276                            "New collection type must wrap a collection that contains exactly\
277                             one type."
278                        );
279                    }
280
281                    let parm = angled_args.args.first().unwrap();
282
283                    let field_idx = Index::from(i);
284                    tokens.append_all(impl_new_vec_collection(
285                        &ast.generics,
286                        name,
287                        &field.ty,
288                        parm,
289                        field_idx,
290                    ));
291                } else {
292                    panic!("New collection type must wrap a collection that contains a type.");
293                }
294            } else if let Type::Array(TypeArray {
295                ref elem, ref len, ..
296            }) = field.ty
297            {
298                let parm = &**elem;
299
300                let field_idx = Index::from(i);
301
302                tokens.append_all(impl_new_array_collection(
303                    &ast.generics,
304                    name,
305                    parm,
306                    len,
307                    field_idx,
308                ));
309            } else {
310                panic!("New collection type must wrap a Vec or an array.");
311            }
312        }
313    }
314    tokens
315}