mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
91 lines
2.9 KiB
Rust
91 lines
2.9 KiB
Rust
//! Test utilities for `Compact` derive macro
|
|
|
|
/// Macro to ensure that derived `Compact` types can be extended with new fields while maintaining
|
|
/// backwards compatibility.
|
|
///
|
|
/// Verifies that the unused bits in the bitflag struct remain as expected: `Zero` or `NotZero`. For
|
|
/// more on bitflag struct: [`reth_codecs_derive::Compact`].
|
|
///
|
|
/// Possible failures:
|
|
/// ### 1. `NotZero` -> `Zero`
|
|
/// This wouldn't allow new fields to be added in the future. Instead, the new field of `T`
|
|
/// should be `Option<TExtension>` to allow for new fields. The new user field should be included
|
|
/// in `TExtension` type. **Only then, update the test to expect `Zero` for `T` and
|
|
/// add a new test for `TExtension`.**
|
|
///
|
|
/// **Goal:**
|
|
///
|
|
/// ```rust,ignore
|
|
/// {
|
|
/// struct T {
|
|
/// // ... other fields
|
|
/// ext: Option<TExtension>
|
|
/// }
|
|
///
|
|
/// // Use an extension type for new fields:
|
|
/// struct TExtension {
|
|
/// new_field_b: Option<u8>,
|
|
/// }
|
|
///
|
|
/// // Change tests
|
|
/// validate_bitflag_backwards_compat!(T, UnusedBits::Zero);
|
|
/// validate_bitflag_backwards_compat!(TExtension, UnusedBits::NotZero);
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// ### 2. `Zero` -> `NotZero`
|
|
/// If it becomes `NotZero`, it would break backwards compatibility, so there is not an action item,
|
|
/// and should be handled with care in a case by case scenario.
|
|
#[macro_export]
|
|
macro_rules! validate_bitflag_backwards_compat {
|
|
($type:ty, $expected_unused_bits:expr) => {
|
|
let actual_unused_bits = <$type>::bitflag_unused_bits();
|
|
|
|
match $expected_unused_bits {
|
|
UnusedBits::NotZero => {
|
|
assert_ne!(
|
|
actual_unused_bits,
|
|
0,
|
|
"Assertion failed: `bitflag_unused_bits` for type `{}` unexpectedly went from non-zero to zero!",
|
|
stringify!($type)
|
|
);
|
|
}
|
|
UnusedBits::Zero => {
|
|
assert_eq!(
|
|
actual_unused_bits,
|
|
0,
|
|
"Assertion failed: `bitflag_unused_bits` for type `{}` unexpectedly went from zero to non-zero!",
|
|
stringify!($type)
|
|
);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Whether there are zero or more unused bits on `Compact` bitflag struct.
|
|
///
|
|
/// To be used with [`validate_bitflag_backwards_compat`].
|
|
#[derive(Debug)]
|
|
pub enum UnusedBits {
|
|
/// Zero bits available for a new field.
|
|
Zero,
|
|
/// Bits available for a new field.
|
|
NotZero,
|
|
}
|
|
|
|
impl UnusedBits {
|
|
/// Returns true if the variant is [`Self::NotZero`].
|
|
pub const fn not_zero(&self) -> bool {
|
|
matches!(self, Self::NotZero)
|
|
}
|
|
}
|
|
|
|
/// Tests decoding and re-encoding to ensure correctness.
|
|
pub fn test_decode<T: crate::Compact>(buf: &[u8]) {
|
|
let (decoded, _) = T::from_compact(buf, buf.len());
|
|
let mut encoded = Vec::with_capacity(buf.len());
|
|
|
|
decoded.to_compact(&mut encoded);
|
|
assert_eq!(buf, &encoded[..]);
|
|
}
|