1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(debug_assertions), deny(warnings))]
3#![deny(clippy::all, rust_2018_idioms)]
4#![warn(
5 missing_docs,
6 missing_debug_implementations,
7 trivial_casts,
8 trivial_numeric_casts,
9 unsafe_code,
10 unstable_features,
11 unused_import_braces,
12 unused_qualifications
13)]
14
15use proc_macro::TokenStream;
16use proc_macro2::TokenStream as TokenStream2;
17use proc_macro_error::proc_macro_error;
18use quote::*;
19use syn::*;
20
21fn top_type_of_enumeration<'a>(
22 variants: impl IntoIterator<Item = &'a Variant> + 'a,
23) -> TokenStream2 {
24 let variant = variants.into_iter().next().expect("empty enum!");
25 let vec: Vec<_> = variant.fields.iter().collect();
26 match vec.len() {
27 0 => panic!("empty field!"),
28 1 => vec[0].ty.to_token_stream(),
29 _ => unimplemented!(),
30 }
31}
32
33fn enumerate_impl_return_something<'a>(
34 variants: impl IntoIterator<Item = &'a Variant> + 'a,
35 method: TokenStream2,
36 method_variants: TokenStream2,
37) -> TokenStream2 {
38 let impls: Vec<_> = variants
39 .into_iter()
40 .map(|variant| {
41 let variant_name = &variant.ident;
42 let vec: Vec<_> = variant.fields.iter().collect();
43 match vec.len() {
44 0 => panic!("empty field!"),
45 1 => match &vec[0].ident {
46 Some(ident) => quote! {
47 Self::#variant_name { #ident } => #method(#ident, #method_variants)
48 },
49 None => quote! {
50 Self::#variant_name(got) => #method(got, #method_variants)
51 },
52 },
53 _ => unimplemented!(),
54 }
55 })
56 .collect();
57 quote! { match self { #(#impls),* } }
58}
59
60fn enumerate_impl_return_self<'a>(
61 variants: impl IntoIterator<Item = &'a Variant> + 'a,
62 method: TokenStream2,
63 method_variants: TokenStream2,
64) -> TokenStream2 {
65 let impls: Vec<_> = variants
66 .into_iter()
67 .map(|variant| {
68 let variant_name = &variant.ident;
69 let vec: Vec<_> = variant.fields.iter().collect();
70 match vec.len() {
71 0 => panic!("empty field!"),
72 1 => match &vec[0].ident {
73 Some(ident) => {
74 quote! {
75 Self::#variant_name { #ident } => Self::#variant_name { #ident: #method(#ident, #method_variants) }
76 }
77 }
78 None => {
79 quote! {
80 Self::#variant_name(got) => Self::#variant_name(#method(got, #method_variants))
81 }
82 }
83 },
84 _ => unimplemented!(),
85 }
86 })
87 .collect();
88 quote! {
89 match self {
90 #(#impls),*
91 }
92 }
93}
94
95#[derive(Clone, Debug)]
96struct Field {
97 var: TokenStream2,
98 ty: TokenStream2,
99}
100
101macro_rules! fields {
102 ($($var: tt : $ty: tt),*) => {
103 vec![$(Field {
104 var: quote! { $var },
105 ty: quote! { $ty },
106 }),*]
107 };
108}
109
110#[derive(Clone, Debug)]
111struct Method<I> {
112 name: TokenStream2,
113 generics: Option<TokenStream2>,
114 self_field: TokenStream2,
115 fields: Vec<Field>,
116 return_type: TokenStream2,
117 variants: I,
118 trait_name: TokenStream2,
119}
120
121macro_rules! methods {
122 (
123 $variants: ident, $trait_name: ident,
124 $(fn $name: ident (
125 $self_field: expr,
126 $($var: ident: $ty: ty),*$(,)?
127 ) -> $return_type: ty),*$(,)?
128 ) => {
129 vec![$(Method {
130 name: quote! { $name },
131 generics: None,
132 self_field: quote! { $self_field, },
133 fields: fields!($($var: $ty),*),
134 return_type: quote! { $return_type },
135 variants: $variants,
136 trait_name: $trait_name.clone(),
137 }
138 .to_token_stream()),*]
139 };
140 (
141 $variants: ident, $trait_name: ident,
142 $(fn $name: ident <$($gen: ident: $path: path),*> (
143 $self_field: expr,
144 $($var: ident: $ty: ty),*$(,)?
145 ) -> $return_type: ty),*$(,)?
146 ) => {
147 vec![$(Method {
148 name: quote! { $name },
149 generics: Some(quote! { <$($gen: $path),*> }),
150 self_field: quote! { $self_field, },
151 fields: fields!($($var: $ty),*),
152 return_type: quote! { $return_type },
153 variants: $variants,
154 trait_name: $trait_name.clone(),
155 }
156 .to_token_stream()),*]
157 };
158}
159
160impl<'a, I> Method<I>
161where I: IntoIterator<Item = &'a Variant> + 'a + Copy
162{
163 fn to_token_stream(&'a self) -> TokenStream2 {
164 let method_name = &self.name;
165 let generics = &self.generics;
166 let trait_name = &self.trait_name;
167 let self_field = &self.self_field;
168 let fields = self
169 .fields
170 .iter()
171 .map(|f| {
172 let var = &f.var;
173 let ty = &f.ty;
174 quote! { #var: #ty }
175 })
176 .collect::<Vec<_>>();
177 let vals = self
178 .fields
179 .iter()
180 .map(|f| f.var.to_token_stream())
181 .collect::<Vec<_>>();
182 let return_type = &self.return_type;
183 let implement = if return_type.to_string() == "Self" {
184 enumerate_impl_return_self::<'_>(
185 self.variants,
186 quote! { #trait_name::#method_name },
187 quote! { #(#vals),* },
188 )
189 } else {
190 enumerate_impl_return_something::<'a>(
191 self.variants,
192 quote! { #trait_name::#method_name },
193 quote! { #(#vals),* },
194 )
195 };
196 quote! {
197 #[inline(always)]
198 fn #method_name #generics (#self_field #(#fields),*) -> #return_type { #implement }
199 }
200 }
201}
202
203#[proc_macro_error]
205#[proc_macro_derive(BoundedCurve)]
206pub fn derive_bounded_curve(input: TokenStream) -> TokenStream {
207 let input = parse_macro_input!(input as DeriveInput);
208 let trait_name = quote! { BoundedCurve };
209 let ty = input.ident;
210 let gen = input.generics;
211 match input.data {
212 Data::Enum(DataEnum { ref variants, .. }) => {
213 let methods = methods! {
214 variants, trait_name,
215 fn parameter_range(&self,) -> (f64, f64),
216 };
217 quote! {
218 #[automatically_derived]
219 impl #gen truck_geotrait::#trait_name for #ty {
220 #(#methods)*
221 }
222 }
223 }
224 Data::Struct(DataStruct { ref fields, .. }) => {
225 let field: Vec<_> = fields.iter().collect();
226 if field.len() != 1 || field[0].ident.is_some() {
227 unimplemented!();
228 }
229 quote! {
230 #[automatically_derived]
231 impl #gen truck_geotrait::#trait_name for #ty {
232 #[inline(always)]
233 fn parameter_range(&self) -> (f64, f64) { self.0.parameter_range() }
234 }
235 }
236 }
237 _ => unimplemented!(),
238 }
239 .into()
240}
241
242#[proc_macro_error]
244#[proc_macro_derive(BoundedSurface)]
245pub fn derive_bounded_surface(input: TokenStream) -> TokenStream {
246 let input = parse_macro_input!(input as DeriveInput);
247 let trait_name = quote! { BoundedSurface };
248 let ty = input.ident;
249 let gen = input.generics;
250 match input.data {
251 Data::Enum(DataEnum { ref variants, .. }) => {
252 let methods = methods! {
253 variants, trait_name,
254 fn parameter_range(&self,) -> ((f64, f64), (f64, f64)),
255 };
256 quote! {
257 #[automatically_derived]
258 impl #gen truck_geotrait::#trait_name for #ty {
259 #(#methods)*
260 }
261 }
262 }
263 Data::Struct(DataStruct { ref fields, .. }) => {
264 let field: Vec<_> = fields.iter().collect();
265 if field.len() != 1 || field[0].ident.is_some() {
266 unimplemented!();
267 }
268 quote! {
269 #[automatically_derived]
270 impl #gen truck_geotrait::#trait_name for #ty {
271 #[inline(always)]
272 fn parameter_range(&self) -> ((f64, f64), (f64, f64)) {
273 self.0.parameter_range()
274 }
275 }
276 }
277 }
278 _ => unimplemented!(),
279 }
280 .into()
281}
282
283#[proc_macro_error]
285#[proc_macro_derive(Cut)]
286pub fn derive_cut(input: TokenStream) -> TokenStream {
287 let input = parse_macro_input!(input as DeriveInput);
288 let trait_name = quote! { Cut };
289 let ty = input.ident;
290 let gen = input.generics;
291 match input.data {
292 Data::Enum(DataEnum { ref variants, .. }) => {
293 let methods = methods! {
294 variants, trait_name,
295 fn cut(&mut self, t: f64) -> Self,
296 };
297 quote! {
298 #[automatically_derived]
299 impl #gen truck_geotrait::#trait_name for #ty {
300 #(#methods)*
301 }
302 }
303 }
304 Data::Struct(DataStruct { ref fields, .. }) => {
305 let field: Vec<_> = fields.iter().collect();
306 if field.len() != 1 || field[0].ident.is_some() {
307 unimplemented!();
308 }
309 quote! {
310 #[automatically_derived]
311 impl #gen truck_geotrait::#trait_name for #ty {
312 #[inline(always)]
313 fn cut(&mut self, t: f64) -> Self { Self(self.0.cut(t)) }
314 }
315 }
316 }
317 _ => unimplemented!(),
318 }
319 .into()
320}
321
322#[proc_macro_error]
324#[proc_macro_derive(Invertible)]
325pub fn derive_invertible(input: TokenStream) -> TokenStream {
326 let input = parse_macro_input!(input as DeriveInput);
327 let trait_name = quote! { Invertible };
328 let ty = input.ident;
329 let gen = input.generics;
330 match input.data {
331 Data::Enum(DataEnum { ref variants, .. }) => {
332 let methods = methods! {
333 variants, trait_name,
334 fn invert(&mut self,) -> (),
335 fn inverse(&self,) -> Self,
336 };
337 quote! {
338 #[automatically_derived]
339 impl #gen truck_geotrait::#trait_name for #ty {
340 #(#methods)*
341 }
342 }
343 }
344 Data::Struct(DataStruct { ref fields, .. }) => {
345 let field: Vec<_> = fields.iter().collect();
346 if field.len() != 1 || field[0].ident.is_some() {
347 unimplemented!();
348 }
349 quote! {
350 #[automatically_derived]
351 impl #gen truck_geotrait::#trait_name for #ty {
352 #[inline(always)]
353 fn invert(&mut self) { self.0.invert() }
354 #[inline(always)]
355 fn inverse(&self) -> Self { Self(self.0.inverse()) }
356 }
357 }
358 }
359 _ => unimplemented!(),
360 }
361 .into()
362}
363
364#[proc_macro_error]
366#[proc_macro_derive(ParameterDivision1D)]
367pub fn derive_parameter_division_1d(input: TokenStream) -> TokenStream {
368 let input = parse_macro_input!(input as DeriveInput);
369 let trait_name = quote! { ParameterDivision1D };
370 let ty = input.ident;
371 let gen = input.generics;
372 match input.data {
373 Data::Enum(DataEnum { ref variants, .. }) => {
374 let top_ty = top_type_of_enumeration(variants);
375 let methods = methods! {
376 variants, trait_name,
377 fn parameter_division(&self, range: (f64, f64), tol: f64) -> (Vec<f64>, Vec<Self::Point>),
378 };
379 quote! {
380 #[automatically_derived]
381 impl #gen truck_geotrait::#trait_name for #ty {
382 type Point = <#top_ty as #trait_name>::Point;
383 #(#methods)*
384 }
385 }
386 }
387 Data::Struct(DataStruct { ref fields, .. }) => {
388 let field: Vec<_> = fields.iter().collect();
389 if field.len() != 1 || field[0].ident.is_some() {
390 unimplemented!();
391 }
392 let field_type = &field[0].ty;
393 quote! {
394 #[automatically_derived]
395 impl #gen truck_geotrait::#trait_name for #ty {
396 type Point = <#field_type as #trait_name>::Point;
397 #[inline(always)]
398 fn parameter_division(&self, range: (f64, f64), tol: f64) -> (Vec<f64>, Vec<Self::Point>) {
399 self.0.parameter_division(range, tol)
400 }
401 }
402 }
403 }
404 _ => unimplemented!(),
405 }
406 .into()
407}
408
409#[proc_macro_error]
411#[proc_macro_derive(ParameterDivision2D)]
412pub fn derive_parameter_division_2d(input: TokenStream) -> TokenStream {
413 let input = parse_macro_input!(input as DeriveInput);
414 let trait_name = quote! { ParameterDivision2D };
415 let ty = input.ident;
416 let gen = input.generics;
417 match input.data {
418 Data::Enum(DataEnum { ref variants, .. }) => {
419 let methods = methods! {
420 variants, trait_name,
421 fn parameter_division(&self, range: ((f64, f64), (f64, f64)), tol: f64) -> (Vec<f64>, Vec<f64>),
422 };
423 quote! {
424 #[automatically_derived]
425 impl #gen truck_geotrait::#trait_name for #ty {
426 #(#methods)*
427 }
428 }
429 }
430 Data::Struct(DataStruct { ref fields, .. }) => {
431 let field: Vec<_> = fields.iter().collect();
432 if field.len() != 1 || field[0].ident.is_some() {
433 unimplemented!();
434 }
435 quote! {
436 #[automatically_derived]
437 impl #gen truck_geotrait::#trait_name for #ty {
438 #[inline(always)]
439 fn parameter_division(&self, range: ((f64, f64), (f64, f64)), tol: f64) -> (Vec<f64>, Vec<f64>) {
440 self.0.parameter_division(range, tol)
441 }
442 }
443 }
444 }
445 _ => unimplemented!(),
446 }
447 .into()
448}
449
450#[proc_macro_error]
452#[proc_macro_derive(ParametricCurve)]
453pub fn derive_parametric_curve(input: TokenStream) -> TokenStream {
454 let input = parse_macro_input!(input as DeriveInput);
455 let trait_name = quote! { ParametricCurve };
456 let ty = input.ident;
457 let gen = input.generics;
458 match input.data {
459 Data::Enum(DataEnum { ref variants, .. }) => {
460 let top_ty = top_type_of_enumeration(variants);
461 let methods = methods!(
462 variants,
463 trait_name,
464 fn subs(&self, t: f64) -> Self::Point,
465 fn der(&self, t: f64) -> Self::Vector,
466 fn der2(&self, t: f64) -> Self::Vector,
467 );
468 quote! {
469 #[automatically_derived]
470 impl #gen truck_geotrait::#trait_name for #ty {
471 type Point = <#top_ty as #trait_name>::Point;
472 type Vector = <#top_ty as #trait_name>::Vector;
473 #(#methods)*
474 }
475 }
476 }
477 Data::Struct(DataStruct { ref fields, .. }) => {
478 let field: Vec<_> = fields.iter().collect();
479 if field.len() != 1 || field[0].ident.is_some() {
480 unimplemented!();
481 }
482 let field_type = &field[0].ty;
483 quote! {
484 #[automatically_derived]
485 impl #gen truck_geotrait::#trait_name for #ty {
486 type Point = <#field_type as #trait_name>::Point;
487 type Vector = <#field_type as #trait_name>::Vector;
488 #[inline(always)]
489 fn subs(&self, t: f64) -> Self::Point { self.0.subs(t) }
490 #[inline(always)]
491 fn der(&self, t: f64) -> Self::Vector { self.0.der(t) }
492 #[inline(always)]
493 fn der2(&self, t: f64) -> Self::Vector { self.0.der2(t) }
494 }
495 }
496 }
497 _ => unimplemented!(),
498 }
499 .into()
500}
501
502#[proc_macro_error]
504#[proc_macro_derive(ParametricSurface)]
505pub fn derive_parametric_surface(input: TokenStream) -> TokenStream {
506 let input = parse_macro_input!(input as DeriveInput);
507 let trait_name = quote! { ParametricSurface };
508 let ty = input.ident;
509 let gen = input.generics;
510 match input.data {
511 Data::Enum(DataEnum { ref variants, .. }) => {
512 let top_ty = top_type_of_enumeration(variants);
513 let methods = methods!(
514 variants,
515 trait_name,
516 fn subs(&self, s: f64, t: f64) -> Self::Point,
517 fn uder(&self, s: f64, t: f64) -> Self::Vector,
518 fn vder(&self, s: f64, t: f64) -> Self::Vector,
519 fn uuder(&self, s: f64, t: f64) -> Self::Vector,
520 fn uvder(&self, s: f64, t: f64) -> Self::Vector,
521 fn vvder(&self, s: f64, t: f64) -> Self::Vector,
522 );
523 quote! {
524 #[automatically_derived]
525 impl #gen truck_geotrait::#trait_name for #ty {
526 type Point = <#top_ty as #trait_name>::Point;
527 type Vector = <#top_ty as #trait_name>::Vector;
528 #(#methods)*
529 }
530 }
531 }
532 Data::Struct(DataStruct { ref fields, .. }) => {
533 let field: Vec<_> = fields.iter().collect();
534 if field.len() != 1 || field[0].ident.is_some() {
535 unimplemented!();
536 }
537 let field_type = &field[0].ty;
538 quote! {
539 #[automatically_derived]
540 impl #gen truck_geotrait::#trait_name for #ty {
541 type Point = <#field_type as #trait_name>::Point;
542 type Vector = <#field_type as #trait_name>::Vector;
543 #[inline(always)]
544 fn subs(&self, s: f64, t: f64) -> Self::Point { self.0.subs(s, t) }
545 #[inline(always)]
546 fn uder(&self, s: f64, t: f64) -> Self::Vector { self.0.uder(s, t) }
547 #[inline(always)]
548 fn vder(&self, s: f64, t: f64) -> Self::Vector { self.0.vder(s, t) }
549 #[inline(always)]
550 fn uuder(&self, s: f64, t: f64) -> Self::Vector { self.0.uuder(s, t) }
551 #[inline(always)]
552 fn uvder(&self, s: f64, t: f64) -> Self::Vector { self.0.uvder(s, t) }
553 #[inline(always)]
554 fn vvder(&self, s: f64, t: f64) -> Self::Vector { self.0.vvder(s, t) }
555 }
556 }
557 }
558 _ => unimplemented!(),
559 }
560 .into()
561}
562
563#[proc_macro_error]
565#[proc_macro_derive(ParametricSurface3D)]
566pub fn derive_parametric_surface3d(input: TokenStream) -> TokenStream {
567 let input = parse_macro_input!(input as DeriveInput);
568 let trait_name0 = quote! { ParametricSurface };
569 let trait_name1 = quote! { ParametricSurface3D };
570 let ty = input.ident;
571 let gen = input.generics;
572 match input.data {
573 Data::Enum(DataEnum { ref variants, .. }) => {
574 let methods0 = methods!(
575 variants,
576 trait_name0,
577 fn subs(&self, s: f64, t: f64) -> Self::Point,
578 fn uder(&self, s: f64, t: f64) -> Self::Vector,
579 fn vder(&self, s: f64, t: f64) -> Self::Vector,
580 fn uuder(&self, s: f64, t: f64) -> Self::Vector,
581 fn uvder(&self, s: f64, t: f64) -> Self::Vector,
582 fn vvder(&self, s: f64, t: f64) -> Self::Vector,
583 );
584 let methods1 = methods!(
585 variants,
586 trait_name1,
587 fn normal(&self, u: f64, v: f64) -> Vector3,
588 );
589 quote! {
590 #[automatically_derived]
591 impl #gen truck_geotrait::#trait_name0 for #ty {
592 type Point = Point3;
593 type Vector = Vector3;
594 #(#methods0)*
595 }
596
597 #[automatically_derived]
598 impl #gen truck_geotrait::#trait_name1 for #ty {
599 #(#methods1)*
600 }
601 }
602 }
603 Data::Struct(DataStruct { ref fields, .. }) => {
604 let field: Vec<_> = fields.iter().collect();
605 if field.len() != 1 || field[0].ident.is_some() {
606 unimplemented!();
607 }
608 quote! {
609 #[automatically_derived]
610 impl #gen truck_geotrait::#trait_name0 for #ty {
611 type Point = Point3;
612 type Vector = Vector3;
613 #[inline(always)]
614 fn subs(&self, s: f64, t: f64) -> Self::Point { self.0.subs(s, t) }
615 #[inline(always)]
616 fn uder(&self, s: f64, t: f64) -> Self::Vector { self.0.uder(s, t) }
617 #[inline(always)]
618 fn vder(&self, s: f64, t: f64) -> Self::Vector { self.0.vder(s, t) }
619 #[inline(always)]
620 fn uuder(&self, s: f64, t: f64) -> Self::Vector { self.0.uuder(s, t) }
621 #[inline(always)]
622 fn uvder(&self, s: f64, t: f64) -> Self::Vector { self.0.uvder(s, t) }
623 #[inline(always)]
624 fn vvder(&self, s: f64, t: f64) -> Self::Vector { self.0.vvder(s, t) }
625 }
626 #[automatically_derived]
627 impl #gen truck_geotrait::#trait_name1 for #ty {
628 #[inline(always)]
629 fn normal(&self, u: f64, v: f64) -> Vector3 { self.0.normal(u, v) }
630 }
631 }
632 }
633 _ => unimplemented!(),
634 }
635 .into()
636}
637
638#[proc_macro_error]
640#[proc_macro_derive(SearchNearestParameterD1)]
641pub fn derive_snp_d1(input: TokenStream) -> TokenStream {
642 let input = parse_macro_input!(input as DeriveInput);
643 let trait_name = quote! { SearchNearestParameter::<D1> };
644 let ty = input.ident;
645 let gen = input.generics;
646 match input.data {
647 Data::Enum(DataEnum { ref variants, .. }) => {
648 let top_ty = top_type_of_enumeration(variants);
649 let methods = methods!(
650 variants,
651 trait_name,
652 fn search_nearest_parameter<H: Into<SPHint1D>>(
653 &self,
654 pt: Self::Point,
655 hint: H,
656 trials: usize,
657 ) -> Option<f64>,
658 );
659 quote! {
660 #[automatically_derived]
661 impl #gen truck_geotrait::SearchNearestParameter<D1> for #ty {
662 type Point = <#top_ty as #trait_name>::Point;
663 #(#methods)*
664 }
665 }
666 }
667 Data::Struct(DataStruct { ref fields, .. }) => {
668 let field: Vec<_> = fields.iter().collect();
669 if field.len() != 1 || field[0].ident.is_some() {
670 unimplemented!();
671 }
672 let field_type = &field[0].ty;
673 quote! {
674 #[automatically_derived]
675 impl #gen truck_geotrait::SearchNearestParameter<D1> for #ty {
676 type Point = <#field_type as #trait_name>::Point;
677 #[inline(always)]
678 fn search_nearest_parameter<H: Into<SPHint1D>>(
679 &self,
680 pt: Self::Point,
681 hint: H,
682 trials: usize,
683 ) -> Option<f64> {
684 self.0.search_nearest_parameter(pt, hint, trials)
685 }
686 }
687 }
688 }
689 _ => unimplemented!(),
690 }
691 .into()
692}
693
694#[proc_macro_error]
696#[proc_macro_derive(SearchNearestParameterD2)]
697pub fn derive_snp_d2(input: TokenStream) -> TokenStream {
698 let input = parse_macro_input!(input as DeriveInput);
699 let trait_name = quote! { SearchNearestParameter::<D2> };
700 let ty = input.ident;
701 let gen = input.generics;
702 match input.data {
703 Data::Enum(DataEnum { ref variants, .. }) => {
704 let top_ty = top_type_of_enumeration(variants);
705 let methods = methods!(
706 variants,
707 trait_name,
708 fn search_nearest_parameter<H: Into<SPHint2D>>(
709 &self,
710 pt: Self::Point,
711 hint: H,
712 trials: usize,
713 ) -> Option<(f64, f64)>,
714 );
715 quote! {
716 #[automatically_derived]
717 impl #gen truck_geotrait::SearchNearestParameter<D2> for #ty {
718 type Point = <#top_ty as #trait_name>::Point;
719 #(#methods)*
720 }
721 }
722 }
723 Data::Struct(DataStruct { ref fields, .. }) => {
724 let field: Vec<_> = fields.iter().collect();
725 if field.len() != 1 || field[0].ident.is_some() {
726 unimplemented!();
727 }
728 let field_type = &field[0].ty;
729 quote! {
730 #[automatically_derived]
731 impl #gen truck_geotrait::SearchNearestParameter<D2> for #ty {
732 type Point = <#field_type as #trait_name>::Point;
733 #[inline(always)]
734 fn search_nearest_parameter<H: Into<SPHint2D>>(
735 &self,
736 pt: Self::Point,
737 hint: H,
738 trials: usize,
739 ) -> Option<(f64, f64)> {
740 self.0.search_nearest_parameter(pt, hint, trials)
741 }
742 }
743 }
744 }
745 _ => unimplemented!(),
746 }
747 .into()
748}
749
750#[proc_macro_error]
752#[proc_macro_derive(SearchParameterD1)]
753pub fn derive_sp_d1(input: TokenStream) -> TokenStream {
754 let input = parse_macro_input!(input as DeriveInput);
755 let trait_name = quote! { SearchParameter::<D1> };
756 let ty = input.ident;
757 let gen = input.generics;
758 match input.data {
759 Data::Enum(DataEnum { ref variants, .. }) => {
760 let top_ty = top_type_of_enumeration(variants);
761 let methods = methods!(
762 variants,
763 trait_name,
764 fn search_parameter<H: Into<SPHint1D>>(
765 &self,
766 pt: Self::Point,
767 hint: H,
768 trials: usize,
769 ) -> Option<f64>,
770 );
771 quote! {
772 #[automatically_derived]
773 impl #gen truck_geotrait::SearchParameter<D1> for #ty {
774 type Point = <#top_ty as #trait_name>::Point;
775 #(#methods)*
776 }
777 }
778 }
779 Data::Struct(DataStruct { ref fields, .. }) => {
780 let field: Vec<_> = fields.iter().collect();
781 if field.len() != 1 || field[0].ident.is_some() {
782 unimplemented!();
783 }
784 let field_type = &field[0].ty;
785 quote! {
786 #[automatically_derived]
787 impl #gen truck_geotrait::SearchParameter<D1> for #ty {
788 type Point = <#field_type as #trait_name>::Point;
789 #[inline(always)]
790 fn search_parameter<H: Into<SPHint1D>>(
791 &self,
792 pt: Self::Point,
793 hint: H,
794 trials: usize,
795 ) -> Option<f64> {
796 self.0.search_nearest_parameter(pt, hint, trials)
797 }
798 }
799 }
800 }
801 _ => unimplemented!(),
802 }
803 .into()
804}
805
806#[proc_macro_error]
808#[proc_macro_derive(SearchParameterD2)]
809pub fn derive_sp_d2(input: TokenStream) -> TokenStream {
810 let input = parse_macro_input!(input as DeriveInput);
811 let trait_name = quote! { SearchParameter::<D2> };
812 let ty = input.ident;
813 let gen = input.generics;
814 match input.data {
815 Data::Enum(DataEnum { ref variants, .. }) => {
816 let top_ty = top_type_of_enumeration(variants);
817 let methods = methods!(
818 variants,
819 trait_name,
820 fn search_parameter<H: Into<SPHint2D>>(
821 &self,
822 pt: Self::Point,
823 hint: H,
824 trials: usize,
825 ) -> Option<(f64, f64)>,
826 );
827 quote! {
828 #[automatically_derived]
829 impl #gen truck_geotrait::SearchParameter<D2> for #ty {
830 type Point = <#top_ty as #trait_name>::Point;
831 #(#methods)*
832 }
833 }
834 }
835 Data::Struct(DataStruct { ref fields, .. }) => {
836 let field: Vec<_> = fields.iter().collect();
837 if field.len() != 1 || field[0].ident.is_some() {
838 unimplemented!();
839 }
840 let field_type = &field[0].ty;
841 quote! {
842 #[automatically_derived]
843 impl #gen truck_geotrait::SearchParameter<D2> for #ty {
844 type Point = <#field_type as #trait_name>::Point;
845 #[inline(always)]
846 fn search_parameter<H: Into<SPHint2D>>(
847 &self,
848 pt: Self::Point,
849 hint: H,
850 trials: usize,
851 ) -> Option<(f64, f64)> {
852 self.0.search_nearest_parameter(pt, hint, trials)
853 }
854 }
855 }
856 }
857 _ => unimplemented!(),
858 }
859 .into()
860}