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 enumerate_impl_return_something<'a>(
22 variants: impl IntoIterator<Item = &'a Variant> + 'a,
23 method: TokenStream2,
24 method_variants: TokenStream2,
25) -> TokenStream2 {
26 let impls: Vec<_> = variants
27 .into_iter()
28 .map(|variant| {
29 let variant_name = &variant.ident;
30 let vec: Vec<_> = variant.fields.iter().collect();
31 match vec.len() {
32 0 => panic!("empty field!"),
33 1 => match &vec[0].ident {
34 Some(ident) => quote! {
35 Self::#variant_name { #ident } => #method(#ident, #method_variants)
36 },
37 None => quote! {
38 Self::#variant_name(got) => #method(got, #method_variants)
39 },
40 },
41 _ => unimplemented!(),
42 }
43 })
44 .collect();
45 quote! { match self { #(#impls),* } }
46}
47
48fn enumerate_impl_return_self<'a>(
49 variants: impl IntoIterator<Item = &'a Variant> + 'a,
50 method: TokenStream2,
51 method_variants: TokenStream2,
52) -> TokenStream2 {
53 let impls: Vec<_> = variants
54 .into_iter()
55 .map(|variant| {
56 let variant_name = &variant.ident;
57 let vec: Vec<_> = variant.fields.iter().collect();
58 match vec.len() {
59 0 => panic!("empty field!"),
60 1 => match &vec[0].ident {
61 Some(ident) => {
62 quote! {
63 Self::#variant_name { #ident } => Self::#variant_name { #ident: #method(#ident, #method_variants) }
64 }
65 }
66 None => {
67 quote! {
68 Self::#variant_name(got) => Self::#variant_name(#method(got, #method_variants))
69 }
70 }
71 },
72 _ => unimplemented!(),
73 }
74 })
75 .collect();
76 quote! {
77 match self {
78 #(#impls),*
79 }
80 }
81}
82
83#[derive(Clone, Debug)]
84struct Field {
85 var: TokenStream2,
86 ty: TokenStream2,
87}
88
89macro_rules! fields {
90 ($($var: tt : $ty: tt),*) => {
91 vec![$(Field {
92 var: quote! { $var },
93 ty: quote! { $ty },
94 }),*]
95 };
96}
97
98#[derive(Clone, Debug)]
99struct Method<I> {
100 name: TokenStream2,
101 generics: Option<TokenStream2>,
102 self_field: TokenStream2,
103 fields: Vec<Field>,
104 return_type: TokenStream2,
105 variants: I,
106 trait_name: TokenStream2,
107}
108
109macro_rules! methods {
110 (
111 $variants: ident, $trait_name: ident,
112 $(fn $name: ident (
113 $self_field: expr,
114 $($var: ident: $ty: ty),*$(,)?
115 ) -> $return_type: ty),*$(,)?
116 ) => {
117 vec![$(Method {
118 name: quote! { $name },
119 generics: None,
120 self_field: quote! { $self_field, },
121 fields: fields!($($var: $ty),*),
122 return_type: quote! { $return_type },
123 variants: $variants,
124 trait_name: $trait_name.clone(),
125 }
126 .to_token_stream()),*]
127 };
128 (
129 $variants: ident, $trait_name: ident,
130 $(fn $name: ident <$($gen: ident: $path: path),*> (
131 $self_field: expr,
132 $($var: ident: $ty: ty),*$(,)?
133 ) -> $return_type: ty),*$(,)?
134 ) => {
135 vec![$(Method {
136 name: quote! { $name },
137 generics: Some(quote! { <$($gen: $path),*> }),
138 self_field: quote! { $self_field, },
139 fields: fields!($($var: $ty),*),
140 return_type: quote! { $return_type },
141 variants: $variants,
142 trait_name: $trait_name.clone(),
143 }
144 .to_token_stream()),*]
145 };
146}
147
148impl<'a, I> Method<I>
149where I: IntoIterator<Item = &'a Variant> + 'a + Copy
150{
151 fn to_token_stream(&'a self) -> TokenStream2 {
152 let method_name = &self.name;
153 let generics = &self.generics;
154 let trait_name = &self.trait_name;
155 let self_field = &self.self_field;
156 let fields = self
157 .fields
158 .iter()
159 .map(|f| {
160 let var = &f.var;
161 let ty = &f.ty;
162 quote! { #var: #ty }
163 })
164 .collect::<Vec<_>>();
165 let vals = self.fields.iter().map(|f| &f.var).collect::<Vec<_>>();
166 let return_type = &self.return_type;
167 let implement = if return_type.to_string() == "Self" {
168 enumerate_impl_return_self::<'_>(
169 self.variants,
170 quote! { #trait_name::#method_name },
171 quote! { #(#vals),* },
172 )
173 } else {
174 enumerate_impl_return_something::<'a>(
175 self.variants,
176 quote! { #trait_name::#method_name },
177 quote! { #(#vals),* },
178 )
179 };
180 quote! {
181 fn #method_name #generics (#self_field #(#fields),*) -> #return_type { #implement }
182 }
183 }
184}
185
186#[proc_macro_error]
188#[proc_macro_derive(BoundedCurve)]
189pub fn derive_bounded_curve(input: TokenStream) -> TokenStream {
190 let input = parse_macro_input!(input as DeriveInput);
191 let trait_name = quote! { truck_geotrait::BoundedCurve };
192 let ty = input.ident;
193 let gen = input.generics;
194 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
195 match input.data {
196 Data::Enum(DataEnum { ref variants, .. }) => {
197 let variant = variants.into_iter().next().expect("empty enum!");
198 let tys: Vec<_> = variant
199 .fields
200 .iter()
201 .map(|field| &field.ty)
202 .collect();
203 let top_ty = &tys[0];
204 let tys = &tys[1..];
205 let methods = methods! {
206 variants, trait_name,
207 fn range_tuple(&self,) -> (f64, f64),
208 fn front(&self,) -> Self::Point,
209 fn back(&self,) -> Self::Point,
210 };
211 quote! {
212 #[automatically_derived]
213 impl #gen #trait_name for #ty #gen
214 where
215 #(#where_predicates,)*
216 #top_ty: #trait_name,
217 #(#tys: #trait_name<Point = <#top_ty as ParametricCurve>::Point>,)*
218 Self: truck_geotrait::ParametricCurve<Point = <#top_ty as ParametricCurve>::Point>, {
219 #(#methods)*
220 }
221 }
222 }
223 Data::Struct(DataStruct { ref fields, .. }) => {
224 let field: Vec<_> = fields.iter().collect();
225 if field.len() != 1 || field[0].ident.is_some() {
226 unimplemented!();
227 }
228 let field_type = &field[0].ty;
229 quote! {
230 #[automatically_derived]
231 impl #gen #trait_name for #ty #gen
232 where
233 #(#where_predicates,)*
234 #field_type: #trait_name,
235 Self: truck_geotrait::ParametricCurve<Point
236 = <#field_type as truck_geotrait::ParametricCurve>::Point>, {
237 fn range_tuple(&self) -> (f64, f64) { self.0.range_tuple() }
238 fn front(&self) -> Self::Point { self.0.front() }
239 fn back(&self) -> Self::Point { self.0.back() }
240 }
241 }
242 }
243 _ => unimplemented!(),
244 }
245 .into()
246}
247
248#[proc_macro_error]
250#[proc_macro_derive(BoundedSurface)]
251pub fn derive_bounded_surface(input: TokenStream) -> TokenStream {
252 let input = parse_macro_input!(input as DeriveInput);
253 let trait_name = quote! { truck_geotrait::BoundedSurface };
254 let ty = input.ident;
255 let gen = input.generics;
256 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
257 match input.data {
258 Data::Enum(DataEnum { ref variants, .. }) => {
259 let variant = variants.into_iter().next().expect("empty enum!");
260 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
261 let methods = methods! {
262 variants, trait_name,
263 fn range_tuple(&self,) -> ((f64, f64), (f64, f64)),
264 };
265 quote! {
266 #[automatically_derived]
267 impl #gen #trait_name for #ty #gen
268 where
269 #(#where_predicates,)*
270 #(#tys: #trait_name,)* {
271 #(#methods)*
272 }
273 }
274 }
275 Data::Struct(DataStruct { ref fields, .. }) => {
276 let field: Vec<_> = fields.iter().collect();
277 if field.len() != 1 || field[0].ident.is_some() {
278 unimplemented!();
279 }
280 let field_type = &field[0].ty;
281 quote! {
282 #[automatically_derived]
283 impl #gen #trait_name for #ty #gen
284 where
285 #(#where_predicates,)*
286 #field_type: #trait_name {
287 fn range_tuple(&self) -> ((f64, f64), (f64, f64)) {
288 self.0.range_tuple()
289 }
290 }
291 }
292 }
293 _ => unimplemented!(),
294 }
295 .into()
296}
297
298#[proc_macro_error]
300#[proc_macro_derive(Cut)]
301pub fn derive_cut(input: TokenStream) -> TokenStream {
302 let input = parse_macro_input!(input as DeriveInput);
303 let trait_name = quote! { truck_geotrait::Cut };
304 let ty = input.ident;
305 let gen = input.generics;
306 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
307 match input.data {
308 Data::Enum(DataEnum { ref variants, .. }) => {
309 let variant = variants.into_iter().next().expect("empty enum!");
310 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
311 let methods = methods! {
312 variants, trait_name,
313 fn cut(&mut self, t: f64) -> Self,
314 };
315 quote! {
316 #[automatically_derived]
317 impl #gen #trait_name for #ty #gen
318 where
319 #(#where_predicates,)*
320 #(#tys: #trait_name,)* {
321 #(#methods)*
322 }
323 }
324 }
325 Data::Struct(DataStruct { ref fields, .. }) => {
326 let field: Vec<_> = fields.iter().collect();
327 if field.len() != 1 || field[0].ident.is_some() {
328 unimplemented!();
329 }
330 let field_type = &field[0].ty;
331 quote! {
332 #[automatically_derived]
333 impl #gen #trait_name for #ty #gen
334 where
335 #(#where_predicates,)*
336 #field_type: #trait_name {
337 fn cut(&mut self, t: f64) -> Self { Self(self.0.cut(t)) }
338 }
339 }
340 }
341 _ => unimplemented!(),
342 }
343 .into()
344}
345
346#[proc_macro_error]
348#[proc_macro_derive(Invertible)]
349pub fn derive_invertible(input: TokenStream) -> TokenStream {
350 let input = parse_macro_input!(input as DeriveInput);
351 let trait_name = quote! { truck_geotrait::Invertible };
352 let ty = input.ident;
353 let gen = input.generics;
354 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
355 match input.data {
356 Data::Enum(DataEnum { ref variants, .. }) => {
357 let variant = variants.into_iter().next().expect("empty enum!");
358 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
359 let methods = methods! {
360 variants, trait_name,
361 fn invert(&mut self,) -> (),
362 fn inverse(&self,) -> Self,
363 };
364 quote! {
365 #[automatically_derived]
366 impl #gen #trait_name for #ty #gen
367 where
368 #(#where_predicates,)*
369 #(#tys: #trait_name,)*
370 Self: Clone {
371 #(#methods)*
372 }
373 }
374 }
375 Data::Struct(DataStruct { ref fields, .. }) => {
376 let field: Vec<_> = fields.iter().collect();
377 if field.len() != 1 || field[0].ident.is_some() {
378 unimplemented!();
379 }
380 let field_type = &field[0].ty;
381 quote! {
382 #[automatically_derived]
383 impl #gen #trait_name for #ty #gen
384 where
385 #(#where_predicates,)*
386 #field_type: #trait_name,
387 Self: Clone {
388 fn invert(&mut self) { self.0.invert() }
389 fn inverse(&self) -> Self { Self(self.0.inverse()) }
390 }
391 }
392 }
393 _ => unimplemented!(),
394 }
395 .into()
396}
397
398#[proc_macro_error]
400#[proc_macro_derive(ParameterDivision1D)]
401pub fn derive_parameter_division_1d(input: TokenStream) -> TokenStream {
402 let input = parse_macro_input!(input as DeriveInput);
403 let trait_name = quote! { truck_geotrait::ParameterDivision1D };
404 let ty = input.ident;
405 let gen = input.generics;
406 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
407 match input.data {
408 Data::Enum(DataEnum { ref variants, .. }) => {
409 let variant = variants.into_iter().next().expect("empty enum!");
410 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
411 let top_ty = match tys.len() {
412 0 => panic!("empty field!"),
413 1 => tys[0].clone(),
414 _ => unimplemented!(),
415 };
416 let tys = &tys[1..];
417 let methods = methods! {
418 variants, trait_name,
419 fn parameter_division(&self, range: (f64, f64), tol: f64) -> (Vec<f64>, Vec<Self::Point>),
420 };
421 quote! {
422 #[automatically_derived]
423 impl #gen #trait_name for #ty #gen
424 where
425 #(#where_predicates,)*
426 #top_ty: #trait_name,
427 #(#tys: #trait_name<Point = <#top_ty as #trait_name>::Point>,)* {
428 type Point = <#top_ty as #trait_name>::Point;
429 #(#methods)*
430 }
431 }
432 }
433 Data::Struct(DataStruct { ref fields, .. }) => {
434 let field: Vec<_> = fields.iter().collect();
435 if field.len() != 1 || field[0].ident.is_some() {
436 unimplemented!();
437 }
438 let field_type = &field[0].ty;
439 quote! {
440 #[automatically_derived]
441 impl #gen #trait_name for #ty #gen
442 where
443 #(#where_predicates,)*
444 #field_type: #trait_name {
445 type Point = <#field_type as #trait_name>::Point;
446 fn parameter_division(&self, range: (f64, f64), tol: f64) -> (Vec<f64>, Vec<Self::Point>) {
447 self.0.parameter_division(range, tol)
448 }
449 }
450 }
451 }
452 _ => unimplemented!(),
453 }
454 .into()
455}
456
457#[proc_macro_error]
459#[proc_macro_derive(ParameterDivision2D)]
460pub fn derive_parameter_division_2d(input: TokenStream) -> TokenStream {
461 let input = parse_macro_input!(input as DeriveInput);
462 let trait_name = quote! { truck_geotrait::ParameterDivision2D };
463 let ty = input.ident;
464 let gen = input.generics;
465 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
466 match input.data {
467 Data::Enum(DataEnum { ref variants, .. }) => {
468 let variant = variants.into_iter().next().expect("empty enum!");
469 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
470 let methods = methods! {
471 variants, trait_name,
472 fn parameter_division(&self, range: ((f64, f64), (f64, f64)), tol: f64) -> (Vec<f64>, Vec<f64>),
473 };
474 quote! {
475 #[automatically_derived]
476 impl #gen #trait_name for #ty #gen
477 where
478 #(#where_predicates,)*
479 #(#tys: #trait_name,)* {
480 #(#methods)*
481 }
482 }
483 }
484 Data::Struct(DataStruct { ref fields, .. }) => {
485 let field: Vec<_> = fields.iter().collect();
486 if field.len() != 1 || field[0].ident.is_some() {
487 unimplemented!();
488 }
489 let field_type = &field[0].ty;
490 quote! {
491 #[automatically_derived]
492 impl #gen #trait_name for #ty #gen
493 where
494 #(#where_predicates,)*
495 #field_type: #trait_name {
496 fn parameter_division(&self, range: ((f64, f64), (f64, f64)), tol: f64) -> (Vec<f64>, Vec<f64>) {
497 self.0.parameter_division(range, tol)
498 }
499 }
500 }
501 }
502 _ => unimplemented!(),
503 }
504 .into()
505}
506
507#[proc_macro_error]
509#[proc_macro_derive(ParametricCurve)]
510pub fn derive_parametric_curve(input: TokenStream) -> TokenStream {
511 let input = parse_macro_input!(input as DeriveInput);
512 let trait_name = quote! { truck_geotrait::ParametricCurve };
513 let ty = input.ident;
514 let gen = input.generics;
515 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
516 match input.data {
517 Data::Enum(DataEnum { ref variants, .. }) => {
518 let variant = variants.into_iter().next().expect("empty enum!");
519 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
520 let top_ty = &tys[0];
521 let methods = methods!(
522 variants,
523 trait_name,
524 fn subs(&self, t: f64) -> Self::Point,
525 fn der(&self, t: f64) -> Self::Vector,
526 fn der2(&self, t: f64) -> Self::Vector,
527 fn parameter_range(&self,) -> ParameterRange,
528 fn period(&self,) -> Option<f64>,
529 );
530 quote! {
531 #[automatically_derived]
532 impl #gen #trait_name for #ty #gen
533 where #(#where_predicates,)*
534 #(#tys: #trait_name,)*
535 Self: Clone {
536 type Point = <#top_ty as #trait_name>::Point;
537 type Vector = <#top_ty as #trait_name>::Vector;
538 #(#methods)*
539 }
540 }
541 }
542 Data::Struct(DataStruct { ref fields, .. }) => {
543 let field: Vec<_> = fields.iter().collect();
544 if field.len() != 1 || field[0].ident.is_some() {
545 unimplemented!();
546 }
547 let field_type = &field[0].ty;
548 quote! {
549 #[automatically_derived]
550 impl #gen #trait_name for #ty #gen
551 where #(#where_predicates,)*
552 #field_type: #trait_name,
553 Self: Clone, {
554 type Point = <#field_type as #trait_name>::Point;
555 type Vector = <#field_type as #trait_name>::Vector;
556 fn subs(&self, t: f64) -> Self::Point { self.0.subs(t) }
557 fn der(&self, t: f64) -> Self::Vector { self.0.der(t) }
558 fn der2(&self, t: f64) -> Self::Vector { self.0.der2(t) }
559 fn parameter_range(&self) -> ParameterRange { self.0.parameter_range() }
560 fn period(&self) -> Option<f64> { self.0.period() }
561 }
562 }
563 }
564 _ => unimplemented!(),
565 }
566 .into()
567}
568
569#[proc_macro_error]
571#[proc_macro_derive(ParametricSurface)]
572pub fn derive_parametric_surface(input: TokenStream) -> TokenStream {
573 let input = parse_macro_input!(input as DeriveInput);
574 let trait_name = quote! { truck_geotrait::ParametricSurface };
575 let ty = input.ident;
576 let gen = input.generics;
577 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
578 match input.data {
579 Data::Enum(DataEnum { ref variants, .. }) => {
580 let variant = variants.into_iter().next().expect("empty enum!");
581 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
582 let top_ty = &tys[0];
583 let methods = methods!(
584 variants,
585 trait_name,
586 fn subs(&self, s: f64, t: f64) -> Self::Point,
587 fn uder(&self, s: f64, t: f64) -> Self::Vector,
588 fn vder(&self, s: f64, t: f64) -> Self::Vector,
589 fn uuder(&self, s: f64, t: f64) -> Self::Vector,
590 fn uvder(&self, s: f64, t: f64) -> Self::Vector,
591 fn vvder(&self, s: f64, t: f64) -> Self::Vector,
592 fn parameter_range(&self,) -> (truck_geotrait::ParameterRange, truck_geotrait::ParameterRange),
593 fn u_period(&self,) -> Option<f64>,
594 fn v_period(&self,) -> Option<f64>,
595 );
596 quote! {
597 #[automatically_derived]
598 impl #gen #trait_name for #ty #gen
599 where
600 #(#where_predicates,)*
601 #(#tys: #trait_name,)* {
602 type Point = <#top_ty as #trait_name>::Point;
603 type Vector = <#top_ty as #trait_name>::Vector;
604 #(#methods)*
605 }
606 }
607 }
608 Data::Struct(DataStruct { ref fields, .. }) => {
609 let field: Vec<_> = fields.iter().collect();
610 if field.len() != 1 || field[0].ident.is_some() {
611 unimplemented!();
612 }
613 let field_type = &field[0].ty;
614 quote! {
615 #[automatically_derived]
616 impl #gen #trait_name for #ty #gen
617 where
618 #(#where_predicates,)*
619 #field_type: #trait_name, {
620 type Point = <#field_type as #trait_name>::Point;
621 type Vector = <#field_type as #trait_name>::Vector;
622 fn subs(&self, s: f64, t: f64) -> Self::Point { self.0.subs(s, t) }
623 fn uder(&self, s: f64, t: f64) -> Self::Vector { self.0.uder(s, t) }
624 fn vder(&self, s: f64, t: f64) -> Self::Vector { self.0.vder(s, t) }
625 fn uuder(&self, s: f64, t: f64) -> Self::Vector { self.0.uuder(s, t) }
626 fn uvder(&self, s: f64, t: f64) -> Self::Vector { self.0.uvder(s, t) }
627 fn vvder(&self, s: f64, t: f64) -> Self::Vector { self.0.vvder(s, t) }
628 fn parameter_range(&self,) -> ((std::ops::Bound<f64>, std::ops::Bound<f64>), (std::ops::Bound<f64>, std::ops::Bound<f64>)) {
629 self.0.parameter_range()
630 }
631 fn u_period(&self) -> Option<f64> { self.0.u_period() }
632 fn v_period(&self) -> Option<f64> { self.0.v_period() }
633 }
634 }
635 }
636 _ => unimplemented!(),
637 }
638 .into()
639}
640
641#[proc_macro_error]
643#[proc_macro_derive(ParametricSurface3D)]
644pub fn derive_parametric_surface3d(input: TokenStream) -> TokenStream {
645 let input = parse_macro_input!(input as DeriveInput);
646 let trait_name0 = quote! { truck_geotrait::ParametricSurface };
647 let trait_name1 = quote! { truck_geotrait::ParametricSurface3D };
648 let ty = input.ident;
649 let gen = input.generics;
650 let where_predicates = gen
651 .where_clause
652 .iter()
653 .flat_map(|x| &x.predicates)
654 .collect::<Vec<_>>();
655 match input.data {
656 Data::Enum(DataEnum { ref variants, .. }) => {
657 let variant = variants.into_iter().next().expect("empty enum!");
658 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
659 let methods0 = methods!(
660 variants,
661 trait_name0,
662 fn subs(&self, s: f64, t: f64) -> Self::Point,
663 fn uder(&self, s: f64, t: f64) -> Self::Vector,
664 fn vder(&self, s: f64, t: f64) -> Self::Vector,
665 fn uuder(&self, s: f64, t: f64) -> Self::Vector,
666 fn uvder(&self, s: f64, t: f64) -> Self::Vector,
667 fn vvder(&self, s: f64, t: f64) -> Self::Vector,
668 fn parameter_range(&self,) -> (truck_geotrait::ParameterRange, truck_geotrait::ParameterRange),
669 fn u_period(&self,) -> Option<f64>,
670 fn v_period(&self,) -> Option<f64>,
671 );
672 let methods1 = methods!(
673 variants,
674 trait_name1,
675 fn normal(&self, u: f64, v: f64) -> Vector3,
676 );
677 quote! {
678 #[automatically_derived]
679 impl #gen #trait_name0 for #ty #gen
680 where
681 #(#where_predicates,)*
682 #(#tys: #trait_name0,)* {
683 type Point = Point3;
684 type Vector = Vector3;
685 #(#methods0)*
686 }
687
688 #[automatically_derived]
689 impl #gen #trait_name1 for #ty #gen
690 where
691 #(#where_predicates,)*
692 #(#tys: #trait_name0,)* {
693 #(#methods1)*
694 }
695 }
696 }
697 Data::Struct(DataStruct { ref fields, .. }) => {
698 let field: Vec<_> = fields.iter().collect();
699 if field.len() != 1 || field[0].ident.is_some() {
700 unimplemented!();
701 }
702 let field_type = &field[0].ty;
703 quote! {
704 #[automatically_derived]
705 impl #gen #trait_name0 for #ty #gen
706 where
707 #(#where_predicates,)*
708 #field_type: #trait_name0, {
709 type Point = Point3;
710 type Vector = Vector3;
711 fn subs(&self, s: f64, t: f64) -> Self::Point { self.0.subs(s, t) }
712 fn uder(&self, s: f64, t: f64) -> Self::Vector { self.0.uder(s, t) }
713 fn vder(&self, s: f64, t: f64) -> Self::Vector { self.0.vder(s, t) }
714 fn uuder(&self, s: f64, t: f64) -> Self::Vector { self.0.uuder(s, t) }
715 fn uvder(&self, s: f64, t: f64) -> Self::Vector { self.0.uvder(s, t) }
716 fn vvder(&self, s: f64, t: f64) -> Self::Vector { self.0.vvder(s, t) }
717 fn parameter_range(&self,) -> (truck_geotrait::ParmaterRange, truck_geotrait::ParameterRange) {
718 self.0.parameter_range()
719 }
720 fn u_period(&self) -> Option<f64> { self.0.u_period() }
721 fn v_period(&self) -> Option<f64> { self.0.v_period() }
722 }
723 #[automatically_derived]
724 impl #gen #trait_name1 for #ty #gen
725 where
726 #(#where_predicates,)*
727 #field_type: #trait_name0, {
728 fn normal(&self, u: f64, v: f64) -> Vector3 { self.0.normal(u, v) }
729 }
730 }
731 }
732 _ => unimplemented!(),
733 }
734 .into()
735}
736
737#[proc_macro_error]
739#[proc_macro_derive(SearchNearestParameterD1)]
740pub fn derive_snp_d1(input: TokenStream) -> TokenStream {
741 let input = parse_macro_input!(input as DeriveInput);
742 let trait_name = quote! { truck_geotrait::SearchNearestParameter::<D1> };
743 let ty = input.ident;
744 let gen = input.generics;
745 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
746 match input.data {
747 Data::Enum(DataEnum { ref variants, .. }) => {
748 let variant = variants.into_iter().next().expect("empty enum!");
749 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
750 let top_ty = &tys[0];
751 let methods = methods!(
752 variants,
753 trait_name,
754 fn search_nearest_parameter<H: Into<SPHint1D>>(
755 &self,
756 pt: Self::Point,
757 hint: H,
758 trials: usize,
759 ) -> Option<f64>,
760 );
761 quote! {
762 #[automatically_derived]
763 impl #gen #trait_name for #ty #gen
764 where
765 #(#where_predicates,)*
766 #(#tys: #trait_name,)* {
767 type Point = <#top_ty as #trait_name>::Point;
768 #(#methods)*
769 }
770 }
771 }
772 Data::Struct(DataStruct { ref fields, .. }) => {
773 let field: Vec<_> = fields.iter().collect();
774 if field.len() != 1 || field[0].ident.is_some() {
775 unimplemented!();
776 }
777 let field_type = &field[0].ty;
778 quote! {
779 #[automatically_derived]
780 impl #gen #trait_name for #ty #gen
781 where
782 #(#where_predicates,)*
783 #field_type: #trait_name, {
784 type Point = <#field_type as #trait_name>::Point;
785 fn search_nearest_parameter<H: Into<SPHint1D>>(
786 &self,
787 pt: Self::Point,
788 hint: H,
789 trials: usize,
790 ) -> Option<f64> {
791 self.0.search_nearest_parameter(pt, hint, trials)
792 }
793 }
794 }
795 }
796 _ => unimplemented!(),
797 }
798 .into()
799}
800
801#[proc_macro_error]
803#[proc_macro_derive(SearchNearestParameterD2)]
804pub fn derive_snp_d2(input: TokenStream) -> TokenStream {
805 let input = parse_macro_input!(input as DeriveInput);
806 let trait_name = quote! { truck_geotrait::SearchNearestParameter::<D2> };
807 let ty = input.ident;
808 let gen = input.generics;
809 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
810 match input.data {
811 Data::Enum(DataEnum { ref variants, .. }) => {
812 let variant = variants.into_iter().next().expect("empty enum!");
813 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
814 let top_ty = &tys[0];
815 let methods = methods!(
816 variants,
817 trait_name,
818 fn search_nearest_parameter<H: Into<SPHint2D>>(
819 &self,
820 pt: Self::Point,
821 hint: H,
822 trials: usize,
823 ) -> Option<(f64, f64)>,
824 );
825 quote! {
826 #[automatically_derived]
827 impl #gen #trait_name for #ty #gen
828 where
829 #(#where_predicates,)*
830 #(#tys: #trait_name,)* {
831 type Point = <#top_ty as #trait_name>::Point;
832 #(#methods)*
833 }
834 }
835 }
836 Data::Struct(DataStruct { ref fields, .. }) => {
837 let field: Vec<_> = fields.iter().collect();
838 if field.len() != 1 || field[0].ident.is_some() {
839 unimplemented!();
840 }
841 let field_type = &field[0].ty;
842 quote! {
843 #[automatically_derived]
844 impl #gen #trait_name for #ty #gen
845 where
846 #(#where_predicates,)*
847 #field_type: #trait_name, {
848 type Point = <#field_type as #trait_name>::Point;
849 fn search_nearest_parameter<H: Into<SPHint2D>>(
850 &self,
851 pt: Self::Point,
852 hint: H,
853 trials: usize,
854 ) -> Option<(f64, f64)> {
855 self.0.search_nearest_parameter(pt, hint, trials)
856 }
857 }
858 }
859 }
860 _ => unimplemented!(),
861 }
862 .into()
863}
864
865#[proc_macro_error]
867#[proc_macro_derive(SearchParameterD1)]
868pub fn derive_sp_d1(input: TokenStream) -> TokenStream {
869 let input = parse_macro_input!(input as DeriveInput);
870 let trait_name = quote! { truck_geotrait::SearchParameter::<D1> };
871 let ty = input.ident;
872 let gen = input.generics;
873 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
874 match input.data {
875 Data::Enum(DataEnum { ref variants, .. }) => {
876 let variant = variants.into_iter().next().expect("empty enum!");
877 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
878 let top_ty = &tys[0];
879 let tys = &tys[1..];
880 let methods = methods!(
881 variants,
882 trait_name,
883 fn search_parameter<H: Into<SPHint1D>>(
884 &self,
885 pt: Self::Point,
886 hint: H,
887 trials: usize,
888 ) -> Option<f64>,
889 );
890 quote! {
891 #[automatically_derived]
892 impl #gen #trait_name for #ty #gen
893 where
894 #(#where_predicates,)*
895 #top_ty: #trait_name,
896 #(#tys: #trait_name<Point = <#top_ty as #trait_name>::Point>,)* {
897 type Point = <#top_ty as #trait_name>::Point;
898 #(#methods)*
899 }
900 }
901 }
902 Data::Struct(DataStruct { ref fields, .. }) => {
903 let field: Vec<_> = fields.iter().collect();
904 if field.len() != 1 || field[0].ident.is_some() {
905 unimplemented!();
906 }
907 let field_type = &field[0].ty;
908 quote! {
909 #[automatically_derived]
910 impl #gen #trait_name for #ty #gen
911 where
912 #(#where_predicates,)*
913 #field_type: #trait_name, {
914 type Point = <#field_type as #trait_name>::Point;
915 fn search_parameter<H: Into<SPHint1D>>(
916 &self,
917 pt: Self::Point,
918 hint: H,
919 trials: usize,
920 ) -> Option<f64> {
921 self.0.search_parameter(pt, hint, trials)
922 }
923 }
924 }
925 }
926 _ => unimplemented!(),
927 }
928 .into()
929}
930
931#[proc_macro_error]
933#[proc_macro_derive(SearchParameterD2)]
934pub fn derive_sp_d2(input: TokenStream) -> TokenStream {
935 let input = parse_macro_input!(input as DeriveInput);
936 let trait_name = quote! { truck_geotrait::SearchParameter::<D2> };
937 let ty = input.ident;
938 let gen = input.generics;
939 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
940 match input.data {
941 Data::Enum(DataEnum { ref variants, .. }) => {
942 let variant = variants.into_iter().next().expect("empty enum!");
943 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
944 let top_ty = &tys[0];
945 let methods = methods!(
946 variants,
947 trait_name,
948 fn search_parameter<H: Into<SPHint2D>>(
949 &self,
950 pt: Self::Point,
951 hint: H,
952 trials: usize,
953 ) -> Option<(f64, f64)>,
954 );
955 quote! {
956 #[automatically_derived]
957 impl #gen #trait_name for #ty #gen
958 where
959 #(#where_predicates,)*
960 #(#tys: #trait_name,)* {
961 type Point = <#top_ty as #trait_name>::Point;
962 #(#methods)*
963 }
964 }
965 }
966 Data::Struct(DataStruct { ref fields, .. }) => {
967 let field: Vec<_> = fields.iter().collect();
968 if field.len() != 1 || field[0].ident.is_some() {
969 unimplemented!();
970 }
971 let field_type = &field[0].ty;
972 quote! {
973 #[automatically_derived]
974 impl #gen #trait_name for #ty #gen
975 where
976 #(#where_predicates,)*
977 #field_type: #trait_name, {
978 type Point = <#field_type as #trait_name>::Point;
979 fn search_parameter<H: Into<SPHint2D>>(
980 &self,
981 pt: Self::Point,
982 hint: H,
983 trials: usize,
984 ) -> Option<(f64, f64)> {
985 self.0.search_parameter(pt, hint, trials)
986 }
987 }
988 }
989 }
990 _ => unimplemented!(),
991 }
992 .into()
993}
994
995#[proc_macro_error]
997#[proc_macro_derive(TransformedM3)]
998pub fn derive_transform_m3(input: TokenStream) -> TokenStream {
999 let input = parse_macro_input!(input as DeriveInput);
1000 let trait_name = quote! { truck_geotrait::Transformed::<Matrix3> };
1001 let ty = input.ident;
1002 let gen = input.generics;
1003 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
1004 match input.data {
1005 Data::Enum(DataEnum { ref variants, .. }) => {
1006 let variant = variants.into_iter().next().expect("empty enum!");
1007 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
1008 let methods = methods!(
1009 variants,
1010 trait_name,
1011 fn transform_by(&mut self, mat: truck_geometry::prelude::Matrix3) -> (),
1012 fn transformed(&self, mat: truck_geometry::prelude::Matrix3) -> Self,
1013 );
1014 quote! {
1015 #[automatically_derived]
1016 impl #gen #trait_name for #ty #gen
1017 where
1018 #(#where_predicates,)*
1019 #(#tys: #trait_name,)* {
1020 #(#methods)*
1021 }
1022 }
1023 }
1024 Data::Struct(DataStruct { ref fields, .. }) => {
1025 let field: Vec<_> = fields.iter().collect();
1026 if field.len() != 1 || field[0].ident.is_some() {
1027 unimplemented!();
1028 }
1029 let field_type = &field[0].ty;
1030 quote! {
1031 #[automatically_derived]
1032 impl #gen #trait_name for #ty #gen
1033 where
1034 #(#where_predicates,)*
1035 #field_type: #trait_name, {
1036 fn transform_by(&mut self, mat: truck_geometry::prelude::Matrix3) {
1037 self.0.transformed(mat)
1038 }
1039 fn transformed(&self, mat: truck_geometry::prelude::Matrix3) -> Self {
1040 Self(self.0.transformed(mat))
1041 }
1042 }
1043 }
1044 }
1045 _ => unimplemented!(),
1046 }
1047 .into()
1048}
1049
1050#[proc_macro_error]
1052#[proc_macro_derive(TransformedM4)]
1053pub fn derive_transform_m4(input: TokenStream) -> TokenStream {
1054 let input = parse_macro_input!(input as DeriveInput);
1055 let trait_name = quote! { truck_geotrait::Transformed::<Matrix4> };
1056 let ty = input.ident;
1057 let gen = input.generics;
1058 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
1059 match input.data {
1060 Data::Enum(DataEnum { ref variants, .. }) => {
1061 let variant = variants.into_iter().next().expect("empty enum!");
1062 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
1063 let methods = methods!(
1064 variants,
1065 trait_name,
1066 fn transform_by(&mut self, mat: truck_geometry::prelude::Matrix4) -> (),
1067 fn transformed(&self, mat: truck_geometry::prelude::Matrix4) -> Self,
1068 );
1069 quote! {
1070 #[automatically_derived]
1071 impl #gen #trait_name for #ty #gen
1072 where
1073 #(#where_predicates,)*
1074 #(#tys: #trait_name,)* {
1075 #(#methods)*
1076 }
1077 }
1078 }
1079 Data::Struct(DataStruct { ref fields, .. }) => {
1080 let field: Vec<_> = fields.iter().collect();
1081 if field.len() != 1 || field[0].ident.is_some() {
1082 unimplemented!();
1083 }
1084 let field_type = &field[0].ty;
1085 quote! {
1086 #[automatically_derived]
1087 impl #gen #trait_name for #ty #gen
1088 where
1089 #(#where_predicates,)*
1090 #field_type: #trait_name, {
1091 fn transform_by(&mut self, mat: truck_geometry::prelude::Matrix4) {
1092 self.0.transformed(mat)
1093 }
1094 fn transformed(&self, mat: truck_geometry::prelude::Matrix4) -> Self {
1095 Self(self.0.transformed(mat))
1096 }
1097 }
1098 }
1099 }
1100 _ => unimplemented!(),
1101 }
1102 .into()
1103}
1104#[proc_macro_error]
1106#[proc_macro_derive(StepLength)]
1107pub fn derive_step_length(input: TokenStream) -> TokenStream {
1108 let input = parse_macro_input!(input as DeriveInput);
1109 let trait_name = quote! { truck_stepio::out::StepLength };
1110 let ty = input.ident;
1111 let gen = input.generics;
1112 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
1113 match input.data {
1114 Data::Enum(DataEnum { ref variants, .. }) => {
1115 let variant = variants.into_iter().next().expect("empty enum!");
1116 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
1117 let methods = methods!(
1118 variants,
1119 trait_name,
1120 fn step_length(&self,) -> usize,
1121 );
1122 quote! {
1123 #[automatically_derived]
1124 impl #gen #trait_name for #ty #gen
1125 where
1126 #(#where_predicates,)*
1127 #(#tys: #trait_name,)* {
1128 #(#methods)*
1129 }
1130 }
1131 }
1132 Data::Struct(DataStruct { ref fields, .. }) => {
1133 let field: Vec<_> = fields.iter().collect();
1134 if field.len() != 1 || field[0].ident.is_some() {
1135 unimplemented!();
1136 }
1137 let field_type = &field[0].ty;
1138 quote! {
1139 #[automatically_derived]
1140 impl #gen #trait_name for #ty #gen
1141 where
1142 #(#where_predicates,)*
1143 #field_type: #trait_name, {
1144 fn step_length(&self) -> usize { self.0.step_length() }
1145 }
1146 }
1147 }
1148 _ => unimplemented!(),
1149 }
1150 .into()
1151}
1152
1153#[proc_macro_error]
1155#[proc_macro_derive(DisplayByStep)]
1156pub fn derive_display_by_step(input: TokenStream) -> TokenStream {
1157 let input = parse_macro_input!(input as DeriveInput);
1158 let trait_name = quote! { truck_stepio::out::DisplayByStep };
1159 let ty = input.ident;
1160 let gen = input.generics;
1161 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
1162 match input.data {
1163 Data::Enum(DataEnum { ref variants, .. }) => {
1164 let variant = variants.into_iter().next().expect("empty enum!");
1165 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
1166 let methods = methods!(
1167 variants,
1168 trait_name,
1169 fn fmt(&self, idx: usize, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result,
1170 );
1171 quote! {
1172 #[automatically_derived]
1173 impl #gen #trait_name for #ty #gen
1174 where
1175 #(#where_predicates,)*
1176 #(#tys: #trait_name,)* {
1177 #(#methods)*
1178 }
1179 }
1180 }
1181 Data::Struct(DataStruct { ref fields, .. }) => {
1182 let field: Vec<_> = fields.iter().collect();
1183 if field.len() != 1 || field[0].ident.is_some() {
1184 unimplemented!();
1185 }
1186 let field_type = &field[0].ty;
1187 quote! {
1188 #[automatically_derived]
1189 impl #gen #trait_name for #ty #gen
1190 where
1191 #(#where_predicates,)*
1192 #field_type: #trait_name, {
1193 fn fmt(&self, idx: usize, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1194 #trait_name::fmt(&self.0, idx, f)
1195 }
1196 }
1197 }
1198 }
1199 _ => unimplemented!(),
1200 }
1201 .into()
1202}
1203
1204#[proc_macro_error]
1206#[proc_macro_derive(StepCurve)]
1207pub fn derive_step_curve(input: TokenStream) -> TokenStream {
1208 let input = parse_macro_input!(input as DeriveInput);
1209 let trait_name = quote! { truck_stepio::out::StepCurve };
1210 let ty = input.ident;
1211 let gen = input.generics;
1212 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
1213 match input.data {
1214 Data::Enum(DataEnum { ref variants, .. }) => {
1215 let variant = variants.into_iter().next().expect("empty enum!");
1216 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
1217 let methods = methods!(
1218 variants,
1219 trait_name,
1220 fn same_sense(&self,) -> bool,
1221 );
1222 quote! {
1223 #[automatically_derived]
1224 impl #gen #trait_name for #ty #gen
1225 where
1226 #(#where_predicates,)*
1227 #(#tys: #trait_name,)* {
1228 #(#methods)*
1229 }
1230 }
1231 }
1232 Data::Struct(DataStruct { ref fields, .. }) => {
1233 let field: Vec<_> = fields.iter().collect();
1234 if field.len() != 1 || field[0].ident.is_some() {
1235 unimplemented!();
1236 }
1237 let field_type = &field[0].ty;
1238 quote! {
1239 #[automatically_derived]
1240 impl #gen #trait_name for #ty #gen
1241 where
1242 #(#where_predicates,)*
1243 #field_type: #trait_name, {
1244 fn same_sense(&self) -> bool { #trait_name::same_sense(&self.0) }
1245 }
1246 }
1247 }
1248 _ => unimplemented!(),
1249 }
1250 .into()
1251}
1252
1253#[proc_macro_error]
1255#[proc_macro_derive(StepSurface)]
1256pub fn derive_step_surface(input: TokenStream) -> TokenStream {
1257 let input = parse_macro_input!(input as DeriveInput);
1258 let trait_name = quote! { truck_stepio::out::StepSurface };
1259 let ty = input.ident;
1260 let gen = input.generics;
1261 let where_predicates = gen.where_clause.iter().flat_map(|x| &x.predicates);
1262 match input.data {
1263 Data::Enum(DataEnum { ref variants, .. }) => {
1264 let variant = variants.into_iter().next().expect("empty enum!");
1265 let tys: Vec<_> = variant.fields.iter().map(|field| &field.ty).collect();
1266 let methods = methods!(
1267 variants,
1268 trait_name,
1269 fn same_sense(&self,) -> bool,
1270 );
1271 quote! {
1272 #[automatically_derived]
1273 impl #gen #trait_name for #ty #gen
1274 where
1275 #(#where_predicates,)*
1276 #(#tys: #trait_name,)* {
1277 #(#methods)*
1278 }
1279 }
1280 }
1281 Data::Struct(DataStruct { ref fields, .. }) => {
1282 let field: Vec<_> = fields.iter().collect();
1283 if field.len() != 1 || field[0].ident.is_some() {
1284 unimplemented!();
1285 }
1286 let field_type = &field[0].ty;
1287 quote! {
1288 #[automatically_derived]
1289 impl #gen #trait_name for #ty #gen
1290 where
1291 #(#where_predicates,)*
1292 #field_type: #trait_name, {
1293 fn same_sense(&self) -> bool { #trait_name::same_sense(&self.0) }
1294 }
1295 }
1296 }
1297 _ => unimplemented!(),
1298 }
1299 .into()
1300}