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}