#[macro_export]
macro_rules! dyn_newtype_define {
( $(#[$outer:meta])*
$vis:vis $name:ident<$lifetime:lifetime>(Box<$trait:ident>)
) => {
$crate::_dyn_newtype_define_inner!{
$(#[$outer])*
$vis $name<$lifetime>(Box<$trait>)
}
$crate::_dyn_newtype_impl_deref_mut!($name<$lifetime>);
};
( $(#[$outer:meta])*
$vis:vis $name:ident(Box<$trait:ident>)
) => {
$crate::_dyn_newtype_define_inner!{
$(#[$outer])*
$vis $name(Box<$trait>)
}
$crate::_dyn_newtype_impl_deref_mut!($name);
};
( $(#[$outer:meta])*
$vis:vis $name:ident<$lifetime:lifetime>(Arc<$trait:ident>)
) => {
$crate::_dyn_newtype_define_inner!{
$(#[$outer])*
$vis $name<$lifetime>(Arc<$trait>)
}
};
( $(#[$outer:meta])*
$vis:vis $name:ident(Arc<$trait:ident>)
) => {
$crate::_dyn_newtype_define_inner!{
$(#[$outer])*
$vis $name(Arc<$trait>)
}
};
}
#[macro_export]
macro_rules! _dyn_newtype_define_inner {
( $(#[$outer:meta])*
$vis:vis $name:ident($container:ident<$trait:ident>)
) => {
$(#[$outer])*
$vis struct $name { inner: $container<$crate::maybe_add_send_sync!(dyn $trait + 'static)> }
impl std::ops::Deref for $name {
type Target = $crate::maybe_add_send_sync!(dyn $trait + 'static);
fn deref(&self) -> &<Self as std::ops::Deref>::Target {
&*self.inner
}
}
impl $name {
pub fn get_mut(&mut self) -> Option<&mut <Self as std::ops::Deref>::Target> {
Arc::get_mut(&mut self.inner)
}
}
impl<I> From<I> for $name
where
I: $trait + $crate::task::MaybeSend + $crate::task::MaybeSync + 'static,
{
fn from(i: I) -> Self {
Self { inner: $container::new(i) }
}
}
impl std::fmt::Debug for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.inner, f)
}
}
};
( $(#[$outer:meta])*
$vis:vis $name:ident<$lifetime:lifetime>($container:ident<$trait:ident>)
) => {
$(#[$outer])*
$vis struct $name<$lifetime> { inner: $container<dyn $trait<$lifetime> + Send + $lifetime> }
impl<$lifetime> std::ops::Deref for $name<$lifetime> {
type Target = $crate::maybe_add_send!(dyn $trait<$lifetime> + $lifetime);
fn deref(&self) -> &<Self as std::ops::Deref>::Target {
&*self.inner
}
}
impl<$lifetime, I> From<I> for $name<$lifetime>
where
I: $trait<$lifetime> + $crate::task::MaybeSend + $lifetime,
{
fn from(i: I) -> Self {
Self($container::new(i))
}
}
};
}
#[macro_export]
macro_rules! dyn_newtype_display_passthrough {
($newtype:ty) => {
impl std::fmt::Display for $newtype {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.inner, f)
}
}
};
}
#[macro_export]
macro_rules! module_plugin_dyn_newtype_define{
( $(#[$outer:meta])*
$vis:vis $name:ident<$lifetime:lifetime>(Box<$trait:ident>)
) => {
$crate::_dyn_newtype_define_with_instance_id_inner!{
$(#[$outer])*
$vis $name<$lifetime>(Box<$trait>)
}
$crate::_dyn_newtype_impl_deref_mut!($name<$lifetime>);
};
( $(#[$outer:meta])*
$vis:vis $name:ident(Box<$trait:ident>)
) => {
$crate::_dyn_newtype_define_with_instance_id_inner!{
$(#[$outer])*
$vis $name(Box<$trait>)
}
$crate::_dyn_newtype_impl_deref_mut!($name);
};
( $(#[$outer:meta])*
$vis:vis $name:ident<$lifetime:lifetime>(Arc<$trait:ident>)
) => {
$crate::_dyn_newtype_define_with_instance_id_inner!{
$(#[$outer])*
$vis $name<$lifetime>(Arc<$trait>)
}
};
( $(#[$outer:meta])*
$vis:vis $name:ident(Arc<$trait:ident>)
) => {
$crate::_dyn_newtype_define_with_instance_id_inner!{
$(#[$outer])*
$vis $name(Arc<$trait>)
}
};
}
#[macro_export]
macro_rules! _dyn_newtype_define_with_instance_id_inner {
( $(#[$outer:meta])*
$vis:vis $name:ident($container:ident<$trait:ident>)
) => {
$(#[$outer])*
$vis struct $name {
module_instance_id: $crate::core::ModuleInstanceId,
inner: $container<$crate::maybe_add_send_sync!(dyn $trait + 'static)>,
}
impl std::ops::Deref for $name {
type Target = $crate::maybe_add_send_sync!(dyn $trait + 'static);
fn deref(&self) -> &<Self as std::ops::Deref>::Target {
&*self.inner
}
}
impl $name {
pub fn module_instance_id(&self) -> ::fedimint_core::core::ModuleInstanceId {
self.module_instance_id
}
pub fn from_typed<I>(
module_instance_id: ::fedimint_core::core::ModuleInstanceId,
typed: I
) -> Self
where
I: $trait + $crate::task::MaybeSend + $crate::task::MaybeSync + 'static {
Self { inner: $container::new(typed), module_instance_id }
}
pub fn from_parts(
module_instance_id: $crate::core::ModuleInstanceId,
dynbox: $container<$crate::maybe_add_send_sync!(dyn $trait + 'static)>
) -> Self {
Self { inner: dynbox, module_instance_id }
}
}
impl std::fmt::Debug for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(stringify!($name))
.field("id", &self.module_instance_id)
.field("kind", &self.module_kind())
.field("inner", &self.inner)
.finish()
}
}
};
( $(#[$outer:meta])*
$vis:vis $name:ident<$lifetime:lifetime>($container:ident<$trait:ident>)
) => {
$(#[$outer])*
$vis struct $name<$lifetime>{ inner: $container<dyn $trait<$lifetime> + Send + $lifetime>, module_instance_id: ModuleInstanceId }
impl $name {
pub fn module_instance_id(&self) -> ::fedimint_core::core::ModuleInstanceId {
self.1
}
pub fn from_typed<I>(module_instance_id: ::fedimint_core::core::ModuleInstanceId, typed: I) -> Self
where
I: $trait + $crate::task::MaybeSend + $crate::task::MaybeSync + 'static {
Self { inner: $container::new(typed), module_instance_id }
}
}
impl<$lifetime> std::ops::Deref for $name<$lifetime> {
type Target = $crate::maybe_add_send_sync!(dyn $trait + 'static);
fn deref(&self) -> &<Self as std::ops::Deref>::Target {
&*self.inner
}
}
};
}
#[macro_export]
macro_rules! _dyn_newtype_impl_deref_mut {
($name:ident<$lifetime:lifetime>) => {
impl<$lifetime> std::ops::DerefMut for $name<$lifetime> {
fn deref_mut(&mut self) -> &mut <Self as std::ops::Deref>::Target {
&mut *self.inner
}
}
};
($name:ident) => {
impl std::ops::DerefMut for $name {
fn deref_mut(&mut self) -> &mut <Self as std::ops::Deref>::Target {
&mut *self.inner
}
}
};
}
#[macro_export]
macro_rules! dyn_newtype_impl_dyn_clone_passthrough {
($name:ident) => {
impl Clone for $name {
fn clone(&self) -> Self {
self.0.clone()
}
}
};
}
#[macro_export]
macro_rules! module_plugin_dyn_newtype_clone_passthrough {
($name:ident) => {
impl Clone for $name {
fn clone(&self) -> Self {
self.inner.clone(self.module_instance_id)
}
}
};
}
#[macro_export]
macro_rules! module_plugin_dyn_newtype_encode_decode {
($name:ident) => {
impl Encodable for $name {
fn consensus_encode<W: std::io::Write>(
&self,
writer: &mut W,
) -> Result<usize, std::io::Error> {
let mut written = self.module_instance_id.consensus_encode(writer)?;
let mut buf = Vec::with_capacity(512);
let buf_written = self.inner.consensus_encode_dyn(&mut buf)?;
assert_eq!(buf.len(), buf_written);
written += buf.consensus_encode(writer)?;
Ok(written)
}
}
impl Decodable for $name {
fn consensus_decode_from_finite_reader<R: std::io::Read>(
reader: &mut R,
decoders: &$crate::module::registry::ModuleDecoderRegistry,
) -> Result<Self, fedimint_core::encoding::DecodeError> {
let module_instance_id =
fedimint_core::core::ModuleInstanceId::consensus_decode_from_finite_reader(
reader, decoders,
)?;
let val = match decoders.get(module_instance_id) {
Some(decoder) => {
let total_len_u64 =
u64::consensus_decode_from_finite_reader(reader, decoders)?;
decoder.decode_complete(
reader,
total_len_u64,
module_instance_id,
decoders,
)?
}
None => match decoders.decoding_mode() {
$crate::module::registry::DecodingMode::Reject => {
return Err(fedimint_core::encoding::DecodeError::new_custom(
anyhow::anyhow!(
"Module decoder not available: {module_instance_id} when decoding {}", std::any::type_name::<Self>()
),
));
}
$crate::module::registry::DecodingMode::Fallback => $name::from_typed(
module_instance_id,
$crate::core::DynUnknown(
Vec::<u8>::consensus_decode_from_finite_reader(
reader,
&Default::default(),
)?,
),
),
},
};
Ok(val)
}
}
};
}
#[macro_export]
macro_rules! module_plugin_static_trait_define{
( $(#[$outer:meta])*
$dyn_newtype:ident, $static_trait:ident, $dyn_trait:ident, { $($extra_methods:tt)* }, { $($extra_impls:tt)* }
) => {
pub trait $static_trait:
std::fmt::Debug + std::fmt::Display + std::cmp::PartialEq + std::hash::Hash + DynEncodable + Decodable + Encodable + Clone + IntoDynInstance<DynType = $dyn_newtype> + Send + Sync + 'static
{
const KIND : ModuleKind;
$($extra_methods)*
}
impl $dyn_trait for ::fedimint_core::core::DynUnknown {
fn as_any(&self) -> &(dyn Any + Send + Sync) {
self
}
fn module_kind(&self) -> Option<ModuleKind> {
None
}
fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
$dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
}
fn dyn_hash(&self) -> u64 {
use std::hash::Hash;
let mut s = std::collections::hash_map::DefaultHasher::new();
self.hash(&mut s);
std::hash::Hasher::finish(&s)
}
$($extra_impls)*
}
impl<T> $dyn_trait for T
where
T: $static_trait + DynEncodable + 'static + Send + Sync,
{
fn as_any(&self) -> &(dyn Any + Send + Sync) {
self
}
fn module_kind(&self) -> Option<ModuleKind> {
Some(<Self as $static_trait>::KIND)
}
fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
$dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
}
fn dyn_hash(&self) -> u64 {
let mut s = std::collections::hash_map::DefaultHasher::new();
self.hash(&mut s);
std::hash::Hasher::finish(&s)
}
$($extra_impls)*
}
impl std::hash::Hash for $dyn_newtype {
fn hash<H>(&self, state: &mut H)
where
H: std::hash::Hasher
{
self.module_instance_id.hash(state);
self.inner.dyn_hash().hash(state);
}
}
};
}
#[macro_export]
macro_rules! module_plugin_static_trait_define_config{
( $(#[$outer:meta])*
$dyn_newtype:ident, $static_trait:ident, $dyn_trait:ident, { $($extra_methods:tt)* }, { $($extra_impls:tt)* }, { $($extra_impls_unknown:tt)* }
) => {
pub trait $static_trait:
std::fmt::Debug + std::fmt::Display + std::cmp::PartialEq + std::hash::Hash + DynEncodable + Decodable + Encodable + Clone + IntoDynInstance<DynType = $dyn_newtype> + Send + Sync + serde::Serialize + serde::de::DeserializeOwned + 'static
{
const KIND : ::fedimint_core::core::ModuleKind;
$($extra_methods)*
}
impl $dyn_trait for ::fedimint_core::core::DynUnknown {
fn as_any(&self) -> &(dyn Any + Send + Sync) {
self
}
fn module_kind(&self) -> Option<::fedimint_core::core::ModuleKind> {
None
}
fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
$dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
}
fn dyn_hash(&self) -> u64 {
use std::hash::Hash;
let mut s = std::collections::hash_map::DefaultHasher::new();
self.hash(&mut s);
std::hash::Hasher::finish(&s)
}
$($extra_impls_unknown)*
}
impl<T> $dyn_trait for T
where
T: $static_trait + DynEncodable + 'static + Send + Sync,
{
fn as_any(&self) -> &(dyn Any + Send + Sync) {
self
}
fn module_kind(&self) -> Option<::fedimint_core::core::ModuleKind> {
Some(<T as $static_trait>::KIND)
}
fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
$dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
}
fn dyn_hash(&self) -> u64 {
let mut s = std::collections::hash_map::DefaultHasher::new();
self.hash(&mut s);
std::hash::Hasher::finish(&s)
}
$($extra_impls)*
}
impl std::hash::Hash for $dyn_newtype {
fn hash<H>(&self, state: &mut H)
where
H: std::hash::Hasher
{
self.module_instance_id.hash(state);
self.inner.dyn_hash().hash(state);
}
}
};
}
#[macro_export]
macro_rules! plugin_types_trait_impl_config {
($common_gen:ty, $gen:ty, $gen_local:ty, $gen_consensus:ty, $cfg:ty, $cfg_local:ty, $cfg_private:ty, $cfg_consensus:ty, $cfg_client:ty) => {
impl fedimint_core::config::ModuleInitParams for $gen {
type Local = $gen_local;
type Consensus = $gen_consensus;
fn from_parts(local: Self::Local, consensus: Self::Consensus) -> Self {
Self { local, consensus }
}
fn to_parts(self) -> (Self::Local, Self::Consensus) {
(self.local, self.consensus)
}
}
impl fedimint_core::config::TypedServerModuleConsensusConfig for $cfg_consensus {
fn kind(&self) -> fedimint_core::core::ModuleKind {
<$common_gen as fedimint_core::module::CommonModuleInit>::KIND
}
fn version(&self) -> fedimint_core::module::ModuleConsensusVersion {
<$common_gen as fedimint_core::module::CommonModuleInit>::CONSENSUS_VERSION
}
}
impl fedimint_core::config::TypedServerModuleConfig for $cfg {
type Local = $cfg_local;
type Private = $cfg_private;
type Consensus = $cfg_consensus;
fn from_parts(
local: Self::Local,
private: Self::Private,
consensus: Self::Consensus,
) -> Self {
Self {
local,
private,
consensus,
}
}
fn to_parts(self) -> (ModuleKind, Self::Local, Self::Private, Self::Consensus) {
(
<$common_gen as fedimint_core::module::CommonModuleInit>::KIND,
self.local,
self.private,
self.consensus,
)
}
}
};
}
#[macro_export]
macro_rules! plugin_types_trait_impl_common {
($kind:expr, $types:ty, $client_config:ty, $input:ty, $output:ty, $outcome:ty, $ci:ty, $input_error:ty, $output_error:ty) => {
impl fedimint_core::module::ModuleCommon for $types {
type ClientConfig = $client_config;
type Input = $input;
type Output = $output;
type OutputOutcome = $outcome;
type ConsensusItem = $ci;
type InputError = $input_error;
type OutputError = $output_error;
}
impl fedimint_core::core::ClientConfig for $client_config {
const KIND: ModuleKind = $kind;
}
impl fedimint_core::core::IntoDynInstance for $client_config {
type DynType = fedimint_core::core::DynClientConfig;
fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
fedimint_core::core::DynClientConfig::from_typed(instance_id, self)
}
}
impl fedimint_core::core::Input for $input {
const KIND: ModuleKind = $kind;
}
impl fedimint_core::core::IntoDynInstance for $input {
type DynType = fedimint_core::core::DynInput;
fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
fedimint_core::core::DynInput::from_typed(instance_id, self)
}
}
impl fedimint_core::core::Output for $output {
const KIND: ModuleKind = $kind;
}
impl fedimint_core::core::IntoDynInstance for $output {
type DynType = fedimint_core::core::DynOutput;
fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
fedimint_core::core::DynOutput::from_typed(instance_id, self)
}
}
impl fedimint_core::core::OutputOutcome for $outcome {
const KIND: ModuleKind = $kind;
}
impl fedimint_core::core::IntoDynInstance for $outcome {
type DynType = fedimint_core::core::DynOutputOutcome;
fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
fedimint_core::core::DynOutputOutcome::from_typed(instance_id, self)
}
}
impl fedimint_core::core::ModuleConsensusItem for $ci {
const KIND: ModuleKind = $kind;
}
impl fedimint_core::core::IntoDynInstance for $ci {
type DynType = fedimint_core::core::DynModuleConsensusItem;
fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
fedimint_core::core::DynModuleConsensusItem::from_typed(instance_id, self)
}
}
impl fedimint_core::core::InputError for $input_error {
const KIND: ModuleKind = $kind;
}
impl fedimint_core::core::IntoDynInstance for $input_error {
type DynType = fedimint_core::core::DynInputError;
fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
fedimint_core::core::DynInputError::from_typed(instance_id, self)
}
}
impl fedimint_core::core::OutputError for $output_error {
const KIND: ModuleKind = $kind;
}
impl fedimint_core::core::IntoDynInstance for $output_error {
type DynType = fedimint_core::core::DynOutputError;
fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
fedimint_core::core::DynOutputError::from_typed(instance_id, self)
}
}
};
}
#[macro_export]
macro_rules! erased_eq_no_instance_id {
($newtype:ty) => {
fn erased_eq_no_instance_id(&self, other: &$newtype) -> bool {
let other: &Self = other
.as_any()
.downcast_ref()
.expect("Type is ensured in previous step");
self == other
}
};
}
#[macro_export]
macro_rules! module_plugin_dyn_newtype_eq_passthrough {
($newtype:ty) => {
impl PartialEq for $newtype {
fn eq(&self, other: &Self) -> bool {
if self.module_instance_id != other.module_instance_id {
return false;
}
self.erased_eq_no_instance_id(other)
}
}
impl Eq for $newtype {}
};
}
#[macro_export]
macro_rules! module_plugin_dyn_newtype_display_passthrough {
($newtype:ty) => {
impl std::fmt::Display for $newtype {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}-{}", self.module_instance_id, self.inner))
}
}
};
}
#[macro_export]
macro_rules! extensible_associated_module_type {
($name:ident, $name_v0:ident, $error:ident) => {
#[derive(
Debug,
Clone,
Eq,
PartialEq,
Hash,
serde::Deserialize,
serde::Serialize,
fedimint_core::encoding::Encodable,
fedimint_core::encoding::Decodable,
)]
pub enum $name {
V0($name_v0),
#[encodable_default]
Default {
variant: u64,
bytes: Vec<u8>,
},
}
impl $name {
pub fn maybe_v0_ref(&self) -> Option<&$name_v0> {
match self {
$name::V0(v0) => Some(v0),
$name::Default { .. } => None,
}
}
pub fn ensure_v0_ref(&self) -> Result<&$name_v0, $error> {
match self {
$name::V0(v0) => Ok(v0),
$name::Default { variant, .. } => Err($error { variant: *variant }),
}
}
}
#[derive(
Debug,
thiserror::Error,
Clone,
Eq,
PartialEq,
Hash,
serde::Deserialize,
serde::Serialize,
fedimint_core::encoding::Encodable,
fedimint_core::encoding::Decodable,
)]
#[error("Unknown {} variant {variant}", stringify!($name))]
pub struct $error {
pub variant: u64,
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
$name::V0(inner) => std::fmt::Display::fmt(inner, f),
$name::Default { variant, .. } => {
write!(f, "Unknown {} (variant={variant})", stringify!($name))
}
}
}
}
};
}