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#[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#[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 #name #ty_generics #where_clause {
69 #[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 #name #ty_generics #where_clause {
130 #[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 #[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 #[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}