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.
This commit is contained in:
Tobin C. Harding 2022-04-20 09:17:46 +10:00
parent e7a3bdda66
commit 7a3bb7d3ec
3 changed files with 12 additions and 3 deletions

View File

@ -242,7 +242,7 @@ macro_rules! decoder_fn {
($name:ident, $val_type:ty, $readfn:ident, $byte_len: expr) => { ($name:ident, $val_type:ty, $readfn:ident, $byte_len: expr) => {
#[inline] #[inline]
fn $name(&mut self) -> Result<$val_type, Error> { 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]; let mut val = [0; $byte_len];
self.read_exact(&mut val[..]).map_err(Error::Io)?; self.read_exact(&mut val[..]).map_err(Error::Io)?;
Ok(endian::$readfn(&val)) Ok(endian::$readfn(&val))

View File

@ -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] = [];
}
};
}

View File

@ -28,7 +28,7 @@ macro_rules! define_be_to_array {
($name: ident, $type: ty, $byte_len: expr) => { ($name: ident, $type: ty, $byte_len: expr) => {
#[inline] #[inline]
pub fn $name(val: $type) -> [u8; $byte_len] { 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]; let mut res = [0; $byte_len];
for i in 0..$byte_len { for i in 0..$byte_len {
res[i] = ((val >> ($byte_len - i - 1)*8) & 0xff) as u8; 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) => { ($name: ident, $type: ty, $byte_len: expr) => {
#[inline] #[inline]
pub fn $name(val: $type) -> [u8; $byte_len] { 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]; let mut res = [0; $byte_len];
for i in 0..$byte_len { for i in 0..$byte_len {
res[i] = ((val >> i*8) & 0xff) as u8; res[i] = ((val >> i*8) & 0xff) as u8;