From 038a2db53ce7fe81aabc41a44787f313c08b6d5d Mon Sep 17 00:00:00 2001 From: Omar Abdulla Date: Thu, 17 Jul 2025 14:22:18 +0300 Subject: [PATCH] Add support for wrapper types --- crates/core/src/common.rs | 96 +++++++++++++++++++++++++++++++++++++++ crates/core/src/lib.rs | 3 +- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 crates/core/src/common.rs diff --git a/crates/core/src/common.rs b/crates/core/src/common.rs new file mode 100644 index 0000000..3a6d260 --- /dev/null +++ b/crates/core/src/common.rs @@ -0,0 +1,96 @@ +/// Defines wrappers around types. +/// +/// For example, the macro invocation seen below: +/// +/// ```rust,no_run +/// define_wrapper_type!(CaseId => usize); +/// ``` +/// +/// Would define a wrapper type that looks like the following: +/// +/// ```rust,no_run +/// pub struct CaseId(usize); +/// ``` +/// +/// And would also implement a number of methods on this type making it easier +/// to use. +/// +/// These wrapper types become very useful as they make the code a lot easier +/// to read. +/// +/// Take the following as an example: +/// +/// ```rust,no_run +/// struct State { +/// contracts: HashMap>> +/// } +/// ``` +/// +/// In the above code it's hard to understand what the various types refer to or +/// what to expect them to contain. +/// +/// With these wrapper types we're able to create code that's self-documenting +/// in that the types tell us what the code is referring to. The above code is +/// transformed into +/// +/// ```rust,no_run +/// struct State { +/// contracts: HashMap> +/// } +/// ``` +#[macro_export] +macro_rules! define_wrapper_type { + ( + $(#[$meta: meta])* + $ident: ident => $ty: ty + ) => { + $(#[$meta])* + pub struct $ident($ty); + + impl $ident { + pub fn new(value: $ty) -> Self { + Self(value) + } + + pub fn into_inner(self) -> $ty { + self.0 + } + + pub fn as_inner(&self) -> &$ty { + &self.0 + } + } + + impl AsRef<$ty> for $ident { + fn as_ref(&self) -> &$ty { + &self.0 + } + } + + impl AsMut<$ty> for $ident { + fn as_mut(&mut self) -> &mut $ty { + &mut self.0 + } + } + + impl std::ops::Deref for $ident { + type Target = $ty; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl std::ops::DerefMut for $ident { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + }; +} + +define_wrapper_type!( + /// Represents the ID of one of the cases in a metadata file. + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + CaseId => usize +); diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index 52b8b37..e9bcdd1 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -1,13 +1,14 @@ //! The revive differential testing core library. //! //! This crate defines the testing configuration and -//! provides a helper utilty to execute tests. +//! provides a helper utility to execute tests. use revive_dt_compiler::{SolidityCompiler, revive_resolc, solc}; use revive_dt_config::TestingPlatform; use revive_dt_node::{geth, kitchensink::KitchensinkNode}; use revive_dt_node_interaction::EthereumNode; +pub mod common; pub mod driver; /// One platform can be tested differentially against another.