From 7a3bb7d3ecaa0ba1ef425a2bb9669b60b8f48059 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 20 Apr 2022 09:17:46 +1000 Subject: [PATCH] Replace runtime size check with compile time check Add a macro `const_assert` that uses some const declaration trickery to trigger a compile time error if a boolean expression is false. Replace runtime checks using `debug_assert_eq!` with the newly defined `const_assert!` macro. --- src/consensus/encode.rs | 2 +- src/internal_macros.rs | 9 +++++++++ src/util/endian.rs | 4 ++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 603d47bf..9e3b2804 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -242,7 +242,7 @@ macro_rules! decoder_fn { ($name:ident, $val_type:ty, $readfn:ident, $byte_len: expr) => { #[inline] fn $name(&mut self) -> Result<$val_type, Error> { - debug_assert_eq!(::core::mem::size_of::<$val_type>(), $byte_len); // size_of isn't a constfn in 1.22 + const_assert!(::core::mem::size_of::<$val_type>() == $byte_len); let mut val = [0; $byte_len]; self.read_exact(&mut val[..]).map_err(Error::Io)?; Ok(endian::$readfn(&val)) diff --git a/src/internal_macros.rs b/src/internal_macros.rs index c0581130..f8e6b160 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -593,3 +593,12 @@ macro_rules! write_err { } } } + +/// Asserts a boolean expression at compile time. +macro_rules! const_assert { + ($x:expr) => { + { + const _: [(); 0 - !$x as usize] = []; + } + }; +} diff --git a/src/util/endian.rs b/src/util/endian.rs index f09a1237..c63a906b 100644 --- a/src/util/endian.rs +++ b/src/util/endian.rs @@ -28,7 +28,7 @@ macro_rules! define_be_to_array { ($name: ident, $type: ty, $byte_len: expr) => { #[inline] pub fn $name(val: $type) -> [u8; $byte_len] { - debug_assert_eq!(::core::mem::size_of::<$type>(), $byte_len); // size_of isn't a constfn in 1.22 + const_assert!(::core::mem::size_of::<$type>() == $byte_len); let mut res = [0; $byte_len]; for i in 0..$byte_len { res[i] = ((val >> ($byte_len - i - 1)*8) & 0xff) as u8; @@ -41,7 +41,7 @@ macro_rules! define_le_to_array { ($name: ident, $type: ty, $byte_len: expr) => { #[inline] pub fn $name(val: $type) -> [u8; $byte_len] { - debug_assert_eq!(::core::mem::size_of::<$type>(), $byte_len); // size_of isn't a constfn in 1.22 + const_assert!(::core::mem::size_of::<$type>() == $byte_len); let mut res = [0; $byte_len]; for i in 0..$byte_len { res[i] = ((val >> i*8) & 0xff) as u8;