diff --git a/src/range_macros.rs b/src/range_macros.rs index d8ac900d..ead2d8eb 100644 --- a/src/range_macros.rs +++ b/src/range_macros.rs @@ -3,39 +3,43 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. // An omnibus macro that includes all simple macros. -macro_rules! range { +macro_rules! range_u64 { + ( $(#[$comment:meta])? $T: ident, $display_name: expr) => { + range!($(#[$comment])? $T, $display_name, u64, serialize_u64); + from_u64!($T); + mul!($T, u64, u32, u16, u8); + div!($T, u64, u32, u16, u8); + } +} + +macro_rules! range_u128 { ( $(#[$comment:meta])? $T: ident, $display_name: expr) => { + range!($(#[$comment])? $T, $display_name, u128, serialize_u128); + from_u128!($T); + mul!($T, u128, u64, u32, u16, u8); + div!($T, u128, u64, u32, u16, u8); + } +} + +macro_rules! range { + ( $(#[$comment:meta])? $T: ident, $display_name: expr, $inner:ty, $serde_method:ident) => { $( #[$comment] )? #[derive(Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd)] - pub struct $T(pub u64); + pub struct $T(pub $inner); checked_add!($T); debug_macro!($T); display!($T, $display_name); - serde_macro!($T); + serde_macro!($T, $serde_method); sum!($T); add!($T); add_assign!($T); sub!($T); sub_assign!($T); - mul!($T); - div!($T); rem!($T); - deref!($T); - from!($T); - }; -} - -macro_rules! self_div { - ($T:ident) => { - impl std::ops::Div<$T> for $T { - type Output = u64; - fn div(self, rhs: $T) -> u64 { - self.0 / *rhs - } - } + deref!($T, $inner); }; } @@ -82,10 +86,10 @@ macro_rules! sub_assign { } macro_rules! deref { - ($T:ident) => { + ($T:ident, $inner:ty) => { impl std::ops::Deref for $T { - type Target = u64; - fn deref(&self) -> &u64 { + type Target = $inner; + fn deref(&self) -> &$inner { &self.0 } } @@ -93,15 +97,41 @@ macro_rules! deref { } macro_rules! from { - ($T:ident) => { - impl From for $T { - fn from(t: u64) -> $T { + ($T:ident, $inner:ty, $($t:ty),+) => { + $( + impl From<$t> for $T { + fn from(t: $t) -> $T { + $T(<$inner>::from(t)) + } + } + )+ + + impl From for $T { + fn from(t: usize) -> $T { + $T(t as $inner) + } + } + + impl From<$inner> for $T { + fn from(t: $inner) -> $T { $T(t) } } }; } +macro_rules! from_u64 { + ($T:ident) => { + from!($T, u64, u32, u16, u8); + }; +} + +macro_rules! from_u128 { + ($T:ident) => { + from!($T, u128, u64, u32, u16, u8); + }; +} + macro_rules! debug_macro { ($T:ident) => { impl std::fmt::Debug for $T { @@ -124,13 +154,13 @@ macro_rules! display { } macro_rules! serde_macro { - ($T:ident) => { + ($T:ident, $serde_method:ident) => { impl serde::Serialize for $T { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { - serializer.serialize_u64(**self) + serializer.$serde_method(**self) } } @@ -157,34 +187,34 @@ macro_rules! sum { // Define a complete set of division operations. macro_rules! div { - ($T: ident) => { - unsigned_div!(u64, $T); - unsigned_div!(u32, $T); - unsigned_div!(u16, $T); - unsigned_div!(u8, $T); - usize_div!($T); - self_div!($T); - }; -} + ($T:ident, $inner:ty, $($t:ty),+) => { + $( + impl std::ops::Div<$t> for $T { + type Output = $T; + fn div(self, rhs: $t) -> $T { + $T(self.0 / <$inner>::from(rhs)) + } + } + )+ -macro_rules! unsigned_div { - ($t:ty, $T:ident) => { - impl std::ops::Div<$t> for $T { + impl std::ops::Div for $T { type Output = $T; - fn div(self, rhs: $t) -> $T { - $T(self.0 / u64::from(rhs)) + fn div(self, rhs: usize) -> $T { + $T(self.0 / rhs as $inner) } } - }; -} -macro_rules! usize_div { - ($T:ident) => { - impl std::ops::Div for $T { + impl std::ops::Div<$inner> for $T { type Output = $T; - fn div(self, rhs: usize) -> $T { - #[allow(clippy::cast_lossless)] - $T(self.0 / rhs as u64) + fn div(self, rhs: $inner) -> $T { + $T(self.0 / rhs) + } + } + + impl std::ops::Div for $T { + type Output = $inner; + fn div(self, rhs: $T) -> $inner { + self.0 / *rhs } } }; @@ -192,48 +222,48 @@ macro_rules! usize_div { // Define a complete set of multiplication operations. macro_rules! mul { - ($T: ident) => { - unsigned_mul!(u64, $T); - unsigned_mul!(u32, $T); - unsigned_mul!(u16, $T); - unsigned_mul!(u8, $T); - usize_mul!($T); - }; -} + ($T:ident, $inner:ty, $($t:ty),+) => { + $( + impl std::ops::Mul<$t> for $T { + type Output = $T; + fn mul(self, rhs: $t) -> $T { + $T(self.0 * <$inner>::from(rhs)) + } + } + + impl std::ops::Mul<$T> for $t { + type Output = $T; + fn mul(self, rhs: $T) -> $T { + $T(rhs.0 * <$inner>::from(self)) + } + } + )+ -macro_rules! unsigned_mul { - ($t:ty, $T:ident) => { - impl std::ops::Mul<$t> for $T { + impl std::ops::Mul<$inner> for $T { type Output = $T; - fn mul(self, rhs: $t) -> $T { - $T(self.0 * u64::from(rhs)) + fn mul(self, rhs: $inner) -> $T { + $T(self.0 * rhs) } } - impl std::ops::Mul<$T> for $t { + impl std::ops::Mul<$T> for $inner { type Output = $T; fn mul(self, rhs: $T) -> $T { - $T(u64::from(self) * rhs.0) + $T(rhs.0 * self) } } - }; -} -macro_rules! usize_mul { - ($T:ident) => { impl std::ops::Mul for $T { type Output = $T; fn mul(self, rhs: usize) -> $T { - #[allow(clippy::cast_lossless)] - $T(self.0 * rhs as u64) + $T(self.0 * rhs as $inner) } } impl std::ops::Mul<$T> for usize { type Output = $T; fn mul(self, rhs: $T) -> $T { - #[allow(clippy::cast_lossless)] - $T(self as u64 * rhs.0) + $T(rhs.0 * self as $inner) } } }; @@ -242,44 +272,13 @@ macro_rules! usize_mul { // Define a complete set of remainder operations. macro_rules! rem { ($T: ident) => { - unsigned_rem!(u64, $T); - unsigned_rem!(u32, $T); - unsigned_rem!(u16, $T); - unsigned_rem!(u8, $T); - usize_rem!($T); - self_rem!($T); - }; -} - -macro_rules! unsigned_rem { - ($t:ty, $T:ident) => { - impl std::ops::Rem<$t> for $T { - type Output = $T; - fn rem(self, rhs: $t) -> $T { - $T(self.0 % u64::from(rhs)) - } - } - }; -} - -macro_rules! usize_rem { - ($T:ident) => { - impl std::ops::Rem for $T { - type Output = $T; - fn rem(self, rhs: usize) -> $T { - #[allow(clippy::cast_lossless)] - $T(self.0 % rhs as u64) - } - } - }; -} - -macro_rules! self_rem { - ($T:ident) => { - impl std::ops::Rem<$T> for $T { + impl std::ops::Rem for $T + where + $T: From, + { type Output = $T; - fn rem(self, rhs: $T) -> $T { - $T(self.0 % u64::from(rhs.0)) + fn rem(self, rhs: T) -> $T { + $T(self.0 % <$T>::from(rhs).0) } } }; @@ -301,7 +300,7 @@ mod tests { use std::u64; - range!(Units, "units"); + range_u64!(Units, "units"); #[test] /// Test implicit derivations for Units @@ -330,7 +329,7 @@ mod tests { /// Test non-arithmetic derivations that are derived explicitly fn test_explicit_derivations() { // Test From - assert_eq!(Units::from(3) + Units(3), Units(6)); + assert_eq!(Units::from(3u8) + Units(3), Units(6)); // Test Deref assert_eq!(*Units(3) + 3, 6); diff --git a/src/testing/loopbacked.rs b/src/testing/loopbacked.rs index e8bee355..24eabd90 100644 --- a/src/testing/loopbacked.rs +++ b/src/testing/loopbacked.rs @@ -3,6 +3,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. use std::{ + convert::TryInto, fs::OpenOptions, io::{self, Seek, SeekFrom, Write}, os::unix::io::AsRawFd, @@ -28,7 +29,7 @@ fn write_sectors>( ) -> io::Result<()> { let mut f = OpenOptions::new().write(true).open(path)?; - f.seek(SeekFrom::Start(*offset.bytes()))?; + f.seek(SeekFrom::Start((*offset.bytes()).try_into().unwrap()))?; for _ in 0..*length { f.write_all(buf)?; } @@ -59,7 +60,12 @@ impl LoopTestDev { // Wipe one MiB at the start of the device. Devicemapper data may be // left on the device even after a teardown. - wipe_sectors(&ld.path().unwrap(), Sectors(0), Bytes(IEC::Mi).sectors()).unwrap(); + wipe_sectors( + &ld.path().unwrap(), + Sectors(0), + Bytes(u128::from(IEC::Mi)).sectors(), + ) + .unwrap(); LoopTestDev { ld } } diff --git a/src/testing/test_lib.rs b/src/testing/test_lib.rs index 9c6f6e28..4930ccef 100644 --- a/src/testing/test_lib.rs +++ b/src/testing/test_lib.rs @@ -55,7 +55,7 @@ pub fn blkdev_size(file: &File) -> Bytes { let mut val: u64 = 0; unsafe { blkgetsize64(file.as_raw_fd(), &mut val) }.unwrap(); - Bytes(val) + Bytes(u128::from(val)) } fn get_dm() -> &'static DM { diff --git a/src/units.rs b/src/units.rs index 2aa55910..41550027 100644 --- a/src/units.rs +++ b/src/units.rs @@ -19,13 +19,13 @@ const META_BLOCK_SIZE: Sectors = Sectors(8); #[allow(dead_code)] const MAX_META_DEV_SIZE: MetaBlocks = MetaBlocks(255 * ((1 << 14) - 64)); -range!( +range_u64!( /// A type for data blocks DataBlocks, "data blocks" ); -range!( +range_u64!( /// A type for meta blocks MetaBlocks, "meta blocks" @@ -38,7 +38,7 @@ impl MetaBlocks { } } -range!( +range_u128!( /// A type for bytes Bytes, "bytes" @@ -47,11 +47,11 @@ range!( impl Bytes { /// Return the number of Sectors fully contained in these bytes. pub fn sectors(self) -> Sectors { - Sectors(self.0 / SECTOR_SIZE as u64) + Sectors((self.0 / SECTOR_SIZE as u128) as u64) } } -range!( +range_u64!( /// A type for sectors Sectors, "sectors" @@ -60,7 +60,8 @@ range!( impl Sectors { /// The number of bytes in these sectors. pub fn bytes(self) -> Bytes { - Bytes(self.0 * SECTOR_SIZE as u64) + // Keep both as u128 before multiplication or overflow could occur + Bytes(u128::from(self.0) * SECTOR_SIZE as u128) } /// The number of whole metablocks contained in these sectors.