fast_map_derive/
lib.rs

1#![recursion_limit = "128"]
2#![type_length_limit = "1880989"]
3
4extern crate proc_macro;
5
6#[macro_use]
7extern crate quote;
8
9#[macro_use]
10extern crate syn;
11
12use proc_macro::TokenStream;
13
14#[proc_macro_derive(FastMap, attributes(fast_map))]
15pub fn fastmap_derive(input: TokenStream) -> TokenStream {
16    let input = parse_macro_input!(input as syn::DeriveInput);
17    fastmap_derive_inner(input).unwrap()
18}
19
20fn fastmap_derive_inner(
21    input: syn::DeriveInput,
22) -> Result<TokenStream, Box<dyn std::error::Error>> {
23    let name = &input.ident;
24
25    let mut key_type = None;
26    let mut out_type = None;
27
28    if let syn::Data::Struct(ref st) = input.data {
29        if let syn::Fields::Unnamed(ref fields) = st.fields {
30            if fields.unnamed.len() == 1 {
31                let field = fields.unnamed.first().unwrap();
32
33                if let syn::Type::Path(ref ty_path) = field.ty {
34                    if let Some(ref last) = ty_path.path.segments.last() {
35                        if let syn::PathArguments::AngleBracketed(ref ab) = last.arguments {
36                            match ab.args.iter().collect::<Vec<_>>().as_slice() {
37                                &[key, out] => {
38                                    key_type = Some(key.clone());
39                                    out_type = Some(out.clone());
40                                }
41                                _ => {}
42                            }
43                        }
44                    }
45                }
46            }
47        }
48    }
49
50    let key_type = &key_type;
51    let out_type = &out_type;
52
53    if key_type.is_none() || out_type.is_none() {
54        return Err("`FastMap` can only be derived on a `MapX` wrapping struct".into());
55    }
56
57    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
58
59    let fast_map_path: syn::Path = parse_quote!(fast_map);
60    let keys_path: syn::Path = parse_quote!(keys);
61    let crate_name_path: syn::Path = parse_quote!(crate_name);
62    let infallible_path: syn::Path = parse_quote!(infallible);
63
64    let l_attrs = input
65        .attrs
66        .iter()
67        .flat_map(|x| x.parse_meta())
68        .filter(|x| x.path() == &fast_map_path)
69        .filter_map(|x| match x {
70            syn::Meta::List(ml) => Some(ml),
71            _ => None,
72        })
73        .flat_map(|x| x.nested)
74        .filter_map(|x| match x {
75            syn::NestedMeta::Meta(m) => Some(m),
76            _ => None,
77        });
78
79    let keys = l_attrs
80        .clone()
81        .filter_map(|x| match x {
82            syn::Meta::List(ml) => Some(ml),
83            _ => None,
84        })
85        .filter(|x| &x.path == &keys_path)
86        .flat_map(|x| x.nested)
87        .collect::<Vec<_>>();
88
89    let crate_name = l_attrs
90        .clone()
91        .filter_map(|x| match x {
92            syn::Meta::NameValue(mnv) => Some(mnv),
93            _ => None,
94        })
95        .filter(|x| &x.path == &crate_name_path)
96        .filter_map(|x| match x.lit {
97            syn::Lit::Str(s) => Some(s),
98            _ => None,
99        })
100        .map(|x| syn::Ident::new(&x.value(), proc_macro2::Span::call_site()))
101        .next()
102        .unwrap_or_else(|| syn::Ident::new("fast_map", proc_macro2::Span::call_site()));
103
104    let is_infallible = l_attrs
105        .clone()
106        .filter_map(|x| match x {
107            syn::Meta::NameValue(mnv) => Some(mnv),
108            _ => None,
109        })
110        .filter(|x| &x.path == &infallible_path)
111        .filter_map(|x| match x.lit {
112            syn::Lit::Bool(s) => Some(s.value),
113            _ => None,
114        })
115        .next()
116        .unwrap_or(false);
117
118    let get_cases = keys
119        .iter()
120        .enumerate()
121        .map(|(idx, k)| {
122            let idx = syn::Index::from(idx);
123            let ret = quote!(Ok(self.0.tup.#idx.as_ref()));
124            quote!(#k => #ret)
125        })
126        .collect::<Vec<_>>();
127
128    let get_mut_cases = keys
129        .iter()
130        .enumerate()
131        .map(|(idx, k)| {
132            let idx = syn::Index::from(idx);
133            let ret = quote!(Ok(self.0.tup.#idx.as_mut()));
134            quote!(#k => #ret)
135        })
136        .collect::<Vec<_>>();
137
138    let insert_cases = keys
139        .iter()
140        .enumerate()
141        .map(|(idx, k)| {
142            let idx = syn::Index::from(idx);
143            let ret = quote!(Ok(self.0.tup.#idx.replace(val)));
144            quote!(#k => #ret)
145        })
146        .collect::<Vec<_>>();
147
148    let remove_cases = keys
149        .iter()
150        .enumerate()
151        .map(|(idx, k)| {
152            let idx = syn::Index::from(idx);
153            let ret = quote!(Ok(self.0.tup.#idx.take()));
154            quote!(#k => #ret)
155        })
156        .collect::<Vec<_>>();
157
158    let values = keys
159        .iter()
160        .enumerate()
161        .map(|(idx, _)| {
162            let idx = syn::Index::from(idx);
163            quote!(self.0.tup.#idx.as_ref())
164        })
165        .collect::<Vec<_>>();
166    let out = if is_infallible {
167        quote! {
168            impl #impl_generics #name #ty_generics #where_clause {
169
170                fn get<T: std::borrow::Borrow<#key_type>>(&self, key: T) -> Option<&#out_type> {
171                    (match key.borrow() {
172                        #(#get_cases,)*
173                        _ => Err(#crate_name::Error::KeyNotFound),
174                    }).unwrap()
175                }
176
177                fn get_mut<T: std::borrow::Borrow<#key_type>>(&mut self, key: T) -> Option<&mut #out_type> {
178                    (match key.borrow() {
179                        #(#get_mut_cases,)*
180                        _ => Err(#crate_name::Error::KeyNotFound),
181                    }).unwrap()
182                }
183
184                fn insert<T: std::borrow::Borrow<#key_type>>(&mut self, key: T, mut val: #out_type) -> Option<#out_type> {
185                    (match key.borrow() {
186                        #(#insert_cases,)*
187                        _ => Err(#crate_name::Error::KeyNotFound),
188                    }).unwrap()
189                }
190
191                fn remove<T: std::borrow::Borrow<#key_type>>(&mut self, key: T) -> Option<#out_type> {
192                    (match key.borrow() {
193                        #(#remove_cases,)*
194                        _ => Err(#crate_name::Error::KeyNotFound),
195                    }).unwrap()
196                }
197
198                fn values<'fast_map>(&'fast_map self) -> #crate_name::Values<'fast_map, #out_type> {
199                    #crate_name::Values::new(vec![#(#values,)*].into_iter())
200                }
201
202            }
203        }
204    } else {
205        quote! {
206            impl #impl_generics #name #ty_generics #where_clause {
207
208                fn get<T: std::borrow::Borrow<#key_type>>(&self, key: T) -> std::result::Result<Option<&#out_type>, #crate_name::Error> {
209                    match key.borrow() {
210                        #(#get_cases,)*
211                        _ => Err(#crate_name::Error::KeyNotFound),
212                    }
213                }
214
215                fn get_mut<T: std::borrow::Borrow<#key_type>>(&mut self, key: T) -> std::result::Result<Option<&mut #out_type>, #crate_name::Error> {
216                    match key.borrow() {
217                        #(#get_mut_cases,)*
218                        _ => Err(#crate_name::Error::KeyNotFound),
219                    }
220                }
221
222                fn insert<T: std::borrow::Borrow<#key_type>>(&mut self, key: T, val: #out_type) -> std::result::Result<Option<#out_type>, #crate_name::Error> {
223                    let mut val = val;
224                    match key.borrow() {
225                        #(#insert_cases,)*
226                        _ => Err(#crate_name::Error::KeyNotFound),
227                    }
228                }
229
230                fn remove<T: std::borrow::Borrow<#key_type>>(&mut self, key: T) -> std::result::Result<Option<#out_type>, #crate_name::Error> {
231                    match key.borrow() {
232                        #(#remove_cases,)*
233                        _ => Err(#crate_name::Error::KeyNotFound),
234                    }
235                }
236
237                fn values<'fast_map>(&'fast_map self) -> #crate_name::Values<'fast_map, #out_type> {
238                    #crate_name::Values::new(vec![#(#values,)*].into_iter())
239                }
240
241            }
242        }
243    };
244
245    Ok(out.into())
246}