1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
macro_rules! forward_symmetric { ( $(#[$cattr:meta])* impl $tn:ident($name:ident, $cname:ident, $wname:ident, $oname:ident) for $target:ty ) => { forward_symmetric!( $(#[$cattr])* impl $tn<$target>($name, $cname, $wname, $oname) for $target ); }; ( $(#[$cattr:meta])* impl $tn:ident<$arg:ty>($name:ident, $cname:ident, $wname:ident, $oname:ident) for $target:ty ) => { forward_impl! { $(#[$cattr])* impl $tn< $arg; $arg { y => y }; Wrapping<$arg> { x => x.0 } > ($name, $cname, $wname, $oname) for $target, "arithmetic operation overflowed" } } } macro_rules! forward_shift { ( $(#[$cattr:meta])* impl $tn:ident($name:ident, $cname:ident, $wname:ident, $oname:ident) for $target:ty ) => { forward_impl! { $(#[$cattr])* impl $tn< u32; u8|u16|u32|u64|usize|i8|i16|i32|i64|isize { y => y.to_u32().unwrap_or_else(|| panic!("shift operation overflowed")) }; u32 { x => x } > ($name, $cname, $wname, $oname) for $target, "shift operation overflowed" } } } macro_rules! forward_assign { ($tn:ident($name:ident, $fwd:ident) for $target:ty) => { forward_assign!($tn<$target>($name, $fwd) for $target); }; ($tn:ident<$($targ:ty)|+>($name:ident, $fwd:ident) for $target:ty) => { $(impl $tn<$targ> for $target { fn $name(&mut self, other: $targ) { *self = self.$fwd(other); } })+ } } macro_rules! forward_impl { ( $(#[$cattr:meta])* impl $tn:ident< $arg:ty; $($targ:ty)|+ { $t:pat => $uncheck_cast:expr }; $wrarg:ty { $u:pat => $unwrap:expr } > ($name:ident, $cname:ident, $wname:ident, $oname:ident) for $target:ty, $emsg:expr ) => { impl $target { $(#[$cattr])* pub fn $cname(self, other: $arg) -> Option<$target> { match self.$oname(other) { (v, false) => Some(v), (_, true) => None, } } } $(impl $tn<$targ> for $target { type Output = Self; #[cfg(debug_assertions)] #[allow(unused_comparisons, overflowing_literals)] fn $name(self, other: $targ) -> Self { let other = match other { $t => $uncheck_cast, }; self.$cname(other).unwrap_or_else(|| panic!($emsg)) } #[cfg(not(debug_assertions))] fn $name(self, other: $targ) -> Self { self.$wname(match other { $t => $uncheck_cast }) } })+ impl $tn<$wrarg> for Wrapping<$target> { type Output = Self; fn $name(self, other: $wrarg) -> Self { match other { $u => Wrapping((self.0).$wname($unwrap)) } } } } }