macro_rules! forward_val_val_binop { (impl $imp:ident for $res:ty, $method:ident) => { impl $imp<$res> for $res { type Output = $res; #[inline] fn $method(self, other: $res) -> $res { // forward to val-ref $imp::$method(self, &other) } } } } macro_rules! forward_val_val_binop_commutative { (impl $imp:ident for $res:ty, $method:ident) => { impl $imp<$res> for $res { type Output = $res; #[inline] fn $method(self, other: $res) -> $res { // forward to val-ref, with the larger capacity as val if self.data.capacity() >= other.data.capacity() { $imp::$method(self, &other) } else { $imp::$method(other, &self) } } } } } macro_rules! forward_ref_val_binop { (impl $imp:ident for $res:ty, $method:ident) => { impl<'a> $imp<$res> for &'a $res { type Output = $res; #[inline] fn $method(self, other: $res) -> $res { // forward to ref-ref $imp::$method(self, &other) } } } } macro_rules! forward_ref_val_binop_commutative { (impl $imp:ident for $res:ty, $method:ident) => { impl<'a> $imp<$res> for &'a $res { type Output = $res; #[inline] fn $method(self, other: $res) -> $res { // reverse, forward to val-ref $imp::$method(other, self) } } } } macro_rules! forward_val_ref_binop { (impl $imp:ident for $res:ty, $method:ident) => { impl<'a> $imp<&'a $res> for $res { type Output = $res; #[inline] fn $method(self, other: &$res) -> $res { // forward to ref-ref $imp::$method(&self, other) } } } } macro_rules! forward_ref_ref_binop { (impl $imp:ident for $res:ty, $method:ident) => { impl<'a, 'b> $imp<&'b $res> for &'a $res { type Output = $res; #[inline] fn $method(self, other: &$res) -> $res { // forward to val-ref $imp::$method(self.clone(), other) } } } } macro_rules! forward_ref_ref_binop_commutative { (impl $imp:ident for $res:ty, $method:ident) => { impl<'a, 'b> $imp<&'b $res> for &'a $res { type Output = $res; #[inline] fn $method(self, other: &$res) -> $res { // forward to val-ref, choosing the larger to clone if self.data.len() >= other.data.len() { $imp::$method(self.clone(), other) } else { $imp::$method(other.clone(), self) } } } } } // Forward everything to ref-ref, when reusing storage is not helpful macro_rules! forward_all_binop_to_ref_ref { (impl $imp:ident for $res:ty, $method:ident) => { forward_val_val_binop!(impl $imp for $res, $method); forward_val_ref_binop!(impl $imp for $res, $method); forward_ref_val_binop!(impl $imp for $res, $method); }; } // Forward everything to val-ref, so LHS storage can be reused macro_rules! forward_all_binop_to_val_ref { (impl $imp:ident for $res:ty, $method:ident) => { forward_val_val_binop!(impl $imp for $res, $method); forward_ref_val_binop!(impl $imp for $res, $method); forward_ref_ref_binop!(impl $imp for $res, $method); }; } // Forward everything to val-ref, commutatively, so either LHS or RHS storage can be reused macro_rules! forward_all_binop_to_val_ref_commutative { (impl $imp:ident for $res:ty, $method:ident) => { forward_val_val_binop_commutative!(impl $imp for $res, $method); forward_ref_val_binop_commutative!(impl $imp for $res, $method); forward_ref_ref_binop_commutative!(impl $imp for $res, $method); }; }