simple_si_units_macros/
lib.rs

1#![no_std]
2#![warn(missing_docs)]
3#![ doc = include_str!("../README.md")]
4use proc_macro::TokenStream;
5use quote::{quote};
6use syn::*;
7
8// Test with $ rm ./tests/expand/derive_tester.expanded.rs ; cargo +nightly test -- --nocapture
9
10/// This macro uses the `NumLike` trait from
11/// [simple-si-units-core](https://crates.io/crates/simple-si-units-core) to
12/// derive all of the relevant mathematical operators for the derived struct,
13/// so long as that struct contains only a single named field. For example:
14/// 
15/// ```rust
16/// use simple_si_units_macros::UnitStruct;
17/// use simple_si_units_core::NumLike;
18/// 
19/// #[derive(UnitStruct, Debug, Clone)]
20/// struct HyperVelocity<T: NumLike>{
21///   square_meters_per_second: T
22/// }
23/// 
24/// fn weighted_hypervel_sum<T: NumLike>(a: HyperVelocity<T>, b: HyperVelocity<T>, weight: f64) -> HyperVelocity<T>
25///   where T:NumLike + From<f64>
26/// {
27///   return weight*a + (1.-weight)*b;
28/// }
29/// ```
30#[proc_macro_derive(UnitStruct)]
31pub fn derive_unit(tokens: TokenStream) -> TokenStream {
32	// convert the input tokens into an ast, specially from a derive
33	let input: syn::DeriveInput = syn::parse(tokens).expect("syn::parse failed on proc macro \
34	input for simple_si_units_macros::UnitStruct");
35
36	// Build the trait implementation
37	impl_derive_unit(&input)
38}
39
40fn impl_derive_unit(input: &syn::DeriveInput) -> TokenStream {
41	let requirements_msg = "Derive macro simple_si_units::UnitStruct can only be applied to structs \
42	with a single field, whose type implements core::ops::{Add, Sub, Div, Mul} (eg \
43	<T: NumLike>). For \
44	example:\n\nuse simple_si_units::{UnitStruct, NumLike};\n#[derive(UnitStruct, Debug, Copy, Clone)\
45	]\nstruct MyNewUnitStruct<T: NumLike>{\n    pub x: \
46	T\n}\n\nfn \
47	weighted_sum<T: NumLike>(a: MyNewUnitStruct<T>, b: MyNewUnitStruct<T>, weight: f64) -> MyNewUnitStruct<T> where T:\
48	 NumLike + From<f64>\n{\n    return weight*a + (1.-weight)*b;\n}\n";
49	let name = &input.ident;
50	let fields = match &input.data {
51		Data::Struct(DataStruct {
52						 fields: Fields::Named(fields),
53						 ..
54					 }) => &fields.named,
55		_ => panic!("Only structs with named fields can derive simple_si_units::UnitStruct.\n\n{}",
56					requirements_msg),
57	};
58	if fields.len() != 1 {
59		panic!("proc macro simple_si_units::UnitStruct can only be used on structs with a single \
60		 named field. \n\n{}", requirements_msg)
61	}
62	let data_name = &fields[0].ident.as_ref().unwrap();
63	let data_type = &fields[0].ty;
64	let gen = quote! {
65		#[doc="This struct implements the Copy marker trait if it's member data type also has the \
66		Copy trait"]
67		impl<#data_type> core::marker::Copy for #name<#data_type>
68			where #data_type: NumLike + core::marker::Copy { }
69		#[doc="This struct implements the PartialEq trait if it's member data type also has the \
70		PartialEq trait"]
71		impl<#data_type> core::cmp::PartialEq for #name<#data_type>
72			where #data_type: NumLike + core::cmp::PartialEq {
73			fn eq(&self, other: &Self) -> bool {
74				#data_type::eq(&self.#data_name, &other.#data_name)
75			}
76			fn ne(&self, other: &Self) -> bool {
77				#data_type::ne(&self.#data_name, &other.#data_name)
78			}
79		}
80		#[doc="This struct implements the core::cmp::Eq trait if it's member data type also has the \
81		core::cmp::Eq trait"]
82		impl<#data_type> core::cmp::Eq for #name<#data_type>
83			where #data_type: NumLike + core::cmp::PartialEq + core::cmp::Eq {}
84		#[doc="This struct implements the Hash trait if it's member data type also has the \
85		Hash trait"]
86		impl<#data_type> core::hash::Hash for #name<#data_type>
87			where #data_type: NumLike + core::hash::Hash {
88			fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
89				#data_type::hash(&self.#data_name, hasher);
90			}
91		}
92		#[doc="This struct implements the PartialOrd trait if it's member data type also has the \
93		PartialOrd trait"]
94		impl<#data_type> core::cmp::PartialOrd for #name<#data_type>
95			where #data_type: NumLike + core::cmp::PartialOrd {
96			fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
97				#data_type::partial_cmp(&self.#data_name, &other.#data_name)
98			}
99		}
100		#[doc="This struct implements the Ord trait if it's member data type also has the \
101		Ord trait"]
102		impl<#data_type> core::cmp::Ord for #name<#data_type>
103			where #data_type: NumLike + core::cmp::Ord {
104			fn cmp(&self, other: &Self) -> core::cmp::Ordering {
105				#data_type::cmp(&self.#data_name, &other.#data_name)
106			}
107		}
108
109		#[doc="Adding two unit values of the same type returns a new unit value of the same type"]
110		impl<#data_type: NumLike> core::ops::Add<Self> for #name<#data_type> {
111			type Output = Self;
112			fn add(self, rhs: Self) -> Self::Output {
113				return Self{#data_name: self.#data_name + rhs.#data_name}
114			}
115		}
116		#[doc="Adds the given unit value to this unit value"]
117		impl<#data_type: NumLike> core::ops::AddAssign for #name<#data_type> {
118			fn add_assign(&mut self, rhs: Self){
119				self.#data_name += rhs.#data_name;
120			}
121		}
122		#[doc="Subtracting two unit values of the same type returns a new unit value of the same \
123		type"]
124		impl<#data_type: NumLike> core::ops::Sub<Self> for
125		#name<#data_type> {
126			type Output = Self;
127			fn sub(self, rhs: Self) -> Self::Output {
128				return Self{#data_name: self.#data_name - rhs.#data_name}
129			}
130		}
131		#[doc="Subtracts the given unit value from this unit value"]
132		impl<#data_type: NumLike> core::ops::SubAssign for #name<#data_type> {
133			fn sub_assign(&mut self, rhs: Self){
134				self.#data_name -= rhs.#data_name;
135			}
136		}
137		#[doc="Dividing a unit value by another of the same type returns a scalar value"]
138		impl<#data_type: NumLike> core::ops::Div<Self> for
139		#name<#data_type> {
140			type Output = #data_type;
141			fn div(self, rhs: Self) -> Self::Output {
142				return self.#data_name / rhs.#data_name;
143			}
144		}
145		#[doc="Dividing a unit value by a scalar value returns a unit value"]
146		impl<#data_type: NumLike> core::ops::Div<#data_type> for
147		#name<#data_type> {
148			type Output = Self;
149			fn div(self, rhs: #data_type) -> Self::Output {
150				return Self{#data_name: self.#data_name / rhs}
151			}
152		}
153		#[doc="Divides this unit value by a scalar"]
154		impl<#data_type: NumLike> core::ops::DivAssign<#data_type> for #name<#data_type> {
155			fn div_assign(&mut self, rhs: #data_type){
156				self.#data_name /= rhs;
157			}
158		}
159		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
160		impl<#data_type: NumLike> core::ops::Mul<#data_type> for
161		#name<#data_type> {
162			type Output = Self;
163			fn mul(self, rhs: #data_type) -> Self::Output {
164				return Self{#data_name: self.#data_name * rhs}
165			}
166		}
167		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
168		impl<#data_type> core::ops::Mul<&#data_type> for #name<#data_type>
169			where #data_type: NumLike {
170			type Output = #name<#data_type>;
171			fn mul(self, rhs: &#data_type) -> Self::Output {
172				#name{#data_name: self.#data_name * rhs.clone()}
173			}
174		}
175		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
176		impl<#data_type> core::ops::Mul<&#data_type> for &#name<#data_type>
177			where #data_type: NumLike {
178			type Output = #name<#data_type>;
179			fn mul(self, rhs: &#data_type) -> Self::Output {
180				#name{#data_name: self.#data_name.clone() * rhs.clone()}
181			}
182		}
183		#[doc="Multiplies this unit value by a scalar"]
184		impl<#data_type: NumLike> core::ops::MulAssign<#data_type> for #name<#data_type> {
185			fn mul_assign(&mut self, rhs: #data_type){
186				self.#data_name *= rhs;
187			}
188		}
189		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
190		impl<#data_type>
191		core::ops::Mul<#name<#data_type>> for
192		 f64 where #data_type: NumLike + From<f64>{
193			type Output = #name<#data_type>;
194			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
195				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
196			}
197		}
198		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
199		impl<#data_type>
200		core::ops::Mul<#name<#data_type>> for
201		 f32 where #data_type: NumLike + From<f32>{
202			type Output = #name<#data_type>;
203			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
204				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
205			}
206		}
207		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
208		impl<#data_type>
209		core::ops::Mul<#name<#data_type>> for
210		 u8 where #data_type: NumLike + From<u8>{
211			type Output = #name<#data_type>;
212			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
213				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
214			}
215		}
216		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
217		impl<#data_type>
218		core::ops::Mul<#name<#data_type>> for
219		 i8 where #data_type: NumLike + From<i8>{
220			type Output = #name<#data_type>;
221			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
222				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
223			}
224		}
225		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
226		impl<#data_type>
227		core::ops::Mul<#name<#data_type>> for
228		 u16 where #data_type: NumLike + From<u16>{
229			type Output = #name<#data_type>;
230			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
231				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
232			}
233		}
234		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
235		impl<#data_type>
236		core::ops::Mul<#name<#data_type>> for
237		 i16 where #data_type: NumLike + From<i16>{
238			type Output = #name<#data_type>;
239			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
240				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
241			}
242		}
243		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
244		impl<#data_type>
245		core::ops::Mul<#name<#data_type>> for
246		 u32 where #data_type: NumLike + From<u32>{
247			type Output = #name<#data_type>;
248			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
249				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
250			}
251		}
252		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
253		impl<#data_type>
254		core::ops::Mul<#name<#data_type>> for
255		 i32 where #data_type: NumLike + From<i32>{
256			type Output = #name<#data_type>;
257			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
258				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
259			}
260		}
261		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
262		impl<#data_type>
263		core::ops::Mul<#name<#data_type>> for
264		 u64 where #data_type: NumLike + From<u64>{
265			type Output = #name<#data_type>;
266			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
267				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
268			}
269		}
270		#[doc="Multiplying a unit value by a scalar value returns a unit value"]
271		impl<#data_type>
272		core::ops::Mul<#name<#data_type>> for
273		 i64 where #data_type: NumLike + From<i64>{
274			type Output = #name<#data_type>;
275			fn mul(self, rhs: #name<#data_type>) -> Self::Output {
276				return #name{#data_name: #data_type::from(self) * rhs.#data_name}
277			}
278		}
279		#[doc="Flips the sign of this unit value"]
280		impl<#data_type: NumLike> core::ops::Neg for
281		#name<#data_type> {
282			type Output = Self;
283			fn neg(self) -> Self::Output {
284				return Self{#data_name: self.#data_name.neg()}
285			}
286		}
287
288		// ref operators automatically clone the referenced data for convenient ergonomics
289		#[doc="Adding two unit values of the same type returns a new unit value of the same type \
290		(automatically clones the referenced data for convenient ergonomics)"]
291		impl<#data_type: NumLike> core::ops::Add<Self> for &#name<#data_type> {
292			type Output = #name<#data_type>;
293			fn add(self, rhs: Self) -> Self::Output {
294				return Self::Output{#data_name: self.#data_name.clone() + rhs.#data_name.clone()}
295			}
296		}
297		#[doc="Subtracting two unit values of the same type returns a new unit value of the same \
298		type (automatically clones the referenced data for convenient ergonomics)"]
299		impl<#data_type: NumLike> core::ops::Sub<Self> for
300		&#name<#data_type> {
301			type Output = #name<#data_type>;
302			fn sub(self, rhs: Self) -> Self::Output {
303				return Self::Output{#data_name: self.#data_name.clone() - rhs.#data_name.clone()}
304			}
305		}
306		#[doc="Dividing a unit value by another of the same type returns a scalar value \
307		(automatically clones the referenced data for convenient ergonomics)"]
308		impl<#data_type: NumLike> core::ops::Div<Self> for
309		&#name<#data_type> {
310			type Output = #data_type;
311			fn div(self, rhs: Self) -> Self::Output {
312				return self.#data_name.clone() / rhs.#data_name.clone();
313			}
314		}
315		#[doc="Dividing a unit value by a scalar value returns a unit value (automatically clones \
316		the referenced data for convenient ergonomics)"]
317		impl<#data_type: NumLike> core::ops::Div<#data_type> for
318		&#name<#data_type> {
319			type Output = #name<#data_type>;
320			fn div(self, rhs: #data_type) -> Self::Output {
321				return Self::Output{#data_name: self.#data_name.clone() / rhs}
322			}
323		}
324		#[doc="Dividing a unit value by a scalar value returns a unit value"]
325		impl<#data_type> core::ops::Div<&#data_type> for #name<#data_type>
326			where #data_type: NumLike {
327			type Output = #name<#data_type>;
328			fn div(self, rhs: &#data_type) -> Self::Output {
329				#name{#data_name: self.#data_name / rhs.clone()}
330			}
331		}
332		#[doc="Dividing a unit value by a scalar value returns a unit value"]
333		impl<#data_type> core::ops::Div<&#data_type> for &#name<#data_type>
334			where #data_type: NumLike {
335			type Output = #name<#data_type>;
336			fn div(self, rhs: &#data_type) -> Self::Output {
337				#name{#data_name: self.#data_name.clone() / rhs.clone()}
338			}
339		}
340		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
341		clones the referenced data for convenient ergonomics)"]
342		impl<#data_type: NumLike> core::ops::Mul<#data_type> for
343		&#name<#data_type> {
344			type Output = #name<#data_type>;
345			fn mul(self, rhs: #data_type) -> Self::Output {
346				return Self::Output{#data_name: self.#data_name.clone() * rhs}
347			}
348		}
349		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
350		clones the referenced data for convenient ergonomics)"]
351		impl<#data_type>
352		core::ops::Mul<&#name<#data_type>> for
353		 f64 where #data_type: NumLike + From<f64>{
354			type Output = #name<#data_type>;
355			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
356				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
357			}
358		}
359		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
360		clones the referenced data for convenient ergonomics)"]
361		impl<#data_type>
362		core::ops::Mul<&#name<#data_type>> for
363		 f32 where #data_type: NumLike + From<f32>{
364			type Output = #name<#data_type>;
365			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
366				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
367			}
368		}
369		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
370		clones the referenced data for convenient ergonomics)"]
371		impl<#data_type>
372		core::ops::Mul<&#name<#data_type>> for
373		 u8 where #data_type: NumLike + From<u8>{
374			type Output = #name<#data_type>;
375			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
376				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
377			}
378		}
379		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
380		clones the referenced data for convenient ergonomics)"]
381		impl<#data_type>
382		core::ops::Mul<&#name<#data_type>> for
383		 i8 where #data_type: NumLike + From<i8>{
384			type Output = #name<#data_type>;
385			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
386				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
387			}
388		}
389		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
390		clones the referenced data for convenient ergonomics)"]
391		impl<#data_type>
392		core::ops::Mul<&#name<#data_type>> for
393		 u16 where #data_type: NumLike + From<u16>{
394			type Output = #name<#data_type>;
395			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
396				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
397			}
398		}
399		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
400		clones the referenced data for convenient ergonomics)"]
401		impl<#data_type>
402		core::ops::Mul<&#name<#data_type>> for
403		 i16 where #data_type: NumLike + From<i16>{
404			type Output = #name<#data_type>;
405			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
406				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
407			}
408		}
409		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
410		clones the referenced data for convenient ergonomics)"]
411		impl<#data_type>
412		core::ops::Mul<&#name<#data_type>> for
413		 u32 where #data_type: NumLike + From<u32>{
414			type Output = #name<#data_type>;
415			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
416				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
417			}
418		}
419		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
420		clones the referenced data for convenient ergonomics)"]
421		impl<#data_type>
422		core::ops::Mul<&#name<#data_type>> for
423		 i32 where #data_type: NumLike + From<i32>{
424			type Output = #name<#data_type>;
425			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
426				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
427			}
428		}
429		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
430		clones the referenced data for convenient ergonomics)"]
431		impl<#data_type>
432		core::ops::Mul<&#name<#data_type>> for
433		 u64 where #data_type: NumLike + From<u64>{
434			type Output = #name<#data_type>;
435			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
436				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
437			}
438		}
439		#[doc="Multiplying a unit value by a scalar value returns a unit value (automatically \
440		clones the referenced data for convenient ergonomics)"]
441		impl<#data_type>
442		core::ops::Mul<&#name<#data_type>> for
443		 i64 where #data_type: NumLike + From<i64>{
444			type Output = #name<#data_type>;
445			fn mul(self, rhs: &#name<#data_type>) -> Self::Output {
446				return #name{#data_name: #data_type::from(self) * rhs.#data_name.clone()}
447			}
448		}
449		#[doc="Flips the sign of this unit value (automatically clones the referenced data for \
450		convenient ergonomics)"]
451		impl<#data_type: NumLike> core::ops::Neg for
452		&#name<#data_type> {
453			type Output = #name<#data_type>;
454			fn neg(self) -> Self::Output {
455				return Self::Output{#data_name: self.#data_name.clone().neg()}
456			}
457		}
458		// Mul DT by Self and Self by DT -> Self
459
460        // impl #name {
461        //     fn hello_macro() {
462        //         println!("Hello, Macro! My name is {}!", stringify!(#name));
463        //     }
464		// 	fn my_attr(){
465		// 		println!("X is {} of {}", stringify!(#data_name), stringify!(#data_type));
466		// 	}
467        // }
468    };
469	let output = gen.into();
470	// uncomment next line to see macro output as compiler error
471	//panic!("impl_derive_unit macro output: {}", output.to_string());
472	return output;
473}
474
475
476// #[test]
477// fn macro_test() {
478// 	println!("Testing UnitStruct procedural macro...");
479// 	use core::str::FromStr;
480// 	use proc_macro2::TokenStream;
481// 	//
482// 	let test_struct = "\
483// struct Temperature<NT> { \
484// 	k : NT\
485// }";
486// 	let tokens = TokenStream::from_str(test_struct).unwrap();
487// 	let ast: syn::DeriveInput = syn::parse2(tokens).unwrap();
488// 	// let struct_type = ast.ident.to_string();
489// 	// assert_eq!(struct_type, "Temperature");
490// 	let output = impl_derive_unit(&ast);
491// 	println!("{}", output.to_string());
492// }