1#[macro_export]
10macro_rules! dyn_newtype_define {
11 ( $(#[$outer:meta])*
12 $vis:vis $name:ident<$lifetime:lifetime>(Box<$trait:ident>)
13 ) => {
14 $crate::_dyn_newtype_define_inner!{
15 $(#[$outer])*
16 $vis $name<$lifetime>(Box<$trait>)
17 }
18 $crate::_dyn_newtype_impl_deref_mut!($name<$lifetime>);
19 };
20 ( $(#[$outer:meta])*
21 $vis:vis $name:ident(Box<$trait:ident>)
22 ) => {
23 $crate::_dyn_newtype_define_inner!{
24 $(#[$outer])*
25 $vis $name(Box<$trait>)
26 }
27 $crate::_dyn_newtype_impl_deref_mut!($name);
28 };
29 ( $(#[$outer:meta])*
30 $vis:vis $name:ident<$lifetime:lifetime>(Arc<$trait:ident>)
31 ) => {
32 $crate::_dyn_newtype_define_inner!{
33 $(#[$outer])*
34 $vis $name<$lifetime>(Arc<$trait>)
35 }
36 };
37 ( $(#[$outer:meta])*
38 $vis:vis $name:ident(Arc<$trait:ident>)
39 ) => {
40 $crate::_dyn_newtype_define_inner!{
41 $(#[$outer])*
42 $vis $name(Arc<$trait>)
43 }
44 };
45}
46
47#[macro_export]
48macro_rules! _dyn_newtype_define_inner {
49 ( $(#[$outer:meta])*
50 $vis:vis $name:ident($container:ident<$trait:ident>)
51 ) => {
52 $(#[$outer])*
53 $vis struct $name { inner: $container<$crate::maybe_add_send_sync!(dyn $trait + 'static)> }
54
55 impl std::ops::Deref for $name {
56 type Target = $crate::maybe_add_send_sync!(dyn $trait + 'static);
57
58 fn deref(&self) -> &<Self as std::ops::Deref>::Target {
59 &*self.inner
60 }
61
62 }
63
64 impl $name {
65 pub fn get_mut(&mut self) -> Option<&mut <Self as std::ops::Deref>::Target> {
66 Arc::get_mut(&mut self.inner)
67 }
68 }
69
70 impl<I> From<I> for $name
71 where
72 I: $trait + $crate::task::MaybeSend + $crate::task::MaybeSync + 'static,
73 {
74 fn from(i: I) -> Self {
75 Self { inner: $container::new(i) }
76 }
77 }
78
79 impl std::fmt::Debug for $name {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 std::fmt::Debug::fmt(&self.inner, f)
82 }
83 }
84 };
85 ( $(#[$outer:meta])*
86 $vis:vis $name:ident<$lifetime:lifetime>($container:ident<$trait:ident>)
87 ) => {
88 $(#[$outer])*
89 $vis struct $name<$lifetime> { inner: $container<dyn $trait<$lifetime> + Send + $lifetime> }
90
91 impl<$lifetime> std::ops::Deref for $name<$lifetime> {
92 type Target = $crate::maybe_add_send!(dyn $trait<$lifetime> + $lifetime);
93
94 fn deref(&self) -> &<Self as std::ops::Deref>::Target {
95 &*self.inner
96 }
97 }
98
99 impl<$lifetime, I> From<I> for $name<$lifetime>
100 where
101 I: $trait<$lifetime> + $crate::task::MaybeSend + $lifetime,
102 {
103 fn from(i: I) -> Self {
104 Self($container::new(i))
105 }
106 }
107 };
108}
109
110#[macro_export]
113macro_rules! dyn_newtype_display_passthrough {
114 ($newtype:ty) => {
115 impl std::fmt::Display for $newtype {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 std::fmt::Display::fmt(&self.inner, f)
118 }
119 }
120 };
121}
122
123#[macro_export]
126macro_rules! module_plugin_dyn_newtype_define{
127 ( $(#[$outer:meta])*
128 $vis:vis $name:ident<$lifetime:lifetime>(Box<$trait:ident>)
129 ) => {
130 $crate::_dyn_newtype_define_with_instance_id_inner!{
131 $(#[$outer])*
132 $vis $name<$lifetime>(Box<$trait>)
133 }
134 $crate::_dyn_newtype_impl_deref_mut!($name<$lifetime>);
135 };
136 ( $(#[$outer:meta])*
137 $vis:vis $name:ident(Box<$trait:ident>)
138 ) => {
139 $crate::_dyn_newtype_define_with_instance_id_inner!{
140 $(#[$outer])*
141 $vis $name(Box<$trait>)
142 }
143 $crate::_dyn_newtype_impl_deref_mut!($name);
144 };
145 ( $(#[$outer:meta])*
146 $vis:vis $name:ident<$lifetime:lifetime>(Arc<$trait:ident>)
147 ) => {
148 $crate::_dyn_newtype_define_with_instance_id_inner!{
149 $(#[$outer])*
150 $vis $name<$lifetime>(Arc<$trait>)
151 }
152 };
153 ( $(#[$outer:meta])*
154 $vis:vis $name:ident(Arc<$trait:ident>)
155 ) => {
156 $crate::_dyn_newtype_define_with_instance_id_inner!{
157 $(#[$outer])*
158 $vis $name(Arc<$trait>)
159 }
160 };
161}
162
163#[macro_export]
164macro_rules! _dyn_newtype_define_with_instance_id_inner {
165 ( $(#[$outer:meta])*
166 $vis:vis $name:ident($container:ident<$trait:ident>)
167 ) => {
168 $(#[$outer])*
169 $vis struct $name {
170 module_instance_id: $crate::core::ModuleInstanceId,
171 inner: $container<$crate::maybe_add_send_sync!(dyn $trait + 'static)>,
172 }
173
174 impl std::ops::Deref for $name {
175 type Target = $crate::maybe_add_send_sync!(dyn $trait + 'static);
176
177 fn deref(&self) -> &<Self as std::ops::Deref>::Target {
178 &*self.inner
179 }
180
181 }
182
183 impl $name {
184 pub fn module_instance_id(&self) -> ::fedimint_core::core::ModuleInstanceId {
185 self.module_instance_id
186 }
187
188 pub fn from_typed<I>(
189 module_instance_id: ::fedimint_core::core::ModuleInstanceId,
190 typed: I
191 ) -> Self
192 where
193 I: $trait + $crate::task::MaybeSend + $crate::task::MaybeSync + 'static {
194
195 Self { inner: $container::new(typed), module_instance_id }
196 }
197
198 pub fn from_parts(
199 module_instance_id: $crate::core::ModuleInstanceId,
200 dynbox: $container<$crate::maybe_add_send_sync!(dyn $trait + 'static)>
201 ) -> Self {
202 Self { inner: dynbox, module_instance_id }
203 }
204 }
205
206 impl std::fmt::Debug for $name {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 let mut d = f.debug_struct(stringify!($name));
209 d.field("id", &self.module_instance_id);
210 if let Some(kind) = self.module_kind() {
211 d.field("kind", &kind);
212 } else {
213 d.field("kind", &"?");
214
215 }
216 d
217 .field("inner", &self.inner)
218 .finish()
219 }
220 }
221 };
222 ( $(#[$outer:meta])*
223 $vis:vis $name:ident<$lifetime:lifetime>($container:ident<$trait:ident>)
224 ) => {
225 $(#[$outer])*
226 $vis struct $name<$lifetime>{ inner: $container<dyn $trait<$lifetime> + Send + $lifetime>, module_instance_id: ModuleInstanceId }
227
228 impl $name {
229 pub fn module_instance_id(&self) -> ::fedimint_core::core::ModuleInstanceId {
230 self.1
231 }
232
233 pub fn from_typed<I>(module_instance_id: ::fedimint_core::core::ModuleInstanceId, typed: I) -> Self
234 where
235 I: $trait + $crate::task::MaybeSend + $crate::task::MaybeSync + 'static {
236
237 Self { inner: $container::new(typed), module_instance_id }
238 }
239 }
240
241 impl<$lifetime> std::ops::Deref for $name<$lifetime> {
242 type Target = $crate::maybe_add_send_sync!(dyn $trait + 'static);
243
244 fn deref(&self) -> &<Self as std::ops::Deref>::Target {
245 &*self.inner
246 }
247 }
248 };
249}
250
251#[macro_export]
252macro_rules! _dyn_newtype_impl_deref_mut {
253 ($name:ident<$lifetime:lifetime>) => {
254 impl<$lifetime> std::ops::DerefMut for $name<$lifetime> {
255 fn deref_mut(&mut self) -> &mut <Self as std::ops::Deref>::Target {
256 &mut *self.inner
257 }
258 }
259 };
260 ($name:ident) => {
261 impl std::ops::DerefMut for $name {
262 fn deref_mut(&mut self) -> &mut <Self as std::ops::Deref>::Target {
263 &mut *self.inner
264 }
265 }
266 };
267}
268
269#[macro_export]
284macro_rules! dyn_newtype_impl_dyn_clone_passthrough {
285 ($name:ident) => {
286 impl Clone for $name {
287 fn clone(&self) -> Self {
288 self.0.clone()
289 }
290 }
291 };
292}
293
294#[macro_export]
295macro_rules! module_plugin_dyn_newtype_clone_passthrough {
296 ($name:ident) => {
297 impl Clone for $name {
298 fn clone(&self) -> Self {
299 self.inner.clone(self.module_instance_id)
300 }
301 }
302 };
303}
304
305#[macro_export]
310macro_rules! module_plugin_dyn_newtype_encode_decode {
311 ($name:ident) => {
312 impl Encodable for $name {
313 fn consensus_encode<W: std::io::Write>(
314 &self,
315 writer: &mut W,
316 ) -> Result<usize, std::io::Error> {
317 let mut written = self.module_instance_id.consensus_encode(writer)?;
318
319 let mut buf = Vec::with_capacity(512);
320 let buf_written = self.inner.consensus_encode_dyn(&mut buf)?;
321 assert_eq!(buf.len(), buf_written);
322
323 written += buf.consensus_encode(writer)?;
324
325 Ok(written)
326 }
327 }
328
329 impl Decodable for $name {
330 fn consensus_decode_partial_from_finite_reader<R: std::io::Read>(
331 reader: &mut R,
332 decoders: &$crate::module::registry::ModuleDecoderRegistry,
333 ) -> Result<Self, fedimint_core::encoding::DecodeError> {
334 let module_instance_id =
335 fedimint_core::core::ModuleInstanceId::consensus_decode_partial_from_finite_reader(
336 reader, decoders,
337 )?;
338 let val = match decoders.get(module_instance_id) {
339 Some(decoder) => {
340 let total_len_u64 =
341 u64::consensus_decode_partial_from_finite_reader(reader, decoders)?;
342 decoder.decode_complete(
343 reader,
344 total_len_u64,
345 module_instance_id,
346 decoders,
347 )?
348 }
349 None => match decoders.decoding_mode() {
350 $crate::module::registry::DecodingMode::Reject => {
351 return Err(fedimint_core::encoding::DecodeError::new_custom(
352 anyhow::anyhow!(
353 "Module decoder not available for module instance: {module_instance_id} when decoding {}", std::any::type_name::<Self>()
354 ),
355 ));
356 }
357 $crate::module::registry::DecodingMode::Fallback => $name::from_typed(
358 module_instance_id,
359 $crate::core::DynUnknown(
360 Vec::<u8>::consensus_decode_partial_from_finite_reader(
361 reader,
362 &Default::default(),
363 )?,
364 ),
365 ),
366 },
367 };
368
369 Ok(val)
370 }
371 }
372 };
373}
374
375#[macro_export]
386macro_rules! module_plugin_static_trait_define{
387 ( $(#[$outer:meta])*
388 $dyn_newtype:ident, $static_trait:ident, $dyn_trait:ident, { $($extra_methods:tt)* }, { $($extra_impls:tt)* }
389 ) => {
390 pub trait $static_trait:
391 std::fmt::Debug + std::fmt::Display + std::cmp::PartialEq + std::hash::Hash + DynEncodable + Decodable + Encodable + Clone + IntoDynInstance<DynType = $dyn_newtype> + Send + Sync + 'static
392 {
393 const KIND : ModuleKind;
394
395 $($extra_methods)*
396 }
397
398 impl $dyn_trait for ::fedimint_core::core::DynUnknown {
399 fn as_any(&self) -> &(dyn Any + Send + Sync) {
400 self
401 }
402
403 fn module_kind(&self) -> Option<ModuleKind> {
404 None
405 }
406
407 fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
408 $dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
409 }
410
411 fn dyn_hash(&self) -> u64 {
412 use std::hash::Hash;
413 let mut s = std::collections::hash_map::DefaultHasher::new();
414 self.hash(&mut s);
415 std::hash::Hasher::finish(&s)
416 }
417
418 $($extra_impls)*
419 }
420
421 impl<T> $dyn_trait for T
422 where
423 T: $static_trait + DynEncodable + 'static + Send + Sync,
424 {
425 fn as_any(&self) -> &(dyn Any + Send + Sync) {
426 self
427 }
428
429 fn module_kind(&self) -> Option<ModuleKind> {
430 Some(<Self as $static_trait>::KIND)
431 }
432
433 fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
434 $dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
435 }
436
437 fn dyn_hash(&self) -> u64 {
438 let mut s = std::collections::hash_map::DefaultHasher::new();
439 self.hash(&mut s);
440 std::hash::Hasher::finish(&s)
441 }
442
443 $($extra_impls)*
444 }
445
446 impl std::hash::Hash for $dyn_newtype {
447 fn hash<H>(&self, state: &mut H)
448 where
449 H: std::hash::Hasher
450 {
451 self.module_instance_id.hash(state);
452 self.inner.dyn_hash().hash(state);
453 }
454 }
455 };
456}
457
458#[macro_export]
464macro_rules! module_plugin_static_trait_define_config{
465 ( $(#[$outer:meta])*
466 $dyn_newtype:ident, $static_trait:ident, $dyn_trait:ident, { $($extra_methods:tt)* }, { $($extra_impls:tt)* }, { $($extra_impls_unknown:tt)* }
467 ) => {
468 pub trait $static_trait:
469 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
470 {
471 const KIND : ::fedimint_core::core::ModuleKind;
472 $($extra_methods)*
473 }
474
475 impl $dyn_trait for ::fedimint_core::core::DynUnknown {
476 fn as_any(&self) -> &(dyn Any + Send + Sync) {
477 self
478 }
479
480 fn module_kind(&self) -> Option<::fedimint_core::core::ModuleKind> {
481 None
482 }
483
484 fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
485 $dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
486 }
487
488 fn dyn_hash(&self) -> u64 {
489 use std::hash::Hash;
490 let mut s = std::collections::hash_map::DefaultHasher::new();
491 self.hash(&mut s);
492 std::hash::Hasher::finish(&s)
493 }
494
495 $($extra_impls_unknown)*
496 }
497
498 impl<T> $dyn_trait for T
499 where
500 T: $static_trait + DynEncodable + 'static + Send + Sync,
501 {
502 fn as_any(&self) -> &(dyn Any + Send + Sync) {
503 self
504 }
505
506 fn module_kind(&self) -> Option<::fedimint_core::core::ModuleKind> {
507 Some(<T as $static_trait>::KIND)
508 }
509
510 fn clone(&self, instance_id: ::fedimint_core::core::ModuleInstanceId) -> $dyn_newtype {
511 $dyn_newtype::from_typed(instance_id, <Self as Clone>::clone(self))
512 }
513
514 fn dyn_hash(&self) -> u64 {
515 let mut s = std::collections::hash_map::DefaultHasher::new();
516 self.hash(&mut s);
517 std::hash::Hasher::finish(&s)
518 }
519
520 $($extra_impls)*
521 }
522
523 impl std::hash::Hash for $dyn_newtype {
524 fn hash<H>(&self, state: &mut H)
525 where
526 H: std::hash::Hasher
527 {
528 self.module_instance_id.hash(state);
529 self.inner.dyn_hash().hash(state);
530 }
531 }
532 };
533}
534
535#[macro_export]
538macro_rules! plugin_types_trait_impl_config {
539 ($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) => {
540 impl fedimint_core::config::ModuleInitParams for $gen {
541 type Local = $gen_local;
542 type Consensus = $gen_consensus;
543
544 fn from_parts(local: Self::Local, consensus: Self::Consensus) -> Self {
545 Self { local, consensus }
546 }
547
548 fn to_parts(self) -> (Self::Local, Self::Consensus) {
549 (self.local, self.consensus)
550 }
551 }
552
553 impl fedimint_core::config::TypedServerModuleConsensusConfig for $cfg_consensus {
554 fn kind(&self) -> fedimint_core::core::ModuleKind {
555 <$common_gen as fedimint_core::module::CommonModuleInit>::KIND
556 }
557
558 fn version(&self) -> fedimint_core::module::ModuleConsensusVersion {
559 <$common_gen as fedimint_core::module::CommonModuleInit>::CONSENSUS_VERSION
560 }
561 }
562
563 impl fedimint_core::config::TypedServerModuleConfig for $cfg {
564 type Local = $cfg_local;
565 type Private = $cfg_private;
566 type Consensus = $cfg_consensus;
567
568 fn from_parts(
569 local: Self::Local,
570 private: Self::Private,
571 consensus: Self::Consensus,
572 ) -> Self {
573 Self {
574 local,
575 private,
576 consensus,
577 }
578 }
579
580 fn to_parts(self) -> (ModuleKind, Self::Local, Self::Private, Self::Consensus) {
581 (
582 <$common_gen as fedimint_core::module::CommonModuleInit>::KIND,
583 self.local,
584 self.private,
585 self.consensus,
586 )
587 }
588 }
589 };
590}
591
592#[macro_export]
595macro_rules! plugin_types_trait_impl_common {
596 ($kind:expr, $types:ty, $client_config:ty, $input:ty, $output:ty, $outcome:ty, $ci:ty, $input_error:ty, $output_error:ty) => {
597 impl fedimint_core::module::ModuleCommon for $types {
598 type ClientConfig = $client_config;
599 type Input = $input;
600 type Output = $output;
601 type OutputOutcome = $outcome;
602 type ConsensusItem = $ci;
603 type InputError = $input_error;
604 type OutputError = $output_error;
605 }
606
607 impl fedimint_core::core::ClientConfig for $client_config {
608 const KIND: ModuleKind = $kind;
609 }
610
611 impl fedimint_core::core::IntoDynInstance for $client_config {
612 type DynType = fedimint_core::core::DynClientConfig;
613
614 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
615 fedimint_core::core::DynClientConfig::from_typed(instance_id, self)
616 }
617 }
618
619 impl fedimint_core::core::Input for $input {
620 const KIND: ModuleKind = $kind;
621 }
622
623 impl fedimint_core::core::IntoDynInstance for $input {
624 type DynType = fedimint_core::core::DynInput;
625
626 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
627 fedimint_core::core::DynInput::from_typed(instance_id, self)
628 }
629 }
630
631 impl fedimint_core::core::Output for $output {
632 const KIND: ModuleKind = $kind;
633 }
634
635 impl fedimint_core::core::IntoDynInstance for $output {
636 type DynType = fedimint_core::core::DynOutput;
637
638 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
639 fedimint_core::core::DynOutput::from_typed(instance_id, self)
640 }
641 }
642
643 impl fedimint_core::core::OutputOutcome for $outcome {
644 const KIND: ModuleKind = $kind;
645 }
646
647 impl fedimint_core::core::IntoDynInstance for $outcome {
648 type DynType = fedimint_core::core::DynOutputOutcome;
649
650 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
651 fedimint_core::core::DynOutputOutcome::from_typed(instance_id, self)
652 }
653 }
654
655 impl fedimint_core::core::ModuleConsensusItem for $ci {
656 const KIND: ModuleKind = $kind;
657 }
658
659 impl fedimint_core::core::IntoDynInstance for $ci {
660 type DynType = fedimint_core::core::DynModuleConsensusItem;
661
662 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
663 fedimint_core::core::DynModuleConsensusItem::from_typed(instance_id, self)
664 }
665 }
666
667 impl fedimint_core::core::InputError for $input_error {
668 const KIND: ModuleKind = $kind;
669 }
670
671 impl fedimint_core::core::IntoDynInstance for $input_error {
672 type DynType = fedimint_core::core::DynInputError;
673
674 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
675 fedimint_core::core::DynInputError::from_typed(instance_id, self)
676 }
677 }
678
679 impl fedimint_core::core::OutputError for $output_error {
680 const KIND: ModuleKind = $kind;
681 }
682
683 impl fedimint_core::core::IntoDynInstance for $output_error {
684 type DynType = fedimint_core::core::DynOutputError;
685
686 fn into_dyn(self, instance_id: ModuleInstanceId) -> Self::DynType {
687 fedimint_core::core::DynOutputError::from_typed(instance_id, self)
688 }
689 }
690 };
691}
692
693#[macro_export]
694macro_rules! erased_eq_no_instance_id {
695 ($newtype:ty) => {
696 fn erased_eq_no_instance_id(&self, other: &$newtype) -> bool {
697 let other: &Self = other
698 .as_any()
699 .downcast_ref()
700 .expect("Type is ensured in previous step");
701
702 self == other
703 }
704 };
705}
706
707#[macro_export]
708macro_rules! module_plugin_dyn_newtype_eq_passthrough {
709 ($newtype:ty) => {
710 impl PartialEq for $newtype {
711 fn eq(&self, other: &Self) -> bool {
712 if self.module_instance_id != other.module_instance_id {
713 return false;
714 }
715 self.erased_eq_no_instance_id(other)
716 }
717 }
718
719 impl Eq for $newtype {}
720 };
721}
722
723#[macro_export]
724macro_rules! module_plugin_dyn_newtype_display_passthrough {
725 ($newtype:ty) => {
726 impl std::fmt::Display for $newtype {
727 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
728 f.write_fmt(format_args!("{}-{}", self.module_instance_id, self.inner))
729 }
730 }
731 };
732}
733
734#[macro_export]
747macro_rules! extensible_associated_module_type {
748 ($name:ident, $name_v0:ident, $error:ident) => {
749 #[derive(
750 Clone,
751 Eq,
752 PartialEq,
753 Hash,
754 serde::Deserialize,
755 serde::Serialize,
756 fedimint_core::encoding::Encodable,
757 fedimint_core::encoding::Decodable,
758 )]
759 pub enum $name {
760 V0($name_v0),
761 #[encodable_default]
762 Default {
763 variant: u64,
764 bytes: Vec<u8>,
765 },
766 }
767
768 impl $name {
769 pub fn maybe_v0_ref(&self) -> Option<&$name_v0> {
770 match self {
771 $name::V0(v0) => Some(v0),
772 $name::Default { .. } => None,
773 }
774 }
775
776 pub fn ensure_v0_ref(&self) -> Result<&$name_v0, $error> {
777 match self {
778 $name::V0(v0) => Ok(v0),
779 $name::Default { variant, .. } => Err($error { variant: *variant }),
780 }
781 }
782 }
783
784 impl std::fmt::Debug for $name {
785 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
786 use $crate::bitcoin::hashes::hex::DisplayHex;
787 match self {
788 $name::V0(v0) => {
789 v0.fmt(f)?;
790 }
791 $name::Default { variant, bytes } => {
792 f.debug_struct(stringify!($name))
793 .field("variant", variant)
794 .field("bytes", &bytes.as_hex())
795 .finish()?;
796 }
797 }
798 Ok(())
799 }
800 }
801
802 #[derive(
803 Debug,
804 thiserror::Error,
805 Clone,
806 Eq,
807 PartialEq,
808 Hash,
809 serde::Deserialize,
810 serde::Serialize,
811 fedimint_core::encoding::Encodable,
812 fedimint_core::encoding::Decodable,
813 )]
814 #[error("Unknown {} variant {variant}", stringify!($name))]
815 pub struct $error {
816 pub variant: u64,
817 }
818
819 impl std::fmt::Display for $name {
820 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
821 match self {
822 $name::V0(inner) => std::fmt::Display::fmt(inner, f),
823 $name::Default { variant, .. } => {
824 write!(f, "Unknown {} (variant={variant})", stringify!($name))
825 }
826 }
827 }
828 }
829 };
830}