use std::ops::*; #[const_trait] pub trait F32Util { fn lerp + const Add>(self, from: T, to: T) -> T; } impl const F32Util for f32 { fn lerp + const Add>(self, from: T, to: T) -> T { from * (1.0 - self) + to * self } } macro_rules! impl_op { ($T:ident $op:ident $fn:ident $opa:ident $fna:ident; $($field:ident)*) => { mod ${concat(op_, $fn, _impl)} { use super::*; #[allow(unused_imports)] use std::ops::*; impl const $op for $T { type Output = Self; fn $fn(self, rhs: Self) -> Self::Output { Self { $($field: self.$field.$fn(rhs.$field),)* } } } impl $opa for $T { fn $fna(&mut self, rhs: Self) { $(self.$field.$fna(rhs.$field);)* } } impl const $op for $T { type Output = Self; fn $fn(self, rhs: f32) -> Self::Output { Self { $($field: self.$field.$fn(rhs),)* } } } impl $opa for $T { fn $fna(&mut self, rhs: f32) { $(self.$field.$fna(rhs);)* } } } }; ($T:ident $op:ident $fn:ident; $($field:ident)*) => { impl_op!($T $op $fn ${concat($op,Assign)} ${concat($fn,_assign)}; $($field)*); }; (impl $op:ident for $T:ident: $fn:ident $($field:ident)*) => { impl_op!($T $op $fn ${concat($op,Assign)} ${concat($fn,_assign)}; $($field)*); }; } pub(crate) use impl_op;